///|
pub(all) struct ImageSpec {
width : Int
height : Int
} derive(Debug, Eq, ToJson)
///|
pub fn ImageSpec::new(width~ : Int, height~ : Int) -> ImageSpec {
{ width, height }
}
///|
pub fn ImageSpec::area(self : ImageSpec) -> Int {
self.width * self.height
}
///|
pub fn ImageSpec::valid(self : ImageSpec) -> Bool {
self.width > 0 && self.height > 0
}
///|
pub(all) struct Point {
x : Double
y : Double
} derive(Debug, ToJson)
///|
pub fn Point::new(x~ : Double, y~ : Double) -> Point {
{ x, y }
}
///|
pub fn Point::translate(self : Point, dx~ : Double, dy~ : Double) -> Point {
{ x: self.x + dx, y: self.y + dy }
}
///|
pub fn Point::scale(self : Point, sx~ : Double, sy~ : Double) -> Point {
{ x: self.x * sx, y: self.y * sy }
}
///|
pub(all) struct Size {
width : Double
height : Double
} derive(Debug, ToJson)
///|
pub fn Size::new(width~ : Double, height~ : Double) -> Size {
{ width, height }
}
///|
pub(all) struct Rect {
x : Double
y : Double
width : Double
height : Double
} derive(Debug, ToJson)
///|
pub fn Rect::new(
x~ : Double,
y~ : Double,
width~ : Double,
height~ : Double,
) -> Rect {
{ x, y, width, height }
}
///|
pub fn Rect::right(self : Rect) -> Double {
self.x + self.width
}
///|
pub fn Rect::bottom(self : Rect) -> Double {
self.y + self.height
}
///|
pub fn Rect::area(self : Rect) -> Double {
if self.width <= 0.0 || self.height <= 0.0 {
0.0
} else {
self.width * self.height
}
}
///|
pub fn Rect::translate(self : Rect, dx~ : Double, dy~ : Double) -> Rect {
{ x: self.x + dx, y: self.y + dy, width: self.width, height: self.height }
}
///|
pub fn Rect::scale(self : Rect, sx~ : Double, sy~ : Double) -> Rect {
{
x: self.x * sx,
y: self.y * sy,
width: self.width * sx,
height: self.height * sy,
}
}
///|
pub fn Rect::intersects(self : Rect, other : Rect) -> Bool {
self.x < other.right() &&
other.x < self.right() &&
self.y < other.bottom() &&
other.y < self.bottom()
}
///|
pub fn Rect::intersection(self : Rect, other : Rect) -> Rect? {
let left = max_double(self.x, other.x)
let top = max_double(self.y, other.y)
let right = min_double(self.right(), other.right())
let bottom = min_double(self.bottom(), other.bottom())
if right <= left || bottom <= top {
None
} else {
Some(Rect::new(x=left, y=top, width=right - left, height=bottom - top))
}
}
///|
pub fn Rect::iou(self : Rect, other : Rect) -> Double {
match self.intersection(other) {
None => 0.0
Some(overlap) => {
let inter = overlap.area()
let union = self.area() + other.area() - inter
if union <= 0.0 {
0.0
} else {
inter / union
}
}
}
}
///|
fn min_double(a : Double, b : Double) -> Double {
if a < b {
a
} else {
b
}
}
///|
fn max_double(a : Double, b : Double) -> Double {
if a > b {
a
} else {
b
}
}