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

commonMain.ru.casperix.math.geometry.float64.Geometry2Double.kt Maven / Gradle / Ivy

package ru.casperix.math.geometry.float64

import ru.casperix.math.geometry.GeometryApi
import ru.casperix.math.geometry.Line2d
import ru.casperix.math.geometry.PointAroundRay
import ru.casperix.math.geometry.Quad2d
import ru.casperix.math.intersection.float64.Intersection2Double
import ru.casperix.math.vector.float64.Vector2d
import kotlin.math.*

object Geometry2Double : GeometryApi {

    override fun getPointAroundRay(
        start: Vector2d,
        finish: Vector2d,
        point: Vector2d,
        error: Double
    ): PointAroundRay {
        val D = calculateDeterminant(start, finish, point)
        if (D > error) return PointAroundRay.LEFT
        if (D < -error) return PointAroundRay.RIGHT
        return PointAroundRay.INSIDE
    }

    override fun calculateDeterminant(start: Vector2d, finish: Vector2d, point: Vector2d): Double {
        return (finish.x - start.x) * (point.y - start.y) - (finish.y - start.y) * (point.x - start.x)
    }

    override fun distPointToQuad(P: Vector2d, quad: Quad2d): Double {
        if (Intersection2Double.hasPointWithQuad(P, quad)) return 0.0

        return quad.getEdgeList().minOf { edge ->
            distPointToSegment(P, edge)
        }
    }

    override fun distPointToLine(P: Vector2d, T: Line2d): Double {
        val x0 = P.x
        val y0 = P.y

        val x1 = T.v0.x
        val y1 = T.v0.y
        val x2 = T.v1.x
        val y2 = T.v1.y

        val f = (x2 - x1) * (y1 - y0) - (x1 - x0) * (y2 - y1)

        val d = sqrt((x2 - x1).pow(2) + (y2 - y1).pow(2))

        if (d == 0.0) {
            return P.distTo(T.v0)
        }
        return (f.absoluteValue / d)
    }


    /**
     * https://www.geeksforgeeks.org/minimum-distance-from-a-point-to-the-line-segment-using-vectors/
     */
    override fun distPointToSegment(P: Vector2d, A: Vector2d, B: Vector2d): Double {
        val AB = B - A
        val BP = P - B
        val AP = P - A

        // Variables to store dot product
        // Calculating the dot product
        val AB_BP = AB.dot(BP)
        val AB_AP = AB.dot(AP)

        // Minimum distance from
        // point E to the line segment
        return if (AB_BP > 0) {
            // Case 1
            val x = P.x - B.x
            val y = P.y - B.y
            sqrt(x * x + y * y)
        } else if (AB_AP < 0) {
            // Case 2
            val x = P.x - A.x
            val y = P.y - A.y
            sqrt(x * x + y * y)
        } else {
            // Case 3
            // Finding the perpendicular distance
            val x1 = AB.x
            val y1 = AB.y
            val x2 = AP.x
            val y2 = AP.y
            val mod = sqrt(x1 * x1 + y1 * y1)
            abs(x1 * y2 - y1 * x2) / mod
        }
    }

    override fun projectionByDirection(source: Vector2d, direction: Vector2d): Vector2d {
        val normalized = direction.normalize()
        val length = source.dot(normalized)
        return normalized * length
    }

    override fun projectionByDirectionLength(source: Vector2d, direction: Vector2d): Double {
        val normalized = direction.normalize()
        return source.dot(normalized)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy