Depending on what you need to do with the results, you can work with the appropriate return type you configured in the trace
-
Elements—Element results provide the utility elements
A utility element is an entity in a utility network that corresponds to a feature or a part of a feature (for example, a terminal inside a device). that are found by a trace. Use these results when you need access to individual utility elements, their corresponding featuresA feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. , and their attributesAttributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. . This is the default trace result type. -
Geometry—Geometry results contains multipart geometries that represent the union of the geometry
A geometry is a geometric shape, such as a point, polyline, or polygon, that contains one or more coordinates and a spatial reference. for all elements returned. These results are best for displaying the trace result on a map. -
Functions—A function is a trace configuration that allows you to run calculations on network attributes associated with traced features. A function output is returned for every function defined in the configuration.
var traceResults = await utilityNetwork.TraceAsync(traceParameters);
foreach (var result in traceResults)
{
if (result.Warnings.Count > 0)
Debug.WriteLine($"Trace Result Warnings:\n\t{string.Join("\n", result.Warnings)}");
if (result.NearestNeighborResult != UtilityNearestNeighborResult.NotApplicable)
Debug.WriteLine($"Nearest Neighbor: {result.NearestNeighborResult}");
}
Element results
If you need fine-grained access to the results, such as the ability to work with individual utility elements
You can use the element's network source
if (traceResult is UtilityElementTraceResult elementResult)
{
foreach (var layer in MainMapView.Map.OperationalLayers.OfType<FeatureLayer>())
{
var elements = elementResult.Elements.Where(el => el.NetworkSource.FeatureTable == layer.FeatureTable);
if (!elements.Any())
continue;
var features = await utilityNetwork.GetFeaturesForElementsAsync(elements);
if (!features.Any())
continue;
layer.SelectFeatures(features);
}
}
Function results
If function results are included, they will contain a UtilityTraceFunctionOutput for every UtilityTraceFunction that was defined in the UtilityTraceConfiguration. Each UtilityTraceFunctionOutput contains the original function definition as well as the function result.
if (traceResult is UtilityFunctionTraceResult functionResult)
{
foreach (var functionOutput in functionResult.FunctionOutputs)
{
Debug.WriteLine($"{functionOutput.Function.FunctionType} on " +
$"'{functionOutput.Function.NetworkAttribute.Name}':\n\t" +
$"{functionOutput.Result}");
}
}
If the function includes a condition, you can summarize this expression Get using the following helper methods:
private static string GetExpression(UtilityTraceCondition? expression)
{
if (expression is null)
return string.Empty;
if (expression is UtilityCategoryComparison categoryComparison)
return $"`{categoryComparison.Category.Name}` {categoryComparison.ComparisonOperator}";
if (expression is UtilityNetworkAttributeComparison attributeComparison)
{
var value = GetValue(attributeComparison.NetworkAttribute.DataType, attributeComparison.Value);
if (attributeComparison.NetworkAttribute.Domain is CodedValueDomain codedValueDomain)
value = codedValueDomain.CodedValues.FirstOrDefault(c => value?.Equals(GetValue(attributeComparison.NetworkAttribute.DataType, c.Code)) == true)?.Name;
return $"`{attributeComparison.NetworkAttribute.Name}` {attributeComparison.ComparisonOperator} {value}";
}
if (expression is UtilityTraceAndCondition andCondition)
return $"({GetExpression(andCondition.LeftExpression)} AND {GetExpression(andCondition.RightExpression)})";
if (expression is UtilityTraceOrCondition orCondition)
return $"({GetExpression(orCondition.LeftExpression)} OR {GetExpression(orCondition.RightExpression)})";
return string.Empty;
}
private static object? GetValue(UtilityNetworkAttributeDataType type, object? value)
{
if (value is null)
return value;
switch (type)
{
case UtilityNetworkAttributeDataType.Boolean:
return System.Convert.ToBoolean(value);
case UtilityNetworkAttributeDataType.Double:
return System.Convert.ToDouble(value);
case UtilityNetworkAttributeDataType.Float:
return System.Convert.ToSingle(value);
case UtilityNetworkAttributeDataType.Integer:
return System.Convert.ToInt32(value);
default:
break;
}
return value;
}
Geometry results
Geometry results make it easy to display the tracex,y values. Each coordinate can also optionally include a z value for height and/or a m value for measure (typically used in linear referencing).UtilityGeometryTraceResult exposes the geometry result for each potential geometry type. If the result does not include a certain geometry type, the corresponding property will be null.
Get the geometry results from the trace results. Depending how the trace parameters were defined (i.e. which result types were requested), there may be more than one result type. Create a new graphic for each geometry in the geometry results, check if there's any need to reproject to the map's spatial reference
if (traceResult is UtilityGeometryTraceResult geometryResult)
{
if (geometryResult.Multipoint is Multipoint multipoint)
{
if (MainMapView.SpatialReference != null &&
multipoint.SpatialReference != MainMapView.SpatialReference &&
GeometryEngine.Project(multipoint, MainMapView.SpatialReference) is Multipoint projectedMultipoint)
multipoint = projectedMultipoint;
var graphic = new Graphic(multipoint, pointSymbol);
overlay.Graphics.Add(graphic);
}
if (geometryResult.Polyline is Polyline polyline)
{
if (MainMapView.SpatialReference != null &&
polyline.SpatialReference != MainMapView.SpatialReference &&
GeometryEngine.Project(polyline, MainMapView.SpatialReference) is Polyline projectedPolyline)
polyline = projectedPolyline;
var graphic = new Graphic(polyline, lineSymbol);
overlay.Graphics.Add(graphic);
}
if (geometryResult.Polygon is Polygon polygon)
{
if (MainMapView.SpatialReference != null &&
polygon.SpatialReference != MainMapView.SpatialReference &&
GeometryEngine.Project(polygon, MainMapView.SpatialReference) is Polygon projectedPolygon)
polygon = projectedPolygon;
var graphic = new Graphic(polygon, fillSymbol);
overlay.Graphics.Add(graphic);
}
}