Last active
March 26, 2019 01:05
-
-
Save Pooh3Mobi/f0905fd70db12b99a9f3c0bd29045b87 to your computer and use it in GitHub Desktop.
the intersection of two lines
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.AssertionError | |
data class Point(val x: Float, val y: Float) | |
fun pointAt(x: Float, y: Float) = Point(x, y) | |
data class Line(val p1: Point, val p2: Point) | |
infix fun Point.to(other: Point) = Line(this, other) | |
// 傾き | |
fun Line.slope() = (p2.y - p1.y) / (p2.x - p1.x) | |
// Y軸切片 | |
fun Line.interceptYAxis() = p1.y - slope() * p1.x | |
// y = f(x) | |
fun Line.getY(x: Float): Float = slope() * x + interceptYAxis() | |
// 交点 | |
fun Line.getIntercept(other: Line): Point? { | |
val slopeA = this.slope() | |
val slopeB = other.slope() | |
return if (slopeA == slopeB) { | |
// parallel | |
null | |
} else { | |
val interceptX = (other.interceptYAxis() - this.interceptYAxis()) / (slopeA - slopeB) | |
val interceptY = this.getY(interceptX) | |
pointAt(interceptX, interceptY) | |
} | |
} | |
// 線上に存在するかどうか | |
fun Line.contains(point: Point): Boolean { | |
val x = point.x | |
val y = point.y | |
val containsX = (x in p1.x..p2.x) || (x in p2.x..p1.x) | |
val containsY = (y in p1.y..p2.y) || (y in p2.y..p1.y) | |
return containsX && containsY | |
} | |
// 交差しているかどうか | |
fun Line.isIntersect(other: Line): Boolean { | |
if (this.slope() == other.slope()) return false | |
val intercept = this.getIntercept(other) ?: return false | |
return this.contains(intercept) && other.contains(intercept) | |
} | |
fun Point.move(point: Point) = copy(x = x + point.x, y = y + point.y) | |
fun Line.parallelTransport(point: Point) = copy(p1 = p1.move(point), p2 = p2.move(point)) | |
fun main() { | |
run { | |
val lineA = pointAt(1f, 1f) to pointAt(-1f, -1f) | |
val lineB = pointAt(-1f, 1f) to pointAt(1f, -1f) | |
// 交点を持つ | |
val interceptPoint = lineA.getIntercept(lineB) | |
if (interceptPoint != pointAt(0f, 0f)) throw AssertionError("$interceptPoint") | |
val isIntersect = lineA.isIntersect(lineB) | |
if (!isIntersect) throw AssertionError("$lineA : $lineB") | |
} | |
run { | |
val lineA = pointAt(1f, 1f) to pointAt(0f, 0f) | |
val lineB = pointAt(0f, 0f) to pointAt(1f, -1f) | |
// 交点を持つ | |
val interceptPoint = lineA.getIntercept(lineB) | |
if (interceptPoint != pointAt(0f, 0f)) throw AssertionError("$interceptPoint") | |
val isIntersect = lineA.isIntersect(lineB) | |
if (!isIntersect) throw AssertionError("$lineA : $lineB") | |
} | |
run { | |
val dist = pointAt(3f, -3f) | |
val lineA = pointAt(1f, 1f) to pointAt(-1f, -1f) | |
val lineB = pointAt(-1f, 1f).move(dist) to pointAt(1f, -1f).move(dist) | |
// 直線上の延長線上に交点を持つが、範囲内では交差しない | |
val interceptPoint = lineA.getIntercept(lineB) | |
if (interceptPoint != pointAt(0f, 0f)) throw AssertionError("$interceptPoint") | |
val isIntersect = lineA.isIntersect(lineB) | |
if (isIntersect) throw AssertionError("$lineA : $lineB") | |
} | |
run { | |
val dist = pointAt(-3f, 3f) | |
val lineA = pointAt(1f, 1f) to pointAt(-1f, -1f) | |
val lineB = pointAt(-1f, 1f).move(dist) to pointAt(1f, -1f).move(dist) | |
// 直線上の延長線上に交点を持つが、範囲内では交差しない | |
val interceptPoint = lineA.getIntercept(lineB) | |
if (interceptPoint != pointAt(0f, 0f)) throw AssertionError("$interceptPoint") | |
val isIntersect = lineA.isIntersect(lineB) | |
if (isIntersect) throw AssertionError("$lineA : $lineB") | |
} | |
run { | |
val dist = pointAt(-5f, -5f) | |
val lineA = pointAt(1f, 1f) to pointAt(-1f, -1f) | |
val lineB = pointAt(-1f, 1f).move(dist) to pointAt(1f, -1f).move(dist) | |
// 直線上の延長線上に交点を持つが、範囲内では交差しない | |
val interceptPoint = lineA.getIntercept(lineB) | |
if (interceptPoint != pointAt(-5f, -5f)) throw AssertionError("$interceptPoint") | |
val isIntersect = lineA.isIntersect(lineB) | |
if (isIntersect) throw AssertionError("$lineA : $lineB") | |
} | |
run { | |
val dist = pointAt(5f, 5f) | |
val lineA = pointAt(1f, 1f) to pointAt(-1f, -1f) | |
val lineB = pointAt(-1f, 1f).move(dist) to pointAt(1f, -1f).move(dist) | |
// 直線上の延長線上に交点を持つが、範囲内では交差しない | |
val interceptPoint = lineA.getIntercept(lineB) | |
if (interceptPoint != pointAt(5f, 5f)) throw AssertionError("$interceptPoint") | |
val isIntersect = lineA.isIntersect(lineB) | |
if (isIntersect) throw AssertionError("$lineA : $lineB") | |
} | |
run { | |
val dist = pointAt(5f, 5f) | |
val lineA = pointAt(1f, 1f) to pointAt(1f, -1f) | |
val lineB = lineA.parallelTransport(dist) | |
// 直線上の延長線上に持たず、範囲内では交差しない | |
val interceptPoint = lineA.getIntercept(lineB) | |
if (interceptPoint != null) throw AssertionError("$interceptPoint") | |
val isIntersect = lineA.isIntersect(lineB) | |
if (isIntersect) throw AssertionError("$lineA : $lineB") | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment