fun checkPath()

in plot-builder/src/commonMain/kotlin/org/jetbrains/letsPlot/core/plot/builder/tooltip/loc/TargetDetector.kt [22:95]


    fun checkPath(
        cursorCoord: DoubleVector,
        pathProjection: PathTargetProjection,
        closestPointChecker: ClosestPointChecker
    ): Pair<PathPoint, DoubleVector?>? {
        if (pathProjection.points.isEmpty()) {
            return null
        }

        val lookupResult: Pair<PathPoint, DoubleVector?>? = when (locatorLookupSpace) {
            LookupSpace.NONE -> null
            LookupSpace.X -> when (locatorLookupStrategy) {
                LookupStrategy.NONE -> null
                LookupStrategy.NEAREST -> searchNearest(cursorCoord.x, pathProjection.points) { it.projection().x() } to null
                LookupStrategy.HOVER ->
                    if (cursorCoord.x < pathProjection.points.first().projection().x() ||
                        cursorCoord.x > pathProjection.points.last().projection().x()
                    ) {
                        null
                    } else {
                        searchNearest(cursorCoord.x, pathProjection.points) { it.projection().x() } to null
                    }
            }

            LookupSpace.Y -> when (locatorLookupStrategy) {
                LookupStrategy.NONE -> null
                LookupStrategy.NEAREST -> searchNearest(cursorCoord.y, pathProjection.points) { it.projection().y() } to null
                LookupStrategy.HOVER ->
                    if (cursorCoord.y < pathProjection.points.first().projection().y() ||
                        cursorCoord.y > pathProjection.points.last().projection().y()
                    ) {
                        null
                    } else {
                        searchNearest(cursorCoord.y, pathProjection.points) { it.projection().y() } to null
                    }
            }

            LookupSpace.XY -> when (locatorLookupStrategy) {
                LookupStrategy.NONE -> null
                LookupStrategy.HOVER -> {
                    var candidate: Pair<PathPoint, DoubleVector>? = null

                    pathProjection.points.asSequence().windowed(2).forEach() {
                        val p1 = it[0].projection().xy()
                        val p2 = it[1].projection().xy()

                        if (isOnSegment(cursorCoord, p1, p2)) {
                            val targetPointCoord = projection(cursorCoord, p1, p2)
                            if (closestPointChecker.check(targetPointCoord)) {
                                candidate = it[0] to targetPointCoord
                            }
                        } else if (closestPointChecker.check(p1)) {
                            candidate = it[0] to p1
                        }
                    }

                    candidate
                }

                LookupStrategy.NEAREST -> {
                    var candidate: PathPoint? = null
                    for (pathPoint in pathProjection.points) {
                        val targetPointCoord = pathPoint.projection().xy()
                        if (closestPointChecker.check(targetPointCoord)) {
                            candidate = pathPoint
                        }
                    }
                    candidate?.let { it to null }
                }
            }
        }

        return lookupResult
    }