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

commonMain.jetbrains.datalore.base.algorithms.Geometry.kt Maven / Gradle / Ivy

There is a newer version: 4.5.3-alpha1
Show newest version
/*
 * 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