Select to view content in your preferred language

Using data expression to find intersection with separate polygon layer

134
6
Jump to solution
Thursday
Labels (1)
ChristineLazina11
Occasional Contributor

Hello all!

I'm hoping to find some help troubleshooting this Arcade code used in a data expression for a dashboard. I'm far from an expert on Arcade so there may be something silly I'm misunderstanding. 

The situation: 
I have one large feature layer of all sewer lines in our network, that I am looking to break into 3 separate service areas in the dashboard, so I can track stats for each service area separately. (Unfortunately I do not have the ability to edit this UN sewer line layer, and there is not an appropriate attribute in existence to filter for these service areas without using a spatial query). 

My code: 

//Define the Enterprise portal connection
var myportal = Portal("https://samplesite.net/portal"
)

// Get the line layer: UN - Sewer Lines
var SewerLines = FeatureSetByPortalItem(
    myportal,
    '2c08361d8abe4308afba3d25c857a11c',
    3,
    ['*'], 
    true
)

// Get the polygon layer: Separated Service Areas, 
//filtered for Core Service Area feature only
var CoreSvcArea = Filter(
    FeatureSetByPortalItem( 
    myportal,
    '41c17045b4cf4359a8237db163fe82a6',
    0,
    ['*'], 
    true), 
    "ServiceAreaName = 'RVSS Core Service Area'"
)

// Create an empty array to store intersecting features
var CoreLines = []

// Loop through each sewer line
for (var line in SewerLines) {
    //Check if the given line intersects any core service area polygon, 
    //Filter() returns those intersection polygon features (if any) in 
    //a new array called intersxtion
    var intersxtion = Filter(CoreSvcArea, Intersects(line, CoreSvcArea))

//If count of features in intersxtion is not 0, means an intersxtion
//with given line exists, and it is added to the end feature set
    if (Count(intersxtion) > 0) {
        // Add the intersecting line to the result array
        Push(CoreLines, line)
    }
}

// Return the intersecting sewer lines as a FeatureSet
return FeatureSet(CoreLines)

 

Issues:
When I test this code it returns the error "g.charAt is not a function". I believe I have isolated the issue as coming from the filter/intersection expression on line 34, but it could potentially be from the next few lines of code in the loop expression as that was a bit hard to isolate and test directly. Can anyone tell me what functionality inside this expression would be trying to call a string and not finding one? (this is my understanding of the error). Or if there is a better way to achieve the identification of overlapping features in this scenario I'm all ears! 

Many thanks for any insight,

Christine

0 Kudos
1 Solution

Accepted Solutions
KenBuja
MVP Esteemed Contributor

I had edited my first response to explain why you were getting that error.

In addition, there was another issue with your code. A data expression has to return a FeatureSet, but you were returning an array. You would have to convert the array of lines into a FeatureSet to use it in the dashboard.

This code should work when a service area is comprised of multiple polygons

//Define the Enterprise portal connection
var myportal = Portal("https://samplesite.net/portal");

// Get the line layer: UN - Sewer Lines
var SewerLines = FeatureSetByPortalItem(
  myportal,
  "2c08361d8abe4308afba3d25c857a11c",
  3,
  ["*"],
  true
);

// Get the polygon layer: Separated Service Areas,
//filtered for Core Service Area feature only
var CoreSvcAreas = Filter(
  FeatureSetByPortalItem(
    myportal,
    "41c17045b4cf4359a8237db163fe82a6",
    0,
    ["*"],
    true
  ),
  "ServiceAreaName = 'RVSS Core Service Area'"
);

var dict = {
  fields: Schema(SewerLines)["fields"],
  geometryType: Schema(SewerLines)["geometryType"],
  features: []
};

for (var CoreSvcArea in CoreSvcAreas) {
  for (var line in Intersects(SewerLines, CoreSvcArea)) {
    var attributes = {};
    for (var attr in line) {
      attributes[attr] = line[attr];
    }
    Push(dict["features"], { attributes: attributes });
  }
}

return FeatureSet(dict);

View solution in original post

0 Kudos
6 Replies
KenBuja
MVP Esteemed Contributor

Is each of the CoreSvcAreas a single polygon or is it multiple polygons? If it's a single polygon, then you can make this much simpler

//Define the Enterprise portal connection
var myportal = Portal("https://samplesite.net/portal");

// Get the line layer: UN - Sewer Lines
var SewerLines = FeatureSetByPortalItem(
  myportal,
  "2c08361d8abe4308afba3d25c857a11c",
  3,
  ["*"],
  true
);

// Get the polygon layer: Separated Service Areas,
// filtered for Core Service Area feature only
// This works only if there is one polygon per service area
var CoreSvcArea = First(
  Filter(
    FeatureSetByPortalItem(
      myportal,
      "41c17045b4cf4359a8237db163fe82a6",
      0,
      ["*"],
      true
    ),
    "ServiceAreaName = 'RVSS Core Service Area'"
  )
);

return Intersects(SewerLines, CoreSvcArea);

You were getting that error in the Filter function since you had a syntax wrong. Filter expects an SQL expression (a string) as the second parameter, but you were supplying it a FeatureSet (the result from the Intersects function)

ChristineLazina11
Occasional Contributor

@KenBuja thanks for your quick reply! Currently each service area is covered by a single polygon, but in the future I believe we could have multiple polygons in use for a single service area, so I was trying to cover that possibility... That being said, your code did work perfectly so it might be worth it for me to just go with that and cross the multiple poly bridge if I come to it! 

Just for my own edification, do you have any idea why my original expression may have been causing the error? 

Thanks so much, Christine

0 Kudos
KenBuja
MVP Esteemed Contributor

I had edited my first response to explain why you were getting that error.

In addition, there was another issue with your code. A data expression has to return a FeatureSet, but you were returning an array. You would have to convert the array of lines into a FeatureSet to use it in the dashboard.

This code should work when a service area is comprised of multiple polygons

//Define the Enterprise portal connection
var myportal = Portal("https://samplesite.net/portal");

// Get the line layer: UN - Sewer Lines
var SewerLines = FeatureSetByPortalItem(
  myportal,
  "2c08361d8abe4308afba3d25c857a11c",
  3,
  ["*"],
  true
);

// Get the polygon layer: Separated Service Areas,
//filtered for Core Service Area feature only
var CoreSvcAreas = Filter(
  FeatureSetByPortalItem(
    myportal,
    "41c17045b4cf4359a8237db163fe82a6",
    0,
    ["*"],
    true
  ),
  "ServiceAreaName = 'RVSS Core Service Area'"
);

var dict = {
  fields: Schema(SewerLines)["fields"],
  geometryType: Schema(SewerLines)["geometryType"],
  features: []
};

for (var CoreSvcArea in CoreSvcAreas) {
  for (var line in Intersects(SewerLines, CoreSvcArea)) {
    var attributes = {};
    for (var attr in line) {
      attributes[attr] = line[attr];
    }
    Push(dict["features"], { attributes: attributes });
  }
}

return FeatureSet(dict);
0 Kudos
ChristineLazina11
Occasional Contributor

@KenBuja Got it, that makes sense re: the Filter() parameters. And thanks so much for supplying that code for multiple polygons, that's awesome! I appreciate all your help. 

0 Kudos
KenBuja
MVP Esteemed Contributor

After giving this a little thought, there's an even faster way to do this. Cycling through each set of lines in each service area polygon to write them to a dictionary is pretty inefficient. Instead, this version unions each of the service areas into a single polygon to use in a single Intersects function. And if there is only one polygon in the service area, it skips that step.

//Define the Enterprise portal connection
var myportal = Portal("https://samplesite.net/portal");

// Get the line layer: UN - Sewer Lines
var SewerLines = FeatureSetByPortalItem(
  myportal,
  "2c08361d8abe4308afba3d25c857a11c",
  3,
  ["*"],
  true
);

// Get the polygon layer: Separated Service Areas,
//filtered for Core Service Area feature only
var CoreSvcAreas = Filter(
  FeatureSetByPortalItem(
    myportal,
    "41c17045b4cf4359a8237db163fe82a6",
    0,
    ["*"],
    true
  ),
  "ServiceAreaName = 'RVSS Core Service Area'"
);

// return the intersection if there's only one service area
if (Count(CoreSvcAreas) == 1) return Intersects(SewerLines, First(CoreSvcAreas)); 

// otherwise, union the service areas together and return the intersection
var areas = [];
for (var area in CoreSvcAreas) {
  Push(areas, area)
}
return Intersects(SewerLines, Union(areas));

 

ChristineLazina11
Occasional Contributor

Amazing, there are a decent number of records in the datasets I'm working with so any increased efficiency is well appreciated. I will use that option going forward!

0 Kudos