Pull Attribute from multiple layers into one layer using Arcade

414
4
Jump to solution
01-24-2023 01:38 AM
RonParis
Occasional Contributor

Bare with me on this...

The scenario I have is that I have users plot points on a map. These plotted points need a column populated with a unique value from other nearby points and lines ('id'). The issue I have is that these nearby points and lines are in different layers.

I am able to achieve when the nearby points are in one layer, however I am struggling to achieve this when there are multiple layers. Below is a snippet of the Arcade...

 

 

 

 

 

// FeatureClass2
var FeatureClass2 = FeatureSetById($map, /* Layer */ "***")


// Buffer FeatureClass1
var inspBuffer = Buffer($feature,1,'m')

// Undertake an intersection between FeatureClass2
// and FeatureClass1. 
// These 2 should intersect when used correctly
var inspIntersection = Intersects(FeatureClass2, inspBuffer)

// Calculate the distance between the parcel and the current location
// Store the feature and distance as a dictionary and push it into an array
var featuresWithDistances = []
for (var f in inspIntersection) {
    Push(featuresWithDistances, 
        {
            'distance': Distance($feature, f, 'm'),
            'feature': f
        }
    )
}


function sortByDistance(a, b) {
    return a['distance'] - b['distance']
}

var sorted = Sort(featuresWithDistances, sortByDistance)

var closestFeatureWithDistance = First(sorted)


// If there is no id, return null
if (IsEmpty(closestFeatureWithDistance)) { 
    return `${closestFeatureWithDistance['feature']['id']}`
}
else {
    return null
}

 

 

 

 

 

TIA

 

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

OK for the "m", but the null check really should not work. Curious...

 

Anyway, here is one way to solve your problem:

// load the two (or more) feature classes
var featuresets = [
    FeaturesetByName($datastore, "TestLines"),
    FeaturesetByName($datastore, "TestPolygons"),
    ]
// get the id of the closest feature in a 1 meter radius
var f_buffer = Buffer($feature, 1, "meters")
var smallest_distance = 1000
var id = null
for(var i in featuresets) {
    var i_fs = Intersects(featuresets[i], f_buffer)
    for(var f in i_fs) {
        var d = Distance(f, $feature, "meters")
        if(d >= smallest_distance) { continue }
        smallest_distance = d
        id = f.id
    }
}
return id

 

 

Basically, this adds another for loop around your lines 11-23 to take care of different featuresets.

Personally, I like to write out custom Sort()s in a for loop (that is what happens under the hood in your code anyway) because then I can see what's happening all in one place. Plus, because I set the output variable to default to null (line 9), I can eliminate the null check at the end.


Have a great day!
Johannes

View solution in original post

0 Kudos
4 Replies
JohannesLindner
MVP Frequent Contributor

How should the extraced value look? Do you want the id of the closest feature, no matter if it's a point or line? Or do you want something like "closestpoint.id, closestline.id"

 

Things I noticed at a first glance:

  • GYinspIntersection and GYfeaturesWithDistances are not defined
  • Buffer and Distance have a unit attribute that takes the following values: feet | kilometers | miles | nautical-miles | meters | yards. You supply "m". I haven't tested if that works as replacement for "meters", but it's best to avoid undocumented features.
  • Your null check is the wrong way around. Either check for !IsEmpty(...) (is not empty) or swap lines 37 and 40.

Have a great day!
Johannes
0 Kudos
RonParis
Occasional Contributor

Hi Johannes,

I need the id of the closest feature, no matter whether it's a point or a line.

Regarding 'm', this is accepted as meters. Have been using for some time with no issues. The same is also true for the null check, all works as expected.

0 Kudos
JohannesLindner
MVP Frequent Contributor

OK for the "m", but the null check really should not work. Curious...

 

Anyway, here is one way to solve your problem:

// load the two (or more) feature classes
var featuresets = [
    FeaturesetByName($datastore, "TestLines"),
    FeaturesetByName($datastore, "TestPolygons"),
    ]
// get the id of the closest feature in a 1 meter radius
var f_buffer = Buffer($feature, 1, "meters")
var smallest_distance = 1000
var id = null
for(var i in featuresets) {
    var i_fs = Intersects(featuresets[i], f_buffer)
    for(var f in i_fs) {
        var d = Distance(f, $feature, "meters")
        if(d >= smallest_distance) { continue }
        smallest_distance = d
        id = f.id
    }
}
return id

 

 

Basically, this adds another for loop around your lines 11-23 to take care of different featuresets.

Personally, I like to write out custom Sort()s in a for loop (that is what happens under the hood in your code anyway) because then I can see what's happening all in one place. Plus, because I set the output variable to default to null (line 9), I can eliminate the null check at the end.


Have a great day!
Johannes
0 Kudos
RonParis
Occasional Contributor

That's done the job. Thank you @JohannesLindner 

0 Kudos