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

commonMain.ru.casperix.math.iteration.Line3Iterator.kt Maven / Gradle / Ivy

package ru.casperix.math.iteration

import ru.casperix.math.axis_aligned.float64.Box3d
import ru.casperix.math.geometry.Line3d
import ru.casperix.math.geometry.float64.isFinite
import ru.casperix.math.intersection.intersectionLineWithBox
import ru.casperix.math.vector.float64.Vector3d
import ru.casperix.math.vector.int32.Vector3i
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.roundToInt

@Deprecated(message = "Bad performance and wrong result")
object Line3Iterator {
	fun iterate3n(line: Line3d, onStep: (Vector3i) -> Boolean): Vector3i? {
		if (!line.isFinite()) return null

		val halfPixel = Vector3d.ONE * 0.5
		var nextStep = (line.v0 - halfPixel).roundToVector3i()
		val lastStep = (line.v1 - halfPixel).roundToVector3i()
		var steps = 1 + (lastStep - nextStep).lengthOne()

		val ray = (line.v1 - line.v0)
		val length = ray.length()
		if (abs(length) <= Double.MIN_VALUE) {
			if (onStep(nextStep)) return nextStep
			return null
		}
		val lineDirection = ray.normalize()
		val signVec = lineDirection.sign.roundToVector3i()




		while (--steps > 0) {
			if (onStep(nextStep)) return nextStep

			//	Потенциальные кандидаты
			val nextX = Vector3i(nextStep.x + signVec.x, nextStep.y, nextStep.z)
			val nextY = Vector3i(nextStep.x, nextStep.y + signVec.y, nextStep.z)
			val nextZ = Vector3i(nextStep.x, nextStep.y, nextStep.z + signVec.z)

			//	Идеальный кандидат тот, кто ближе к линии
//		val nextXRelative = nextX.toVector3d() + halfPixel - line.v0
//		val nextYRelative = nextY.toVector3d() + halfPixel - line.v0
//		val nextZRelative = nextZ.toVector3d() + halfPixel - line.v0
//		val distX = distance3d(stepVariants.x, nextXRelative, lineDirection)
//		val distY = distance3d(stepVariants.y, nextYRelative, lineDirection)
//		val distZ = distance3d(stepVariants.z, nextZRelative, lineDirection)

			val testX = intersectionLineWithBox(line, Box3d.byDimension(nextX.toVector3d(), Vector3d.ONE))
			val testY = intersectionLineWithBox(line, Box3d.byDimension(nextY.toVector3d(), Vector3d.ONE))
			val testZ = intersectionLineWithBox(line, Box3d.byDimension(nextZ.toVector3d(), Vector3d.ONE))
			val distX = if (testX == null || signVec.x == 0) 1.0 else 0.0
			val distY = if (testY == null || signVec.y == 0) 1.0 else 0.0
			val distZ = if (testZ == null || signVec.z == 0) 1.0 else 0.0

			if (distX <= distY && distX <= distZ) {
				nextStep = nextX
			} else if (distY <= distX && distY <= distZ) {
				nextStep = nextY
			} else if (distZ <= distX && distZ <= distY) {
				nextStep = nextZ
			} else {
				throw Error("Invalid state")
			}
		}
		if (onStep(lastStep)) return lastStep
		return null
	}

	private fun distance3d(dir: Int, point: Vector3d, rayDirection: Vector3d): Double {
		if (dir == 0) return Double.MAX_VALUE

		val projection = point.dot(rayDirection)
		val dest = rayDirection * projection - point

		return dest.lengthInf()
	}

	fun iterateDDA(v1: Vector3d, v2: Vector3d, onStep: (Vector3i) -> Boolean): Vector3i? {
		if (!v1.isFinite() || !v2.isFinite()) return null
		val start = (v1 - Vector3d.ONE * 0.5).roundToVector3i()
		val end = (v2 - Vector3d.ONE * 0.5).roundToVector3i()

		val L: Int = 1 + max(max(abs(end.x - start.x), abs(end.y - start.y)), abs(end.z - start.z))
		val fx = v1.x - 0.5
		val fy = v1.y - 0.5
		val fz = v1.z - 0.5
		val dx = (end.x - start.x).toDouble() / L.toDouble()
		val dy = (end.y - start.y).toDouble() / L.toDouble()
		val dz = (end.z - start.z).toDouble() / L.toDouble()

		var first = Vector3i.ZERO
		var last = Vector3i.ZERO

		for (step in 0 until L) {
			val currentX = (fx + step * dx).roundToInt()
			val currentY = (fy + step * dy).roundToInt()
			val currentZ = (fz + step * dz).roundToInt()

			val next = Vector3i(currentX, currentY, currentZ)

			if (step == 0) {
				first = next
			}
			if (step == L - 1) {
				last = next
			}
			if (onStep(next)) return next

		}

		println("from $first to $last")
		return null
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy