Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segment arrow on livemap (padding to geometry) #1016

Merged
merged 9 commits into from
Feb 15, 2024
Prev Previous commit
Next Next commit
Restore fun padLineString() in SegmentGeom, use the same on Vec<Wor…
…ld> in livemap.
  • Loading branch information
OLarionova-HORIS committed Feb 12, 2024
commit 74fdb43d756453451b47533c16e00d585187139e

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@

package org.jetbrains.letsPlot.livemap.chart.path

import org.jetbrains.letsPlot.commons.geometry.DoubleVector
import org.jetbrains.letsPlot.commons.intern.math.padLineString
import org.jetbrains.letsPlot.commons.intern.math.distance
import org.jetbrains.letsPlot.commons.intern.math.distance2
import org.jetbrains.letsPlot.commons.intern.math.pointOnLine
import org.jetbrains.letsPlot.commons.intern.typedGeometry.Scalar
import org.jetbrains.letsPlot.commons.intern.typedGeometry.Vec
import org.jetbrains.letsPlot.commons.intern.typedGeometry.toDoubleVector
import org.jetbrains.letsPlot.commons.intern.typedGeometry.toVec
import org.jetbrains.letsPlot.commons.values.Color
import org.jetbrains.letsPlot.core.canvas.Context2d
Expand Down Expand Up @@ -51,11 +50,7 @@ class PathRenderer : Renderer {
).value

for (lineString in geometry) {
val adjustedGeometry = padLineString(
lineString.map(Vec<World>::toDoubleVector),
startPadding,
endPadding
).map<DoubleVector, Vec<World>>(DoubleVector::toVec)
val adjustedGeometry = padLineString(lineString, startPadding, endPadding)

ctx.beginPath()

Expand Down Expand Up @@ -190,4 +185,53 @@ class PathRenderer : Renderer {
drawArrowAtEnd(start, end, arrowSpec)
}
}

companion object {
// TODO: fix duplication from padLineString(List<DoubleVector>)
private fun padLineString(
lineString: List<WorldPoint>,
startPadding: Double,
endPadding: Double
): List<WorldPoint> {
val startPadded = padStart(lineString, startPadding)
return padEnd(startPadded, endPadding)
}

private fun pad(lineString: List<WorldPoint>, padding: Double): Pair<Int, WorldPoint>? {
if (lineString.size < 2) {
return null
}

val padding2 = padding * padding
val indexOutsidePadding = lineString.indexOfFirst {
distance2(lineString.first().x, lineString.first().y, it.x, it.y) >= padding2
}
if (indexOutsidePadding < 1) { // not found or first points already satisfy the padding
return null
}

val adjustedStartPoint = run {
val insidePadding = lineString[indexOutsidePadding - 1]
val outsidePadding = lineString[indexOutsidePadding]
val overPadding = distance(
lineString.first().x, lineString.first().y,
outsidePadding.x, outsidePadding.y
) - padding

pointOnLine(outsidePadding.x, outsidePadding.y, insidePadding.x, insidePadding.y, overPadding)
}

return indexOutsidePadding to adjustedStartPoint.toVec()
}

private fun padStart(lineString: List<WorldPoint>, padding: Double): List<WorldPoint> {
val (index, adjustedStartPoint) = pad(lineString, padding) ?: return lineString
return listOf(adjustedStartPoint) + lineString.subList(index, lineString.size)
}

private fun padEnd(lineString: List<WorldPoint>, padding: Double): List<WorldPoint> {
val (index, adjustedEndPoint) = pad(lineString.asReversed(), padding) ?: return lineString
return lineString.subList(0, lineString.size - index) + adjustedEndPoint
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
package org.jetbrains.letsPlot.core.plot.base.geom

import org.jetbrains.letsPlot.commons.geometry.DoubleVector
import org.jetbrains.letsPlot.commons.intern.math.padLineString
import org.jetbrains.letsPlot.commons.intern.math.distance
import org.jetbrains.letsPlot.commons.intern.math.distance2
import org.jetbrains.letsPlot.commons.intern.math.pointOnLine
import org.jetbrains.letsPlot.core.commons.data.SeriesUtil.finiteOrNull
import org.jetbrains.letsPlot.core.plot.base.*
import org.jetbrains.letsPlot.core.plot.base.aes.AesScaling
Expand Down Expand Up @@ -91,6 +93,47 @@ class SegmentGeom : GeomBase() {
companion object {
const val HANDLES_GROUPS = false

private fun pad(lineString: List<DoubleVector>, padding: Double): Pair<Int, DoubleVector>? {
if (lineString.size < 2) {
return null
}

val padding2 = padding * padding
val indexOutsidePadding = lineString.indexOfFirst { distance2(lineString.first(), it) >= padding2 }
if (indexOutsidePadding < 1) { // not found or first points already satisfy the padding
return null
}

val adjustedStartPoint = run {
val insidePadding = lineString[indexOutsidePadding - 1]
val outsidePadding = lineString[indexOutsidePadding]
val overPadding = distance(lineString.first(), outsidePadding) - padding

pointOnLine(outsidePadding, insidePadding, overPadding)
}

return indexOutsidePadding to adjustedStartPoint
}

private fun padStart(lineString: List<DoubleVector>, padding: Double): List<DoubleVector> {
val (index, adjustedStartPoint) = pad(lineString, padding) ?: return lineString
return listOf(adjustedStartPoint) + lineString.subList(index, lineString.size)
}

private fun padEnd(lineString: List<DoubleVector>, padding: Double): List<DoubleVector> {
val (index, adjustedEndPoint) = pad(lineString.asReversed(), padding) ?: return lineString
return lineString.subList(0, lineString.size - index) + adjustedEndPoint
}

private fun padLineString(
lineString: List<DoubleVector>,
startPadding: Double,
endPadding: Double
): List<DoubleVector> {
val startPadded = padStart(lineString, startPadding)
return padEnd(startPadded, endPadding)
}

private fun targetSize(p: DataPointAesthetics, atStart: Boolean): Double {
val sizeAes = if (atStart) DataPointAesthetics::sizeStart else DataPointAesthetics::sizeEnd
val strokeAes = if (atStart) DataPointAesthetics::strokeStart else DataPointAesthetics::strokeEnd
Expand Down