Discover connected features in a utility network using connected, subnetwork, upstream, and downstream traces.

Use case
You can use a trace to visualize and validate the network topology of a utility network for quality assurance. Subnetwork traces are used for validating whether subnetworks, such as circuits or zones, are defined or edited appropriately.
How to use the sample
Tap on one or more features while ‘Add starting locations’ or ‘Add barriers’ is selected. When a junction feature is identified, you may be prompted to select a terminal. When an edge feature is identified, the distance from the tapped location to the beginning of the edge feature will be computed. Select the type of trace using the drop down menu. Click ‘Trace’ to initiate a trace on the network. Click ‘Reset’ to clear the trace parameters and start over.
How it works
- Create a
MapViewand connect to itsmouseClickedsignal. - Create and load a
Mapwith a web map item URL that contains aUtilityNetwork. - Get and load the first
UtilityNetworkfrom the web map. - Get the
ServiceGeodatabasefrom the utility network and fetch the lineFeatureLayerfrom theServiceGeodatabase’s tables. - Add a
GraphicsOverlaywith symbology that distinguishes starting locations from barriers. - Identify features on the map and add a
Graphicthat represents its purpose (starting point or barrier) at the location of each identified feature. - Create a
UtilityElementfor the identified feature. - Determine the type of this element using its
NetworkSource::SourceTypeproperty. - If the element is a junction with more than one terminal, display a terminal picker. Then set the junction’s
terminalproperty with the selected terminal. - If an edge, set its
fractionAlongEdgeproperty usingGeometryEngine::fractionAlong. - Add this
UtilityElementto a collection of starting locations or barriers. - Create
UtilityTraceParameterswith the selected trace type along with the collected starting locations and barriers (if applicable). - Set the
UtilityTraceParameters::traceConfigurationwith the utility tier’straceConfigurationproperty. - Run a
UtilityNetwork::traceAsyncwith the specified parameters. - For every
FeatureLayerin the map, select the features using theUtilityElement::objectIdfrom the filtered list ofUtilityElementTraceResult::elements.
Relevant API
- GeometryEngine::fractionAlong
- ServiceGeodatabase
- UtilityAssetType
- UtilityDomainNetwork
- UtilityElement
- UtilityElementTraceResult
- UtilityNetwork
- UtilityNetworkDefinition
- UtilityNetworkSource
- UtilityTerminal
- UtilityTier
- UtilityTraceConfiguration
- UtilityTraceParameters
- UtilityTraceResult
- UtilityTraceType
- UtilityTraversability
About the data
The Naperville Electric Web Map, hosted on ArcGIS Online (authentication required: this is handled within the sample code), contains a utility network used to run the subnetwork-based trace shown in this sample.
Additional information
Using utility network on ArcGIS Enterprise 10.8 requires an ArcGIS Enterprise member account licensed with the Utility Network user type extension. Please refer to the utility network services documentation.
Credentials:
- Username: viewer01
- Password: I68VGU^nMurF
Tags
condition barriers, downstream trace, network analysis, subnetwork trace, trace configuration, traversability, upstream trace, utility network, validate consistency
Sample Code
// [WriteFile Name=TraceUtilityNetwork, Category=UtilityNetwork]// [Legal]// Copyright 2019 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 "TraceUtilityNetwork.h"
// ArcGIS Maps SDK headers#include "ArcGISRuntimeEnvironment.h"#include "ArcGISFeature.h"#include "AttributeListModel.h"#include "Authentication/AuthenticationManager.h"#include "Authentication/ArcGISAuthenticationChallenge.h"#include "Authentication/TokenCredential.h"#include "Envelope.h"#include "Error.h"#include "ErrorException.h"#include "FeatureLayer.h"#include "FeatureQueryResult.h"#include "GeometryEngine.h"#include "Graphic.h"#include "GraphicListModel.h"#include "GraphicsOverlay.h"#include "GraphicsOverlayListModel.h"#include "IdentifyLayerResult.h"#include "LayerListModel.h"#include "Map.h"#include "MapQuickView.h"#include "MapTypes.h"#include "Polyline.h"#include "QueryParameters.h"#include "ServiceFeatureTable.h"#include "ServiceGeodatabase.h"#include "SimpleLineSymbol.h"#include "SimpleMarkerSymbol.h"#include "SpatialReference.h"#include "SymbolTypes.h"#include "UniqueValue.h"#include "UniqueValueListModel.h"#include "UniqueValueRenderer.h"#include "UtilityAssetGroup.h"#include "UtilityAssetType.h"#include "UtilityDomainNetwork.h"#include "UtilityElement.h"#include "UtilityElementTraceResult.h"#include "UtilityNetwork.h"#include "UtilityNetworkDefinition.h"#include "UtilityNetworkListModel.h"#include "UtilityNetworkSource.h"#include "UtilityNetworkTypes.h"#include "UtilityTerminalConfiguration.h"#include "UtilityTier.h"#include "UtilityTraceParameters.h"#include "UtilityTraceResultListModel.h"#include "Viewpoint.h"
// Qt headers#include <QFuture>
// Other headers#include "TaskCanceler.h"
using namespace Esri::ArcGISRuntime;using namespace Esri::ArcGISRuntime::Authentication;
TraceUtilityNetwork::TraceUtilityNetwork(QObject* parent /* = nullptr */): ArcGISAuthenticationChallengeHandler(parent), m_map(new Map(QUrl("https://sampleserver7.arcgisonline.com/portal/home/item.html?id=be0e4637620a453584118107931f718b"), this)), m_startingSymbol(new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Cross, QColor(Qt::green), 20, this)), m_barrierSymbol(new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::X, QColor(Qt::red), 20, this)), m_mediumVoltageSymbol(new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor(Qt::darkCyan), 3, this)), m_lowVoltageSymbol(new SimpleLineSymbol(SimpleLineSymbolStyle::Dash, QColor(Qt::darkCyan), 3, this)), m_serviceGeodatabase(new ServiceGeodatabase(m_serviceUrl, this)), m_graphicParent(new QObject()), m_taskCanceler(std::make_unique<TaskCanceler>()){ ArcGISRuntimeEnvironment::authenticationManager()->setArcGISAuthenticationChallengeHandler(this);
m_map->setInitialViewpoint(Viewpoint(Envelope(-9813547.35557238, 5129980.36635111, -9813185.0602376, 5130215.41254146, SpatialReference::webMercator())));
connect(m_map, &Map::doneLoading, this, &TraceUtilityNetwork::loadUtilityNetwork);}
void TraceUtilityNetwork::createFeatureLayers(){ setBusyIndicator(false);
// Get the feature table from the 4th table (index = 3) in the serviceGeodatabase m_serviceGeodatabase = m_utilityNetwork->serviceGeodatabase(); m_lineFeatureTable = m_serviceGeodatabase->table(3); m_lineLayer = qobject_cast<FeatureLayer*>(m_lineFeatureTable->layer());}
void TraceUtilityNetwork::createRenderers(){ // create unique renderer m_uniqueValueRenderer = new UniqueValueRenderer(this); m_uniqueValueRenderer->setFieldNames(QStringList("ASSETGROUP")); UniqueValue* mediumVoltageUniqueValue = createUniqueValue(QString("Medium Voltage"), m_mediumVoltageSymbol, 5); UniqueValue* lowVoltageUniqueValue = createUniqueValue(QString("Low Voltage"), m_lowVoltageSymbol, 3);
// append to UniqueValueRenderer m_uniqueValueRenderer->uniqueValues()->append(mediumVoltageUniqueValue); m_uniqueValueRenderer->uniqueValues()->append(lowVoltageUniqueValue);
// set unique value renderer to the line layer m_lineLayer->setRenderer(m_uniqueValueRenderer);}
void TraceUtilityNetwork::loadUtilityNetwork(const Error& error){ if (hasErrorOccurred(error)) return;
m_utilityNetwork = m_map->utilityNetworks()->first(); m_utilityNetwork->load();
// Create graphics overlay and append to mapview m_graphicsOverlay = new GraphicsOverlay(this); m_mapView->graphicsOverlays()->append(m_graphicsOverlay);
connect(m_utilityNetwork, &UtilityNetwork::errorOccurred, this, &TraceUtilityNetwork::hasErrorOccurred);
connect(m_utilityNetwork, &UtilityNetwork::doneLoading, this, [this](const Error& error) { if (hasErrorOccurred(error)) return;
createFeatureLayers(); createRenderers(); connectSignals(); });
setBusyIndicator(true);}
bool TraceUtilityNetwork::hasErrorOccurred(const Error& error){ if (error.isEmpty()) return false;
m_dialogText = QString(error.message() + " - " + error.additionalMessage()); emit dialogVisibleChanged(); return true;}
void TraceUtilityNetwork::onTaskFailed_(const Esri::ArcGISRuntime::ErrorException& exception){ m_dialogText = QString(exception.error().message() + " - " + exception.error().additionalMessage()); emit dialogVisibleChanged();}
void TraceUtilityNetwork::connectSignals(){ // identify layers on mouse click connect(m_mapView, &MapQuickView::mouseClicked, this, [this](QMouseEvent& mouseEvent) { if (m_map->loadStatus() != LoadStatus::Loaded) return;
constexpr double tolerance = 10.0; constexpr bool returnPopups = false; m_clickPoint = m_mapView->screenToLocation(mouseEvent.position().x(), mouseEvent.position().y()); m_taskCanceler->addTask(m_mapView->identifyLayersAsync(mouseEvent.position(), tolerance, returnPopups).then(this, [this](const QList<IdentifyLayerResult*>& results) { onIdentifyLayersCompleted_(results); })); });}
TraceUtilityNetwork::~TraceUtilityNetwork() = default;
void TraceUtilityNetwork::init(){ // Register the map view for QML qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView"); qmlRegisterType<TraceUtilityNetwork>("Esri.Samples", 1, 0, "TraceUtilityNetworkSample");}
MapQuickView* TraceUtilityNetwork::mapView() const{ return m_mapView;}
// Set the view (created in QML)void TraceUtilityNetwork::setMapView(MapQuickView* mapView){ if (!mapView || mapView == m_mapView) return;
m_mapView = mapView; m_mapView->setMap(m_map);
emit mapViewChanged();}
void TraceUtilityNetwork::multiTerminalIndex(int index){ if (m_terminals.isEmpty()) return;
if (!m_feature) return;
UtilityElement* element = m_utilityNetwork->createElementWithArcGISFeature(m_feature, m_terminals[index]); updateTraceParams(element);}
void TraceUtilityNetwork::updateTraceParams(UtilityElement* element){ if (m_startingLocationsEnabled) { m_startingLocations.append(element); Graphic* traceLocation = new Graphic(m_clickPoint, m_startingSymbol, m_graphicParent.get()); m_graphicsOverlay->graphics()->append(traceLocation); } else { m_barriers.append(element); Graphic* traceLocation = new Graphic(m_clickPoint, m_barrierSymbol, m_graphicParent.get()); m_graphicsOverlay->graphics()->append(traceLocation); }}
void TraceUtilityNetwork::trace(int index){ setBusyIndicator(true);
delete m_traceParams;
switch (index) { case 0: m_traceParams = new UtilityTraceParameters(UtilityTraceType::Connected, {}, this); break; case 1: m_traceParams = new UtilityTraceParameters(UtilityTraceType::Subnetwork, {}, this); break; case 2: m_traceParams = new UtilityTraceParameters(UtilityTraceType::Upstream, {}, this); break; case 3: m_traceParams = new UtilityTraceParameters(UtilityTraceType::Downstream, {}, this); break; default: return; }
if (m_mediumVoltageTier) m_traceParams->setTraceConfiguration(m_mediumVoltageTier->defaultTraceConfiguration());
m_traceParams->setStartingLocations(m_startingLocations); m_traceParams->setBarriers(m_barriers); // Perform a connected trace on the utility network m_taskCanceler->addTask(m_utilityNetwork->traceAsync(m_traceParams).then(this, [this](QList<UtilityTraceResult*>) { onTraceCompleted_(); }).onFailed([this](const ErrorException& exception) { onTaskFailed_(exception); }));}
void TraceUtilityNetwork::reset(){ m_startingLocations.clear(); m_barriers.clear(); if (m_traceParams) { m_traceParams->setStartingLocations(m_startingLocations); m_traceParams->setBarriers(m_barriers); }
m_graphicsOverlay->graphics()->clear(); m_graphicParent.reset(new QObject());
for (Layer* layer : *m_map->operationalLayers()) { FeatureLayer* featureLayer = dynamic_cast<FeatureLayer*>(layer); if (!featureLayer) return;
featureLayer->clearSelection(); }}
void TraceUtilityNetwork::onIdentifyLayersCompleted_(const QList<IdentifyLayerResult*>& results){ if (results.isEmpty()) { m_dialogText = QString("Could not identify location."); emit dialogTextChanged(); m_dialogVisible = true; emit dialogVisibleChanged(); return; }
// Get domain network const UtilityDomainNetwork* domainNetwork = m_utilityNetwork->definition()->domainNetwork("ElectricDistribution"); m_mediumVoltageTier = domainNetwork->tier("Medium Voltage Radial");
const IdentifyLayerResult* result = results[0]; m_feature = static_cast<ArcGISFeature*>(std::as_const(result)->geoElements()[0]); UtilityElement* element = nullptr; const UtilityNetworkSource* networkSource = m_utilityNetwork->definition()->networkSource(m_feature->featureTable()->tableName());
if (networkSource->sourceType() == UtilityNetworkSourceType::Junction) { m_junctionSelected = true; emit junctionSelectedChanged();
const QString assetGroupFieldName = static_cast<ArcGISFeatureTable*>(m_feature->featureTable())->subtypeField(); const int assetGroupCode = m_feature->attributes()->attributeValue(assetGroupFieldName).toInt(); UtilityAssetGroup* assetGroup = nullptr;
const auto groups = networkSource->assetGroups(); for (UtilityAssetGroup* group : groups) { if (group->code() == assetGroupCode) { assetGroup = group; break; } } if (!assetGroup) return;
const int assetTypeCode = m_feature->attributes()->attributeValue("assettype").toInt();
UtilityAssetType* assetType = nullptr; const auto types = assetGroup->assetTypes(); for (UtilityAssetType* type : types) { if (type->code() == assetTypeCode) { assetType = type; break; } }
if (!assetType) return;
m_terminals = assetType->terminalConfiguration()->terminals();
if (m_terminals.size() > 1) { m_terminalDialogVisisble = true; emit terminalDialogVisisbleChanged(); return; } else if (m_terminals.size() == 1) element = m_utilityNetwork->createElementWithArcGISFeature(m_feature, m_terminals[0]); else return;
} else if (networkSource->sourceType() == UtilityNetworkSourceType::Edge) { m_junctionSelected = false; emit junctionSelectedChanged();
element = m_utilityNetwork->createElementWithArcGISFeature(m_feature, nullptr, this);
// Compute how far tapped location is along the edge feature. if (m_feature->geometry().geometryType() == GeometryType::Polyline) { const Polyline line = geometry_cast<Polyline>(GeometryEngine::removeZ(m_feature->geometry())); // Set how far the element is along the edge. element->setFractionAlongEdge(GeometryEngine::fractionAlong(line, m_clickPoint, -1)); m_fractionAlongEdge = element->fractionAlongEdge(); emit fractionAlongEdgeChanged(); } } else { return; }
updateTraceParams(element);}
void TraceUtilityNetwork::onTraceCompleted_(){ m_dialogVisible = true; emit dialogVisibleChanged();
if (m_utilityNetwork->traceResult()->isEmpty()) { setBusyIndicator(false); return; }
m_dialogText = QString("Trace completed."); emit dialogTextChanged();
UtilityTraceResult* result = m_utilityNetwork->traceResult()->at(0);
const QList<UtilityElement*> elements = static_cast<UtilityElementTraceResult*>(result)->elements(this);
QueryParameters lineParams; QList<qint64> lineObjIds;
for (UtilityElement* item : elements) { if (item->networkSource()->name() == "Electric Distribution Line") lineObjIds.append(item->objectId()); }
lineParams.setObjectIds(lineObjIds);
m_taskCanceler->addTask(m_lineLayer->selectFeaturesAsync(lineParams, SelectionMode::Add).then(this, [this](FeatureQueryResult*) { setBusyIndicator(false); }));}
UniqueValue* TraceUtilityNetwork::createUniqueValue(const QString& label, Esri::ArcGISRuntime::Symbol* fillSymbol, int value){ // add state's attribute value for field "STATE_ABBR" to QVariantList QVariantList labelValue; labelValue.append(value);
// set value for a State to be rendered. (label, description, attribute value list, symbol, parent) UniqueValue* uniqueValue = new UniqueValue(label, "", labelValue, fillSymbol, this);
// return Unique value created return uniqueValue;}
void TraceUtilityNetwork::setBusyIndicator(bool status){ m_busy = status; emit busyChanged();
return;}
void TraceUtilityNetwork::handleArcGISAuthenticationChallenge(ArcGISAuthenticationChallenge* challenge){ TokenCredential::createWithChallengeAsync(challenge, "viewer01", "I68VGU^nMurF", {}, this).then(this, [challenge](TokenCredential* tokenCredential) { challenge->continueWithCredential(tokenCredential); }).onFailed(this, [challenge](const ErrorException& e) { challenge->continueWithError(e.error()); });}// [WriteFile Name=TraceUtilityNetwork, Category=UtilityNetwork]// [Legal]// Copyright 2019 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 TraceUtilityNetwork_H#define TraceUtilityNetwork_H
// ArcGIS Maps SDK headers#include "Authentication/ArcGISAuthenticationChallengeHandler.h"#include "Point.h"
// Qt headers#include <QUrl>#include <QUuid>
namespace Esri::ArcGISRuntime{class ArcGISFeature;class Error;class ErrorException;class FeatureLayer;class GraphicsOverlay;class IdentifyLayerResult;class Map;class MapQuickView;class ServiceFeatureTable;class ServiceGeodatabase;class SimpleFillSymbol;class SimpleLineSymbol;class SimpleMarkerSymbol;class Symbol;class UniqueValue;class UniqueValueRenderer;class UtilityElement;class UtilityNetwork;class UtilityTerminal;class UtilityTier;class UtilityTraceParameters;}
namespace Esri::ArcGISRuntime::Authentication{ class ArcGISAuthenticationChallenge;}
Q_MOC_INCLUDE("MapQuickView.h")Q_MOC_INCLUDE("IdentifyLayerResult.h")
class TaskCanceler;
class TraceUtilityNetwork : public Esri::ArcGISRuntime::Authentication::ArcGISAuthenticationChallengeHandler{ Q_OBJECT
Q_PROPERTY(Esri::ArcGISRuntime::MapQuickView* mapView READ mapView WRITE setMapView NOTIFY mapViewChanged) Q_PROPERTY(bool terminalDialogVisisble MEMBER m_terminalDialogVisisble NOTIFY terminalDialogVisisbleChanged) Q_PROPERTY(bool dialogVisible MEMBER m_dialogVisible NOTIFY dialogVisibleChanged) Q_PROPERTY(QString dialogText MEMBER m_dialogText NOTIFY dialogTextChanged) Q_PROPERTY(bool startingLocationsEnabled MEMBER m_startingLocationsEnabled NOTIFY startingLocationsChanged) Q_PROPERTY(double fractionAlongEdge MEMBER m_fractionAlongEdge NOTIFY fractionAlongEdgeChanged) Q_PROPERTY(bool busy MEMBER m_busy NOTIFY busyChanged) Q_PROPERTY(bool junctionSelected MEMBER m_junctionSelected NOTIFY junctionSelectedChanged)
public: explicit TraceUtilityNetwork(QObject* parent = nullptr); ~TraceUtilityNetwork();
static void init();
Q_INVOKABLE void multiTerminalIndex(int index); Q_INVOKABLE void trace(int index); Q_INVOKABLE void reset();
signals: void mapViewChanged(); void terminalDialogVisisbleChanged(); void dialogVisibleChanged(); void dialogTextChanged(); void startingLocationsChanged(); void fractionAlongEdgeChanged(); void junctionSelectedChanged(); void busyChanged();
private: Esri::ArcGISRuntime::MapQuickView* mapView() const; void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView); void connectSignals(); void updateTraceParams(Esri::ArcGISRuntime::UtilityElement* element); Esri::ArcGISRuntime::UniqueValue* createUniqueValue(const QString& label, Esri::ArcGISRuntime::Symbol* fillSymbol, int value); void createFeatureLayers(); void createRenderers(); void loadUtilityNetwork(const Esri::ArcGISRuntime::Error& error); bool hasErrorOccurred(const Esri::ArcGISRuntime::Error& error); void setBusyIndicator(bool status); void onIdentifyLayersCompleted_(const QList<Esri::ArcGISRuntime::IdentifyLayerResult*>& results); void onTraceCompleted_(); void onTaskFailed_(const Esri::ArcGISRuntime::ErrorException& exception);
void handleArcGISAuthenticationChallenge(Esri::ArcGISRuntime::Authentication::ArcGISAuthenticationChallenge* challenge) override;
const QUrl m_serviceUrl = QUrl("https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer");
Esri::ArcGISRuntime::Map* m_map = nullptr; Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr; Esri::ArcGISRuntime::FeatureLayer* m_lineLayer = nullptr; Esri::ArcGISRuntime::ServiceFeatureTable* m_deviceFeatureTable = nullptr; Esri::ArcGISRuntime::ServiceFeatureTable* m_lineFeatureTable = nullptr; Esri::ArcGISRuntime::SimpleMarkerSymbol* m_startingSymbol = nullptr; Esri::ArcGISRuntime::SimpleMarkerSymbol* m_barrierSymbol = nullptr; Esri::ArcGISRuntime::SimpleLineSymbol* m_mediumVoltageSymbol = nullptr; Esri::ArcGISRuntime::SimpleLineSymbol* m_lowVoltageSymbol = nullptr; Esri::ArcGISRuntime::GraphicsOverlay* m_graphicsOverlay = nullptr; Esri::ArcGISRuntime::ServiceGeodatabase* m_serviceGeodatabase = nullptr; Esri::ArcGISRuntime::UtilityNetwork* m_utilityNetwork = nullptr; Esri::ArcGISRuntime::UtilityTraceParameters* m_traceParams = nullptr; Esri::ArcGISRuntime::ArcGISFeature* m_feature = nullptr; Esri::ArcGISRuntime::UtilityTier * m_mediumVoltageTier = nullptr; Esri::ArcGISRuntime::UniqueValueRenderer* m_uniqueValueRenderer = nullptr;
bool m_terminalDialogVisisble = false; bool m_dialogVisible = false; bool m_startingLocationsEnabled = true; bool m_busy = false; bool m_junctionSelected = false; double m_fractionAlongEdge = 0.0; QString m_dialogText; Esri::ArcGISRuntime::Point m_clickPoint; QList<Esri::ArcGISRuntime::UtilityElement*> m_startingLocations; QList<Esri::ArcGISRuntime::UtilityElement*> m_barriers; QList<Esri::ArcGISRuntime::UtilityTerminal*> m_terminals; QScopedPointer<QObject> m_graphicParent; std::unique_ptr<TaskCanceler> m_taskCanceler;};
#endif // TraceUtilityNetwork_H// [WriteFile Name=TraceUtilityNetwork, Category=UtilityNetwork]// [Legal]// Copyright 2019 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 QtQuick.Layoutsimport Esri.Samples
Item {
// add a mapView component MapView { id: view anchors.fill: parent
Component.onCompleted: { // Set the focus on MapView to initially enable keyboard navigation forceActiveFocus(); } }
// Declare the C++ instance which creates the map etc. and supply the view TraceUtilityNetworkSample { id: model mapView: view }
Dialog { modal: true standardButtons: Dialog.Ok | Dialog.Cancel x: (parent.width - width) / 2 y: (parent.height - height) / 2 visible: model.terminalDialogVisisble
ColumnLayout { Text { text: qsTr("Select the terminal for this junction.") Layout.alignment: Qt.AlignHCenter }
ComboBox { id: terminalSelection model: ["High", "Low"] Layout.alignment: Qt.AlignHCenter } }
onAccepted: model.multiTerminalIndex(terminalSelection.currentIndex); }
Dialog { modal: true standardButtons: Dialog.Ok x: (parent.width - width) / 2 y: (parent.height - height) / 2 visible: model.dialogVisible
Text { text: model.dialogText anchors.centerIn: parent } }
BusyIndicator { id: busy anchors.centerIn: parent visible: model.busy }
Rectangle { id: backBox anchors { left: parent.left top: parent.top margins: 3 } width: childrenRect.width height: childrenRect.height color: "lightgrey" opacity: 0.8 radius: 5
// catch mouse signals from propagating to parent MouseArea { anchors.fill: parent onClicked: mouse => mouse.accepted = true onWheel: wheel => wheel.accepted = true }
Column {
GridLayout { columns: 2 rows: 3 flow: GridLayout.LeftToRight RadioButton { id: startingLocBtn Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter checked: true text: qsTr("Add starting location(s)") onToggled: model.startingLocationsEnabled = checked; }
RadioButton { id: barriersBtn Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter text: qsTr("Add barrier(s)") onToggled: model.startingLocationsEnabled = !checked; }
Text { text: qsTr("Trace Type:") Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter }
ComboBox { id: traceTypes Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter model: ["Connected", "Subnetwork", "Upstream", "Downstream"] }
Button { id: resetBtn text: qsTr("Reset") Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter enabled: !busy.visible onClicked: model.reset(); }
Button { id: traceBtn text: qsTr("Trace") Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter enabled: !busy.visible onClicked: model.trace(traceTypes.currentIndex); } }
Text { // Displays fraction along edge or if a junction is selected text: model.junctionSelected ? qsTr("Junction selected") : qsTr("Fraction along edge: %1".arg(model.fractionAlongEdge.toFixed(6))) anchors.horizontalCenter: parent.horizontalCenter }
} }}// [Legal]// Copyright 2019 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 "TraceUtilityNetwork.h"
// ArcGIS Maps SDK headers#include "ArcGISRuntimeEnvironment.h"
// Qt headers#include <QDir>#include <QGuiApplication>#include <QQmlApplicationEngine>
// 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("TraceUtilityNetwork"));
// 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 TraceUtilityNetwork::init();
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
// Initialize application view QQmlApplicationEngine engine; // Add the import Path engine.addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml")); // Add the Runtime and Extras path engine.addImportPath(arcGISRuntimeImportPath);
// Set the source engine.load(QUrl("qrc:/Samples/UtilityNetwork/TraceUtilityNetwork/main.qml"));
return app.exec();}// Copyright 2019 ESRI//// All rights reserved under the copyright laws of the United States// and applicable international laws, treaties, and conventions.//// You may freely redistribute and use this sample code, with or// without modification, provided you include the original copyright// notice and use restrictions.//// See the Sample code usage restrictions document for further information.//
import QtQuick.Controlsimport Esri.Samples
ApplicationWindow { visible: true width: 800 height: 600
TraceUtilityNetwork { anchors.fill: parent }}