commonMain.jetbrains.datalore.base.algorithms.Geometry.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lets-plot-common Show documentation
Show all versions of lets-plot-common Show documentation
Lets-Plot JVM package without rendering part
/*
* Copyright (c) 2019. JetBrains s.r.o.
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/
package jetbrains.datalore.base.algorithms
import jetbrains.datalore.base.gcommon.collect.ClosedRange
import jetbrains.datalore.base.geometry.DoubleVector
import kotlin.math.abs
fun splitRings(points: List): List> {
val rings = findRingIntervals(points).map { points.sublist(it) }.toMutableList()
if (rings.isNotEmpty()) {
if (!rings.last().isClosed()) {
rings.set(rings.lastIndex, makeClosed(rings.last()))
}
}
return rings
}
private fun makeClosed(path: List) = path.toMutableList() + path.first()
fun List.isClosed() = first() == last()
private fun findRingIntervals(path: List): List> {
val intervals = ArrayList>()
var startIndex = 0
var i = 0
val n = path.size
while (i < n) {
if (startIndex != i && path[startIndex] == path[i]) {
intervals.add(ClosedRange(startIndex, i + 1))
startIndex = i + 1
}
i++
}
if (startIndex != path.size) {
intervals.add(ClosedRange(startIndex, path.size))
}
return intervals
}
private fun List.sublist(range: ClosedRange): List {
return this.subList(range.lowerEnd, range.upperEnd)
}
fun calculateArea(ring: List): Double {
return calculateArea(ring, DoubleVector::x, DoubleVector::y)
}
fun isClockwise(ring: List, x: (T) -> Double, y: (T) -> Double): Boolean {
check(ring.isNotEmpty()) { "Ring shouldn't be empty to calculate clockwise" }
var sum = 0.0
var prev = ring[ring.size - 1]
for (point in ring) {
sum += x(prev) * y(point) - x(point) * y(prev)
prev = point
}
return sum < 0.0
}
fun calculateArea(ring: List, x: T.() -> Double, y: T.() -> Double): Double {
var area = 0.0
var j = ring.size - 1
for (i in ring.indices) {
val p1 = ring[i]
val p2 = ring[j]
area += (p2.x() + p1.x()) * (p2.y() - p1.y())
j = i
}
return abs(area / 2)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy