Update ID field using another feature class

997
16
Jump to solution
02-03-2021 11:36 AM
Labels (1)
SarahHartholt
Occasional Contributor III

I am fairly new to Arcade and am trying to update the CoordinatedID field in my WaterMain layer using an attribute rule with the help of some code found here: Attribute rule script expression examples—ArcGIS Pro | Documentation

What I would like to do it grab the CoordinatedID field from my Roads (Centreline_Assets) layer and use it to populate the CoordinatedID field in my WaterMains (WaterMains_Assets) layer. They layers don't line up exactly so I am trying to buffer the road by 10m and populate the Coordinated field based on an intersection between the buffer and the WaterMains layer. Here's what I have so far:

 

 

//On Insert or Update populate Coordinate ID 
var fcRoad=FeatureSetByName($datastore, "Centreline_Assets",["Coordinated_ID"])
var fcWaterMain=FeatureSetByName($datastore,"WaterMain_Assets_SplitLine",["Coordinated_ID"])
Var RoadIntersect = Intersects(Buffer(fcRoad,10,'meter'),fcWaterMain)
var AddList = []
var counter = 0
var noCID = Count(RoadIntersect)
if (noCID>0){
    for (var Road in RoadIntersect){
        AddList[counter]={
            'Coordinated_ID':Centreline_Assets.CoordinatedID,
            'attributes':{
                'add_CoordinateID':$feature.Coordinated_ID
            }
        }
        counter++
    }
    return {
        'result': noCID + ' Coordinated ID found',
        'edit': [{
            'className':'Centreline_Assets',
            'updates': AddList
        }]
    }
}else{
    return 'No Coordinated ID'
}

 

 

I keep getting the following error:

Invalid expression. Error on line 4. Geometry type null expected.

Any suggestions?

 

0 Kudos
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

Hi @SarahHartholt ,

Since you are editing the same layer of the feature the return type does not have to be the object including the name of the featureclass. Have a look at the example below (without using NextSequenceValue):

//On Insert or Update populate Coordinate ID 
var fsRoads = FeatureSetByName($datastore, "Centreline_Assets",["Coordinated_ID"], True);
var watermain = $feature;
var watermainbuf = Buffer(watermain, 10, 'meter');
var roads = Intersects(fsRoads, watermainbuf);
var cnt = Count(RoadIntersect);

// check different situations
if (cnt == 0) {
    // there are no roads found
    return null;
} else if (cnt == 1) {
    // there is a one road, return the Coordinate_ID
    return First(roads)["Coordinated_ID"];
} else {
    // there are multiple roads found, find the longest segment
    var maxsegmentlength = 0;
    var CoordID = null;
    for (var road in roads) {
        var segment = Intersection(road, watermainbuf);
        var segmentlength = Length(segment, 'meter');
        if (segmentlength > maxsegmentlength) {
            CoordID = road["Coordinated_ID"];
            maxsegmentlength = segmentlength;
        }
    }
    return CoordID;
}

View solution in original post

0 Kudos
16 Replies
JoeBorgione
MVP Esteemed Contributor

Did you mean to spell Centerline this way?  Centreline

 

That should just about do it....
0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi @SarahHartholt ,

The error is pointing to line 4 and it is because you can't buffer a featureset, you can only buffer and single feature.

SarahHartholt
Occasional Contributor III

Thanks @XanderBakker . Is there any way for me to run my arcade expressions through a debugger? I've started using the Arcade playground but I haven't figured out a way to bring my features and attributes into it for testing. Please let me know if there are any useful articles that I could read on the topic.

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi @SarahHartholt ,

I agree that debugging attribute rules is a bit tricky. However, you could use part of the expression in a pop-up to validate the result. You cannot use a return type that writes to a featureclass, but at least you will be able to see if the logic that occurs before returning the result is working. 

Using the playground is great to check functions and logic, but you won't have access to your data and the sample data provided is very limited (2 polygon layers).

Related to the specific problem you are trying to tackle, there might be some additional complications since I suppose a waterline could intersect with multiple road buffers. 

When you create an attribute rule on your waterlines, you will want to read the current waterline feature and buffer it and intersect the buffer with the road features. Then (maybe) you would have to check the length of the road segments inside the waterline buffer, to see which Coordinated_ID you should take. 

0 Kudos
SarahHartholt
Occasional Contributor III

Yes there are some other issues that I need to consider. Like you said, the waterlines will intersect with multiple road buffers (blue lines are waterlines, black lines are roads & 10m buffer is grey): 

SarahHartholt_0-1612445039662.png

I was hoping that I could automate some of the processes I want to achieve using Arcade rather than having to run geoprocessing tools when I add data to my layers but I think I'm in over my head on this one.

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi @SarahHartholt ,

I think this is something that can be done. You can intersect the waterline buffer with the roads and evaluate the length of the road inside the buffer and take the Coordinate_ID of the longest road segment. 

I do have a couple of questions:

  • Do you want to do this as a Batch or as an immediate calculation triggered by an edit?
  • How will you handle waterlines that are not contained by the roadbuffer in your screenshot? Should these get the Coordinate_ID of the road it crosses or no Coordinate_ID?
0 Kudos
SarahHartholt
Occasional Contributor III

Hi @XanderBakker 

I  don't think I know arcade well enough to accomplish this myself.

I was hoping I could do this as an immediate calculation. Right now when a road segment is added to my roads layer, I have an update rule that populates the Coordinated_ID field with the Next Sequence Value. Once the road layer is populated, I think I need to split the waterlines at vertices - the idea being that the U shaped segments will be separated into smaller pieces that line up with the roads more closely, making it easier to assign the correct Coordinated_ID. I was hoping that splitting the water lines would trigger the expression to grab the Coordinated_ID from the roads feature.

Waterlines that are not contained in the road buffer will need to be manually inspected and would likely be assigned a separate Coordinated_ID that is not associated with a road segment. 

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi @SarahHartholt ,

Since you are editing the same layer of the feature the return type does not have to be the object including the name of the featureclass. Have a look at the example below (without using NextSequenceValue):

//On Insert or Update populate Coordinate ID 
var fsRoads = FeatureSetByName($datastore, "Centreline_Assets",["Coordinated_ID"], True);
var watermain = $feature;
var watermainbuf = Buffer(watermain, 10, 'meter');
var roads = Intersects(fsRoads, watermainbuf);
var cnt = Count(RoadIntersect);

// check different situations
if (cnt == 0) {
    // there are no roads found
    return null;
} else if (cnt == 1) {
    // there is a one road, return the Coordinate_ID
    return First(roads)["Coordinated_ID"];
} else {
    // there are multiple roads found, find the longest segment
    var maxsegmentlength = 0;
    var CoordID = null;
    for (var road in roads) {
        var segment = Intersection(road, watermainbuf);
        var segmentlength = Length(segment, 'meter');
        if (segmentlength > maxsegmentlength) {
            CoordID = road["Coordinated_ID"];
            maxsegmentlength = segmentlength;
        }
    }
    return CoordID;
}
0 Kudos
SarahHartholt
Occasional Contributor III

Thanks @XanderBakker , looks great and I find the comments very helpful! I am getting an error on line 6 though - object not found roadintersect. When I change the variable to roads I get a general function failure. Not sure what's going on there.

0 Kudos