# Pull Attribute from multiple layers into one layer using Arcade

414
4
01-24-2023 01:38 AM
by
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)
1 Solution

Accepted Solutions
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
4 Replies
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
by
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.

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
by
Occasional Contributor

That's done the job. Thank you @JohannesLindner