///|
pub(all) struct Circle(Vec2, Double)
///|
pub impl ConvexShape for Circle with far(self, dir) {
let Circle(c, r) = self
c + dir.normal_then_mul(r)
}
///|
/// Note: The FixedArray must not be empty.
pub(all) struct Polygon(FixedArray[Vec2])
///|
pub impl ConvexShape for Polygon with far(self, dir) {
self.0.unsafe_max_by(dir.dot(_))
}
///|
fn[A, B : Compare] FixedArray::unsafe_max_by(
self : FixedArray[A],
f : (A) -> B,
) -> A {
guard self is [a0, .. rest]
for am = a0, bm = f(a0), rest = rest {
match rest {
[] => break am
[ai, .. rest] => {
let bi = f(ai)
if bi > bm {
continue ai, bi, rest
} else {
continue am, bm, rest
}
}
}
}
}
///|
test "circle far" {
let s1 = Circle(Vec2(0, 0), 5)
let s2 = Circle(Vec2(-1, -1), 5)
let d1 = Vec2(3, 4)
let d2 = Vec2(1, 0)
inspect(s1.far(d1), content="(3, 4)")
inspect(s1.far(d2), content="(5, 0)")
inspect(s2.far(d1), content="(2, 3)")
inspect(s2.far(d2), content="(4, -1)")
}
///|
test "polygon far" {
let s1 = Polygon([Vec2(0, 0), Vec2(0, 1), Vec2(1, 0), Vec2(1, 1)])
let s2 = Polygon([Vec2(0, 0), Vec2(0, 1), Vec2(1, 0)])
let s3 = Polygon([Vec2(1, 1), Vec2(1, 2), Vec2(2, 1), Vec2(2, 2)])
let d1 = Vec2(5, -1)
let d2 = Vec2(1, 5)
inspect(s1.far(d1), content="(1, 0)")
inspect(s1.far(d2), content="(1, 1)")
inspect(s2.far(d1), content="(1, 0)")
inspect(s2.far(d2), content="(0, 1)")
inspect(s3.far(d1), content="(2, 1)")
inspect(s3.far(d2), content="(2, 2)")
}