[WIP] generic features
This commit is contained in:
parent
7735d667bc
commit
c2157c8351
@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package center.sciprog.maps.features
|
|
||||||
|
|
||||||
import kotlin.math.PI
|
|
||||||
import kotlin.math.floor
|
|
||||||
|
|
||||||
// Taken from KMath dev version, to be used directly in the future
|
|
||||||
|
|
||||||
|
|
||||||
public sealed interface Angle : Comparable<Angle> {
|
|
||||||
public val radians: Radians
|
|
||||||
public val degrees: Degrees
|
|
||||||
|
|
||||||
public operator fun plus(other: Angle): Angle
|
|
||||||
public operator fun minus(other: Angle): Angle
|
|
||||||
|
|
||||||
public operator fun times(other: Number): Angle
|
|
||||||
public operator fun div(other: Number): Angle
|
|
||||||
public operator fun div(other: Angle): Double
|
|
||||||
public operator fun unaryMinus(): Angle
|
|
||||||
|
|
||||||
public companion object {
|
|
||||||
public val zero: Angle = 0.radians
|
|
||||||
public val pi: Angle = PI.radians
|
|
||||||
public val piTimes2: Angle = (2 * PI).radians
|
|
||||||
public val piDiv2: Angle = (PI / 2).radians
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type safe radians
|
|
||||||
*/
|
|
||||||
@JvmInline
|
|
||||||
public value class Radians(public val value: Double) : Angle {
|
|
||||||
override val radians: Radians
|
|
||||||
get() = this
|
|
||||||
override val degrees: Degrees
|
|
||||||
get() = Degrees(value * 180 / PI)
|
|
||||||
|
|
||||||
public override fun plus(other: Angle): Radians = Radians(value + other.radians.value)
|
|
||||||
public override fun minus(other: Angle): Radians = Radians(value - other.radians.value)
|
|
||||||
|
|
||||||
public override fun times(other: Number): Radians = Radians(value * other.toDouble())
|
|
||||||
public override fun div(other: Number): Radians = Radians(value / other.toDouble())
|
|
||||||
override fun div(other: Angle): Double = value / other.radians.value
|
|
||||||
public override fun unaryMinus(): Radians = Radians(-value)
|
|
||||||
|
|
||||||
override fun compareTo(other: Angle): Int = value.compareTo(other.radians.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun sin(angle: Angle): Double = kotlin.math.sin(angle.radians.value)
|
|
||||||
public fun cos(angle: Angle): Double = kotlin.math.cos(angle.radians.value)
|
|
||||||
public fun tan(angle: Angle): Double = kotlin.math.tan(angle.radians.value)
|
|
||||||
|
|
||||||
public val Number.radians: Radians get() = Radians(toDouble())
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type safe degrees
|
|
||||||
*/
|
|
||||||
@JvmInline
|
|
||||||
public value class Degrees(public val value: Double) : Angle {
|
|
||||||
override val radians: Radians
|
|
||||||
get() = Radians(value * PI / 180)
|
|
||||||
override val degrees: Degrees
|
|
||||||
get() = this
|
|
||||||
|
|
||||||
public override fun plus(other: Angle): Degrees = Degrees(value + other.degrees.value)
|
|
||||||
public override fun minus(other: Angle): Degrees = Degrees(value - other.degrees.value)
|
|
||||||
|
|
||||||
public override fun times(other: Number): Degrees = Degrees(value * other.toDouble())
|
|
||||||
public override fun div(other: Number): Degrees = Degrees(value / other.toDouble())
|
|
||||||
override fun div(other: Angle): Double = value / other.degrees.value
|
|
||||||
public override fun unaryMinus(): Degrees = Degrees(-value)
|
|
||||||
|
|
||||||
override fun compareTo(other: Angle): Int = value.compareTo(other.degrees.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public val Number.degrees: Degrees get() = Degrees(toDouble())
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalized angle 2 PI range symmetric around [center]. By default, uses (0, 2PI) range.
|
|
||||||
*/
|
|
||||||
public fun Angle.normalized(center: Angle = Angle.pi): Angle =
|
|
||||||
this - Angle.piTimes2 * floor((radians.value + PI - center.radians.value) / PI/2)
|
|
||||||
|
|
||||||
public fun abs(angle: Angle): Angle = if (angle < Angle.zero) -angle else angle
|
|
||||||
|
|
||||||
public fun Radians.toFloat(): Float = value.toFloat()
|
|
||||||
|
|
||||||
public fun Degrees.toFloat(): Float = value.toFloat()
|
|
@ -0,0 +1,34 @@
|
|||||||
|
package center.sciprog.maps.features
|
||||||
|
|
||||||
|
import androidx.compose.ui.unit.DpSize
|
||||||
|
|
||||||
|
|
||||||
|
public interface Rectangle<T : Any> {
|
||||||
|
public val topLeft: T
|
||||||
|
public val bottomRight: T
|
||||||
|
|
||||||
|
public operator fun contains(point: T): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface CoordinateSpace<T : Any> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a rectangle by two opposing corners
|
||||||
|
*/
|
||||||
|
public fun buildRectangle(first: T, second: T): Rectangle<T>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a rectangle of visual size [size]
|
||||||
|
*/
|
||||||
|
public fun buildRectangle(center: T, zoom: Double, size: DpSize): Rectangle<T>
|
||||||
|
//GmcRectangle.square(center, (size.height.value / scale).radians, (size.width.value / scale).radians)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move given rectangle to be centered at [center]
|
||||||
|
*/
|
||||||
|
public fun Rectangle<T>.withCenter(center: T): Rectangle<T>
|
||||||
|
|
||||||
|
public fun Iterable<Rectangle<T>>.computeRectangle(): Rectangle<T>?
|
||||||
|
|
||||||
|
public fun Iterable<T>.computeRectangle(): Rectangle<T>?
|
||||||
|
}
|
@ -9,30 +9,17 @@ import androidx.compose.ui.graphics.drawscope.Fill
|
|||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.graphics.vector.VectorPainter
|
import androidx.compose.ui.graphics.vector.VectorPainter
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.DpSize
|
import androidx.compose.ui.unit.DpSize
|
||||||
import androidx.compose.ui.unit.IntSize
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param T type of coordinates used for the view point
|
|
||||||
*/
|
|
||||||
public interface ViewPoint<T: Any> {
|
|
||||||
public val focus: T
|
|
||||||
public val zoom: Double
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Rectangle<T: Any>{
|
|
||||||
public val topLeft: T
|
|
||||||
public val bottomRight: T
|
|
||||||
|
|
||||||
public operator fun contains(point: T): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Feature<T : Any> {
|
public interface Feature<T : Any> {
|
||||||
public interface Attribute<T>
|
public interface Attribute<T>
|
||||||
|
|
||||||
|
public val space: CoordinateSpace<T>
|
||||||
|
|
||||||
public val zoomRange: ClosedFloatingPointRange<Double>
|
public val zoomRange: ClosedFloatingPointRange<Double>
|
||||||
|
|
||||||
public var attributes: AttributeMap
|
public var attributes: AttributeMap
|
||||||
@ -50,8 +37,12 @@ public interface DraggableFeature<T: Any> : SelectableFeature<T> {
|
|||||||
public fun withCoordinates(newCoordinates: T): Feature<T>
|
public fun withCoordinates(newCoordinates: T): Feature<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T: Any> Iterable<Feature<T>>.computeBoundingBox(zoom: Double): Rectangle<T>? =
|
public fun <T : Any> Iterable<Feature<T>>.computeBoundingBox(
|
||||||
mapNotNull { it.getBoundingBox(zoom) }.wrapAll()
|
space: CoordinateSpace<T>,
|
||||||
|
zoom: Double,
|
||||||
|
): Rectangle<T>? = with(space) {
|
||||||
|
mapNotNull { it.getBoundingBox(zoom) }.computeRectangle()
|
||||||
|
}
|
||||||
|
|
||||||
//public fun Pair<Number, Number>.toCoordinates(): GeodeticMapCoordinates =
|
//public fun Pair<Number, Number>.toCoordinates(): GeodeticMapCoordinates =
|
||||||
// GeodeticMapCoordinates.ofDegrees(first.toDouble(), second.toDouble())
|
// GeodeticMapCoordinates.ofDegrees(first.toDouble(), second.toDouble())
|
||||||
@ -62,6 +53,7 @@ internal val defaultZoomRange = 1.0..Double.POSITIVE_INFINITY
|
|||||||
* A feature that decides what to show depending on the zoom value (it could change size of shape)
|
* A feature that decides what to show depending on the zoom value (it could change size of shape)
|
||||||
*/
|
*/
|
||||||
public class FeatureSelector<T : Any>(
|
public class FeatureSelector<T : Any>(
|
||||||
|
override val space: CoordinateSpace<T>,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
public val selector: (zoom: Int) -> Feature<T>,
|
public val selector: (zoom: Int) -> Feature<T>,
|
||||||
) : Feature<T> {
|
) : Feature<T> {
|
||||||
@ -71,21 +63,21 @@ public class FeatureSelector<T: Any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class DrawFeature<T : Any>(
|
public class DrawFeature<T : Any>(
|
||||||
public val position: T,
|
override val space: CoordinateSpace<T>,
|
||||||
|
public val rectangle: Rectangle<T>,
|
||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
public val drawFeature: DrawScope.() -> Unit,
|
public val drawFeature: DrawScope.() -> Unit,
|
||||||
) : DraggableFeature<T> {
|
) : DraggableFeature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> {
|
override fun getBoundingBox(zoom: Double): Rectangle<T> = rectangle
|
||||||
//TODO add box computation
|
|
||||||
return GmcRectangle(position, position)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun withCoordinates(newCoordinates: T): Feature<T> =
|
override fun withCoordinates(newCoordinates: T): Feature<T> = with(space) {
|
||||||
DrawFeature(newCoordinates, zoomRange, attributes, drawFeature)
|
DrawFeature(space, rectangle.withCenter(newCoordinates), zoomRange, attributes, drawFeature)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PathFeature<T : Any>(
|
public class PathFeature<T : Any>(
|
||||||
|
override val space: CoordinateSpace<T>,
|
||||||
public val rectangle: Rectangle<T>,
|
public val rectangle: Rectangle<T>,
|
||||||
public val path: Path,
|
public val path: Path,
|
||||||
public val brush: Brush,
|
public val brush: Brush,
|
||||||
@ -94,14 +86,24 @@ public class PathFeature<T: Any>(
|
|||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableFeature<T> {
|
) : DraggableFeature<T> {
|
||||||
override fun withCoordinates(newCoordinates: T): Feature<T> =
|
override fun withCoordinates(newCoordinates: T): Feature<T> = with(space) {
|
||||||
PathFeature(rectangle.moveTo(newCoordinates), path, brush, style, targetRect, zoomRange)
|
PathFeature(
|
||||||
|
space = space,
|
||||||
|
rectangle = rectangle.withCenter(newCoordinates),
|
||||||
|
path = path,
|
||||||
|
brush = brush,
|
||||||
|
style = style,
|
||||||
|
targetRect = targetRect,
|
||||||
|
zoomRange = zoomRange
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> = rectangle
|
override fun getBoundingBox(zoom: Double): Rectangle<T> = rectangle
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PointsFeature<T : Any>(
|
public class PointsFeature<T : Any>(
|
||||||
|
override val space: CoordinateSpace<T>,
|
||||||
public val points: List<T>,
|
public val points: List<T>,
|
||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
public val stroke: Float = 2f,
|
public val stroke: Float = 2f,
|
||||||
@ -109,49 +111,51 @@ public class PointsFeature<T: Any>(
|
|||||||
public val pointMode: PointMode = PointMode.Points,
|
public val pointMode: PointMode = PointMode.Points,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : Feature<T> {
|
) : Feature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> = GmcRectangle(points.first(), points.last())
|
override fun getBoundingBox(zoom: Double): Rectangle<T>? = with(space) {
|
||||||
|
points.computeRectangle()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public data class CircleFeature<T : Any>(
|
public data class CircleFeature<T : Any>(
|
||||||
|
override val space: CoordinateSpace<T>,
|
||||||
public val center: T,
|
public val center: T,
|
||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
public val size: Float = 5f,
|
public val size: Dp = 5.dp,
|
||||||
public val color: Color = Color.Red,
|
public val color: Color = Color.Red,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableFeature<T> {
|
) : DraggableFeature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> {
|
override fun getBoundingBox(zoom: Double): Rectangle<T> =
|
||||||
val scale = WebMercatorProjection.scaleFactor(zoom)
|
space.buildRectangle(center, zoom, DpSize(size, size))
|
||||||
return GmcRectangle.square(center, (size / scale).radians, (size / scale).radians)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun withCoordinates(newCoordinates: T): Feature<T> =
|
override fun withCoordinates(newCoordinates: T): Feature<T> =
|
||||||
CircleFeature(newCoordinates, zoomRange, size, color, attributes)
|
CircleFeature(space, newCoordinates, zoomRange, size, color, attributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RectangleFeature<T : Any>(
|
public class RectangleFeature<T : Any>(
|
||||||
|
override val space: CoordinateSpace<T>,
|
||||||
public val center: T,
|
public val center: T,
|
||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
public val size: DpSize = DpSize(5.dp, 5.dp),
|
public val size: DpSize = DpSize(5.dp, 5.dp),
|
||||||
public val color: Color = Color.Red,
|
public val color: Color = Color.Red,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableFeature<T> {
|
) : DraggableFeature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> {
|
override fun getBoundingBox(zoom: Double): Rectangle<T> =
|
||||||
val scale = WebMercatorProjection.scaleFactor(zoom)
|
space.buildRectangle(center, zoom, size)
|
||||||
return GmcRectangle.square(center, (size.height.value / scale).radians, (size.width.value / scale).radians)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun withCoordinates(newCoordinates: T): Feature<T> =
|
override fun withCoordinates(newCoordinates: T): Feature<T> =
|
||||||
RectangleFeature(newCoordinates, zoomRange, size, color, attributes)
|
RectangleFeature(space, newCoordinates, zoomRange, size, color, attributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LineFeature<T : Any>(
|
public class LineFeature<T : Any>(
|
||||||
|
override val space: CoordinateSpace<T>,
|
||||||
public val a: T,
|
public val a: T,
|
||||||
public val b: T,
|
public val b: T,
|
||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
public val color: Color = Color.Red,
|
public val color: Color = Color.Red,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : SelectableFeature<T> {
|
) : SelectableFeature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> = GmcRectangle(a, b)
|
override fun getBoundingBox(zoom: Double): Rectangle<T> =
|
||||||
|
space.buildRectangle(a, b)
|
||||||
|
|
||||||
override fun contains(point: ViewPoint<T>): Boolean {
|
override fun contains(point: ViewPoint<T>): Boolean {
|
||||||
return super.contains(point)
|
return super.contains(point)
|
||||||
@ -159,47 +163,51 @@ public class LineFeature<T: Any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param startAngle the angle from parallel downwards for the start of the arc
|
* @param startAngle the angle from 3 o'clock downwards for the start of the arc in radians
|
||||||
* @param arcLength arc length
|
* @param arcLength arc length in radians
|
||||||
*/
|
*/
|
||||||
public class ArcFeature<T : Any>(
|
public class ArcFeature<T : Any>(
|
||||||
|
override val space: CoordinateSpace<T>,
|
||||||
public val oval: Rectangle<T>,
|
public val oval: Rectangle<T>,
|
||||||
public val startAngle: Angle,
|
public val startAngle: Float,
|
||||||
public val arcLength: Angle,
|
public val arcLength: Float,
|
||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
public val color: Color = Color.Red,
|
public val color: Color = Color.Red,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableFeature<T> {
|
) : DraggableFeature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> = oval
|
override fun getBoundingBox(zoom: Double): Rectangle<T> = oval
|
||||||
|
|
||||||
override fun withCoordinates(newCoordinates: T): Feature<T> =
|
override fun withCoordinates(newCoordinates: T): Feature<T> = with(space) {
|
||||||
ArcFeature(oval.moveTo(newCoordinates), startAngle, arcLength, zoomRange, color, attributes)
|
ArcFeature(space, oval.withCenter(newCoordinates), startAngle, arcLength, zoomRange, color, attributes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BitmapImageFeature<T : Any>(
|
public class BitmapImageFeature<T : Any>(
|
||||||
public val position: T,
|
override val space: CoordinateSpace<T>,
|
||||||
|
public val rectangle: Rectangle<T>,
|
||||||
public val image: ImageBitmap,
|
public val image: ImageBitmap,
|
||||||
public val size: IntSize = IntSize(15, 15),
|
|
||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableFeature<T> {
|
) : DraggableFeature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> = GmcRectangle(position, position)
|
override fun getBoundingBox(zoom: Double): Rectangle<T> = rectangle
|
||||||
|
|
||||||
override fun withCoordinates(newCoordinates: T): Feature<T> =
|
override fun withCoordinates(newCoordinates: T): Feature<T> = with(space) {
|
||||||
BitmapImageFeature(newCoordinates, image, size, zoomRange, attributes)
|
BitmapImageFeature(space, rectangle.withCenter(newCoordinates), image, zoomRange, attributes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VectorImageFeature<T : Any>(
|
public class VectorImageFeature<T : Any>(
|
||||||
public val position: T,
|
override val space: CoordinateSpace<T>,
|
||||||
|
public val rectangle: Rectangle<T>,
|
||||||
public val image: ImageVector,
|
public val image: ImageVector,
|
||||||
public val size: DpSize = DpSize(20.dp, 20.dp),
|
|
||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableFeature<T> {
|
) : DraggableFeature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> = GmcRectangle(position, position)
|
override fun getBoundingBox(zoom: Double): Rectangle<T> = rectangle
|
||||||
|
|
||||||
override fun withCoordinates(newCoordinates: T): Feature<T> =
|
override fun withCoordinates(newCoordinates: T): Feature<T> = with(space) {
|
||||||
VectorImageFeature(newCoordinates, image, size, zoomRange, attributes)
|
VectorImageFeature(space, rectangle.withCenter(newCoordinates), image, zoomRange, attributes)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
public fun painter(): VectorPainter = rememberVectorPainter(image)
|
public fun painter(): VectorPainter = rememberVectorPainter(image)
|
||||||
@ -209,12 +217,14 @@ public class VectorImageFeature<T: Any>(
|
|||||||
* A group of other features
|
* A group of other features
|
||||||
*/
|
*/
|
||||||
public class FeatureGroup<T : Any>(
|
public class FeatureGroup<T : Any>(
|
||||||
|
override val space: CoordinateSpace<T>,
|
||||||
public val children: Map<FeatureId<*>, Feature<T>>,
|
public val children: Map<FeatureId<*>, Feature<T>>,
|
||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : Feature<T> {
|
) : Feature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T>? =
|
override fun getBoundingBox(zoom: Double): Rectangle<T>? = with(space) {
|
||||||
children.values.mapNotNull { it.getBoundingBox(zoom) }.wrapAll()
|
children.values.mapNotNull { it.getBoundingBox(zoom) }.computeRectangle()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TextFeature<T : Any>(
|
public class TextFeature<T : Any>(
|
||||||
@ -223,7 +233,7 @@ public class TextFeature<T: Any>(
|
|||||||
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
override val zoomRange: ClosedFloatingPointRange<Double> = defaultZoomRange,
|
||||||
public val color: Color = Color.Black,
|
public val color: Color = Color.Black,
|
||||||
override var attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
public val fontConfig: MapTextFeatureFont.() -> Unit,
|
public val fontConfig: FeatureFont.() -> Unit,
|
||||||
) : DraggableFeature<T> {
|
) : DraggableFeature<T> {
|
||||||
override fun getBoundingBox(zoom: Double): Rectangle<T> = GmcRectangle(position, position)
|
override fun getBoundingBox(zoom: Double): Rectangle<T> = GmcRectangle(position, position)
|
||||||
|
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package center.sciprog.maps.features
|
||||||
|
|
||||||
|
public expect class FeatureFont {
|
||||||
|
public var size: Float
|
||||||
|
}
|
@ -282,7 +282,7 @@ public fun MapFeaturesState.text(
|
|||||||
text: String,
|
text: String,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
font: FeatureFont.() -> Unit = { size = 16f },
|
||||||
id: String? = null,
|
id: String? = null,
|
||||||
): FeatureId<TextFeature> = feature(
|
): FeatureId<TextFeature> = feature(
|
||||||
id,
|
id,
|
||||||
@ -294,7 +294,7 @@ public fun MapFeaturesState.text(
|
|||||||
text: String,
|
text: String,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
font: FeatureFont.() -> Unit = { size = 16f },
|
||||||
id: String? = null,
|
id: String? = null,
|
||||||
): FeatureId<TextFeature> = feature(
|
): FeatureId<TextFeature> = feature(
|
||||||
id,
|
id,
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package center.sciprog.maps.features
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param T type of coordinates used for the view point
|
||||||
|
*/
|
||||||
|
public interface ViewPoint<T: Any> {
|
||||||
|
public val focus: T
|
||||||
|
public val zoom: Double
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package center.sciprog.maps.features
|
||||||
|
|
||||||
|
import org.jetbrains.skia.Font
|
||||||
|
|
||||||
|
public actual typealias FeatureFont = Font
|
Loading…
Reference in New Issue
Block a user