Show coordinates in multiple formats

View on GitHubSample viewer app

Format coordinates in a variety of common notations.

Images of Show coordinates in multiple formats

Use case

The coordinate formatter can format a map location in WGS84 in a number of common coordinate notations. Parsing one of these formats to a location is also supported. Formats include decimal degrees; degrees, minutes, seconds; Universal Transverse Mercator (UTM), and United States National Grid (USNG).

How to use the sample

Tap on the map to see a marker with the tapped location's coordinate formatted in 4 different ways. You can also put a coordinate string in any of these formats in the text field. Hit Enter and the coordinate string will be parsed to a map location which the marker will move to.

How it works

  1. Get or create a map Point with a spatial reference.
  2. Use one of the static "to" methods on CoordinateFormatter such as CoordinateFormatter.toLatitudeLongitudeOrNull(point = newLocation, format = LatitudeLongitudeFormat.DecimalDegrees, decimalPlaces = 4) to get the formatted string.
  3. To go from a formatted string to a Point, use one of the "from" static methods like CoordinateFormatter.fromUtmOrNull(coordinates = coordinateNotation, utmConversionMode = UtmConversionMode.LatitudeBandIndicators, spatialReference = null).

Relevant API

  • CoordinateFormatter
  • CoordinateFormatter.LatitudeLongitudeFormat
  • CoordinateFormatter.UtmConversionMode

Additional information

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

Tags

convert, coordinate, decimal degrees, degree minutes seconds, format, geoview-compose, latitude, longitude, toolkit, USNG, UTM

Sample Code

MapViewModel.ktMapViewModel.ktMainActivity.ktMainScreen.ktCoordinatesLayout.kt
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/* Copyright 2023 Esri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.esri.arcgismaps.sample.showcoordinatesinmultipleformats.components

import android.app.Application
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.AndroidViewModel
import com.arcgismaps.Color
import com.arcgismaps.geometry.CoordinateFormatter
import com.arcgismaps.geometry.LatitudeLongitudeFormat
import com.arcgismaps.geometry.Point
import com.arcgismaps.geometry.SpatialReference
import com.arcgismaps.geometry.UtmConversionMode
import com.arcgismaps.mapping.symbology.SimpleMarkerSymbol
import com.arcgismaps.mapping.symbology.SimpleMarkerSymbolStyle
import com.arcgismaps.mapping.view.Graphic
import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel

class MapViewModel(application: Application) : AndroidViewModel(application) {

    var decimalDegrees by mutableStateOf("")
        private set
    var degreesMinutesSeconds by mutableStateOf("")
        private set

    var utm by mutableStateOf("")
        private set

    var usng by mutableStateOf("")
        private set

    // create a ViewModel to handle dialog interactions
    val messageDialogVM: MessageDialogViewModel = MessageDialogViewModel()

    // set up a graphic to indicate where the coordinates relate to, with an initial location
    val initialPoint = Point(0.0, 0.0, SpatialReference.wgs84())

    val coordinateLocationGraphic = Graphic(
        geometry = initialPoint,
        symbol = SimpleMarkerSymbol(
            style = SimpleMarkerSymbolStyle.Cross,
            color = Color.fromRgba(255, 255, 0, 255),
            size = 20f
        )
    )

    /**
     * Uses CoordinateFormatter to update the UI with coordinate notation strings based on the
     * given [newLocation] point to convert to coordinate notations
     */
    fun toCoordinateNotationFromPoint(newLocation: Point) {
        coordinateLocationGraphic.geometry = newLocation
        // use CoordinateFormatter to convert to Latitude Longitude, formatted as Decimal Degrees
        decimalDegrees = CoordinateFormatter.toLatitudeLongitudeOrNull(
            point = newLocation,
            format = LatitudeLongitudeFormat.DecimalDegrees,
            decimalPlaces = 4
        ) ?: return messageDialogVM.showMessageDialog("Failed to convert from point DD coordinate")

        // use CoordinateFormatter to convert to Latitude Longitude, formatted as Degrees, Minutes, Seconds
        degreesMinutesSeconds = CoordinateFormatter.toLatitudeLongitudeOrNull(
            point = newLocation,
            format = LatitudeLongitudeFormat.DegreesMinutesSeconds,
            decimalPlaces = 4
        ) ?: return messageDialogVM.showMessageDialog("Failed to convert from point DMS coordinate")

        // use CoordinateFormatter to convert to Universal Transverse Mercator, using latitudinal bands indicator
        utm = CoordinateFormatter.toUtmOrNull(
            point = newLocation,
            utmConversionMode = UtmConversionMode.LatitudeBandIndicators,
            addSpaces = true
        ) ?: return messageDialogVM.showMessageDialog("Failed to convert from point UTM coordinate")

        // use CoordinateFormatter to convert to United States National Grid (USNG)
        usng = CoordinateFormatter.toUsngOrNull(
            point = newLocation,
            precision = 4,
            addSpaces = true,
        ) ?: return messageDialogVM.showMessageDialog("Failed to convert from point USNG coordinate")
    }

    /**
     * Uses CoordinateFormatter to update the graphic in the map from the given [coordinateNotation]
     * string entered by the user. Also calls corresponding method to update all the remaining
     * [coordinateNotation] strings using the notation [notationType].
     */
    fun fromCoordinateNotationToPoint(notationType: NotationType, coordinateNotation: String) {
        // ignore empty input coordinate notation strings, do not update UI
        if (coordinateNotation.isEmpty()) return
        val convertedPoint: Point = when (notationType) {
            NotationType.DMS, NotationType.DD -> {
                // use CoordinateFormatter to parse Latitude Longitude - different numeric notations (Decimal Degrees;
                // Degrees, Minutes, Seconds; Degrees, Decimal Minutes) can all be passed to this same method
                CoordinateFormatter.fromLatitudeLongitudeOrNull(
                    coordinates = coordinateNotation,
                    spatialReference = null
                ) ?: return messageDialogVM.showMessageDialog("Failed to convert DMS/DD coordinate to point")
            }

            NotationType.UTM -> {
                // use CoordinateFormatter to parse UTM coordinates
                CoordinateFormatter.fromUtmOrNull(
                    coordinates = coordinateNotation,
                    utmConversionMode = UtmConversionMode.LatitudeBandIndicators,
                    spatialReference = null
                ) ?: return messageDialogVM.showMessageDialog("Failed to convert UTM coordinate to point")
            }

            NotationType.USNG -> {
                // use CoordinateFormatter to parse US National Grid coordinates
                CoordinateFormatter.fromUsngOrNull(
                    coordinates = coordinateNotation,
                    spatialReference = null
                ) ?: return messageDialogVM.showMessageDialog("Failed to convert USNG coordinate to point")
            }
        }

        // update the location shown in the map
        toCoordinateNotationFromPoint(convertedPoint)
    }

    /**
     * Coordinate notations supported by this sample
     */
    enum class NotationType {
        DMS, DD, UTM, USNG
    }

    /**
     * Set's [decimalDegrees] entered in the text field to the [inputString]
     */
    fun setDecimalDegreesCoordinate(inputString: String) {
        decimalDegrees = inputString
    }

    /**
     * Set's [degreesMinutesSeconds] entered in the text field to the [inputString]
     */
    fun degreesMinutesSecondsCoordinate(inputString: String) {
        degreesMinutesSeconds = inputString
    }

    /**
     * Set's [utm] entered in the text field to the [inputString]
     */
    fun setUTMCoordinate(inputString: String) {
        utm = inputString

    }

    /**
     * Set's [usng] entered in the text field to the [inputString]
     */
    fun setUSNGDegreesCoordinate(inputString: String) {
        usng = inputString
    }
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.