173 lines
5.1 KiB
Kotlin
173 lines
5.1 KiB
Kotlin
package center.sciprog.maps.compose
|
|
|
|
import androidx.compose.ui.graphics.Color
|
|
import androidx.compose.ui.graphics.drawscope.DrawScope
|
|
import androidx.compose.ui.graphics.vector.ImageVector
|
|
import androidx.compose.ui.unit.Dp
|
|
import androidx.compose.ui.unit.DpSize
|
|
import androidx.compose.ui.unit.dp
|
|
import center.sciprog.maps.coordinates.*
|
|
import center.sciprog.maps.features.*
|
|
import space.kscience.kmath.geometry.Angle
|
|
import kotlin.math.ceil
|
|
|
|
|
|
internal fun FeatureGroup<Gmc>.coordinatesOf(pair: Pair<Number, Number>) =
|
|
GeodeticMapCoordinates.ofDegrees(pair.first.toDouble(), pair.second.toDouble())
|
|
|
|
public typealias MapFeature = Feature<Gmc>
|
|
|
|
public fun FeatureGroup<Gmc>.circle(
|
|
centerCoordinates: Pair<Number, Number>,
|
|
size: Dp = 5.dp,
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, CircleFeature<Gmc>> = feature(
|
|
id, CircleFeature(space, coordinatesOf(centerCoordinates), size)
|
|
)
|
|
|
|
public fun FeatureGroup<Gmc>.rectangle(
|
|
centerCoordinates: Pair<Number, Number>,
|
|
size: DpSize = DpSize(5.dp, 5.dp),
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, RectangleFeature<Gmc>> = feature(
|
|
id, RectangleFeature(space, coordinatesOf(centerCoordinates), size)
|
|
)
|
|
|
|
|
|
public fun FeatureGroup<Gmc>.draw(
|
|
position: Pair<Number, Number>,
|
|
id: String? = null,
|
|
draw: DrawScope.() -> Unit,
|
|
): FeatureRef<Gmc, DrawFeature<Gmc>> = feature(
|
|
id,
|
|
DrawFeature(space, coordinatesOf(position), drawFeature = draw)
|
|
)
|
|
|
|
|
|
public fun FeatureGroup<Gmc>.line(
|
|
curve: GmcCurve,
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, LineFeature<Gmc>> = feature(
|
|
id,
|
|
LineFeature(space, curve.forward.coordinates, curve.backward.coordinates)
|
|
)
|
|
|
|
/**
|
|
* A segmented geodetic curve
|
|
*/
|
|
public fun FeatureGroup<Gmc>.geodeticLine(
|
|
curve: GmcCurve,
|
|
ellipsoid: GeoEllipsoid = GeoEllipsoid.WGS84,
|
|
maxLineDistance: Distance = 100.kilometers,
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, Feature<Gmc>> = if (curve.distance < maxLineDistance) {
|
|
feature(
|
|
id,
|
|
LineFeature(space, curve.forward.coordinates, curve.backward.coordinates)
|
|
)
|
|
} else {
|
|
val segments = ceil(curve.distance / maxLineDistance).toInt()
|
|
val segmentSize = curve.distance / segments
|
|
val points = buildList<GmcPose> {
|
|
add(curve.forward)
|
|
repeat(segments) {
|
|
val segment = ellipsoid.curveInDirection(this.last(), segmentSize, 1e-2)
|
|
add(segment.backward)
|
|
}
|
|
}
|
|
multiLine(points.map { it.coordinates }, id = id)
|
|
}
|
|
|
|
public fun FeatureGroup<Gmc>.geodeticLine(
|
|
from: Gmc,
|
|
to: Gmc,
|
|
ellipsoid: GeoEllipsoid = GeoEllipsoid.WGS84,
|
|
maxLineDistance: Distance = 100.kilometers,
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, Feature<Gmc>> = geodeticLine(ellipsoid.curveBetween(from, to), ellipsoid, maxLineDistance, id)
|
|
|
|
public fun FeatureGroup<Gmc>.line(
|
|
aCoordinates: Pair<Double, Double>,
|
|
bCoordinates: Pair<Double, Double>,
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, LineFeature<Gmc>> = feature(
|
|
id,
|
|
LineFeature(space, coordinatesOf(aCoordinates), coordinatesOf(bCoordinates))
|
|
)
|
|
|
|
public fun FeatureGroup<Gmc>.arc(
|
|
center: Pair<Double, Double>,
|
|
radius: Distance,
|
|
startAngle: Angle,
|
|
arcLength: Angle,
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, ArcFeature<Gmc>> = feature(
|
|
id,
|
|
ArcFeature(
|
|
space,
|
|
oval = space.Rectangle(coordinatesOf(center), radius, radius),
|
|
startAngle = startAngle,
|
|
arcLength = arcLength,
|
|
)
|
|
)
|
|
|
|
public fun FeatureGroup<Gmc>.points(
|
|
points: List<Pair<Double, Double>>,
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, PointsFeature<Gmc>> = feature(id, PointsFeature(space, points.map(::coordinatesOf)))
|
|
|
|
public fun FeatureGroup<Gmc>.multiLine(
|
|
points: List<Pair<Double, Double>>,
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, MultiLineFeature<Gmc>> = feature(id, MultiLineFeature(space, points.map(::coordinatesOf)))
|
|
|
|
public fun FeatureGroup<Gmc>.icon(
|
|
position: Pair<Double, Double>,
|
|
image: ImageVector,
|
|
size: DpSize = DpSize(20.dp, 20.dp),
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, VectorIconFeature<Gmc>> = feature(
|
|
id,
|
|
VectorIconFeature(
|
|
space,
|
|
coordinatesOf(position),
|
|
size,
|
|
image,
|
|
)
|
|
)
|
|
|
|
public fun FeatureGroup<Gmc>.text(
|
|
position: Pair<Double, Double>,
|
|
text: String,
|
|
font: FeatureFont.() -> Unit = { size = 16f },
|
|
id: String? = null,
|
|
): FeatureRef<Gmc, TextFeature<Gmc>> = feature(
|
|
id,
|
|
TextFeature(space, coordinatesOf(position), text, fontConfig = font)
|
|
)
|
|
|
|
public fun FeatureGroup<Gmc>.pixelMap(
|
|
rectangle: Rectangle<Gmc>,
|
|
latitudeDelta: Angle,
|
|
longitudeDelta: Angle,
|
|
id: String? = null,
|
|
builder: (Gmc) -> Color?,
|
|
): FeatureRef<Gmc, PixelMapFeature<Gmc>> = feature(
|
|
id,
|
|
PixelMapFeature(
|
|
space,
|
|
rectangle,
|
|
Structure2D(
|
|
ceil(rectangle.longitudeDelta / latitudeDelta).toInt(),
|
|
ceil(rectangle.latitudeDelta / longitudeDelta).toInt()
|
|
|
|
) { (i, j) ->
|
|
val longitude = rectangle.left + longitudeDelta * i
|
|
val latitude = rectangle.bottom + latitudeDelta * j
|
|
builder(
|
|
Gmc(latitude, longitude)
|
|
)
|
|
}
|
|
)
|
|
)
|