commonMain.ru.casperix.math.intersection.int32.Intersection2Int.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of math Show documentation
Show all versions of math Show documentation
Simple set of geometric and other types
package ru.casperix.math.intersection.int32
import ru.casperix.math.axis_aligned.int32.Box2i
import ru.casperix.math.geometry.float64.Geometry2Double
import ru.casperix.math.geometry.float64.Geometry2Double.distPointToLine
import ru.casperix.math.geometry.*
import ru.casperix.math.intersection.ConvexHullIntersection
import ru.casperix.math.intersection.IntersectionApi
import ru.casperix.math.intersection.float64.Intersection2Double
import ru.casperix.math.vector.float64.Vector2d
import ru.casperix.math.vector.int32.Vector2i
import ru.casperix.misc.toDoubleArray
import kotlin.math.absoluteValue
object Intersection2Int : IntersectionApi {
fun hasBoxWithBox(A: Box2i, B: Box2i): Boolean {
if (A.max.y - B.min.y < 0) return false
if (B.max.y - A.min.y < 0) return false
if (A.max.x - B.min.x < 0) return false
if (B.max.x - A.min.x < 0) return false
return true
}
override fun hasPointWithTriangle(P: Vector2i, triangle: Triangle2i): Boolean {
// Compute vectors
val v0 = triangle.v2 - triangle.v0
val v1 = triangle.v1 - triangle.v0
val v2 = P - triangle.v0
// Compute dot products
val dot00 = v0.dot(v0)
val dot01 = v0.dot(v1)
val dot02 = v0.dot(v2)
val dot11 = v1.dot(v1)
val dot12 = v1.dot(v2)
// Compute barycentric coordinates
val invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01)
val u = (dot11 * dot02 - dot01 * dot12) * invDenom
val v = (dot00 * dot12 - dot01 * dot02) * invDenom
// Check if point is in triangle
return (u >= 0) && (v >= 0) && (u + v <= 1.0)
}
override fun hasPointWithPolygon(P: Vector2i, polygon: Polygon): Boolean {
val vertices = polygon.getVertices()
if (vertices.isEmpty()) return false
if (vertices.size == 1) return P == vertices[0]
if (vertices.size == 2) return hasPointWithLine(P, vertices[0], vertices[1])
repeat(polygon.getTriangleAmount()) { index ->
if (hasPointWithTriangle(P, polygon.getTriangle(index))) return true
}
return false
}
override fun hasTriangleWithTriangle(a: Triangle2i, b: Triangle2i): Boolean {
val listA = intArrayOf(a.v0.x, a.v0.y, a.v1.x, a.v1.y, a.v2.x, a.v2.y).toDoubleArray()
val listB = intArrayOf(b.v0.x, b.v0.y, b.v1.x, b.v1.y, b.v2.x, b.v2.y).toDoubleArray()
return ConvexHullIntersection.hasIntersection(listA, listA.size, listB, listB.size)
}
override fun hasQuadWithQuad(a: Quad2i, b: Quad2i): Boolean {
val listA = intArrayOf(a.v0.x, a.v0.y, a.v1.x, a.v1.y, a.v2.x, a.v2.y, a.v3.x, a.v3.y).toDoubleArray()
val listB = intArrayOf(b.v0.x, b.v0.y, b.v1.x, b.v1.y, b.v2.x, b.v2.y, b.v3.x, b.v3.y).toDoubleArray()
return ConvexHullIntersection.hasIntersection(listA, listA.size, listB, listB.size)
}
override fun hasQuadWithTriangle(a: Quad2i, b: Triangle2i): Boolean {
val listA = intArrayOf(b.v0.x, b.v0.y, b.v1.x, b.v1.y, b.v2.x, b.v2.y).toDoubleArray()
val listB = intArrayOf(a.v0.x, a.v0.y, a.v1.x, a.v1.y, a.v2.x, a.v2.y, a.v3.x, a.v3.y).toDoubleArray()
return ConvexHullIntersection.hasIntersection(listA, listA.size, listB, listB.size)
}
override fun hasPointWithLine(P: Vector2i, T: Line2i): Boolean {
val T2 = T.convert { it.toVector2d() }
val P2 = P.toVector2d()
return distPointToLine(P2, T2) < Intersection2Double.EPSILON
&& (P2.distTo(T2.v0) + P2.distTo(T2.v1) - T2.v0.distTo(T2.v1)).absoluteValue < Intersection2Double.EPSILON
}
override fun hasPointWithSegment(P: Vector2i, T: Line2i): Boolean {
return Geometry2Double.distPointToSegment(P.toVector2d(), T.convert { it.toVector2d() }) < Intersection2Double.EPSILON
}
override fun getSegmentWithSegment(S: Line2i, T: Line2i): Vector2i? {
return intersectSegments(S.v0.x, S.v0.y, S.v1.x, S.v1.y, T.v0.x, T.v0.y, T.v1.x, T.v1.y)
}
override fun getLineWithLine(S: Line2i, T: Line2i): Vector2i? {
return Intersection2Double.getLineWithLine(S.convert { it.toVector2d() }, T.convert { it.toVector2d() })?.roundToVector2i()
}
fun pointWithQuadEdge(P: Vector2i, polygon: Quad2i): Boolean {
return pointWithAbstractPolygon(P, polygon)
}
fun pointWithTriangleEdge(P: Vector2i, polygon: Triangle2i): Boolean {
return pointWithAbstractPolygon(P, polygon)
}
fun pointWithPolygonEdge(P: Vector2i, polygon: Polygon2i): Boolean {
return pointWithAbstractPolygon(P, polygon)
}
private fun pointWithAbstractPolygon(P: Vector2i, quad: Polygon): Boolean {
quad.getEdgeList().forEach { edge ->
if (hasPointWithSegment(P, edge)) return true
}
return false
}
private fun intersectSegments(
x1: Int, y1: Int, x2: Int, y2: Int, x3: Int, y3: Int, x4: Int, y4: Int
): Vector2i? {
val d = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)
if (d == 0) return null
val yd = y1 - y3
val xd = x1 - x3
val ua = ((x4 - x3) * yd - (y4 - y3) * xd) / d.toDouble()
if (ua < 0 || ua > 1) return null
val ub = ((x2 - x1) * yd - (y2 - y1) * xd) / d.toDouble()
if (ub < 0 || ub > 1) return null
return Vector2d(x1 + (x2 - x1) * ua, y1 + (y2 - y1) * ua).roundToVector2i()
}
}