From 90eb7b4575d90b3e850010a993af56a9b67ff2cc Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 13 Feb 2023 16:49:36 +0300 Subject: [PATCH] Split points and multiline --- build.gradle.kts | 2 +- demo/maps/src/jvmMain/kotlin/Main.kt | 10 +-- .../polygon-editor/src/jvmMain/kotlin/Main.kt | 7 +- .../sciprog/maps/compose/mapFeatures.kt | 13 +-- .../center/sciprog/maps/features/Feature.kt | 83 +++++++++++++------ .../sciprog/maps/features/FeatureGroup.kt | 29 +++++-- .../maps/features/mapFeatureAttributes.kt | 37 ++++++--- .../sciprog/maps/compose/clickGestures.kt | 11 ++- .../sciprog/maps/features/drawFeature.kt | 36 +++++--- .../sciprog/maps/geojson/geoJsonToMap.kt | 10 +-- .../sciprog/maps/scheme/schemeFeatures.kt | 2 +- .../center/sciprog/maps/svg/exportToSvg.kt | 25 ++++++ 12 files changed, 173 insertions(+), 92 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ea2e732..f3de3af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ val kmathVersion: String by extra("0.3.1-dev-10") allprojects { group = "center.sciprog" - version = "0.2.2-dev-4" + version = "0.2.2-dev-5" repositories { mavenLocal() diff --git a/demo/maps/src/jvmMain/kotlin/Main.kt b/demo/maps/src/jvmMain/kotlin/Main.kt index ba4da06..ee5f0c1 100644 --- a/demo/maps/src/jvmMain/kotlin/Main.kt +++ b/demo/maps/src/jvmMain/kotlin/Main.kt @@ -8,7 +8,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.PointMode import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp @@ -91,7 +90,7 @@ fun App() { println("line 3 clicked") } - points( + multiLine( points = listOf( 55.742465 to 37.615812, 55.742713 to 37.616370, @@ -100,7 +99,6 @@ fun App() { 55.742086 to 37.616566, 55.741715 to 37.616716 ), - pointMode = PointMode.Polygon ) //remember feature ID @@ -138,13 +136,11 @@ fun App() { println("Click on ${ref.id}") //draw in top-level scope with(this@MapView) { - points( + multiLine( ref.resolve().points, - stroke = 4f, - pointMode = PointMode.Polygon, attributes = Attributes(ZAttribute, 10f), id = "selected", - ).color(Color.Magenta) + ).modifyAttribute(StrokeAttribute, 4f).color(Color.Magenta) } } } diff --git a/demo/polygon-editor/src/jvmMain/kotlin/Main.kt b/demo/polygon-editor/src/jvmMain/kotlin/Main.kt index 0adbc58..4cf447c 100644 --- a/demo/polygon-editor/src/jvmMain/kotlin/Main.kt +++ b/demo/polygon-editor/src/jvmMain/kotlin/Main.kt @@ -6,7 +6,6 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.runtime.snapshots.SnapshotStateList -import androidx.compose.ui.graphics.PointMode import androidx.compose.ui.input.pointer.isSecondaryPressed import androidx.compose.ui.window.Window import androidx.compose.ui.window.application @@ -26,9 +25,8 @@ fun App() { val myPolygon: SnapshotStateList = remember { mutableStateListOf() } val featureState: FeatureGroup = FeatureGroup.remember(XYCoordinateSpace) { - points( + multiLine( listOf(XY(0f, 0f), XY(0f, 1f), XY(1f, 1f), XY(1f, 0f), XY(0f, 0f)), - pointMode = PointMode.Polygon, id = "frame" ) } @@ -36,9 +34,8 @@ fun App() { if(myPolygon.isNotEmpty()) { featureState.group("polygon") { - points( + multiLine( myPolygon + myPolygon.first(), - pointMode = PointMode.Polygon, ) myPolygon.forEachIndexed { index, xy -> circle(xy, id = "point[$index]").draggable { _, to -> diff --git a/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/mapFeatures.kt b/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/mapFeatures.kt index 204e98b..14cd180 100644 --- a/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/mapFeatures.kt +++ b/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/mapFeatures.kt @@ -1,6 +1,5 @@ package center.sciprog.maps.compose -import androidx.compose.ui.graphics.PointMode import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.Dp @@ -32,7 +31,7 @@ public fun FeatureGroup.rectangle( size: DpSize = DpSize(5.dp, 5.dp), id: String? = null, ): FeatureRef> = feature( - id, RectangleFeature(space, coordinatesOf(centerCoordinates), size) + id, RectangleFeature(space, coordinatesOf(centerCoordinates), size) ) @@ -83,11 +82,13 @@ public fun FeatureGroup.arc( public fun FeatureGroup.points( points: List>, - stroke: Float = 2f, - pointMode: PointMode = PointMode.Points, id: String? = null, -): FeatureRef> = - feature(id, PointsFeature(space, points.map(::coordinatesOf), stroke, pointMode)) +): FeatureRef> = feature(id, PointsFeature(space, points.map(::coordinatesOf))) + +public fun FeatureGroup.multiLine( + points: List>, + id: String? = null, +): FeatureRef> = feature(id, MultiLineFeature(space, points.map(::coordinatesOf))) public fun FeatureGroup.image( position: Pair, diff --git a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Feature.kt b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Feature.kt index 2746609..372c992 100644 --- a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Feature.kt +++ b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Feature.kt @@ -3,7 +3,10 @@ package center.sciprog.maps.features import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.graphics.* +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.drawscope.DrawStyle import androidx.compose.ui.graphics.drawscope.Fill @@ -112,8 +115,6 @@ public data class PathFeature( public data class PointsFeature( override val space: CoordinateSpace, public val points: List, - public val stroke: Float = 2f, - public val pointMode: PointMode = PointMode.Points, override val attributes: Attributes = Attributes.EMPTY, ) : Feature { @@ -125,6 +126,59 @@ public data class PointsFeature( override fun withAttributes(modify: (Attributes) -> Attributes): Feature = copy(attributes = modify(attributes)) } + +public interface LineSegmentFeature : Feature + +@Stable +public data class LineFeature( + override val space: CoordinateSpace, + public val a: T, + public val b: T, + override val attributes: Attributes = Attributes.EMPTY, +) : DomainFeature, LineSegmentFeature { + override fun getBoundingBox(zoom: Float): Rectangle = + space.Rectangle(a, b) + + override fun contains(viewPoint: ViewPoint): Boolean = with(space) { + viewPoint.focus in getBoundingBox(viewPoint.zoom) && viewPoint.focus.distanceToLine( + a, + b, + viewPoint.zoom + ).value < clickRadius + } + + override fun withAttributes(modify: (Attributes) -> Attributes): Feature = copy(attributes = modify(attributes)) +} + +public data class MultiLineFeature( + override val space: CoordinateSpace, + public val points: List, + override val attributes: Attributes = Attributes.EMPTY, +) : DomainFeature, LineSegmentFeature { + + private val boundingBox by lazy { + with(space) { points.wrapPoints() } + } + + override fun getBoundingBox(zoom: Float): Rectangle? = boundingBox + override fun withAttributes(modify: (Attributes) -> Attributes): Feature = copy(attributes = modify(attributes)) + + override fun contains(viewPoint: ViewPoint): Boolean = with(space) { + val boundingBox = getBoundingBox(viewPoint.zoom) ?: return@with false + viewPoint.focus in boundingBox && points.zipWithNext().minOf { (a, b) -> + viewPoint.focus.distanceToLine( + a, + b, + viewPoint.zoom + ).value + } < clickRadius + } +} + + +private val > F.clickRadius get() = attributes[ClickRadius] ?: 10f + + @Stable public data class PolygonFeature( override val space: CoordinateSpace, @@ -176,29 +230,6 @@ public data class RectangleFeature( override fun withAttributes(modify: (Attributes) -> Attributes): Feature = copy(attributes = modify(attributes)) } -@Stable -public data class LineFeature( - override val space: CoordinateSpace, - public val a: T, - public val b: T, - override val attributes: Attributes = Attributes.EMPTY, -) : DomainFeature { - override fun getBoundingBox(zoom: Float): Rectangle = - space.Rectangle(a, b) - - private val clickRadius get() = attributes[ClickRadius] ?: 10f - - override fun contains(viewPoint: ViewPoint): Boolean = with(space) { - viewPoint.focus in getBoundingBox(viewPoint.zoom) && viewPoint.focus.distanceToLine( - a, - b, - viewPoint.zoom - ).value < clickRadius - } - - override fun withAttributes(modify: (Attributes) -> Attributes): Feature = copy(attributes = modify(attributes)) -} - /** * @param startAngle the angle from 3 o'clock downwards for the start of the arc in radians * @param arcLength arc length in radians diff --git a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/FeatureGroup.kt b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/FeatureGroup.kt index b7f07bc..c94beed 100644 --- a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/FeatureGroup.kt +++ b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/FeatureGroup.kt @@ -4,7 +4,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.remember import androidx.compose.runtime.snapshots.SnapshotStateMap -import androidx.compose.ui.graphics.PointMode import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.vector.ImageVector @@ -156,56 +155,68 @@ public inline fun > FeatureGroup.forEachWithT public fun FeatureGroup.circle( center: T, size: Dp = 5.dp, + attributes: Attributes = Attributes.EMPTY, id: String? = null, ): FeatureRef> = feature( - id, CircleFeature(space, center, size) + id, CircleFeature(space, center, size, attributes) ) public fun FeatureGroup.rectangle( centerCoordinates: T, size: DpSize = DpSize(5.dp, 5.dp), + attributes: Attributes = Attributes.EMPTY, id: String? = null, ): FeatureRef> = feature( - id, RectangleFeature(space, centerCoordinates, size) + id, RectangleFeature(space, centerCoordinates, size, attributes) ) public fun FeatureGroup.draw( position: T, + attributes: Attributes = Attributes.EMPTY, id: String? = null, draw: DrawScope.() -> Unit, ): FeatureRef> = feature( id, - DrawFeature(space, position, drawFeature = draw) + DrawFeature(space, position, drawFeature = draw, attributes = attributes) ) public fun FeatureGroup.line( aCoordinates: T, bCoordinates: T, + attributes: Attributes = Attributes.EMPTY, id: String? = null, ): FeatureRef> = feature( id, - LineFeature(space, aCoordinates, bCoordinates) + LineFeature(space, aCoordinates, bCoordinates, attributes) ) public fun FeatureGroup.arc( oval: Rectangle, startAngle: Angle, arcLength: Angle, + attributes: Attributes = Attributes.EMPTY, id: String? = null, ): FeatureRef> = feature( id, - ArcFeature(space, oval, startAngle, arcLength) + ArcFeature(space, oval, startAngle, arcLength, attributes) ) public fun FeatureGroup.points( points: List, - stroke: Float = 2f, - pointMode: PointMode = PointMode.Points, attributes: Attributes = Attributes.EMPTY, id: String? = null, ): FeatureRef> = feature( id, - PointsFeature(space, points, stroke, pointMode, attributes) + PointsFeature(space, points, attributes) +) + +public fun FeatureGroup.multiLine( + points: List, + attributes: Attributes = Attributes.EMPTY, + id: String? = null, +): FeatureRef> = feature( + id, + MultiLineFeature(space, points, attributes) ) public fun FeatureGroup.polygon( diff --git a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/mapFeatureAttributes.kt b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/mapFeatureAttributes.kt index c0095a3..9b85e82 100644 --- a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/mapFeatureAttributes.kt +++ b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/mapFeatureAttributes.kt @@ -32,8 +32,18 @@ public object VisibleAttribute : Attribute public object ColorAttribute : Attribute + +public fun > FeatureRef.color(color: Color): FeatureRef = + modifyAttribute(ColorAttribute, color) + + public object ZoomRangeAttribute : Attribute + +public fun > FeatureRef.zoomRange(range: FloatRange): FeatureRef = + modifyAttribute(ZoomRangeAttribute, range) + + public object AlphaAttribute : Attribute public fun > FeatureRef.modifyAttributes(modify: AttributesBuilder.() -> Unit): FeatureRef { @@ -47,7 +57,10 @@ public fun > FeatureRef.modifyAttributes(modify: A return this } -public fun , V> FeatureRef.modifyAttribute(key: Attribute, value: V?): FeatureRef{ +public fun , V> FeatureRef.modifyAttribute( + key: Attribute, + value: V?, +): FeatureRef { @Suppress("UNCHECKED_CAST") parent.feature(id, resolve().withAttributes { withAttribute(key, value) } as F) return this @@ -59,10 +72,10 @@ public fun , V> FeatureRef.modifyAttribute(key: A * @param constraint optional drag constraint */ @Suppress("UNCHECKED_CAST") -public fun > FeatureRef.draggable( +public fun > FeatureRef.draggable( constraint: ((T) -> T)? = null, listener: (PointerEvent.(from: ViewPoint, to: ViewPoint) -> Unit)? = null, -): FeatureRef = with(parent){ +): FeatureRef = with(parent) { if (attributes[DraggableAttribute] == null) { val handle = DragHandle.withPrimaryButton { event, start, end -> val feature = featureMap[id] as? DraggableFeature ?: return@withPrimaryButton DragResult(end) @@ -112,7 +125,7 @@ public fun > FeatureRef.onClick( @OptIn(ExperimentalFoundationApi::class) @Suppress("UNCHECKED_CAST") -public fun > FeatureRef.onClick( +public fun > FeatureRef.onClick( pointerMatcher: PointerMatcher, keyboardModifiers: PointerKeyboardModifiers.() -> Boolean = { true }, onClick: PointerEvent.(click: ViewPoint) -> Unit, @@ -127,7 +140,7 @@ public fun > FeatureRef.onClick( } @Suppress("UNCHECKED_CAST") -public fun > FeatureRef.onHover( +public fun > FeatureRef.onHover( onClick: PointerEvent.(move: ViewPoint) -> Unit, ): FeatureRef = modifyAttributes { HoverListenerAttribute.add( @@ -147,15 +160,13 @@ public fun > FeatureRef.onHover( // ) // } -public fun > FeatureRef.color(color: Color): FeatureRef = - modifyAttribute(ColorAttribute, color) -public fun > FeatureRef.zoomRange(range: FloatRange): FeatureRef = - modifyAttribute(ZoomRangeAttribute, range) +public object PathEffectAttribute : Attribute +public fun FeatureRef>.pathEffect(effect: PathEffect): FeatureRef> = + modifyAttribute(PathEffectAttribute, effect) +public object StrokeAttribute : Attribute -public object PathEffectAttribute: Attribute - -public fun FeatureRef>.pathEffect(effect: PathEffect): FeatureRef> = - modifyAttribute(PathEffectAttribute, effect) \ No newline at end of file +public fun > FeatureRef.stroke(width: Float): FeatureRef = + modifyAttribute(StrokeAttribute, width) \ No newline at end of file diff --git a/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/compose/clickGestures.kt b/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/compose/clickGestures.kt index b528a80..59ca93c 100644 --- a/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/compose/clickGestures.kt +++ b/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/compose/clickGestures.kt @@ -94,13 +94,13 @@ public suspend fun PointerInputScope.detectClicks( if (upOrCancel != null) { // tap was successful. if (onDoubleClick == null) { - onClick?.invoke(this, upOrCancel) // no need to check for double-tap. + onClick?.invoke(this, down) // no need to check for double-tap. } else { // check for second tap val secondDown = awaitSecondDown(upOrCancel.firstChange) if (secondDown == null) { - onClick?.invoke(this, upOrCancel) // no valid second tap started + onClick?.invoke(this, down) // no valid second tap started } else { // Second tap down detected pressScope.reset() @@ -115,16 +115,16 @@ public suspend fun PointerInputScope.detectClicks( if (secondUp != null) { secondUp.consume() pressScope.release() - onDoubleClick(down) + onDoubleClick(secondDown) } else { pressScope.cancel() - onClick?.invoke(this, upOrCancel) + onClick?.invoke(this, down) } } } catch (e: PointerEventTimeoutCancellationException) { // The first tap was valid, but the second tap is a long press. // notify for the first tap - onClick?.invoke(this, upOrCancel) + onClick?.invoke(this, down) // notify for the long press onLongClick?.invoke(this, secondDown) @@ -209,7 +209,6 @@ private suspend fun AwaitPointerEventScope.awaitSecondDown( /** * Reads events until the first down is received. If [requireUnconsumed] is `true` and the first * down is consumed in the [PointerEventPass.Main] pass, that gesture is ignored. - * If it was down caused by [PointerType.Mouse], this function reacts only on primary button. */ internal suspend fun AwaitPointerEventScope.awaitFirstDownEvent( requireUnconsumed: Boolean = true, diff --git a/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/features/drawFeature.kt b/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/features/drawFeature.kt index 6092cd6..8e1f2d4 100644 --- a/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/features/drawFeature.kt +++ b/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/features/drawFeature.kt @@ -2,15 +2,12 @@ package center.sciprog.maps.features import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.* import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.drawscope.drawIntoCanvas import androidx.compose.ui.graphics.drawscope.translate -import androidx.compose.ui.graphics.nativeCanvas import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.graphics.toArgb import center.sciprog.attributes.plus import org.jetbrains.skia.Font import org.jetbrains.skia.Paint @@ -28,7 +25,7 @@ public fun DrawScope.drawFeature( feature: Feature, ): Unit = with(state) { val color = feature.color ?: Color.Red - val alpha = feature.attributes[AlphaAttribute]?:1f + val alpha = feature.attributes[AlphaAttribute] ?: 1f fun T.toOffset(): Offset = toOffset(this@drawFeature) when (feature) { @@ -48,7 +45,14 @@ public fun DrawScope.drawFeature( size = feature.size.toSize() ) - is LineFeature -> drawLine(color, feature.a.toOffset(), feature.b.toOffset()) + is LineFeature -> drawLine( + color, + feature.a.toOffset(), + feature.b.toOffset(), + strokeWidth = feature.attributes[StrokeAttribute] ?: Stroke.HairlineWidth, + pathEffect = feature.attributes[PathEffectAttribute] + ) + is ArcFeature -> { val dpRect = feature.oval.toDpRect().toRect() @@ -119,8 +123,20 @@ public fun DrawScope.drawFeature( drawPoints( points = points, color = color, - strokeWidth = feature.stroke, - pointMode = feature.pointMode, + strokeWidth = feature.attributes[StrokeAttribute] ?: Stroke.HairlineWidth, + pointMode = PointMode.Points, + pathEffect = feature.attributes[PathEffectAttribute], + alpha = alpha + ) + } + + is MultiLineFeature -> { + val points = feature.points.map { it.toOffset() } + drawPoints( + points = points, + color = color, + strokeWidth = feature.attributes[StrokeAttribute] ?: Stroke.HairlineWidth, + pointMode = PointMode.Polygon, pathEffect = feature.attributes[PathEffectAttribute], alpha = alpha ) @@ -131,8 +147,8 @@ public fun DrawScope.drawFeature( val last = points.last() val polygonPath = Path() polygonPath.moveTo(last.x, last.y) - for ((x,y) in points){ - polygonPath.lineTo(x,y) + for ((x, y) in points) { + polygonPath.lineTo(x, y) } drawPath( path = polygonPath, diff --git a/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/geoJsonToMap.kt b/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/geoJsonToMap.kt index b6b20c0..7b91d3b 100644 --- a/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/geoJsonToMap.kt +++ b/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/geoJsonToMap.kt @@ -1,7 +1,6 @@ package center.sciprog.maps.geojson import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.PointMode import center.sciprog.attributes.NameAttribute import center.sciprog.maps.coordinates.Gmc import center.sciprog.maps.features.* @@ -17,23 +16,18 @@ public fun FeatureGroup.geoJsonGeometry( geometry: GeoJsonGeometry, id: String? = null, ): FeatureRef> = when (geometry) { - is GeoJsonLineString -> points( + is GeoJsonLineString -> multiLine( geometry.coordinates, - pointMode = PointMode.Lines ) is GeoJsonMultiLineString -> group(id = id) { geometry.coordinates.forEach { - points( - it, - pointMode = PointMode.Lines - ) + multiLine(it) } } is GeoJsonMultiPoint -> points( geometry.coordinates, - pointMode = PointMode.Points ) is GeoJsonMultiPolygon -> group(id = id) { diff --git a/maps-kt-scheme/src/commonMain/kotlin/center/sciprog/maps/scheme/schemeFeatures.kt b/maps-kt-scheme/src/commonMain/kotlin/center/sciprog/maps/scheme/schemeFeatures.kt index cbb547d..4b6e3ae 100644 --- a/maps-kt-scheme/src/commonMain/kotlin/center/sciprog/maps/scheme/schemeFeatures.kt +++ b/maps-kt-scheme/src/commonMain/kotlin/center/sciprog/maps/scheme/schemeFeatures.kt @@ -51,7 +51,7 @@ fun FeatureGroup.line( aCoordinates: Pair, bCoordinates: Pair, id: String? = null, -): FeatureRef> = line(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), id) +): FeatureRef> = line(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), id = id) public fun FeatureGroup.arc( diff --git a/maps-kt-scheme/src/jvmMain/kotlin/center/sciprog/maps/svg/exportToSvg.kt b/maps-kt-scheme/src/jvmMain/kotlin/center/sciprog/maps/svg/exportToSvg.kt index d1b9119..dae8cc8 100644 --- a/maps-kt-scheme/src/jvmMain/kotlin/center/sciprog/maps/svg/exportToSvg.kt +++ b/maps-kt-scheme/src/jvmMain/kotlin/center/sciprog/maps/svg/exportToSvg.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PointMode import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.drawscope.drawIntoCanvas import androidx.compose.ui.graphics.drawscope.translate @@ -77,6 +78,30 @@ fun FeatureStateSnapshot.generateSvg( alpha = alpha ) + is PointsFeature -> { + val points = feature.points.map { it.toOffset() } + drawPoints( + points = points, + color = color, + strokeWidth = feature.attributes[StrokeAttribute] ?: Stroke.HairlineWidth, + pointMode = PointMode.Points, + pathEffect = feature.attributes[PathEffectAttribute], + alpha = alpha + ) + } + + is MultiLineFeature -> { + val points = feature.points.map { it.toOffset() } + drawPoints( + points = points, + color = color, + strokeWidth = feature.attributes[StrokeAttribute] ?: Stroke.HairlineWidth, + pointMode = PointMode.Polygon, + pathEffect = feature.attributes[PathEffectAttribute], + alpha = alpha + ) + } + is ArcFeature -> { val topLeft = feature.oval.leftTop.toOffset() val bottomRight = feature.oval.rightBottom.toOffset()