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

commonMain.ovh.plrapps.mapcompose.ui.paths.RamerDouglaPeucker.kt Maven / Gradle / Ivy

Go to download

A Compose Multiplatform library to display tiled maps, with support for markers, paths, and rotation

The newest version!
package ovh.plrapps.mapcompose.ui.paths

import androidx.compose.ui.geometry.Offset
import kotlin.math.hypot


internal fun ramerDouglasPeucker(pointList: List, epsilon: Float, out: MutableList) {
    if (pointList.size < 2) throw IllegalArgumentException("Not enough points to simplify")

    // Find the point with the maximum distance from line between start and end
    var dmax = 0.0
    var index = 0
    val end = pointList.size - 1
    for (i in 1 until end) {
        val d = perpendicularDistance(pointList[i], pointList[0], pointList[end])
        if (d > dmax) { index = i; dmax = d }
    }

    // If max distance is greater than epsilon, recursively simplify
    if (dmax > epsilon) {
        val recResults1 = mutableListOf()
        val recResults2 = mutableListOf()
        val firstLine = pointList.take(index + 1)
        val lastLine  = pointList.drop(index)
        ramerDouglasPeucker(firstLine, epsilon, recResults1)
        ramerDouglasPeucker(lastLine, epsilon, recResults2)

        // build the result list
        out.addAll(recResults1.take(recResults1.size - 1))
        out.addAll(recResults2)
        if (out.size < 2) throw RuntimeException("Problem assembling output")
    }
    else {
        // Just return start and end points
        out.clear()
        out.add(pointList.first())
        out.add(pointList.last())
    }
}

private fun perpendicularDistance(pt: Offset, lineStart: Offset, lineEnd: Offset): Double {
    var dx = lineEnd.x - lineStart.x
    var dy = lineEnd.y - lineStart.y

    // Normalize
    val mag = hypot(dx, dy)
    if (mag > 0.0) { dx /= mag; dy /= mag }
    val pvx = pt.x - lineStart.x
    val pvy = pt.y - lineStart.y

    // Get dot product (project pv onto normalized direction)
    val pvdot = dx * pvx + dy * pvy

    // Scale line direction vector and substract it from pv
    val ax = pvx - pvdot * dx
    val ay = pvy - pvdot * dy

    return hypot(ax.toDouble(), ay.toDouble())
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy