Select to view content in your preferred language

Field Maps Tips & Tricks: Using Arcade to Find Intersecting Polygons

2463
8
07-21-2023 08:31 AM
KerriRasmussen
Esri Contributor
10 8 2,463

Before UC Sarah Saint-Ruth and I presented a webinar on Intuitive Field Workflows with ArcGIS Field Maps and Arcade. During the webinar we received a question asking if it were possible to use Arcade to summarize polygon areas that fall within another polygon in a pop-up? The specific example that was asked about was, can you summarize land use types that fall within a tax parcel? Yes- you can! Both layers will need to be vector layers for this expression to work. Below is a sample expression and the results as seen in the pop-up. And a big thank you to my colleague Chris Dunn for authoring these awesome expressions.

We will start with the Intersects() function to find the geometry of areas that are intersecting. Next, we will create a dictionary, this will allow us to iterate through the different land use types that are intersecting our parcel and if we have more than one area of the same land use type, we can then add those areas together, instead of overwriting the pervious sum. That iteration process as seen in the for loop below the dictionary. We also calculate the geographic area for each one of the land use areas, in this case we are using square meters. Using an If statement, we will check for the types of land use that fall inside that parcel and if that type is inside the parcel, we will count the total area for that land use type. And finally, we return fields with our land use type and the corresponding area totals.

 

 

 

 

 

//Return land_polys
var land_polys = Intersects($feature, FeatureSetByName($map, "Land Use"))

//Hide element if no data is found
if (count(land_polys)<1){
  return null
} 

//Create empty array for land use codes and dictionary for field values
var land_uses = []
var land_d = Dictionary()

//Iterate and add to dictionary, adding to value if key exists
for (var l in land_polys) {
  
  //Intersect the selected feature with the current iterated feature
  var land = Intersection($feature, l)

  //Set variables for land use and area
  var l_use = l.LU
  var l_area = AreaGeodetic(land, "square meters")

  //Check for land use key in dict
  if (HasKey(land_d, l_use)==true) {
    //If the land use code is in the dictionary, get the area from the dictionary and add the current area to it
    var current_area = land_d[l_use]
    var total_area = current_area + l_area
    land_d[l_use] = total_area
  
  } else {
    //If the land use code is not in the dictionary, add it with the current area
    land_d[l_use] = l_area
    Push(land_uses,
    {"fieldName":l_use})
  }
}

return {
    type: 'fields',
    title: 'Land Use Sq Meters',
    //description : '',
    fieldInfos: land_uses,
    attributes : land_d
  }

 

 

 

 

 

Pop-up using arcade for land use table and chart.Pop-up using arcade for land use table and chart.

 

As you can see from the pop-up, we have 3 land use types that fall within this parcel, and we can see the total sq meters for each of the 3 types. We also have a pie chart displaying the data below the fields. The code is the same as the code above, with the exception of the else and return statements. In this case, we are returning a pie chart instead of the fields as shown above.

 

 

 

 

 

//Return land_polys
var land_polys = Intersects($feature, FeatureSetByName($map, "Land Use"))

//Hide element if no data is found
if (count(land_polys)<1){
  return null
}

//Create empty array for land use codes and dictionary for field values
var land_uses = []
var land_d = Dictionary()

//Iterate and add to dictionary, adding to value if key exists
for (var l in land_polys) {
  
  //Intersect the selected feature with the current iterated feature
  var land = Intersection($feature, l)

  //Set variables for land use and area
  var l_use = l.LU
  var l_area = AreaGeodetic(land, "square meters")

  //Check for land use key in dict
  if (HasKey(land_d, l_use)==true) {
    //If the land use code is in the dictionary, get the area from the dictionary and add the current area to it
    var current_area = land_d[l_use]
    var total_area = current_area + l_area
    land_d[l_use] = total_area
  
  } else {
    //If the land use code is not in the dictionary, add it with the current area
    land_d[l_use] = l_area
    Push(land_uses, l_use)
  }
}

return {
    type: 'media',
    // title : 'The title for all media in the element',
    // description : '',
    attributes : land_d,  // replace this dictionary with your own key-value pairs,
    mediaInfos: [{
        type : 'piechart', //linechart | barchart | piechart | columnchart
        title : 'Land Use Breakdown',
        // caption : '',
        altText : '', //altText will be read by screen readers
        value : {
          fields: land_uses,  // choose what attributes to use in the chart
          //normalizeField : '',  // the name of the attribute to normalize by or value
        }
      }]
  }

 

 

 

 

 

This is a great use case for Arcade and shows the power of spatial expressions. Arcade can also be used to calculate the number of points in a polygon and just like we did here, you can summarize by the type of point. And bonus, this expression will work both online and offline! Arcade goes beyond just attribute queries and allows you to take advantage of the spatial aspect of your data. And while these types of expressions are incredibly useful and let’s face it, pretty cool, I do recommend using them sparingly. Using lots of Arcade expressions in your maps can impact map performance, especially if you are using spatial expressions. So be adventurous when it comes to Arcade, but also make sure you use it wisely.  With great power, comes great responsibility.

 

8 Comments