Select to view content in your preferred language

Arcade - Look for a matching value by iterating through overlapping polygons in a reference layer

529
2
Jump to solution
05-31-2024 07:59 AM
CarlBeyerhelm
Frequent Contributor

I’m trying to develop an Arcade expression that determines if a newly created plant occurrence feature intersects, or is near, a known plant occurrence of the same species in an underlying reference layer…keeping in mind that there could be multiple overlapping polygons in that reference layer of many different plant species.

I’ve found many examples to pull an attribute from an underlying layer, but haven't come across any that drill down through a reference layer’s multiple overlapping polygons to see if any of those have a matching plant code.  Essentially, I don't know how to iterate through a series of polygons in search of a match.

See the attached image for an example of those multiple overlapping plant polygons in a reference layer.

Any references or examples would be appreciated.  Thank you.

0 Kudos
1 Solution

Accepted Solutions
jcarlson
MVP Esteemed Contributor

It's not terribly difficult, and if you already know how to grab underlying layer attributes, you're halfway there. When we call Intersects, the result is a set of features we can loop through and look for your code. Here's how it might look:

var fs = FeatureSetByName($map, 'species_zones', ['plant_code_field'], true)

// get underlying areas
var xs = Intersects(fs, $feature)

// loop through
for (var x in xs) {
  // check if plant code matches our feature
  if (x['plant_code_field'] == $feature['plant_code_field']) {
    return 'Match!'
  }
}

// fallback if no matches
return 'No Matches!'

Some of this depends on what you want to do with the information, of course. Maybe you want to access a specific attribute of the matching zone? Maybe you want to count how many matching zones intersect?

Since the first return line is inside of the conditional block, it will end the expression as soon as it encounters a match, and won't get to the "no matches" result unless there truly are none.

Alternatively, you could do this without a loop. You could just stick a Filter on the intersection and see how many match that way. This has the benefit of being a bit faster in situations where there are lots of overlaps, but then you'd still need to use a loop or First to access actual attributes of the matching features.

var fs = FeatureSetByName($map, 'species_zones', ['plant_code_field'], true)

// get underlying areas
var xs = Intersects(fs, $feature)

// filter for code
var filt = Filter(xs, `plant_code_field = '${feature['plant_code_field']}'`)

// if any features are left in the filtered set, there was a match
return Iif(
  Count(filt) > 0,
  'Match!',
  'No Matches!'
)
- Josh Carlson
Kendall County GIS

View solution in original post

2 Replies
jcarlson
MVP Esteemed Contributor

It's not terribly difficult, and if you already know how to grab underlying layer attributes, you're halfway there. When we call Intersects, the result is a set of features we can loop through and look for your code. Here's how it might look:

var fs = FeatureSetByName($map, 'species_zones', ['plant_code_field'], true)

// get underlying areas
var xs = Intersects(fs, $feature)

// loop through
for (var x in xs) {
  // check if plant code matches our feature
  if (x['plant_code_field'] == $feature['plant_code_field']) {
    return 'Match!'
  }
}

// fallback if no matches
return 'No Matches!'

Some of this depends on what you want to do with the information, of course. Maybe you want to access a specific attribute of the matching zone? Maybe you want to count how many matching zones intersect?

Since the first return line is inside of the conditional block, it will end the expression as soon as it encounters a match, and won't get to the "no matches" result unless there truly are none.

Alternatively, you could do this without a loop. You could just stick a Filter on the intersection and see how many match that way. This has the benefit of being a bit faster in situations where there are lots of overlaps, but then you'd still need to use a loop or First to access actual attributes of the matching features.

var fs = FeatureSetByName($map, 'species_zones', ['plant_code_field'], true)

// get underlying areas
var xs = Intersects(fs, $feature)

// filter for code
var filt = Filter(xs, `plant_code_field = '${feature['plant_code_field']}'`)

// if any features are left in the filtered set, there was a match
return Iif(
  Count(filt) > 0,
  'Match!',
  'No Matches!'
)
- Josh Carlson
Kendall County GIS
CarlBeyerhelm
Frequent Contributor

Perfect!  That's exactly what I was trying to do...and I was half-way there, just didn't know it.  So, I presume that this would execute in Field Maps only:

  • When a new spatial feature is created, or is subsequently updated and/or
  • When the new feature's plant code is specified, or is subsequently changed

Thank you.

0 Kudos