Select to view content in your preferred language

Dashboard Data Expression Intersects

92
3
Tuesday
LukeGilner1
Frequent Contributor

I'm trying to set up some data expressions in Dashboards to use with Indictor widgets.  I have a tracts layer (322 features) and a lakes layer (11,200 features) and I want to intersect these to get the total number of lakes and a sum of lake acres in the Indicator.  Here is the code, which appears to work, but takes about 20 minutes to run.  What can I do to speed this up?  Can I run an intersection before the loop to filter out most of the lakes?  There should only be about 1,020 lakes that actually intersect with the tracts.  I only know a little Arcade; most of this was done with the help of CoPilot.

var port = Portal("https://www.arcgis.com");

// Load layers with correct area field name
var tracts = FeatureSetByPortalItem(port, "b9fcbedac0384e32bc3dba6aec1a8cf6", 0, ["OBJECTID"], true);
var lakes = FeatureSetByPortalItem(port, "5564b2e702364aefba08df8c95216a1f", 0, ["OBJECTID", "Shape__Area_2"], true);

var fsDict = {
    fields: [
        { name: "OBJECTID", type: "esriFieldTypeOID" },
        { name: "LakeCount", type: "esriFieldTypeInteger" },
        { name: "Acres", type: "esriFieldTypeDouble" }
    ],
    geometryType: "",
    features: []
};

for (var t in tracts) {
    var tractGeom = Geometry(t);
    var lakeCount = 0;
    var totalAcres = 0;

    for (var lake in lakes) {
        if (Intersects(Geometry(lake), tractGeom)) {
            lakeCount += 1;
            totalAcres += lake["Shape__Area_2"] / 4046.8564224;
        }
    }

    Push(fsDict.features, {
        attributes: {
            OBJECTID: t.OBJECTID,
            LakeCount: lakeCount,
            Acres: Round(totalAcres, 1)
        }
    });
}

return FeatureSet(fsDict)

 

0 Kudos
3 Replies
KenBuja
MVP Esteemed Contributor

Doing lots of intersects is a resource hog, since the code has to make external calls for each feature in the loop. @jcarlson wrote a good post about how to store the features in memory (using his Memorize function) to speed up this process. This would be good if you wanted to create a table showing how many lakes are in each tract.

However, since you're looking to just get the sum off all the lakes in all the tracts, you can loop through the tracts FeatureSet to union them into a single feature, then use that feature in your Intersects function. You can get the count of that FeatureSet to see how many lakes there are and use the Area function to get the total area of all the lakes.

var port = Portal("https://www.arcgis.com");

// Load layers with correct area field name
var tracts = FeatureSetByPortalItem(port, "b9fcbedac0384e32bc3dba6aec1a8cf6", 0, ["OBJECTID"], true);
var lakes = FeatureSetByPortalItem(port, "5564b2e702364aefba08df8c95216a1f", 0, ["OBJECTID"], true);

var arrTracts = [];
for (var tract in tracts) {
  Push(arrTracts, tract);
}
var lakesFS = Intersects(lakes, Union(arrTracts));
return FeatureSet(
  {
    fields: [
      { name: "LakeCount", type: "esriFieldTypeSingle" },
      { name: "Acres", type: "esriFieldTypeDouble" }
    ],
    features: [
      {
        attributes:
          {
            LakeCount: Count(lakesFS),
            Acres: Area(lakesFS, "acres")
          }
      }
    ]
  }
);

 

0 Kudos
LukeGilner1
Frequent Contributor

This gives me an "Unknown Error".  I've been trying some other things, but can't figure it out.

0 Kudos
MiaWhite34
Emerging Contributor

Looping through both layers is what’s slowing it down. Pre-filter the lakes using a spatial query (e.g., Intersects or Within at the feature set level) before looping. This limits iterations to only intersecting features and cuts processing time dramatically.

0 Kudos