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

geom_spoke() as a layer of geom_livemap() #1049

Merged
merged 2 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
geom_spoke() as a layer of geom_livemap()
  • Loading branch information
RYangazov committed Mar 14, 2024
commit 9cf4d996ec1210aec23d67f39ac87e308198f0c3
182 changes: 182 additions & 0 deletions docs/f-24b/spoke-livemap.ipynb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class SpokeGeom : GeomBase(), WithWidth, WithHeight {
val y = finiteOrNull(p.y()) ?: continue
val spoke = toSpoke(p) ?: continue
val base = DoubleVector(x, y)
val start = getStart(base, spoke)
val end = getEnd(base, spoke)
val start = getStart(base, spoke, pivot)
val end = getEnd(base, spoke, pivot)
val line = svgElementHelper.createLine(start, end, p) ?: continue

root.add(line)
Expand Down Expand Up @@ -80,8 +80,8 @@ class SpokeGeom : GeomBase(), WithWidth, WithHeight {
loc.flip()
}
val spoke = toSpoke(p) ?: return null
val start = getStart(base, spoke)
val end = getEnd(base, spoke)
val start = getStart(base, spoke, pivot)
val end = getEnd(base, spoke, pivot)
return if (spanAxisAes == Aes.X) {
DoubleSpan(start.x, end.x)
} else {
Expand All @@ -93,23 +93,7 @@ class SpokeGeom : GeomBase(), WithWidth, WithHeight {
val angle = finiteOrNull(p.angle()) ?: return null
val radius = finiteOrNull(p.radius()) ?: return null

return DoubleVector(radius * cos(angle), radius * sin(angle))
}

private fun getStart(base: DoubleVector, spoke: DoubleVector): DoubleVector {
return when (pivot) {
Pivot.TAIL -> base
Pivot.MIDDLE -> base.subtract(spoke.mul(0.5))
Pivot.TIP -> base.subtract(spoke)
}
}

private fun getEnd(base: DoubleVector, spoke: DoubleVector): DoubleVector {
return when (pivot) {
Pivot.TAIL -> base.add(spoke)
Pivot.MIDDLE -> base.add(spoke.mul(0.5))
Pivot.TIP -> base
}
return getSpoke(angle, radius)
}

enum class Pivot {
Expand All @@ -119,6 +103,38 @@ class SpokeGeom : GeomBase(), WithWidth, WithHeight {
companion object {
val DEF_PIVOT = Pivot.TAIL

fun createGeometry(
x: Double,
y: Double,
angle: Double,
radius: Double,
pivot: Pivot
): List<DoubleVector> {
val base = DoubleVector(x, y)
val spoke = getSpoke(angle, radius)
return listOf(getStart(base, spoke, pivot), getEnd(base, spoke, pivot))
}

private fun getStart(base: DoubleVector, spoke: DoubleVector, pivot: Pivot): DoubleVector {
return when (pivot) {
Pivot.TAIL -> base
Pivot.MIDDLE -> base.subtract(spoke.mul(0.5))
Pivot.TIP -> base.subtract(spoke)
}
}

private fun getEnd(base: DoubleVector, spoke: DoubleVector, pivot: Pivot): DoubleVector {
return when (pivot) {
Pivot.TAIL -> base.add(spoke)
Pivot.MIDDLE -> base.add(spoke.mul(0.5))
Pivot.TIP -> base
}
}

private fun getSpoke(angle: Double, radius: Double): DoubleVector {
return DoubleVector(radius * cos(angle), radius * sin(angle))
}

const val HANDLES_GROUPS = false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ internal class DataPointsConverter(
fun toText(geom: Geom) = pointFeatureConverter.text(geom)
fun toPie(geom: PieGeom) = pieConverter(geom)
fun toCurve(geom: CurveGeom) = mySinglePathFeatureConverter.curve(geom)
fun toSpoke(geom: SpokeGeom) = mySinglePathFeatureConverter.spoke(geom)

private abstract class PathFeatureConverterBase(
val aesthetics: Aesthetics
Expand Down Expand Up @@ -230,6 +231,16 @@ internal class DataPointsConverter(
}
}

fun spoke(geom: SpokeGeom): List<DataPointLiveMapAesthetics> {
return process(isClosed = false) {
if (SeriesUtil.allFinite(it.x(), it.y(), it.angle(), it.radius())) {
SpokeGeom.createGeometry(it.x()!!, it.y()!!, it.angle()!!, it.radius()!!, geom.pivot)
} else {
emptyList()
}
}
}

private fun process(
isClosed: Boolean,
dataPointToGeometry: (DataPointAesthetics) -> List<DoubleVector>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import org.jetbrains.letsPlot.core.plot.base.aes.AestheticsUtil
import org.jetbrains.letsPlot.core.plot.base.geom.PieGeom
import org.jetbrains.letsPlot.core.plot.base.geom.PointGeom
import org.jetbrains.letsPlot.core.plot.base.geom.SegmentGeom
import org.jetbrains.letsPlot.core.plot.base.geom.CurveGeom
import org.jetbrains.letsPlot.core.plot.base.geom.SpokeGeom
import org.jetbrains.letsPlot.core.plot.builder.LayerRendererUtil.LayerRendererData
import org.jetbrains.letsPlot.core.canvas.FontStyle
import org.jetbrains.letsPlot.core.canvas.FontWeight
import org.jetbrains.letsPlot.core.plot.base.geom.CurveGeom
import org.jetbrains.letsPlot.livemap.api.*


Expand All @@ -43,6 +44,7 @@ object LayerConverter {
CURVE -> MapLayerKind.PATH to dataPointsConverter.toCurve(layer.geom as CurveGeom)
RECT -> MapLayerKind.POLYGON to dataPointsConverter.toRect()
TILE, BIN_2D -> MapLayerKind.POLYGON to dataPointsConverter.toTile()
SPOKE -> MapLayerKind.PATH to dataPointsConverter.toSpoke(layer.geom as SpokeGeom)
DENSITY2D, CONTOUR, PATH -> MapLayerKind.PATH to dataPointsConverter.toPath(layer.geom)
TEXT, LABEL -> MapLayerKind.TEXT to dataPointsConverter.toText(layer.geom)
DENSITY2DF, CONTOURF, POLYGON, MAP -> MapLayerKind.POLYGON to dataPointsConverter.toPolygon()
Expand Down