Convert features into graphics to show them with mil2525d symbols.

Use case
A dictionary renderer uses a style file along with a rule engine to display advanced symbology. This is useful for displaying features using precise military symbology.
How to use the sample
Pan and zoom around the map. Observe the displayed military symbology on the map.
How it works
- Create a
GeodatabaseusingGeodatabase(geodatabasePath). - Load the geodatabase asynchronously using
Geodatabase::load(). - Instantiate a
DictionarySymbolStyleusingDictionarySymbolStyle::createFromFile(stylePath). - Wait for geodatabase to completely load by connecting to
Geodatabase::loadStatusChangedsignal. - Cycle through each
GeodatabaseFeatureTablefrom the geodatabase usingGeodatabase::geodatabaseFeatureTables(). - Create a
FeatureLayerfrom each table within the geodatabase usingFeatureLayer(GeodatabaseFeatureTable). - Load the feature layer asynchronously with
FeatureLayer::load(). - Wait for each layer to load using
FeatureLayer::loadStatusChanged. - After the last layer has loaded, then create a new
Envelopefrom a union of the extents of all layers.- Set the envelope to be the
Viewpointof the map view usingMapView::setViewpointGeometryAsync(Envelope).
- Set the envelope to be the
- Add the feature layer to map using
Map::operationalLayers()->append(FeatureLayer). - Create
DictionaryRenderer(DictionarySymbolStyle)and attach to the feature layer usingFeatureLayer::setRenderer(DictionaryRenderer).
Relevant API
- DictionaryRenderer
- DictionarySymbolStyle
Offline Data
Read more about how to set up the sample’s offline data here.
| Link | Local Location |
|---|---|
| Mil2525d Stylx File | <userhome>/ArcGIS/Runtime/Data/styles/arcade_style/mil2525d.stylx |
| Military Overlay geodatabase | <userhome>/ArcGIS/Runtime/Data/geodatabase/militaryoverlay.geodatabase |
Tags
military, symbol
Sample Code
// [WriteFile Name=FeatureLayerDictionaryRenderer, Category=Features]// [Legal]// Copyright 2016 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.// [Legal]
#ifdef PCH_BUILD#include "pch.hpp"#endif // PCH_BUILD
// sample headers#include "FeatureLayerDictionaryRenderer.h"
// ArcGIS Maps SDK headers#include "DictionaryRenderer.h"#include "DictionarySymbolStyle.h"#include "Envelope.h"#include "FeatureLayer.h"#include "Geodatabase.h"#include "GeodatabaseFeatureTable.h"#include "GeometryEngine.h"#include "LayerListModel.h"#include "Map.h"#include "MapQuickView.h"#include "MapTypes.h"
// Qt headers#include <QFuture>#include <QStandardPaths>#include <QtCore/qglobal.h>
using namespace Esri::ArcGISRuntime;
// helper method to get cross platform data pathnamespace{ QString defaultDataPath() { QString dataPath;
#ifdef Q_OS_IOS dataPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); #else dataPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); #endif
return dataPath; }} // namespace
FeatureLayerDictionaryRenderer::FeatureLayerDictionaryRenderer(QQuickItem* parent) : QQuickItem(parent), m_dataPath(defaultDataPath() + "/ArcGIS/Runtime/Data"){}
FeatureLayerDictionaryRenderer::~FeatureLayerDictionaryRenderer() = default;
void FeatureLayerDictionaryRenderer::init(){ qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView"); qmlRegisterType<FeatureLayerDictionaryRenderer>("Esri.Samples", 1, 0, "FeatureLayerDictionaryRendererSample");}
void FeatureLayerDictionaryRenderer::componentComplete(){ QQuickItem::componentComplete();
m_mapView = findChild<MapQuickView*>("mapView"); // Create a map using the topo basemap Map* map = new Map(BasemapStyle::ArcGISTopographic, this); // set map on the map view m_mapView->setMap(map);
m_geodatabase = new Geodatabase(m_dataPath + "/geodatabase/militaryoverlay.geodatabase", this);
connect(m_geodatabase, &Geodatabase::loadStatusChanged, this, [this](LoadStatus gdbLoadStatus) { if (gdbLoadStatus == LoadStatus::Loaded) { /** * If the field names in your data don't match the contents of DictionarySymbolStyle::symbologyFieldNames(), * you must add key-value pairs to a QMap<QString, QString> and include this QMap when calling the * DictionaryRenderer constructor. The keys and values are like this: * * "dictionaryFieldName1": "myFieldName1" * "dictionaryFieldName2": "myFieldName2" * * The same principle applies to DictionarySymbolStyle::textFieldNames() for text attributes that appear * as part of military symbols. * * The following commented-out code demonstrates one way to do it, in a scenario where the dictionary * expects the field name "identity" but the database table contains the field "affiliation" instead, * and where the dictionary expects the field name "uniquedesignation" but the database table contains * the field "uniqueId" instead. */ // QMap<QString, QString> symbologyFieldOverrides; // QMap<QString, QString> textFieldOverrides; // symbologyFieldOverrides["identity"] = "affiliation"; // textFieldOverrides["uniquedesignation"] = "uniqueId";
//! [Create Dictionary Symbol Style Cpp] const QString specType = QStringLiteral("mil2525d"); const QString stylePath = m_dataPath + "/styles/arcade_style/mil2525d.stylx"; DictionarySymbolStyle* dictionarySymbolStyle = DictionarySymbolStyle::createFromFile(stylePath, this); //! [Create Dictionary Symbol Style Cpp]
Q_UNUSED(specType)
const auto tables = m_geodatabase->geodatabaseFeatureTables(); for (GeodatabaseFeatureTable* table : tables) { //! [Apply Dictionary Renderer Feature Layer Cpp] // Create a layer and set the feature table FeatureLayer* layer = new FeatureLayer(table, this);
// Create a dictionary renderer and apply to the layer DictionaryRenderer* renderer = new DictionaryRenderer(dictionarySymbolStyle, this); layer->setRenderer(renderer); //! [Apply Dictionary Renderer Feature Layer Cpp]
// Check to see if all layers have loaded connect(layer, &FeatureLayer::loadStatusChanged, this, [this](LoadStatus layerLoadStatus) { if (layerLoadStatus == LoadStatus::Loaded) { m_loadedLayerCount++;
if (m_loadedLayerCount == m_geodatabase->geodatabaseFeatureTables().length()) { /** * If we get here, all the layers loaded. Union the extents and set * the viewpoint. */ LayerListModel* layers = m_mapView->map()->operationalLayers(); if (layers->size() > 0) { Envelope bbox = layers->at(0)->fullExtent(); for (int j = 1; j < layers->size(); j++) { bbox = GeometryEngine::unionOf(bbox, layers->at(j)->fullExtent()); } m_mapView->setViewpointGeometryAsync(bbox, 100); }
emit allLayersLoaded(); } } }, Qt::DirectConnection);
/** * Add the layer to the map. Inserting at index 0 puts the layer below previously added * layers. */ m_mapView->map()->operationalLayers()->insert(0, layer); } } }); m_geodatabase->load();}// [WriteFile Name=FeatureLayerDictionaryRenderer, Category=Features]// [Legal]// Copyright 2016 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.// [Legal]
#ifndef FEATURELAYERDICTIONARYRENDERER_H#define FEATURELAYERDICTIONARYRENDERER_H
// Qt headers#include <QQuickItem>
namespace Esri::ArcGISRuntime{ class Geodatabase; class MapQuickView;}
class FeatureLayerDictionaryRenderer : public QQuickItem{ Q_OBJECT
public: explicit FeatureLayerDictionaryRenderer(QQuickItem* parent = nullptr); ~FeatureLayerDictionaryRenderer() override;
void componentComplete() override; static void init();
signals: void allLayersLoaded();
private: QString m_dataPath; int m_loadedLayerCount = 0; Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr; Esri::ArcGISRuntime::Geodatabase* m_geodatabase = nullptr;};
#endif // FEATURELAYERDICTIONARYRENDERER_H// [WriteFile Name=FeatureLayerDictionaryRenderer, Category=Features]// [Legal]// Copyright 2016 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.// [Legal]
import QtQuickimport QtQuick.Controlsimport Esri.Samples
FeatureLayerDictionaryRendererSample { id: featureLayerDictionaryRendererSample width: 800 height: 600
// Create MapView here, and create its Map in C++ code MapView { objectName: "mapView" anchors.fill: parent
Component.onCompleted: { // Set the focus on MapView to initially enable keyboard navigation forceActiveFocus(); } }
ProgressBar { id: progressBar_loading anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom margins: 5 } indeterminate: true }
onAllLayersLoaded: { progressBar_loading.visible = false; }}// [Legal]// Copyright 2015-2016 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.// [Legal]
// sample headers#include "FeatureLayerDictionaryRenderer.h"
// ArcGIS Maps SDK headers#include "ArcGISRuntimeEnvironment.h"
// Qt headers#include <QDir>#include <QGuiApplication>#include <QQmlEngine>#include <QQuickView>
// Platform specific headers#ifdef Q_OS_WIN#include <Windows.h>#endif
#define STRINGIZE(x) #x#define QUOTE(x) STRINGIZE(x)
int main(int argc, char *argv[]){ Esri::ArcGISRuntime::ArcGISRuntimeEnvironment::setUseLegacyAuthentication(false); QGuiApplication app(argc, argv); app.setApplicationName(QString("FeatureLayerDictionaryRenderer"));
// Use of ArcGIS location services, such as basemap styles, geocoding, and routing services, // requires an access token. For more information see // https://links.esri.com/arcgis-runtime-security-auth.
// The following methods grant an access token:
// 1. User authentication: Grants a temporary access token associated with a user's ArcGIS account. // To generate a token, a user logs in to the app with an ArcGIS account that is part of an // organization in ArcGIS Online or ArcGIS Enterprise.
// 2. API key authentication: Get a long-lived access token that gives your application access to // ArcGIS location services. Go to the tutorial at https://links.esri.com/create-an-api-key. // Copy the API Key access token.
const QString accessToken = QString("");
if (accessToken.isEmpty()) { qWarning() << "Use of ArcGIS location services, such as the basemap styles service, requires" << "you to authenticate with an ArcGIS account or set the API Key property."; } else { Esri::ArcGISRuntime::ArcGISRuntimeEnvironment::setApiKey(accessToken); } // Initialize the sample FeatureLayerDictionaryRenderer::init();
// Initialize application view QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView);
// Add the import Path view.engine()->addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml"));
QString arcGISRuntimeImportPath = QUOTE(ARCGIS_RUNTIME_IMPORT_PATH);
#if defined(LINUX_PLATFORM_REPLACEMENT) // on some linux platforms the string 'linux' is replaced with 1 // fix the replacement paths which were created QString replaceString = QUOTE(LINUX_PLATFORM_REPLACEMENT); arcGISRuntimeImportPath = arcGISRuntimeImportPath.replace(replaceString, "linux", Qt::CaseSensitive); #endif
// Add the Runtime and Extras path view.engine()->addImportPath(arcGISRuntimeImportPath);
// Set the source view.setSource(QUrl("qrc:/Samples/Features/FeatureLayerDictionaryRenderer/FeatureLayerDictionaryRenderer.qml"));
view.show();
return app.exec();}