The dictionary symbol style in this sample is constructed from a portal item containing a MIL-STD-2525D symbol dictionary web style. This ArcGIS Web Style is used to build custom applications that incorporate the MIL-STD-2525D symbol dictionary. This style supports a configuration for modeling locations as ordered anchor points or full geometries.
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
174
175
176
177
178
179
180
181
182
183
/* Copyright 2022 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.arcgisruntime.sample.dictionaryrendererwithgraphicsoverlay
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.esri.arcgisruntime.ArcGISRuntimeEnvironment
import com.esri.arcgisruntime.geometry.Multipoint
import com.esri.arcgisruntime.geometry.Point
import com.esri.arcgisruntime.geometry.PointCollection
import com.esri.arcgisruntime.geometry.SpatialReference
import com.esri.arcgisruntime.loadable.LoadStatus
import com.esri.arcgisruntime.mapping.ArcGISMap
import com.esri.arcgisruntime.mapping.BasemapStyle
import com.esri.arcgisruntime.mapping.view.Graphic
import com.esri.arcgisruntime.mapping.view.GraphicsOverlay
import com.esri.arcgisruntime.mapping.view.MapView
import com.esri.arcgisruntime.portal.Portal
import com.esri.arcgisruntime.portal.PortalItem
import com.esri.arcgisruntime.sample.dictionaryrendererwithgraphicsoverlay.databinding.ActivityMainBinding
import com.esri.arcgisruntime.symbology.DictionaryRenderer
import com.esri.arcgisruntime.symbology.DictionarySymbolStyle
import org.w3c.dom.Document
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import java.io.File
import javax.xml.parsers.DocumentBuilder
import javax.xml.parsers.DocumentBuilderFactory
classMainActivity : AppCompatActivity() {
privateval TAG = MainActivity::class.java.simpleName
privateval graphicsOverlay: GraphicsOverlay = GraphicsOverlay()
privateval activityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
privateval mapView: MapView by lazy {
activityMainBinding.mapView
}
overridefunonCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(activityMainBinding.root)
// authentication with an API key or named user is required to access basemaps and other// location services ArcGISRuntimeEnvironment.setApiKey(BuildConfig.API_KEY)
// create a map with the BasemapStyle topographicval map = ArcGISMap(BasemapStyle.ARCGIS_TOPOGRAPHIC)
// graphics no longer show after zooming passed this scale graphicsOverlay.minScale = 1000000.0 mapView.graphicsOverlays.add(graphicsOverlay)
// create the dictionary symbol style from the Joint Military Symbology MIL-STD-2525D portal itemval portalItem =
PortalItem(Portal("https://www.arcgis.com/", false), "d815f3bdf6e6452bb8fd153b654c94ca")
val dictionarySymbolStyle = DictionarySymbolStyle(portalItem)
// add done loading listeners to the map and dictionary symbol style and check they have loaded map.addDoneLoadingListener {
dictionarySymbolStyle.addDoneLoadingListener {
if (dictionarySymbolStyle.loadStatus == LoadStatus.LOADED) {
// find the first configuration setting which has the property name "model",// and set its value to "ORDERED ANCHOR POINTS" dictionarySymbolStyle.configurations
.first { it.name.equals("model") }.value = "ORDERED ANCHOR POINTS"// create a new dictionary renderer from the dictionary symbol style to render graphics// with symbol dictionary attributes and set it to the graphics overlay rendererval dictionaryRenderer = DictionaryRenderer(dictionarySymbolStyle)
graphicsOverlay.renderer = dictionaryRenderer
// parse graphic attributes from an XML file following the mil2525d specificationtry {
val messages: List<Map<String, Any>> = parseMessages()
val graphics: MutableList<Graphic> = mutableListOf()
// create graphics with attributes and add to graphics overlay messages.mapTo(graphics) { createGraphic(it) }
graphicsOverlay.graphics.addAll(graphics)
// set the viewpoint to the extent of the graphics overlay mapView.setViewpointGeometryAsync(graphicsOverlay.extent)
} catch (e: Exception) {
val message = "Error parsing messages: ${e.message}" Log.e(TAG, message)
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
} else {
val message =
"Failed to load symbol style: ${dictionarySymbolStyle.loadError.cause?.message}" Log.e(TAG, message)
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
// load the dictionary symbol style once the map has loaded dictionarySymbolStyle.loadAsync()
}
// set the map to be displayed in the layout's MapView mapView.map = map
}
/**
* Parses a XML file following the mil2525d specification and creates a message for each block of attributes found.
*/privatefunparseMessages(): List<Map<String, Any>> {
val mil2525dFile = File(getExternalFilesDir(null)?.path + "/Mil2525DMessages.xml")
val documentBuilderFactory: DocumentBuilderFactory? = DocumentBuilderFactory.newInstance()
val documentBuilder: DocumentBuilder? = documentBuilderFactory?.newDocumentBuilder()
val document: Document? = documentBuilder?.parse(mil2525dFile)
document?.documentElement?.normalize()
val messages: MutableList<Map<String, Any>> = ArrayList()
if (document != null) {
for (i in0 until document.getElementsByTagName("message").length) {
val message: Node = document.getElementsByTagName("message").item(i)
val attributes: MutableMap<String, Any> = HashMap()
val childNodes: NodeList = message.childNodes
for (j in0 until childNodes.length) {
attributes[childNodes.item(j).nodeName] = childNodes.item(j).textContent
}
messages.add(attributes)
}
}
return messages
}
/**
* Creates a graphic using a symbol dictionary and the attributes that were passed.
* [attributes] tells symbol dictionary what symbol to apply to graphic
*/privatefuncreateGraphic(attributes: Map<String, Any>): Graphic {
// get spatial referenceval sr = SpatialReference.create((attributes["_wkid"] as String).toInt())
// get points from the coordinate string in the "_control_points" attribute (delimited with ';')val points = PointCollection(sr)
val coordinates = (attributes["_control_points"] as String).split(";").toMutableList()
// if the "_control_points" ends with ';' then a blank coordinate is created, it needs to be removedif (coordinates.last().trim() == "")
coordinates.removeAt(coordinates.lastIndex)
// split the coordinates and assign them to each point using the spatial reference coordinates
.asSequence()
.map { it.split(",").toTypedArray() }
.mapTo(points) { Point(it[0].toDouble(), it[1].toDouble(), sr) }
// return a graphic with multipoint geometryreturn Graphic(Multipoint(points), attributes)
}
overridefunonPause() {
mapView.pause()
super.onPause()
}
overridefunonResume() {
super.onResume()
mapView.resume()
}
overridefunonDestroy() {
mapView.dispose()
super.onDestroy()
}
}