![JAR search and dependency download from the Maven repository](/logo.png)
commonMain.ru.casperix.math.geometry.CurveFactory.kt Maven / Gradle / Ivy
package ru.casperix.math.geometry
import ru.casperix.math.geometry.float32.Geometry2Float
import ru.casperix.math.curve.float32.Arc2f
import ru.casperix.math.curve.float32.ParametricCurve2f
import ru.casperix.math.curve.float32.LineCurve2f
import ru.casperix.math.intersection.float32.Intersection2Float
import ru.casperix.math.vector.float32.Vector2f
import kotlin.math.sqrt
object CurveFactory {
// fun buildLineAndArc2(
// start: Vector2f,
// startAndTangent: Vector2f,
// finishAndTangent: Vector2f,
// finish: Vector2f,
// minLineLength: Float = 0.001f,
// maxArcRange: Float = 1000f
// ): Curve2f {
// val O = Intersection2Float.getLineWithLine(Line2f(start, startAndTangent), Line2f(finish, finishAndTangent))
// ?: return LineCurve2f(Line2f(start, finish))
//
// val rayOS = start - O
// val rayOF = finish - O
//
// val lengthOS = rayOS.length()
// val lengthOF = rayOF.length()
//
// if (lengthOS > maxArcRange || lengthOF > maxArcRange) {
// return LineCurve2f(Line2f(start, finish))
// }
//
// if (lengthOS > lengthOF) {
// return buildLineAndArc2(
// finish,
// finishAndTangent,
// startAndTangent,
// start,
// minLineLength,
// maxArcRange
// ).invert()
// }
//
// val pad1 = Geometry2Float.getPointAroundDirection(start, finish, startAndTangent, 0f)
// val pad2 = Geometry2Float.getPointAroundDirection(start, finish, finishAndTangent, 0f)
// val pad3 = Geometry2Float.getPointAroundDirection(start, finish, O, 0f)
// if (pad1 != pad2 || pad1 != pad3) {
// return LineCurve2f(Line2f(start, finish))
// }
//
// val rayOA = rayOF.normalize() * lengthOS
// val A = O + rayOA
//
// val dirCS = rayOS.rotateCW()
// val dirCA = rayOA.rotateCCW()
// val center = Intersection2Float.getLineWithLine(Line2f.byDelta(start, dirCS), Line2f.byDelta(A, dirCA))
// ?: return LineCurve2f(Line2f(start, finish))
//
// val range = center.distTo(start)
//
// val middleAngle = RadianFloat.byDirection(O - center)
// var deltaAngle = RadianFloat.betweenAngle(middleAngle, RadianFloat.byDirection(start - center))
//
//
// val pad = Geometry2Float.getPointAroundDirection(start, startAndTangent, finish, 0f)
// if (pad != PointAroundDirection.LEFT) {
// deltaAngle = -deltaAngle
// }
//
// val arc = Arc2f(center, middleAngle - deltaAngle, deltaAngle * 2f, range)
// val line = LineCurve2f(A, finish)
// if (line.length() < minLineLength) {
// return arc
// }
// return arc + line
//
// }
fun buildLineAndArc(
start: Vector2f,
startAndTangent: Vector2f,
finishAndTangent: Vector2f,
finish: Vector2f,
minLineLength: Float = 0.001f,
): ParametricCurve2f {
val O = Intersection2Float.getLineWithLine(
Line2f(start, startAndTangent),
Line2f(finish, finishAndTangent)
)?.toVector2f()
?: return LineCurve2f(Line2f(start, finish))
val toStart = start - O
val toFinish = finish - O
val range1 = toStart.lengthSquared()
val range2 = toFinish.lengthSquared()
val k = sqrt(range1 / range2)
if (k > 0.999f && k < 1.001f) {
return Arc2f.byTangent(start, startAndTangent - start, finish)
}
val padSAT = Geometry2Float.getPointAroundRay(start, finish, startAndTangent, 0f)
val padFAT = Geometry2Float.getPointAroundRay(start, finish, finishAndTangent, 0f)
if (padSAT != padFAT) {
return LineCurve2f(Line2f(start, finish))
}
val padO = Geometry2Float.getPointAroundRay(start, finish, O, 0f)
if (padO != padSAT) {
return if (range1 > range2) {
val T = toFinish * k
buildLineAndArcDirect(start, startAndTangent, O + T, finish, true, minLineLength)
} else {
val T = toStart / k
buildLineAndArcDirect(finish, finishAndTangent, O + T, start, false, minLineLength)
}
} else {
return if (range1 < range2) {
val T = toFinish * k
buildLineAndArcDirect(start, startAndTangent, O + T, finish, true, minLineLength)
} else {
val T = toStart / k
buildLineAndArcDirect(finish, finishAndTangent, O + T, start, false, minLineLength)
}
}
}
private fun buildLineAndArcDirect(
arcStart: Vector2f,
arcStartAndTangent: Vector2f,
arcFinish: Vector2f,
lineFinish: Vector2f,
startFromArc: Boolean,
minLineLength: Float,
): ParametricCurve2f {
val line = LineCurve2f(arcFinish, lineFinish)
val excludeLine = line.length() < minLineLength
val actualArcFinish = if (excludeLine) {
lineFinish
} else {
arcFinish
}
val arc = Arc2f.byTangent(arcStart, arcStartAndTangent - arcStart, actualArcFinish)
?: return LineCurve2f(arcStart, lineFinish)
return if (excludeLine) {
if (startFromArc) {
arc
} else {
arc.invert()
}
} else {
if (startFromArc) {
arc + line
} else {
line.invert() + arc.invert()
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy