Using Intersect Attribute Rule on Overlapping Polygons?

458
5
Jump to solution
06-23-2022 04:17 PM
Amarz
by
Occasional Contributor II

Hello,

My Problem: I wanted to use an Attribute Rule on my Address layer (APN field) to intersect the Parcel layer and return the APN field with the proper feature.. The problem I am running into, is that the Parcel layer has overlapping polygons in some area and my logic can only figure out how to return the 1st intersect.

My Goal: To use a attribute rule that intersects the Parcel & does something similar to the logic below:

for Parcel.APN

if Parcel.Unit is not null

if Address.Unit == Parcel.Unit 

    return Parcel.APN

else return First on Parcel.APN intersect.

I am not sure add this functionality into my script.

I am able to get the return first using:

 

 

 

 

var fsParcel = FeatureSetByName($datastore, "Parcel", ["APN"])
var fsParcelIntersect = Intersects(fsParcel, $feature)
var Parcel = First(fsParcelIntersect)

return Iif(IsEmpty(Parcel), Null, Parcel.APN);

 

 

 

 

 But am lacking the logic and understanding to include an if statement that works.

Any help would be appreciated.

Tags (2)
0 Kudos
2 Solutions

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

Something like this?

var fsParcel = FeatureSetByName($datastore, "Parcel", ["APN", "Unit"])  // load Unit, too
var fsParcelIntersect = Intersects(fsParcel, $feature)

// this block returns the APN of the parcel whose unit is equal to the address's unit
for(var Parcel in fsParcelIntersect) {
    if(Parcel.Unit != null && Parcel.Unit == $feature.Unit) {
        return Parcel.APN
    }
}
// if we land here, none of the intersected parcels have the address's unit
// just return the first one
var Parcel = First(fsParcelIntersect)
return IIF(Parcel == null, null, Parcel.APN)

Have a great day!
Johannes

View solution in original post

0 Kudos
JohannesLindner
MVP Frequent Contributor

Your syntax is OK.

You don't need the elses here, because when you return, the rest of the code gets skipped and isn't executed. But that's a small, optional thing.

Back() only works on arrays, not on feature sets, I just added an idea to change that.

So to return the last feature, you need to sort the featureset. Assuming you have some key field (I use OBJECTID here), you could do it like that:

var fsParcel = FeatureSetByName($datastore, "Parcel", ["OBJECTID", "APN", "SitusUnitNumber", "SitusStreetNumber"])
var fsParcelIntersect = OrderBy(Intersects(fsParcel, $feature), "OBJECTID")

// loop through parcel features
for (var Parcel in fsParcelIntersect) {
    // unit number is not empty and matches -> return APN
    if (Parcel.SitusUnitNumber != null && Parcel.SitusUnitNumber ==$feature.Unit){
        return Parcel.APN
    }
    // unit number is empty, but street number matches -> return APN
    if (Parcel.SitusUnitNumber == null && Parcel.SitusStreetNumber == $feature.Add_Number){
       return Parcel.APN
    }
    // both unit number and street number are empty/0 -> return last parcel's APN
    if (Parcel.SitusUnitNumber == null && Parcel.SitusStreetNumber == "0"){
        // to get the last feature, reverse the featureset and call First()
        var LastParcel = First(OrderBy(fsParcelIntersect, "OBJECTID DESC"))
        return Iif(IsEmpty(LastParcel), Null, LastParcel.APN)
    }
}
// if we land here, none of the intersected parcels has the address's Unit
// returns first intersect
var Parcel = First(fsParcelIntersect)
return Iif(IsEmpty(Parcel), Null, Parcel.APN)

 

I don't really understand your last check. If both SitusUnitNumber and SitusStreetNumber are empty (I guess that what "0" represents), why do you want to get the last parcel instead of just letting the loop get to the next parcel?


Have a great day!
Johannes

View solution in original post

0 Kudos
5 Replies
JohannesLindner
MVP Frequent Contributor

Something like this?

var fsParcel = FeatureSetByName($datastore, "Parcel", ["APN", "Unit"])  // load Unit, too
var fsParcelIntersect = Intersects(fsParcel, $feature)

// this block returns the APN of the parcel whose unit is equal to the address's unit
for(var Parcel in fsParcelIntersect) {
    if(Parcel.Unit != null && Parcel.Unit == $feature.Unit) {
        return Parcel.APN
    }
}
// if we land here, none of the intersected parcels have the address's unit
// just return the first one
var Parcel = First(fsParcelIntersect)
return IIF(Parcel == null, null, Parcel.APN)

Have a great day!
Johannes
0 Kudos
Amarz
by
Occasional Contributor II

Thank you! I didn't know how to input the if statement! This works beautifully.

0 Kudos
Amarz
by
Occasional Contributor II

@JohannesLindner 

I am trying to add additional if statements where I have found other errors in the the outcome. After it does its first inspection of:

 

    if(Parcel.Unit != null && Parcel.Unit == $feature.Unit) {
        return Parcel.APN

 

I was attempting to add 

 

     // Checking to see if Parcel unit is pull, and there is a street number that matches the address, return that APN   
    } else if (Parcel.SitusUnitNumber == null && Parcel.SitusStreetNumber == $feature.Add_Number){
       return Parcel.APN
    // else checking if Parcel Unit is null and Parcel Address = 0, return the last item in the intersect array.
    } else if (Parcel.SitusUnitNumber == null && Parcel.SitusStreetNumber == "0"){
        var Parcel = Back(fsParcelIntersect)
        return Iif(IsEmpty(Parcel), Null, Parcel.APN)

 

The script validates, but does not return as expected. My guess is a syntax error. Do you have  sec to look at it?

 

var fsParcel = FeatureSetByName($datastore, "Parcel", ["APN", "SitusUnitNumber", "SitusStreetNumber"])
var fsParcelIntersect = Intersects(fsParcel, $feature)

// this returns the APN of the Parcel whose unit is equal to the address's unit
for (var Parcel in fsParcelIntersect) {
    if (Parcel.SitusUnitNumber != null && Parcel.SitusUnitNumber ==$feature.Unit){
        return Parcel.APN
     
    } else if (Parcel.SitusUnitNumber == null && Parcel.SitusStreetNumber == $feature.Add_Number){
       return Parcel.APN
    
    } else if (Parcel.SitusUnitNumber == null && Parcel.SitusStreetNumber == "0"){
        var Parcel = Back(fsParcelIntersect)
        return Iif(IsEmpty(Parcel), Null, Parcel.APN)
    }

}
// if we land here, none of the intersected parcels has the address's Unit
// returns first intersect
var Parcel = First(fsParcelIntersect)
return Iif(IsEmpty(Parcel), Null, Parcel.APN);

 

I appreciate your feedback. Thank you.

0 Kudos
JohannesLindner
MVP Frequent Contributor

Your syntax is OK.

You don't need the elses here, because when you return, the rest of the code gets skipped and isn't executed. But that's a small, optional thing.

Back() only works on arrays, not on feature sets, I just added an idea to change that.

So to return the last feature, you need to sort the featureset. Assuming you have some key field (I use OBJECTID here), you could do it like that:

var fsParcel = FeatureSetByName($datastore, "Parcel", ["OBJECTID", "APN", "SitusUnitNumber", "SitusStreetNumber"])
var fsParcelIntersect = OrderBy(Intersects(fsParcel, $feature), "OBJECTID")

// loop through parcel features
for (var Parcel in fsParcelIntersect) {
    // unit number is not empty and matches -> return APN
    if (Parcel.SitusUnitNumber != null && Parcel.SitusUnitNumber ==$feature.Unit){
        return Parcel.APN
    }
    // unit number is empty, but street number matches -> return APN
    if (Parcel.SitusUnitNumber == null && Parcel.SitusStreetNumber == $feature.Add_Number){
       return Parcel.APN
    }
    // both unit number and street number are empty/0 -> return last parcel's APN
    if (Parcel.SitusUnitNumber == null && Parcel.SitusStreetNumber == "0"){
        // to get the last feature, reverse the featureset and call First()
        var LastParcel = First(OrderBy(fsParcelIntersect, "OBJECTID DESC"))
        return Iif(IsEmpty(LastParcel), Null, LastParcel.APN)
    }
}
// if we land here, none of the intersected parcels has the address's Unit
// returns first intersect
var Parcel = First(fsParcelIntersect)
return Iif(IsEmpty(Parcel), Null, Parcel.APN)

 

I don't really understand your last check. If both SitusUnitNumber and SitusStreetNumber are empty (I guess that what "0" represents), why do you want to get the last parcel instead of just letting the loop get to the next parcel?


Have a great day!
Johannes
0 Kudos
Amarz
by
Occasional Contributor II

EDIT: removing, due to user error!

 

I didn't realize the 'OBJECTID DESC' was not asking for Description, but in fact descending... and was removing it from my test script..

 var LastParcel = First(OrderBy(fsParcelIntersect, "OBJECTID DESC"))

 The accepted solution above does exactly what is needed.

 

EDIT2: After additional testing, I removed the 3rd if statement, and used the syntax of 

var LastParcel = First(OrderBy(fsParcelIntersect, "OBJECTID DESC"))
return Iif(IsEmpty(LastParcel), Null, LastParcel.APN)

outside of the FOR loop to return the APN.

0 Kudos