io.rtron.math.geometry.euclidean.threed.curve.LineSegment3D.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rtron-math Show documentation
Show all versions of rtron-math Show documentation
Component 'rtron-math' of rtron.
The newest version!
/*
* Copyright 2019-2022 Chair of Geoinformatics, Technical University of Munich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.rtron.math.geometry.euclidean.threed.curve
import com.github.kittinunf.result.Result
import io.rtron.math.geometry.curved.oned.point.CurveRelativeVector1D
import io.rtron.math.geometry.euclidean.threed.point.Vector3D
import io.rtron.math.range.BoundType
import io.rtron.math.range.Range
import org.apache.commons.math3.geometry.euclidean.threed.Segment as CMLineSegment3D
/**
* Line segment in 3D defined by a [start] and [end] vector.
*
* @param start start of the line segment
* @param end end of the line segment
* @param endBoundType
* @param tolerance allowed tolerance
*/
class LineSegment3D(
val start: Vector3D,
val end: Vector3D,
override val tolerance: Double,
endBoundType: BoundType = BoundType.CLOSED
) : AbstractCurve3D() {
// Properties and Initializers
init {
require(start != end) { "Start and end vector must not be identical." }
require(start.fuzzyUnequals(end, tolerance)) { "Start and end vector must be different by at least the tolerance threshold." }
}
override val domain = Range.closedX(0.0, start.distance(end), endBoundType)
/** adapted line segment class of Apache Commons Math */
private val _lineSegment3D by lazy {
CMLineSegment3D(start.toVector3DCm(), end.toVector3DCm(), Line3D(start, end, tolerance).toLine3DCM())
}
/** direction of the line segment as normalized vector */
val direction by lazy { (end - start).normalized() }
/** start and end vertices of the line segment as list */
val vertices by lazy { listOf(start, end) }
// Methods
/**
* Returns the distance between this line segment and a given [point].
* For more, see [StackOverflow](https://stackoverflow.com/a/1501725)
*
* @param point point for which the distance shall be calculated
* @return distance between this and the [point]
*/
fun distance(point: Vector3D): Double {
val lengthSquared: Double = (end - start).normSq
val t = (point - start).dotProduct(end - start) / lengthSquared
val tCoerced = t.coerceIn(0.0, 1.0)
val projectedPoint = start + (end - start).scalarMultiply(tCoerced)
return point.distance(projectedPoint)
}
override fun calculatePointLocalCSUnbounded(curveRelativePoint: CurveRelativeVector1D):
Result {
val point = start + (end - start).scalarMultiply(curveRelativePoint.curvePosition / length)
return Result.success(point)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as LineSegment3D
if (start != other.start) return false
if (end != other.end) return false
if (length != other.length) return false
if (domain != other.domain) return false
return true
}
override fun hashCode(): Int {
var result = start.hashCode()
result = 31 * result + end.hashCode()
result = 31 * result + length.hashCode()
result = 31 * result + domain.hashCode()
return result
}
companion object {
/**
* Creates a [LineSegment3D], if [start] and [end] [Vector3D] are not fuzzily equal according to the [tolerance].
*
*/
fun of(start: Vector3D, end: Vector3D, tolerance: Double, endBoundType: BoundType = BoundType.CLOSED):
Result =
if (start.fuzzyEquals(end, tolerance))
Result.error(
IllegalArgumentException(
"Start and end vector of a line segment must be different " +
"according to the given tolerance."
)
)
else Result.success(LineSegment3D(start, end, tolerance, endBoundType))
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy