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