![JAR search and dependency download from the Maven repository](/logo.png)
commonMain.ru.casperix.math.intersection.Penetration.kt Maven / Gradle / Ivy
package ru.casperix.math.intersection
import ru.casperix.math.vector.float64.Vector2d
import kotlin.math.absoluteValue
import kotlin.math.sign
object Penetration {
fun circleWithCircle(centerA: Vector2d, radiusA: Double, centerB: Vector2d, radiusB: Double): Vector2d? {
val delta = centerB - centerA
val dest = delta.length()
val minDest = radiusA + radiusB
if (dest >= minDest) return null
return delta.normalize() * (minDest - dest)
}
fun rectangleWithRectangle(centerA: Vector2d, sizeA: Vector2d, centerB: Vector2d, sizeB: Vector2d): Vector2d? {
val minX = sizeA.x * 0.5 + sizeB.x * 0.5
val currentX = centerB.x - centerA.x
val depthX = minX - currentX.absoluteValue
if (depthX <= 0.0) return null
val dimY = sizeA.y * 0.5 + sizeB.y * 0.5
val deltaY = centerB.y - centerA.y
val depthY = dimY - deltaY.absoluteValue
if (depthY <= 0.0) return null
if (depthX < depthY) {
return Vector2d(depthX * currentX.sign, 0.0)
} else {
return Vector2d(0.0, depthY * deltaY.sign)
}
}
fun rectangleWithCircle(rectanglePosition: Vector2d, rectangleSize: Vector2d, circlePosition: Vector2d, circleRadius: Double): Vector2d? {
circleWithRectangle(circlePosition, circleRadius, rectanglePosition, rectangleSize)?.let {
return -it
}
return null
}
fun circleWithRectangle(circlePosition: Vector2d, circleRadius: Double, rectanglePosition: Vector2d, rectangleSize: Vector2d): Vector2d? {
val range = Vector2d(circleRadius)
val rectangleMin = rectanglePosition - rectangleSize * 0.5
val rectangleMax = rectanglePosition + rectangleSize * 0.5
if (circlePosition.greater(rectangleMin) && circlePosition.less(rectangleMax)) {
return rectangleWithRectangle(circlePosition, range + range, rectanglePosition, rectangleSize)
}
// left-bottom-corner
if (circlePosition.x < rectangleMin.x && circlePosition.y < rectangleMin.y) {
val dir = rectangleMin - circlePosition
if (dir.length() < circleRadius) return dir.normalize() * (circleRadius - dir.length())
}
// left-top-corner
if (circlePosition.x < rectangleMin.x && circlePosition.y > rectangleMax.y) {
val dir = Vector2d(rectangleMin.x, rectangleMax.y) - circlePosition
if (dir.length() < circleRadius) return dir.normalize() * (circleRadius - dir.length())
}
// right-top-corner
if (circlePosition.x > rectangleMax.x && circlePosition.y > rectangleMax.y) {
val dir = rectangleMax - circlePosition
if (dir.length() < circleRadius) return dir.normalize() * (circleRadius - dir.length())
}
// right-bottom-corner
if (circlePosition.x > rectangleMax.x && circlePosition.y < rectangleMin.y) {
val dir = Vector2d(rectangleMax.x, rectangleMin.y) - circlePosition
if (dir.length() < circleRadius) return dir.normalize() * (circleRadius - dir.length())
}
if (circlePosition.y >= rectangleMin.y && circlePosition.y <= rectangleMax.y) {
val leftSpace = rectangleMin.x - circlePosition.x
if (0.0 < leftSpace && leftSpace < circleRadius) {
return Vector2d(circleRadius - leftSpace, 0.0)
}
val rightSpace = circlePosition.x - rectangleMax.x
if (0.0 < rightSpace && rightSpace < circleRadius) {
return Vector2d(rightSpace - circleRadius, 0.0)
}
}
if (circlePosition.x >= rectangleMin.x && circlePosition.x <= rectangleMax.x) {
val topSpace = circlePosition.y - rectangleMax.y
if (0.0 < topSpace && topSpace < circleRadius) {
return Vector2d(0.0, topSpace - circleRadius)
}
val bottomSpace = rectangleMin.y - circlePosition.y
if (0.0 < bottomSpace && bottomSpace < circleRadius) {
return Vector2d(0.0, circleRadius - bottomSpace)
}
}
return null
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy