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

Find nearest vertex sample #319

Open
wants to merge 14 commits into
base: v.next
Choose a base branch
from
4 changes: 3 additions & 1 deletion samples/find-nearest-vertex/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Click anywhere on the map. A magenta cross will show at that location. A blue ci

The value of `ProximityResult.distance` is planar (Euclidean) distance. Planar distances are only accurate for geometries that have a defined projected coordinate system, which maintain the desired level of accuracy. The example polygon in this sample is defined in California State Plane Coordinate System - Zone 5 (WKID 2229), which maintains accuracy near Southern California. Accuracy declines outside the state plane zone.

This sample uses the GeoView-Compose Toolkit module to be able to implement a composable MapView.

## Tags

analysis, coordinate, geometry, nearest, proximity, vertex
analysis, coordinate, geometry, geoview-compose, nearest, proximity, toolkit, vertex
58 changes: 31 additions & 27 deletions samples/find-nearest-vertex/README.metadata.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
{
"category": "Analysis",
"description": "Find the closest vertex and coordinate of a geometry to a point.",
"formal_name": "FindNearestVertex",
"ignore": false,
"images": [
"find-nearest-vertex.png"
],
"keywords": [
"analysis",
"coordinate",
"geometry",
"nearest",
"proximity",
"vertex",
"GeometryEngine",
"ProximityResult"
],
"language": "kotlin",
"redirect_from": "",
"relevant_apis": [
"GeometryEngine",
"ProximityResult"
],
"snippets": [
"src/main/java/com/esri/arcgismaps/sample/findnearestvertex/MainActivity.kt"
],
"title": "Find nearest vertex"
"category": "Analysis",
"description": "Find the closest vertex and coordinate of a geometry to a point.",
"formal_name": "FindNearestVertex",
"ignore": false,
"images": [
"find-nearest-vertex.png"
],
"keywords": [
"analysis",
"coordinate",
"geometry",
"geoview-compose",
"nearest",
"proximity",
"toolkit",
"vertex",
"GeometryEngine",
"ProximityResult"
],
"language": "kotlin",
"redirect_from": "",
"relevant_apis": [
"GeometryEngine",
"ProximityResult"
],
"snippets": [
"src/main/java/com/esri/arcgismaps/sample/findnearestvertex/components/FindNearestVertexViewModel.kt",
"src/main/java/com/esri/arcgismaps/sample/findnearestvertex/MainActivity.kt",
"src/main/java/com/esri/arcgismaps/sample/findnearestvertex/screens/FindNearestVertexScreen.kt"
],
"title": "Find nearest vertex"
}
3 changes: 1 addition & 2 deletions samples/find-nearest-vertex/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
plugins {
alias(libs.plugins.arcgismaps.android.library)
alias(libs.plugins.arcgismaps.android.library.compose)
alias(libs.plugins.arcgismaps.kotlin.sample)
alias(libs.plugins.gradle.secrets)
}
Expand All @@ -11,9 +12,7 @@ secrets {

android {
namespace = "com.esri.arcgismaps.sample.findnearestvertex"
// For view based samples
buildFeatures {
dataBinding = true
buildConfig = true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,176 +17,37 @@
package com.esri.arcgismaps.sample.findnearestvertex

import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.lifecycleScope
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import com.arcgismaps.ApiKey
import com.arcgismaps.ArcGISEnvironment
import com.arcgismaps.Color
import com.arcgismaps.geometry.GeometryEngine
import com.arcgismaps.geometry.Point
import com.arcgismaps.geometry.Polygon
import com.arcgismaps.geometry.PolygonBuilder
import com.arcgismaps.geometry.SpatialReference
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.layers.FeatureLayer
import com.arcgismaps.mapping.symbology.SimpleFillSymbol
import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle
import com.arcgismaps.mapping.symbology.SimpleLineSymbol
import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle
import com.arcgismaps.mapping.symbology.SimpleMarkerSymbol
import com.arcgismaps.mapping.symbology.SimpleMarkerSymbolStyle
import com.arcgismaps.mapping.view.Graphic
import com.arcgismaps.mapping.view.GraphicsOverlay
import com.arcgismaps.portal.Portal
import com.arcgismaps.mapping.PortalItem
import com.esri.arcgismaps.sample.findnearestvertex.databinding.FindNearestVertexActivityMainBinding
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.launch
import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme
import com.esri.arcgismaps.sample.findnearestvertex.screens.FindNearestVertexScreen

class MainActivity : AppCompatActivity() {

// set up data binding for the activity
private val activityMainBinding: FindNearestVertexActivityMainBinding by lazy {
DataBindingUtil.setContentView(this, R.layout.find_nearest_vertex_activity_main)
}

private val mapView by lazy {
activityMainBinding.mapView
}

private val distanceLayout: ConstraintLayout by lazy {
activityMainBinding.distanceLayout
}

private val vertexDistanceTextView: TextView by lazy {
activityMainBinding.vertexDistanceTextView
}

private val coordinateDistanceTextView: TextView by lazy {
activityMainBinding.coordinateDistanceTextView
}

// California zone 5 (ftUS) state plane coordinate system.
private val statePlaneCaliforniaZone5SpatialReference = SpatialReference(2229)

// create graphics with symbols for tapped location, nearest coordinate, and nearest vertex
private val tappedLocationGraphic =
Graphic(symbol = SimpleMarkerSymbol(SimpleMarkerSymbolStyle.X, Color.magenta, 15f))

// create graphic symbol of the nearest coordinate
private val nearestCoordinateGraphic =
Graphic(symbol = SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Diamond, Color.red, 10f))

// create graphic symbol of the nearest vertex
private val nearestVertexGraphic =
Graphic(symbol = SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.blue, 15f))
class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// authentication with an API key or named user is
// required to access basemaps and other location services
ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ACCESS_TOKEN)
lifecycle.addObserver(mapView)

// create a polygon geometry
val polygon = PolygonBuilder(statePlaneCaliforniaZone5SpatialReference) {
addPoint(Point(6627416.41469281, 1804532.53233782))
addPoint(Point(6669147.89779046, 2479145.16609522))
addPoint(Point(7265673.02678292, 2484254.50442408))
addPoint(Point(7676192.55880379, 2001458.66365744))
}.toGeometry()
// set up the outline and fill color of the polygon
val polygonOutlineSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.green, 2f)
val polygonFillSymbol = SimpleFillSymbol(
SimpleFillSymbolStyle.ForwardDiagonal,
Color.green,
polygonOutlineSymbol
)
// create a polygon graphic
val polygonGraphic = Graphic(polygon, polygonFillSymbol)
// create a graphics overlay to show the polygon, tapped location, and nearest vertex/coordinate
val graphicsOverlay = GraphicsOverlay(
listOf(
polygonGraphic,
tappedLocationGraphic,
nearestCoordinateGraphic,
nearestVertexGraphic
)
)

// create a map using the portal item
val map = ArcGISMap(statePlaneCaliforniaZone5SpatialReference)
val portal = Portal("https://arcgisruntime.maps.arcgis.com")
val portalItem = PortalItem(portal, "99fd67933e754a1181cc755146be21ca")
val usStatesGeneralizedLayer = FeatureLayer.createWithItemAndLayerId(portalItem, 0)
// and add the feature layer to the map's operational layers
map.operationalLayers.add(usStatesGeneralizedLayer)
// add the map to the map view
mapView.map = map
// add the graphics overlay to the map view
mapView.graphicsOverlays.add(graphicsOverlay)
lifecycleScope.launch {
// check if map has loaded
map.load().onSuccess {
// zoom to the polygon's extent
mapView.setViewpointGeometry(polygon.extent, 100.0)
// get point on map tapped
mapView.onSingleTapConfirmed.collect { event ->
// find nearest vertex on map tapped
event.mapPoint?.let { findNearestVertex(it, polygon) }
}
}.onFailure {
showError("Error loading map")
setContent {
SampleAppTheme {
FindNearestVertexApp()
}
}
}

/**
* Finds the nearest vertex from [mapPoint] from the [polygon]
*/
private fun findNearestVertex(mapPoint: Point, polygon: Polygon) {
// show where the user clicked
tappedLocationGraphic.geometry = mapPoint
// use the geometry engine to get the nearest vertex
val nearestVertexResult =
GeometryEngine.nearestVertex(polygon, mapPoint)
// set the nearest vertex graphic's geometry to the nearest vertex
nearestVertexGraphic.geometry = nearestVertexResult?.coordinate
// use the geometry engine to get the nearest coordinate
val nearestCoordinateResult =
GeometryEngine.nearestCoordinate(polygon, mapPoint)
// set the nearest coordinate graphic's geometry to the nearest coordinate
nearestCoordinateGraphic.geometry = nearestCoordinateResult?.coordinate
// show the distances to the nearest vertex and nearest coordinate
distanceLayout.visibility = View.VISIBLE
// convert distance to miles
val vertexDistance = ((nearestVertexResult?.distance)?.div(5280.0))?.toInt()
val coordinateDistance = ((nearestCoordinateResult?.distance)?.div(5280.0))?.toInt()
// set the distance to the text views
vertexDistanceTextView.text = getString(R.string.nearest_vertex, vertexDistance)
coordinateDistanceTextView.text =
getString(R.string.nearest_coordinate, coordinateDistance)

}

private val Color.Companion.blue: Color
get() {
return fromRgba(0, 0, 255, 255)
}

private val Color.Companion.magenta: Color
get() {
return fromRgba(255, 0, 255, 255)
@Composable
private fun FindNearestVertexApp() {
Surface(color = MaterialTheme.colorScheme.background) {
FindNearestVertexScreen(
sampleName = getString(R.string.find_nearest_vertex_app_name)
)
}

private fun showError(message: String) {
Log.e(localClassName, message)
Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show()
}
}
Loading
Loading