Skip to content

Instantly share code, notes, and snippets.

@abhandaru
Created August 15, 2019 21:23
Show Gist options
  • Save abhandaru/f743df4bdb00f47ed7b2c21e29acbd58 to your computer and use it in GitHub Desktop.
Save abhandaru/f743df4bdb00f47ed7b2c21e29acbd58 to your computer and use it in GitHub Desktop.
Line with intersection method
case class Vec(i: Double, j: Double) {
def unary_- = Vec(-i, -j)
def +(v: Vec): Vec = Vec(i + v.i, j + v.j)
def -(v: Vec): Vec = Vec(i - v.i, j - v.j)
def *(s: Double): Vec = Vec(i * s, j * s)
def cross(v: Vec): Int = i * v.j - j * v.i
}
case class Line(a: Vec, b: Vec) {
/**
* Find the intersection of 2 line segments, if any. Naturally, the result
* may be non-integer, and the return type accomodates this thusly.
*
* Algo background:
* https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
*/
def intersect(line: Line): Option[Vec] = {
// Segment starts
val p = a
val q = line.a
// Offset vectors
val r = b - a
val s = line.b - line.a
// Cache
val r_x_s = r cross s
val qp_x_r = (q - p) cross r
val qp_x_s = (q - p) cross s
// Cases
if (r_x_s == 0 && qp_x_r == 0) {
// Lines are collinear, and so intersect if they have any overlap
// TODO (adu): Return some reasonable point on this line.
None
} else if (r_x_s == 0 && qp_x_r != 0) {
None
} else if (r_x_s != 0) {
val t = qp_x_s / r_x_s
val u = qp_x_r / r_x_s
if (0 <= t && t <= 1 && 0 <= u && u <= 1) {
Some(Vec(p.i + t * r.i, p.j + t * r.j))
} else None
} else None
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment