An array of analysis and tracing options usually begin with or include a utility element in the result. This element corresponds to a network feature or object that contains additional information such as a terminal or fraction along value that affects the analysis. For example, the utility element's terminal may limit the number of connectivity associations or change the direction of a trace, while its fraction along value may return a partial geometry from a trace.
This utility element may be created from a feature or asset type with a global id. The feature may be a result of a query or identify operation on a layer or table that is part of the utility network.
Utility element from a feature
You may query for a specific feature using any of its fields or geometry or interactively identify a feature in a map view. When using identify, the feature may be found in the GeoElement
list immediately under IdentifyLayerResult
when part of a FeatureLayer
or from sublayerResults()
when part of a SubtypeFeatureLayer
.
// Create a query parameters.
QueryParameters queryParameters;
// Set the where clause on the query parameters.
queryParameters.setWhereClause("GlobalId like '{D353C10C-E617-4618-BDD0-B48EDB822D07}'");
// Execute an asynchronous query on the feature table using the query parameters resulting
// in a feature query result (via QFuture).
featureTable->queryFeaturesAsync(queryParameters, this).then
(this, [] (FeatureQueryResult* featureQueryResult)
{
// Get a feature iterator from the feature query result.
FeatureIterator featureIterator = featureQueryResult->iterator();
// Get a QList of features from the feature iterator.
const QList<Feature*> features = featureIterator.features();
// Get the first feature from the QList of features.
Feature* feature = features.first();
// Cast the feature to an ArcGIS feature.
ArcGISFeature* arcgisFeature = dynamic_cast<ArcGISFeature*>(feature);
// Provide some feedback.
qDebug() << arcgisFeature->geometry().toJson();
});
// Execute an asynchronous identify on the map view using the map's screen point, a
// tolerance of 5 pixels, and a boolean of false (without returning a popups). This
// returns in an identify layer results. This is done via a QFuture.
m_mapView->identifyLayersAsync(screenPoint, 5, false, this).then
(this, [] (const QList<IdentifyLayerResult*> identifyLayerResults)
{
// Create an empty ArcGIS feature (we will populate it later).
ArcGISFeature* arcgisFeature = nullptr;
// Loop through the identify layer results.
for (IdentifyLayerResult* identifyLayerResult : identifyLayerResults)
{
// Cast the identify layer result's layer content to a sub feature layer.
SubtypeFeatureLayer* subtypeFeatureLayer = dynamic_cast<SubtypeFeatureLayer*>
(identifyLayerResult->layerContent());
// Cast the identify layer result's layer content to a feature layer.
FeatureLayer* featureLayer = dynamic_cast<FeatureLayer*>(identifyLayerResult->layerContent());
// If we have a sub type feature layer (i.e. not null), continue processing.
if (subtypeFeatureLayer)
{
// Get the QList of identify layer results from the sub layer results
// of the identify.
const QList<IdentifyLayerResult*> sublayerIdentifyLayerResults =
identifyLayerResult->sublayerResults();
// Loop thru the identify layer results for the sub layer.
for (IdentifyLayerResult* sublayerIdentifyLayerResult : sublayerIdentifyLayerResults)
{
// Get the QList of geo elements of the the sub layer identify layer result.
const QList<GeoElement*> geoElements = sublayerIdentifyLayerResult->geoElements();
// Test if the ArcGIS feature was previously nullptr.
if (arcgisFeature)
break;
// Loop through the geo elements.
for (GeoElement* geoElement : geoElements)
{
// Test if the ArcGIS feature was previously nullptr.
if (arcgisFeature)
break;
// Cast the geo element to the ArcGIS feature.
arcgisFeature = dynamic_cast<ArcGISFeature*>(geoElement);
}
}
}
// If we have a feature layer (i.e. not null), continue processing.
if (featureLayer)
{
// Get the QList of geo elements of the the identify layer result.
const QList<GeoElement*> geoElements = identifyLayerResult->geoElements();
// Test if the ArcGIS feature was previously nullptr.
if (arcgisFeature)
break;
// Loop through the geo elements.
for (GeoElement* geoElement : geoElements)
{
// Test if the ArcGIS feature was previously nullptr.
if (arcgisFeature)
break;
// Cast the geo element to the ArcGIS feature.
arcgisFeature = dynamic_cast<ArcGISFeature*>(geoElement);
}
}
}
});
// Create a utility element for the feature.
UtilityElement* utilityElement = utilityNetwork->
createElementWithArcGISFeature(feature, nullptr, this);
Utility element from an asset type
An asset type can come from another utility element or be derived from a feature in the utility network, except from a subnet line table that does not have an asset type. You can use the feature's table name to get its network source. Use the network source and the feature's subtype to get its asset group. From the asset group, you can select an asset type by name or code.
// Option 1: Creating utility element from another utility element's asset type.
// -----------------------------------------------------------------------------
// Get the utility asset type from a another utility element.
UtilityAssetType* option1UtilityAssetType = otherUtilityElement->assetType();
// Make a new utility element using an asset type and guid.
UtilityElement* option1UtilityElement = utilityNetwork->createElementWithAssetType
(
option1UtilityAssetType, // utility asset type
globalId // QUuid
);
// Provide some feedback.
qDebug() << option1UtilityElement->assetType()->name();
// Option 2: Creating a utility element from a feature in a utility network.
// -------------------------------------------------------------------------
// Get the feature table from a feature.
FeatureTable* featureTable = feature->featureTable();
// Get the name from the feature table.
const QString featureTableName = featureTable->tableName();
// Get the utility network definition from the utility network.
UtilityNetworkDefinition* utilityNetworkDefinition = utilityNetwork->definition();
// Get the utility network source from the utility network definition.
UtilityNetworkSource* utilityNetworkSource = utilityNetworkDefinition->
networkSource(featureTableName);
// Get an ArcGIS feature from a feature (via casting).
ArcGISFeature* arcgisFeature = dynamic_cast<ArcGISFeature*>(feature);
// Get the feature sub type from the ArcGIS feature.
FeatureSubtype featureSubtype = arcgisFeature->featureSubtype();
// Get the sub type name from the feature sub type.
const QString subtypeName = featureSubtype.name();
// Get the utillity asset group from the network source via it's sub type name.
UtilityAssetGroup* utilityAssetGroup = utilityNetworkSource->assetGroup(subtypeName);
// Get the attribute list model from the feature.
AttributeListModel* attributeListModel = feature->attributes();
// Get the attribute value of "ASSETTYPE" from the attribute list model.
QVariant assetTypeCode = attributeListModel->attributeValue("ASSETTYPE");
// Get the QList of utility asset types from the asset group.
const QList<UtilityAssetType*> utilityAssetTypes = utilityAssetGroup->assetTypes();
// Get the first utility asset type from the QList of utility asset types.
UtilityAssetType* firstUtilityAssetType = utilityAssetTypes.first();
// Get the first utility asset type's code from the utility asset type.
int firstUtilityAssetTypeCode = firstUtilityAssetType->code();
// Test if the first utility asset type's code is the same as the attribute value
// of "ASSETTYPE" from the attribute list model, if true continue processing.
if (firstUtilityAssetTypeCode == assetTypeCode)
{
// Get the utility network source of "Electric Distribution Device" from the utility
// netowrk defintion.
utilityNetworkSource = utilityNetworkDefinition->
networkSource("Electric Distribution Device");
// Get the asset group of "Service Point" from the utility network source.
utilityAssetGroup = utilityNetworkSource->assetGroup("Service Point");
// Get the utility asset type of "Single Phase Low Voltage Meter" from the utility
// asset group.
UtilityAssetType* option2UtilityAssetType =
utilityAssetGroup->assetType("Single Phase Low Voltage Meter");
// Make a new utility element using an asset type (from the first utility asset
// type found in the feature) and guid.
UtilityElement* option2UtilityElement = utilityNetwork->createElementWithAssetType
(
option2UtilityAssetType, // utility asset type
globalId // QUuid
);
// Provide some feedback.
qDebug() << option2UtilityElement->assetType()->name();
}
Utility element properties
A terminal is required when a UtilityElement
that supports more than one terminal is used in a trace and optional when used to get associations. Terminals impact traces and connectivity associations.
// Get the terminals for the feature.
// Get the utility asset type from the utility element.
UtilityAssetType* utilityAssetType = utilityElement->assetType();
// Get the utility terminal configuration from the utility asset type.
UtilityTerminalConfiguration* utilityTerminalConfiguration = utilityAssetType->
terminalConfiguration();
// Get the QList of utility terminalf from the utility terminal configuration.
const QList<UtilityTerminal*> utilityTerminals = utilityTerminalConfiguration->terminals();
// Select the first terminal if present.
if (utilityTerminals.count() > 0)
utilityElement->setTerminal(utilityTerminals.first());
If the feature represents a line, you can optionally specify a location along the line to use as a trace location. This value is a percentage of the length of the line, beginning from the line's 'from' point.
Use UtilityElement::fractionAlongEdge()
to define the location of the point along the line.
The following example uses the GeometryEngine
to get the fraction of a tap location along the line.
// Get the geometry from the feature.
const Geometry geometry = feature->geometry();
// Test if the geometry type is a polyline.
if (geometry.geometryType() == GeometryType::Polyline)
{
// Create a geometry with no z values from the geometry that has z values.
const Geometry geometryNoZvalues = GeometryEngine::removeZ(geometry);
// Get the polyline from the geometry with no z values (via a cast).
const Polyline polyline = geometry_cast<Polyline>(geometryNoZvalues);
// Get the distance along the line's total geodesic length.
const double howFarAway = GeometryEngine::fractionAlong
(
polyline, // polyline
clickPoint, // point
-1 // tolerance - double
);
// Set how far the element is along the edge using the static geometry engine
// fraction along function.
utilityElement->setFractionAlongEdge(howFarAway);
}