class Segment {
constructor(p1, p2) {
this.p1 = p1;
this.p2 = p2;
const diff = this.p2.subtract(this.p1);
this.dir = diff;
this.angle = diff.heading();
this.length = diff.length();
}
ccw(a, b, c) {
return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
}
intersects(other) {
return this.ccw(this.p1, other.p1, other.p2) !== this.ccw(this.p2, other.p1, other.p2) &&
this.ccw(this.p1, this.p2, other.p1) !== this.ccw(this.p1, this.p2, other.p2)
}
distanceFromPoint(p) {
const dist2 = (v, w) => (v.x - w.x) ** 2 + (v.y - w.y) ** 2;
const length2 = dist2(this.p1, this.p2);
if (length2 === 0) {
return p.distanceFrom(this.p1);
}
let t = (
(p.x - this.p1.x) * (this.p2.x - this.p1.x) +
(p.y - this.p1.y) * (this.p2.y - this.p1.y)
) / length2;
t = Math.max(0, Math.min(1, t));
return Math.sqrt(
dist2(
p,
new Vector(
this.p1.x + t * (this.p2.x - this.p1.x),
this.p1.y + t * (this.p2.y - this.p1.y)
)
)
);
}
distanceFromSegment(other) {
if (this.intersects(other)) {
return 0;
}
return Math.min(
this.distanceFromPoint(other.p1),
this.distanceFromPoint(other.p2)
);
}
}