Select to view content in your preferred language

Attribute Rule to Populate a Field When a Line is Split

315
4
08-05-2025 01:55 PM
Labels (3)
ZachBodenner
MVP Regular Contributor

Hello,

Scenario: A line feature class (Trails) is used in an asset management where unique IDs of specific segments tie the segment to past work orders. Sometime these trail segments need to be split into two separate lines. Down the road, I foresee the possibility of work orders getting 'lost' by retaining their relationship to only part of a line segment. Here's what I want to do:

Add a field to the dataset to hold a 'Parent ID' so that a child line segment created by splitting will retain at least a textual reference to a previous line. However, because I do not want two lines with the same ID, I want one line to maintain that original ID, and have the second line 1) inherit the ID to the 'Parent ID' field, and then get a new ID in the primary ID field.

I had the idea to use an calculation rule to run on insert, as splitting the line segment should trigger an Insert edit. Then, as a result of that edit I would A) Generate a new ID in the primary ID field of the new line and B) run an Intersect function and get the original ID from the parent line to populate into the Parent ID field. My concern (and I haven't tested this yet to be honest), is that this might get complicated by the fact that many times the resulting new trail line will intersect multiple other line segments. Any thoughts on how I could single out one specific line segment? There's no guarantee the 'Parent' trail segment is actually First() in the OBJECTIDs, so I'm reluctant to rely on First to do this.

Happy mapping,
- Zach
0 Kudos
4 Replies
Scott_Harris
Esri Regular Contributor

@ZachBodenner If you are willing to change your primary key in your relationship from an OBJECTID to a GlobalID you can change the relationship class split policy to Duplicate Related Objects:

Scott_Harris_0-1754484999079.png

https://pro.arcgis.com/en/pro-app/latest/help/data/relationships/relationship-class-split-policy.htm

 

0 Kudos
ZachBodenner
MVP Regular Contributor

This would be a wonderful solution if the related work orders were contained in the same database. The AM system is a separate product and will create points based on the geometry of the egdb feature that hold the work order info. So unfortunately there isn't a table that I actually can work with.

Happy mapping,
- Zach
0 Kudos
JoeBryant1
Frequent Contributor

I've been experimenting with similar workflows and have a thought (unfortunately I can't code or test this at the moment):

Instead of creating an insert rule to calculate the new ID when the line is split, what it if you allow the new line to be created with the existing ID so that you end up with duplicate IDs? Then create a separate Validation rule to be run at the end of your edit session that looks for duplicate IDs, saves the ID to a variable, selects the shorter of the 2 lines (or maybe selects all lines that are not the longest line to account for more than 1 duplicate if there were multiple splits), writes the existing ID to the parent ID field and uses the db sequence to create the new ID(s). This could also help you find other duplicate IDs you didn't know about 😉!

0 Kudos
ZachBodenner
MVP Regular Contributor

Hey @JoeBryant1 , thanks for the idea! Ultimately, I think I found a slightly simpler solution using a pair of instant calculation rules. I also don't necessarily need a shorter line to be the 'child' so I'm just operating as new feature from split = 'child' feature. Here's the set of three total rules.

// RULE 1 - Initial Trail ID
// If there is no trail ID, assign a new one. If the TrailID exists, keep it the same. 
var trlID = IIF(isEmpty($feature.TrailID),"TRL-"+$feature.objectID,$feature.TrailID)
return trlID
// RULE 2 - Populate Parent Trail ID if the result of the edit results in two or more segments with the same TrailID
var id = $feature.TrailID
var oid = $feature.OBJECTID

// Check if this TrailID already exists in the dataset by filtering based on TrailID AND make sure the object ID of the INSERTED feature is different from any found matches.
var existingTrails = Filter(FeatureSetByName($datastore, 'Trails_Test'),"TrailID = @id AND OBJECTID <> @oid")

// If this ID already exists, this is a split - save the ID as ParentTrailID
if (Count(existingTrails) > 0) {
    return id
}
else {return null}

 

// RULE 3 - The previous rule calculates the TrailID into ParentTrailID but does not affect the TrailID. Now, go back and create a new TrailID for the new feature.
var id = $feature.TrailID
var oid = $feature.OBJECTID

// Check if this TrailID already exists in the dataset by filtering based on TrailID AND make sure that the object ID of the INSERTED feature is different from any found matches.
var existingTrails = Filter(FeatureSetByName($datastore, 'Trails_Test'),"TrailID = @id AND OBJECTID <> @oid")

// Count the number of matches. Count higher than 1 indicates more than one line with the same ID. If this ID already exists, this is a split - generate new ID for the INSERTED feature...
if (Count(existingTrails) > 0) {
    return "TRL-" + Text(oid)
}
// ... otherwise, keep the ID the same
else {return id}

 

So ultimately I think I was thinking too hard about my initial problem. This solution should also make this a bit more efficient by not having to rely on geometry at all.

Happy mapping,
- Zach
0 Kudos