Select to view content in your preferred language

Arcade Intesect Expression for Entire Layer

1014
7
09-26-2023 05:00 AM
Labels (3)
BrandonPrice1
Frequent Contributor

Hello,

My map has a zoning layer. I want to run an expression on the entire layer whenever a feature within it is clicked. I want to calculate the total count of intersecting parcels broken down by zoning type. Is this possible? 

0 Kudos
7 Replies
jcarlson
MVP Esteemed Contributor

I mean, yes, it is possible. But that doesn't really make a lot of sense to put into a popup. What you're describing would probably take a fair bit of time to execute, depending on how many parcels and zoning features are in your two layers.

If you really want to have an Arcade-based means of listing out this information, I would suggest you use a Dashboard Data Expression. That way it will only calculate once and give you a FeatureSet that can be brought into table widgets, charts, indicators, etc.

- Josh Carlson
Kendall County GIS
0 Kudos
BrandonPrice1
Frequent Contributor

Hi Josh. Thanks. I plan to create a dashboard app with the same functionality soon. This one is an eb app (not yet public):

thumbnail.png

The zoning layer is a subset. The intersect stats would go in the feature info above (# of parcels that intersect residential, commercial, etc.). It would only run once and the map popup would be disabled. Do you know of any expression references or doc urls I can refer to so I can take a shot at this?

 

0 Kudos
jcarlson
MVP Esteemed Contributor

That doesn't sound like it would be too bad. Try something like this?

var p = FeatureSetByPortalItem(
  Portal('your portal url'),
  'itemid of parcel service',
  0,
  ['property_class'], // or whatever the field is called
  true
)

// get intersecting features
var xs_p = Intersects($feature, p)

// group and count by property class
var grp =  GroupBy(
  xs_p,
  'property_class',
  {name: 'parcel_count', expression: '1', statistic: 'COUNT'}
)

// do something with grp here

 

The final step is really up to you. If you just want text, you can loop through the grp featureset and build a string. I'd suggest looking at using an Arcade popup element to make a nicely-formatted field list. But again, that will really depend on how you want it to look and what the data looks like.

- Josh Carlson
Kendall County GIS
0 Kudos
BrandonPrice1
Frequent Contributor

This solution actually looks like the right logic for my case. Not well-versed enough to implement it though. Will need to revisit. Thanks for your help. 

0 Kudos
BrandonPrice1
Frequent Contributor

Thanks. The intent here is for the arcade to execute the intersect on all features in the entire zoning layer against all features in the parcel layer. So when the Arcade runs on a selected zoning feature, it actually will run the intersect for all the features in the layer and not just the selected feature. Arcade has no way to do this I think. I remember this being asked before.

0 Kudos
jcarlson
MVP Esteemed Contributor

Oh, it can do that. It's just going to take a while. You're essentially writing a popup expression that has no connection to the selected feature whatsoever, which is doable, but maybe not the right place for it? Regardless, it would be like this:

var prt = Portal('your portal url')

# zoning
var fs1 = FeatureSetByPortalItem(
  prt,
  'itemid of zoning layer',
  0,
  ['zoning_type'],
  true
)

# parcels
var fs2 = FeatureSetByPortalItem(
  prt,
  'itemid of parcel layer',
  0,
  ['property_class'],
  true
)

# array to hold output lines
var output_text = []

# loop through zoning
for (var f in fs1) {
  # get intersecting parcels
  var xs = Intersects(f, fs2)
  
  # do something here with the intersected parcels. depends on what you want the output to be, maybe GroupBy or something

  Push(output_text, 'a line of text')
}

# return all items in output array, separated into own lines
return Concatenate(output_text, '\n')

 

The steps inside the loop are going to depend on what you want to come out of it.

Be aware, the way Arcade is compiled and executed is not the way you wrote it. It may look like this:

  1. Get FeatureSet1 (1 simple query sent to server)
  2. Get FeatureSet2 (1 simple query sent to server)
  3. For everything in 1
    1. Do something with 2

But what actually happens:

  1. Get FeatureSet1 (1 query sent to server)
  2. For everything in 1
    1. Get a spatial subset as FeatureSet2 (1 spatial intersection query sent to server)
    2. Do something with 2

Go ahead an try it, but keep an eye on your browser's Network tab. For, say, 1000 zoning features, this means that you're going to end up with 1001 queries hitting the service endpoint, every time you click on a zoning feature. Even if the data being exchanged is minimal (which, since we're using a spatial operation, it isn't), you're going to hit a bottleneck with that many requests, and the end user experience will be a lot of loading.

I think you're better off using a Data Expression in a Dashboard, which will truly only evaluate one time, and maybe combine it with something like a "memorize" function to push both FeatureSets to RAM and keep your expression down to just 2 queries.

- Josh Carlson
Kendall County GIS
0 Kudos
BrandonPrice1
Frequent Contributor

Thanks Josh. I haven't worked on implementing this yet. I will update the thread with my findings once I get to it.

0 Kudos