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

Drag Marker on Mapbox #2

Open
1232Ga opened this issue Oct 25, 2024 · 0 comments
Open

Drag Marker on Mapbox #2

1232Ga opened this issue Oct 25, 2024 · 0 comments

Comments

@1232Ga
Copy link

1232Ga commented Oct 25, 2024

MicrosoftTeams-video.mp4

from below code i will get above output that is showing to you in video

class DraggableActivity : AppCompatActivity(), MapboxMap.OnMapClickListener {
companion object {
private const val FILL_LAYER_ID = "fill-layer-id"
private const val FILL_SOURCE_ID = "fill-source-id"
private const val ID_ICON_LOCATION = "location"
private const val ID_ICON_ADD = "add"
private const val ID_ICON_LOCATION_SELECTED = "location_selected"
}
private var lastDraggedMidpointId: String? = null
private lateinit var undofab: FloatingActionButton
private var mapView: MapView? = null
private var symbolOptionsMid: SymbolOptions? = null
private var mapboxMap: MapboxMap? = null
private var fillSource: GeoJsonSource? = null
private lateinit var polyList: ArrayList
private lateinit var midPointList: ArrayList
private var rootSymbolId: String? = null
private var newPolygon: Boolean = false
private lateinit var symbolManager: SymbolManager

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Mapbox.getInstance(this, getString(R.string.mapbox_access_token))
setContentView(R.layout.activity_main)

mapView = findViewById(R.id.mapView)
undofab = findViewById(R.id.undo_fab)

mapView?.onCreate(savedInstanceState)
polyList = ArrayList()
midPointList = ArrayList()
mapView?.getMapAsync { mapboxMap ->
    this.mapboxMap = mapboxMap

    mapboxMap.setStyle(Style.SATELLITE) { it ->
        addMarkerIconStyle(it)
        symbolManager = SymbolManager(mapView!!, mapboxMap, mapboxMap.style!!)

        symbolManager.addClickListener{ t ->
            highlightSymbol(t)

            val clickedPoint = polyList.find { it.symbolId == t.id.toString() }
            if (clickedPoint != null) {
                if (t.id.toString() == rootSymbolId && polyList.size > 2) {
                    polyList.add(polyList[0])
                    drawPolygon()
                } else {
                    drawPolygon()
                }
            }
            true
        }

        symbolManager.addDragListener(object : OnSymbolDragListener {

            override fun onAnnotationDragStarted(annotation: Symbol?) {
                highlightSymbol(annotation)
                symbolManager.update(annotation)
            }
            override fun onAnnotationDrag(annotation: Symbol?) {
                if (annotation == null) return
                annotation.let {
                    val pointLatLng = polyList.find { it.symbolId == annotation.id.toString() }
                    pointLatLng?.let { it.latLng = annotation.latLng }
                    drawPolygon()
                    symbolOptionsMid= null
                }
            }
            override fun onAnnotationDragFinished(annotation: Symbol?) {
                if (annotation == null) return
                var isSymbolPresent = false
                var startLatLng: LatLng? = null
                var endLatLng: LatLng? = null
                for (i in polyList.indices) {
                    if (polyList[i].symbolId == annotation.id.toString()) {
                        isSymbolPresent = true
                        polyList[i].latLng = annotation.latLng
                        break
                    }
                }

                // If it's not a main polygon symbol, check if it's a midpoint
                if (!isSymbolPresent) {
                    for (i in midPointList.indices) {
                        if (midPointList[i].symbol.id == annotation.id) {
                            startLatLng = midPointList[i].latlng1
                            endLatLng = midPointList[i].latLng2
                            break
                        }
                    }
                }

                // If a midpoint is dragged, handle the new point insertion and midpoint recalculation
                if (!isSymbolPresent && startLatLng != null && endLatLng != null) {
                    if (lastDraggedMidpointId == annotation.id.toString()) {
                        if (midPointList.size > 1) {
                            midPointList.removeAt(midPointList.size - 1) // Remove last midpoint
                        }
                        if (midPointList.size > 1) {
                            midPointList.removeAt(midPointList.size - 1) // Remove second last midpoint
                        }
                    } else {
                        // Find the index of the midpoint being dragged
                        for (i in polyList.indices) {
                            if (polyList[i].latLng.latitude == startLatLng.latitude &&
                                polyList[i].latLng.longitude == startLatLng.longitude) {

                                // Insert the dragged point into the polyList at the correct position
                                polyList.add(i + 1, PointLatLng(annotation.id.toString(), annotation.latLng))

                                // Remove old midpoints for the affected segments
                                if (midPointList.size > i) {
                                    midPointList.removeAt(i) // Remove first midpoint
                                }
                                if (midPointList.size > i) {
                                    midPointList.removeAt(i) // Remove second midpoint
                                }

                                // Generate new midpoints after insertion
                                addNewMidpointsAfterDrag(i, annotation.latLng, startLatLng, endLatLng)

                                // Update last dragged midpoint ID
                                lastDraggedMidpointId = annotation.id.toString()
                                symbolOptionsMid = null

                                break
                            }
                        }
                    }
                } else {
                    lastDraggedMidpointId = null
                }

                // Redraw the polygon
                drawPolygon()
            }
        })
        fillSource = initFillSource(it)
        initFillLayer(it)
        mapboxMap.addOnMapClickListener(this)
        val position = CameraPosition.Builder()
            .target(LatLng(51.50550, -0.07520))
            .zoom(8.0)
            .build()

        mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), 2000)
    }
}
undofab.setOnClickListener {
    // Handle undo logic by removing the last point
    val lastKey = polyList.last().symbolId
    if (polyList.isNotEmpty()) {
        val annotations = symbolManager.annotations
        for (i in 0 until annotations.size()) {
            val key = annotations.keyAt(i)
            val value = annotations.valueAt(i)

            if (key.toString() == lastKey) {
                symbolManager.delete(value) // Delete the symbol with the matching key
            }
        }
        polyList.removeAt(polyList.size - 1)  // Remove the last element
        drawPolygon()
    }
}

}
private fun addNewMidpointsAfterDrag(index: Int, draggedLatLng: LatLng, startLatLng: LatLng, endLatLng: LatLng) {
// Create new midpoints for the new segments
val newMidpoint1 = getMidpoint(
startLatLng.latitude,
startLatLng.longitude,
draggedLatLng.latitude,
draggedLatLng.longitude
)
val symbolOptions1 = SymbolOptions().withLatLng(newMidpoint1)
.withIconImage(ID_ICON_ADD).withDraggable(true)
.withIconSize(1f)
val newSymbol1 = symbolManager.create(symbolOptions1)
midPointList.add(index, AddMarkerPoint(startLatLng, draggedLatLng, newSymbol1))

val newMidpoint2 = getMidpoint(
    endLatLng.latitude,
    endLatLng.longitude,
    draggedLatLng.latitude,
    draggedLatLng.longitude
)
val symbolOptions2 = SymbolOptions().withLatLng(newMidpoint2)
    .withIconImage(ID_ICON_ADD).withDraggable(true)
    .withIconSize(1f)
val newSymbol2 = symbolManager.create(symbolOptions2)
midPointList.add(index + 1, AddMarkerPoint(draggedLatLng, endLatLng, newSymbol2))

}
private fun initFillSource(loadedMapStyle: Style): GeoJsonSource {
val fillFeatureCollection = FeatureCollection.fromFeatures(arrayOf())
val fillGeoJsonSource = GeoJsonSource(FILL_SOURCE_ID, fillFeatureCollection)
loadedMapStyle.addSource(fillGeoJsonSource)
return fillGeoJsonSource
}

private fun initFillLayer(loadedMapStyle: Style) {
val fillLayer = LineLayer(
FILL_LAYER_ID,
FILL_SOURCE_ID
)
fillLayer.setProperties(
PropertyFactory.lineWidth(2.5f),
PropertyFactory.lineColor(Color.parseColor("#ffffff"))
)
loadedMapStyle.addLayerBelow(fillLayer, symbolManager.layerId)
}

fun highlightSymbol(t: Symbol?) {
val symbols = symbolManager.annotations
val lists = ArrayList(symbols.size())
for (i in 0 until symbols.size()) {
val symbol = symbols.valueAt(i)
symbol.iconImage = ID_ICON_LOCATION
lists.add(symbol)
}
symbolManager.update(lists)
t?.iconImage = ID_ICON_LOCATION_SELECTED
symbolManager.update(t)
}

override fun onMapClick(point: LatLng): Boolean {
val symbolOptions = SymbolOptions().withLatLng(point).withIconImage(ID_ICON_LOCATION).withDraggable(true)
.withIconSize(1f)
val symbol = symbolManager.create(symbolOptions)
if (polyList.isEmpty()) {
rootSymbolId = symbol.id.toString()
} else if (newPolygon) {
newPolygon = false
rootSymbolId = symbol.id.toString()
} else {
val midPoints = getMidpoint(
polyList.last().latLng.latitude,
polyList.last().latLng.longitude,
point.latitude,
point.longitude
)
symbolOptionsMid= SymbolOptions()
.withLatLng(midPoints)
.withIconImage(ID_ICON_ADD)
.withDraggable(true)
.withIconSize(1f)
val midSymbol = symbolManager.create(symbolOptionsMid)
symbolManager.iconAllowOverlap = true
midPointList.add(AddMarkerPoint(polyList.last().latLng, point, midSymbol))
}
polyList.add(PointLatLng(symbol.id.toString(), symbol.latLng))
drawPolygon()
return true
}

private fun addMarkerIconStyle(style: Style) {
style.addImage(
ID_ICON_LOCATION,
BitmapUtils.getBitmapFromDrawable(
ContextCompat.getDrawable(
this,
R.drawable.ic_mark
)
)!!,
false
)
style.addImage(
ID_ICON_ADD,
BitmapUtils.getBitmapFromDrawable(
ContextCompat.getDrawable(
this,
R.drawable.ic_add
)
)!!,
false
)

style.addImage(
    ID_ICON_LOCATION_SELECTED, BitmapUtils.getBitmapFromDrawable(
        ContextCompat.getDrawable(
            this,
            R.drawable.ic_mark
        )
    )!!,
    false
)

}

private fun drawPolygon() {
val latLngList = polyList.map { it.latLng }
val points = latLngList.map { Point.fromLngLat(it.longitude, it.latitude) }
val fillFeatureList = arrayListOf(Feature.fromGeometry(LineString.fromLngLats(points)))
fillSource?.setGeoJson(FeatureCollection.fromFeatures(fillFeatureList))
}
fun getMidpoint(lat1: Double,
lng1: Double,
lat2: Double,
lng2: Double): LatLng {
return LatLng((lat1 + lat2) / 2, (lng1 + lng2) / 2)
}
}
but from this output i want some changes that if i will drag marker others markers can't detach like show in video all markers should attach

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant