All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.math.intersection.int32.Intersection2Int.kt Maven / Gradle / Ivy

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()
    }



}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy