Fix line clickability region

This commit is contained in:
Alexander Nozik 2023-02-22 09:48:18 +03:00
parent 7623e5f622
commit 8f489ea0f9
5 changed files with 51 additions and 18 deletions

View File

@ -18,17 +18,17 @@ internal data class GmcRectangle(
override val a: GeodeticMapCoordinates,
override val b: GeodeticMapCoordinates,
) : Rectangle<Gmc> {
override val center: GeodeticMapCoordinates
get() = GeodeticMapCoordinates.normalized(
(a.latitude + b.latitude) / 2,
(a.longitude + b.longitude) / 2
)
override fun contains(point: Gmc): Boolean =
point.latitude.isBetween(a.latitude, b.latitude) && point.longitude.isBetween(a.longitude, b.longitude)
}
public val Rectangle<Gmc>.center: GeodeticMapCoordinates
get() = GeodeticMapCoordinates.normalized(
(a.latitude + b.latitude) / 2,
(a.longitude + b.longitude) / 2
)
/**
* Minimum longitude
*/

View File

@ -19,6 +19,8 @@ public interface Area<T : Any> {
public interface Rectangle<T : Any> : Area<T> {
public val a: T
public val b: T
public val center: T
}
/**
@ -64,12 +66,12 @@ public interface CoordinateSpace<T : Any> {
public fun T.offsetTo(b: T, zoom: Float): DpOffset
public fun T.distanceTo(b: T, zoom: Float): Dp {
public fun T.distanceTo(b: T, zoom: Float = Float.MAX_VALUE): Dp {
val offset = offsetTo(b, zoom)
return sqrt(offset.x.value * offset.x.value + offset.y.value * offset.y.value).dp
}
public fun T.distanceToLine(a: T, b: T, zoom: Float): Dp {
public fun T.distanceToLine(a: T, b: T, zoom: Float = Float.MAX_VALUE): Dp {
val d12 = a.offsetTo(b, zoom)
val d01 = offsetTo(a, zoom)
val distanceVale = abs(d12.x.value * d01.y.value - d12.y.value * d01.x.value) / a.distanceTo(b, zoom).value

View File

@ -29,7 +29,7 @@ public interface Feature<T : Any> {
public val attributes: Attributes
public fun getBoundingBox(zoom: Float): Rectangle<T>?
public fun getBoundingBox(zoom: Float = Float.MAX_VALUE): Rectangle<T>?
public fun withAttributes(modify: Attributes.() -> Attributes): Feature<T>
}
@ -136,15 +136,15 @@ public data class LineFeature<T : Any>(
public val b: T,
override val attributes: Attributes = Attributes.EMPTY,
) : DomainFeature<T>, LineSegmentFeature<T> {
override fun getBoundingBox(zoom: Float): Rectangle<T> =
space.Rectangle(a, b)
override fun getBoundingBox(zoom: Float): Rectangle<T> = space.Rectangle(a, b)
val center: T by lazy { getBoundingBox().center }
val length: Dp by lazy { with(space) { a.distanceTo(b) } }
override fun contains(viewPoint: ViewPoint<T>): Boolean = with(space) {
viewPoint.focus in getBoundingBox(viewPoint.zoom) && viewPoint.focus.distanceToLine(
a,
b,
viewPoint.zoom
).value < clickRadius
viewPoint.focus.distanceTo(center) <= length / 2 &&
viewPoint.focus.distanceToLine(a, b, viewPoint.zoom).value <= clickRadius
}
override fun withAttributes(modify: (Attributes) -> Attributes): Feature<T> = copy(attributes = modify(attributes))

View File

@ -36,4 +36,35 @@ public fun <T : Any> FeatureGroup<T>.draggableLine(
}
return drawLine()
}
public fun <T : Any> FeatureGroup<T>.draggableMultiLine(
points: List<FeatureRef<T, MarkerFeature<T>>>,
id: String? = null,
): FeatureRef<T, MultiLineFeature<T>> {
var polygonId: FeatureRef<T, MultiLineFeature<T>>? = null
fun drawLines(): FeatureRef<T, MultiLineFeature<T>> {
val currentId = feature(
polygonId?.id ?: id,
MultiLineFeature(
space,
points.map { it.resolve().center },
Attributes {
ZAttribute(-10f)
polygonId?.attributes?.let { from(it) }
}
)
)
polygonId = currentId
return currentId
}
points.forEach {
it.draggable { _, _ ->
drawLines()
}
}
return drawLines()
}

View File

@ -18,6 +18,8 @@ internal data class XYRectangle(
override fun contains(point: XY): Boolean = point.x in a.x..b.x && point.y in a.y..b.y
override val center get() = XY((a.x + b.x) / 2, (a.y + b.y) / 2)
// companion object {
// fun square(center: XY, height: Float, width: Float): XYRectangle = XYRectangle(
// XY(center.x - width / 2, center.y + height / 2),
@ -35,8 +37,6 @@ val Rectangle<XY>.left get() = min(a.x, b.x)
val Rectangle<XY>.width: Float get() = abs(a.x - b.x)
val Rectangle<XY>.height: Float get() = abs(a.y - b.y)
val Rectangle<XY>.center get() = XY((a.x + b.x) / 2, (a.y + b.y) / 2)
public val Rectangle<XY>.leftTop: XY get() = XY(left, top)
public val Rectangle<XY>.rightBottom: XY get() = XY(right, bottom)