|
BLOG
|
In this blog I’ll be sharing techniques for writing efficient applications for rending large numbers of graphics which are being updated very frequently on a map. The ArcGIS Runtime API for Java is used to demonstrate these techniques, but if you are a developer using another ArcGIS Runtime platform such as .NET, iOS, Qt or Android then the same techniques still apply. Situation awareness style applications display the location of moving assets in a central control room, where a common operational picture needs to be viewed to help with operational decision making. These moving assets can range from tens to thousands in number, depending on what assets are being tracked. I’ve seen this style of application used in control centres for police, ambulance, fire service and military command and control settings for example. Regardless of the specific use, there is a common theme for how these applications work. There is usually a feed or stream of data coming from a separate system delivering individual messages which give a status and position updates for items to be displayed on a map display. I will step through an application for an imaginary control centre for despatching and monitoring thousands of emergency vehicles. We will get regular system messages updating vehicle positions and the status of the vehicle which includes states for: Available for new call On route to call Attending call location Off duty These different vehicle states will be used to show how these vehicle positions are rendered to the map. Graphics overlay overview As the data we want to display updates very frequently, it is not suitable to be stored in a data store such as a feature service (which would be backed by a database in the background). In this case, map points are best displayed as graphics in a graphics overlay, which are stored in-memory and are naturally able to be updated frequently (potentially many times a second), whilst still having a fast-responding application when panning and zooming around to explore the data. Going back to basics so we all understand where these graphics live, we should all be familiar with the UI control which displays your mapView (2D visualization) or your sceneView (3D visualization). These controls have a collection where we can store several graphics overlays, each of which can contain multiple graphics. Each graphic is defined by the following items: A geometry (polyline, point or polygon typically) A symbol to define how it is shown on the map (a red dot for example) An optional set of attributes (like fields in a database record) How to organize your graphics in a graphics overlay Graphics overlays are incredibly flexible in that you can use them to store all sorts of graphics regardless of their geometry type. Potentially you could have many thousands of graphics all with different attributes and geometry types all thrown into the same graphics overlay. In terms of rendering performance, to a certain extent this is fine, but you will reach a point where some optimisation is needed as you may see a degradation of performance. If you do see performance issues, I’ve listed some potential improvements you can make: Store geometry types in their own graphics overlays. For example, if you have some points and polygons, these should be stored in separate graphics overlays. If you have complex geometries (polylines or polygons with lots of vertices), you may find that switching the rendering mode of your graphics overlay from Dynamic to Static will improve performance. Static rendering doesn’t look as nice when you are zooming in and out, but it sometimes helps especially if you have a low-end graphics card. The same applies sometimes to point geometries too if you find you are seeing performance issues, but usually these perform fine in Dynamic mode. Renderers would be appropriate to mention here too briefly, since you then go into more detail about them in the next section. Handy having an easy refer to guide here! Create graphics using a renderer The simplest way of creating a graphic to display a dot on a map is as follows: // create a red (0xFFFF0000) circle simple marker symbol
SimpleMarkerSymbol redCircleSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE, 0xFFFF0000, 10);
// create graphics and add to graphics overlay
Graphic graphic;
graphic = new Graphic(new Point(-2.72, 56.065, SPATIAL_REFERENCE), redCircleSymbol);
graphicsOverlay.getGraphics().add(graphic); This code has been taken from a sample which you can see in full here. Note that the graphic contains a new geometry (in this case, a point) and a new symbol. For a small number of graphics this is fine, but if you are adding lots of graphics to your application which share the same symbol then it is faster and more efficient on your hardware resources to use a renderer of some sort. Renderers allow you to define the symbol (or symbols) used to display a graphic in a single place so they can be used multiple times. Depending on your application there are a few different renders to help you do this Simple Renderer Unique value renderer Class breaks renderer Going back to the example where I want to draw a vehicle according to its current operational state, I would choose a Unique value renderer which is associated with an attribute in my graphic. Workflow for updating graphics To demonstrate these techniques in action, I have created a sample in a git repository which has a class which generates vehicle update messages. These messages are generated many times a second for each simulated vehicle and come in the following format: Update Message: VehicleID : Unique identifier for vehicle Position: A point showing the current position Status: Current vehicle status When receiving these messages which in my app come through at a rate of many thousands a second, we will need a quick way of looking up the graphic representation of a vehicle from that unique vehicle identifier. Although it is possible to store the vehicle ID as an attribute in a graphic, and stream through each graphic’s attributes to find the vehicle ID, this doesn’t give you access to a fast way of obtaining an individual graphic to updates its position. I’ve found that using a Java HashMap class to look up the graphic to be nice and fast, as the HashMap is simply a key-value pair structure, but the lookup using the key is very fast and efficient: private HashMap<String, Graphic> vehicles = new HashMap<>(); Now we have this structure, the processing of messages is simple. In short when we receive a message , we establish if a graphic exists for the vehicle. If it exists, we apply a new point geometry to update its location, and if it doesn’t then we just add a new graphic and reference it to the HashMap. The following code snippet from my sample app shows how simple this is: /**
* Method to update a graphic from a vehicle update message. If the message has come from a new vehicle
* then a new graphic will be added.
* @param updateMessage
*/
private void UpdateGraphic(UpdateMessage updateMessage) {
Point position = updateMessage.getPosition();
// does graphic already exist?
if (vehicles.containsKey(updateMessage.getVehicleID())) {
//update the existing graphic with a new point geometry
Graphic existingVehicle = vehicles.get(updateMessage.getVehicleID());
existingVehicle.setGeometry(updateMessage.getPosition());
} else {
// create new graphic
Graphic vehicleGraphic = new Graphic(position);
vehicleGraphic.getAttributes().put("Status", updateMessage.getStatus().toString());
graphicsOverlay.getGraphics().add(vehicleGraphic);
// add vehicle graphic to hash map
vehicles.put(updateMessage.getVehicleID(), vehicleGraphic);
}
} In stress testing I’ve managed to easily display 50,000 graphics all of which are being updated at a rate of 20ms. This was achieved with a standard spec laptop; I’d expect more if you had a fancy gaming spec desktop machine! If you find this demo application of use for getting your situation awareness style applications of use or have any suggestions on useful additions I can make, please let me know; I’m always keen to hear from our developer customers.
... View more
06-16-2021
03:16 AM
|
3
|
0
|
8516
|
|
POST
|
If you configure your build script so it targets the intended architecture which is likely to be ARM you can reduce this quite a lot. I can see you are including x86 (used for emulators), ARM 32bit and ARM 64bit. Read this article https://developers.arcgis.com/android/license-and-deployment/reducing-your-apk-size/ and you'll get a better idea of what you need to do.
... View more
06-15-2021
01:29 AM
|
0
|
1
|
4693
|
|
POST
|
@ShaolinShowdown I'm going to try and find someone who know a little more about ArcGIS Pro to answer these specific questions.
... View more
06-14-2021
08:18 AM
|
1
|
0
|
3465
|
|
POST
|
You can create your own stylx files with ArcGIS Pro which can contain your own collection of symbols for use in your own app. The symbols in the style file can be used as separate entities or you can combine them to make up composite symbols. There is a fun sample showing the use of a custom style file here where you can combine different symbols to make up funny faces: https://github.com/Esri/arcgis-runtime-samples-java/tree/main/symbology/read-symbols-from-mobile-style-file In Pro when you create a stylx file for use in a runtime application you need to remember to create a mobile style file. This is a good blog post explaining the process: https://community.esri.com/t5/arcgis-runtime-sdks-blog/using-custom-pro-symbols-in-arcgis-runtime/ba-p/888699 If you are wanting to create your own symbol shapes, then I believe you will need something like an SVG editor before you bring them into Pro. There is another blog post here which explains a little more about 2525 specific customisation https://www.esri.com/arcgis-blog/products/arcgis-pro/mapping/create-custom-dictionary-styles-for-arcgis/ Does this help?
... View more
06-10-2021
02:57 AM
|
2
|
0
|
3486
|
|
POST
|
The limited experience in our team of SceneBuilder working in IntelliJ is that we just end up with a blank screen and didn't function. Running it as a separate app outside of IntelliJ is the only way I've seen it working. A quick look on StackOverflow came up with https://stackoverflow.com/questions/63425513/scenebuilder-not-loading-in-intellij
... View more
06-08-2021
05:40 AM
|
1
|
0
|
18948
|
|
POST
|
If you ever find there are deficiencies in the JavaDoc we supply with the API, let me know. We aim to have nicely documented JavaDoc which will help our developer community, but I've no doubt there are imperfections which could be improved.
... View more
06-02-2021
08:25 AM
|
0
|
0
|
2416
|
|
POST
|
You can identify this state in code by adding load listener to the map which is trying to use your bad API key. I've done this very crudely in the code below: // authentication with an API key or named user is required to access basemaps and other location services
ArcGISRuntimeEnvironment.setApiKey("bad API key");
// create a map with the standard imagery basemap style
ArcGISMap map = new ArcGISMap(BasemapStyle.ARCGIS_IMAGERY);
map.addDoneLoadingListener(()-> {
System.out.println("load status" + map.getLoadStatus());
if (map.getLoadStatus() == LoadStatus.FAILED_TO_LOAD) {
System.out.println("error " + map.getLoadError().getCause());
}
});
// create a map view and set the map to it
mapView = new MapView();
mapView.setMap(map); We don't throw a specific error for this condition (IOException), but the cause comes up as you spotted in the console window. Does this help?
... View more
06-01-2021
12:00 PM
|
1
|
1
|
1954
|
|
POST
|
The JavaDoc files are in the same place as the jar files. So if you are using the latest version of the SDK (version 100.11.0), you can get them from our maven server here: https://esri.jfrog.io/artifactory/arcgis/com/esri/arcgisruntime/arcgis-java/100.11.0/ We don't publish the source code for the jar files. Even if you cracked it open you are not going to be able to debug very far into the core logic as this is written in C++ and contained in the supplied libraries compiled for the platform you are running on. .so files for linux .dll for Windows .dylib for macOS The jar you use from us mostly contains JNI interop code. The reason we write most of our core logic in C++ is that Java isn't the only development platform we support. We also support .Net, Qt (QML), iOS Swift and Android (Kotlin and Java) developers and compiling from our common C++ codebase we can provide a consistent experience on all platforms. Does this help?
... View more
06-01-2021
11:39 AM
|
0
|
2
|
2422
|
|
POST
|
Take a look at the RasterLayer which can be used to add most types of raster data to your map or scene based application. with DEM data you might need to look at adding a ColorMap to see it rendered as you want, but in the first instance just try adding it as a layer. There is a sample which uses some DEM data in a simple app. It also shows you how to identify raster cell data to get the actual height values out of the dataset. This is a 2D Map app, but the same techniques should work for a 3D scene based application. Does this help?
... View more
06-01-2021
11:28 AM
|
0
|
0
|
1113
|
|
POST
|
We don't directly support GPX data, but its pretty easy to write your own importer. If you look at the file format / specification you will see all the data is XML. https://wiki.openstreetmap.org/wiki/GPX So if you can read a track as shown in the link above you will set a set of points which make up a track. <trk><name>Example gpx</name><number>1</number><trkseg>
<trkpt lat="46.57608333" lon="8.89241667"><ele>2376</ele><time>2007-10-14T10:09:57Z</time></trkpt>
<trkpt lat="46.57619444" lon="8.89252778"><ele>2375</ele><time>2007-10-14T10:10:52Z</time></trkpt>
<trkpt lat="46.57641667" lon="8.89266667"><ele>2372</ele><time>2007-10-14T10:12:39Z</time></trkpt>
<trkpt lat="46.57650000" lon="8.89280556"><ele>2373</ele><time>2007-10-14T10:13:12Z</time></trkpt>
<trkpt lat="46.57638889" lon="8.89302778"><ele>2374</ele><time>2007-10-14T10:13:20Z</time></trkpt>
<trkpt lat="46.57652778" lon="8.89322222"><ele>2375</ele><time>2007-10-14T10:13:48Z</time></trkpt>
<trkpt lat="46.57661111" lon="8.89344444"><ele>2376</ele><time>2007-10-14T10:14:08Z</time></trkpt>
</trkseg></trk> I've hard coded the points into a polyline as shown: // points for the track (remember that longitute is X and latitude is Y!
Point pt1 = new Point(8.89241667, 46.57608333, 2376, SpatialReferences.getWgs84());
Point pt2 = new Point(8.89252778, 46.57619444, 2375, SpatialReferences.getWgs84());
Point pt3 = new Point(8.89266667, 46.57641667, 2372, SpatialReferences.getWgs84());
Point pt4 = new Point(8.89280556, 46.57650000, 2373, SpatialReferences.getWgs84());
Point pt5 = new Point(8.89302778, 46.57638889, 2374, SpatialReferences.getWgs84());
Point pt6 = new Point(8.89322222, 46.57652778, 2375, SpatialReferences.getWgs84());
Point pt7 = new Point(8.89344444, 46.57661111, 2376, SpatialReferences.getWgs84());
// collection for the points
PointCollection points = new PointCollection(SpatialReferences.getWgs84());
points.add(pt1);
points.add(pt2);
points.add(pt3);
points.add(pt4);
points.add(pt5);
points.add(pt6);
points.add(pt7);
// create polyline from the points in the collection
Polyline trackGeometrty = new Polyline(points);
// graphic overlay in a map view (could be a scene view for 3D)
graphicsOverlay = new GraphicsOverlay();
mapView.getGraphicsOverlays().add(graphicsOverlay);
// symbol for line
SimpleLineSymbol lineSymbol = new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, 0xFF00FF00,5);
// graphic from style and polyline
Graphic graphic = new Graphic(trackGeometrty, lineSymbol);
// finally add graphic to graphic overlay
graphicsOverlay.getGraphics().add(graphic); The end result is this: So all you need to do is read the xml file remembering that longitude is X and latitude is Y as they are often mixed up. Does this help?
... View more
05-18-2021
06:18 AM
|
0
|
0
|
1653
|
|
POST
|
GeoPackages are separate to shapefiles so if you have specific questions about GeoPackages then its best if you start a fresh question. This makes the forum easier to search for answers. This sample shows how to display the contents of a GeoPackage https://github.com/Esri/arcgis-runtime-samples-java/tree/master/feature_layers/feature-layer-geopackage
... View more
05-13-2021
04:29 AM
|
0
|
0
|
4115
|
|
POST
|
I don't really understand your question. Are you having trouble running an app from Maven in Eclipse? Do you have any error messages or other details you can share? If you've not already looked at it, we do have a git repository showing a very basic Java application which can be built from a maven script here. There are specific instructions for running in in Eclipse in the readme. If this doesn't help, please share as much information about the issue you are experiencing and I'll try to guide you although my knowledge of IntelliJ and gradle scripting is much better.
... View more
05-06-2021
09:31 AM
|
0
|
0
|
1333
|
|
POST
|
From your picture it looks like you have a number of point based graphics which you have added. Assuming you have a shapefile (potentially an empty one which is set up for point geometries) you can do something like this: - Loop through the graphics in your graphics overlay and for each graphic obtain the geometry (a point in your example). - For each geometry you will need to create a feature which matches the schema of your shape file. A feature will contain the geometry and optionally attributes too. - Using the ShapefileFeatureTable class use the addFeature method https://developers.arcgis.com/java/api-reference/reference/com/esri/arcgisruntime/data/FeatureTable.html#addFeatureAsync(com.esri.arcgisruntime.data.Feature). (Note that ShapefileFeatureTable inherits from FeatureTable) There isn't a specific sample showing how to add features to a shapefile, but essentially its the same for any data source so these references will help: - https://developers.arcgis.com/java/query-and-edit/edit/ - https://developers.arcgis.com/java/sample-code/add-features/ As for browsing shapefiles, just use the JavaFX file chooser and look for .shp files.
... View more
05-06-2021
06:13 AM
|
0
|
2
|
4162
|
|
POST
|
I'm not completely sure of your workflow here, but how are you planning on drawing your sketches? Are you planning on using graphics and maybe the sketch editor like in this sample? If this is your plan, then you could write some code to move these geometries into an existing shapefile. There is API which allows you to display and potentially edit shapefiles. The sample here shows how to open a shapefile. The ShapefileFeatureTable class has methods for adding new features. Remember that a shapefile can only contain one type of geometry. For example if a shapefile schema is for points, then you can't write lines or polygons into the same file. I would however consider if you really need to use the shapefile format here. There are potentially better workflows for editing and sharing data, but I'd need to know a little more about the bigger picture of what you are trying to achieve.
... View more
05-06-2021
02:58 AM
|
0
|
4
|
4183
|
|
POST
|
The Popup class isn't a UI component. To display the data you need to write something yourself. This can be in your own UI container, or you could consider using the Callout which is shown here: https://developers.arcgis.com/java/sample-code/show-callout/ Does this help?
... View more
05-06-2021
02:37 AM
|
0
|
0
|
1198
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 05-12-2026 01:35 AM | |
| 2 | 05-07-2026 06:59 AM | |
| 1 | 08-13-2024 05:17 AM | |
| 1 | 07-10-2024 01:50 AM | |
| 1 | 04-22-2024 01:21 AM |
| Online Status |
Offline
|
| Date Last Visited |
05-13-2026
06:46 AM
|