Trace from ribbon vs from exported feature class

885
2
Jump to solution
11-05-2020 11:55 AM
TimWhiteaker
Occasional Contributor II

As a workaround for the Trace tool not honoring feature selections, I am trying the following:

1. In Pro 2.6, select the junction feature I'm interested in.

2. Export the feature to a new feature class named Flag in my default geodatabase.  Note that my trace network is in another geodatabase.

3. Clear the selection.

4. Run an upstream trace, using Flag as the Starting Points with all other parameters at defaults.

However, in addition to the expected upstream edges, the resulting feature selection includes the edge just downstream of the junction (orange circle in image below).

Image of downstream edge being returned in upstream trace results

When I instead use the ribbon to interactively set a starting point at the desired junction (I made sure it snapped to that junction feature before clicking), and then run an upstream trace (initiated from the ribbon, so it's using the TN_Temp_Starting_Points and all defaults), I get the desired result, which is just the upstream set of edges.

Only upstream edges returned from upstream trace

Why is my exported junction causing a downstream edge to be returned from an upstream trace?

Note that interactively setting starting points isn't an option for me, because I'm trying to automate this for thousands of junctions via ModelBuilder.

Tags (1)
0 Kudos
2 Solutions

Accepted Solutions
TimWhiteaker
Occasional Contributor II

My mistake was simply copying my selected junction to a separate flag feature class. To make this work, I also have to add and populate a couple of fields that you'll notice in the TN_Temp_Starting_Points feature class in your default geodatabase that stores the flags you create interactively (via Data tab on ribbon), namely, SOURCEID and FEATUREGLOBALID. The SOURCEID refers to the identifier given to the junction layer in the trace network. The FEATUREGLOBALID is the GLOBALID of the junction feature where you want the starting point placed.

I discovered this when I noticed that traces initiated from a copy of TN_Temp_Starting_Points worked.  I deleted fields one by one and ran traces to see which fields were actually required, leading me to just the two fields I mentioned above.  I do not know if that works in all cases.  It would be nice if an Esri guru could comment on how to properly make a starting flag feature class.  I wish this information had been in a white paper that I had access to.

Here's code that demonstrates how to trace upstream given a junction layer.

import arcpy


def get_source_id(network, network_layer):
    d = arcpy.Describe(network_layer)
    fc_name = d.featureClass.name
    
    d = arcpy.Describe(network)
    for s in d.sources:
        if s.name == fc_name:
            return s.sourceID

    arcpy.AddError(
        'Could not determine network source ID for ' + network_layer.name)
    raise arcpy.ExecuteError


def point_to_flag(shape_xy, spatial_ref, source_id, global_id):
    flag_fc = arcpy.CreateFeatureclass_management(
        out_path='memory',
        out_name='flag',
        geometry_type='POINT',
        has_m='ENABLED',
        has_z='ENABLED',
        spatial_reference=spatial_ref)[0]
    flag_fc = arcpy.management.AddField(flag_fc, 'SOURCEID', 'LONG')[0]
    flag_fc = arcpy.management.AddField(flag_fc, 'FEATUREGLOBALID', 'GUID')[0]
    fields = ['SHAPE@XY', 'SOURCEID', 'FEATUREGLOBALID']
    with arcpy.da.InsertCursor(flag_fc, fields) as cursor:
        cursor.insertRow((shape_xy, source_id, global_id))
    return flag_fc


arcpy.env.overwriteOutput = True

network = arcpy.GetParameter(0)
junction_layer = arcpy.GetParameter(1)

spatial_ref = arcpy.Describe(junction_layer).spatialReference
source_id = get_source_id(network, junction_layer)

with arcpy.da.SearchCursor(junction_layer, ['SHAPE@XY', 'GLOBALID']) as cursor:
    for i, row in enumerate(cursor):        
        flag = point_to_flag(row[0], spatial_ref, source_id, row[1])

        Updated_Trace_Network = arcpy.tn.Trace(
            in_trace_network=network,
            trace_type='UPSTREAM',
            starting_points=flag)[0]

arcpy.SetParameter(2, junction_layer)

 

View solution in original post

0 Kudos
JonDeRose
Esri Contributor

Copying this from a reply in another thread  to clarify when SOURECEID and FEATUREGLOBALID fields are used when working with starting points and barriers in a trace network trace.

When placing starting points and barriers in a trace network, the SOURCEID / FEATUREGLOBALID are not required; however, these fields are honored if present and require the inclusion of valid values to be used. 

Using SOURCEID and  FEATUREGLOBALID to specify trace locations in a feature class allows you to filter which features are used as trace locations.  Perhaps you have a feature class that contains features you want to use as barriers; however, you only want a certain type of feature, or specific set of features to serve as barriers...  In this case you could populate only the features you want to serve as barriers with SOURCEID/FEATUREGLOBALID information.  When the trace is executed, only these features would be used as either the starting point or barrier for the class. 

  • To clarify, case, if your class has 20 records, but only 2 have SOURCEID/FEATUREGLOBALID populated with a valid value, only those 2 would be used as starting points or barriers in the trace.

If these fields are not present, the geometry of the feature class will be used to intersect the network feature geometry and place either the starting point or barrier. 

Snag_24dd8dda.pnguser-defined feature class used as a barrier feature without SOURCEID/FEATUREGLOBALID

This is outlined here:

If this does not address the original use case above please reach out with additional details and I can review further.

View solution in original post

0 Kudos
2 Replies
TimWhiteaker
Occasional Contributor II

My mistake was simply copying my selected junction to a separate flag feature class. To make this work, I also have to add and populate a couple of fields that you'll notice in the TN_Temp_Starting_Points feature class in your default geodatabase that stores the flags you create interactively (via Data tab on ribbon), namely, SOURCEID and FEATUREGLOBALID. The SOURCEID refers to the identifier given to the junction layer in the trace network. The FEATUREGLOBALID is the GLOBALID of the junction feature where you want the starting point placed.

I discovered this when I noticed that traces initiated from a copy of TN_Temp_Starting_Points worked.  I deleted fields one by one and ran traces to see which fields were actually required, leading me to just the two fields I mentioned above.  I do not know if that works in all cases.  It would be nice if an Esri guru could comment on how to properly make a starting flag feature class.  I wish this information had been in a white paper that I had access to.

Here's code that demonstrates how to trace upstream given a junction layer.

import arcpy


def get_source_id(network, network_layer):
    d = arcpy.Describe(network_layer)
    fc_name = d.featureClass.name
    
    d = arcpy.Describe(network)
    for s in d.sources:
        if s.name == fc_name:
            return s.sourceID

    arcpy.AddError(
        'Could not determine network source ID for ' + network_layer.name)
    raise arcpy.ExecuteError


def point_to_flag(shape_xy, spatial_ref, source_id, global_id):
    flag_fc = arcpy.CreateFeatureclass_management(
        out_path='memory',
        out_name='flag',
        geometry_type='POINT',
        has_m='ENABLED',
        has_z='ENABLED',
        spatial_reference=spatial_ref)[0]
    flag_fc = arcpy.management.AddField(flag_fc, 'SOURCEID', 'LONG')[0]
    flag_fc = arcpy.management.AddField(flag_fc, 'FEATUREGLOBALID', 'GUID')[0]
    fields = ['SHAPE@XY', 'SOURCEID', 'FEATUREGLOBALID']
    with arcpy.da.InsertCursor(flag_fc, fields) as cursor:
        cursor.insertRow((shape_xy, source_id, global_id))
    return flag_fc


arcpy.env.overwriteOutput = True

network = arcpy.GetParameter(0)
junction_layer = arcpy.GetParameter(1)

spatial_ref = arcpy.Describe(junction_layer).spatialReference
source_id = get_source_id(network, junction_layer)

with arcpy.da.SearchCursor(junction_layer, ['SHAPE@XY', 'GLOBALID']) as cursor:
    for i, row in enumerate(cursor):        
        flag = point_to_flag(row[0], spatial_ref, source_id, row[1])

        Updated_Trace_Network = arcpy.tn.Trace(
            in_trace_network=network,
            trace_type='UPSTREAM',
            starting_points=flag)[0]

arcpy.SetParameter(2, junction_layer)

 

0 Kudos
JonDeRose
Esri Contributor

Copying this from a reply in another thread  to clarify when SOURECEID and FEATUREGLOBALID fields are used when working with starting points and barriers in a trace network trace.

When placing starting points and barriers in a trace network, the SOURCEID / FEATUREGLOBALID are not required; however, these fields are honored if present and require the inclusion of valid values to be used. 

Using SOURCEID and  FEATUREGLOBALID to specify trace locations in a feature class allows you to filter which features are used as trace locations.  Perhaps you have a feature class that contains features you want to use as barriers; however, you only want a certain type of feature, or specific set of features to serve as barriers...  In this case you could populate only the features you want to serve as barriers with SOURCEID/FEATUREGLOBALID information.  When the trace is executed, only these features would be used as either the starting point or barrier for the class. 

  • To clarify, case, if your class has 20 records, but only 2 have SOURCEID/FEATUREGLOBALID populated with a valid value, only those 2 would be used as starting points or barriers in the trace.

If these fields are not present, the geometry of the feature class will be used to intersect the network feature geometry and place either the starting point or barrier. 

Snag_24dd8dda.pnguser-defined feature class used as a barrier feature without SOURCEID/FEATUREGLOBALID

This is outlined here:

If this does not address the original use case above please reach out with additional details and I can review further.

0 Kudos