Using Arcade to Find the Nearest Address Point

8414
17
Jump to solution
10-10-2019 02:44 PM
PeterDalrymple
Occasional Contributor

Hello!

I have a web map with a point layer representing manholes and a point layer representing addresses. I am attempting to create an Arcade expression that will display the nearest address point in the popup of a selected manhole. I'm trying to do this by creating a buffer around the selected manhole, calculating the distance of each address point intersecting the buffer, and returning the address of the nearest address point. No matter how I format the code below (I won't get into everything that I've tried), I do get one address point, but it is neither the nearest or the farthest manhole. I have tried sorting, ordering, and using compare functions for the intersecting address points, but I don't seem to have access to the distance value in order to grab the closest one. Can anyone tell me if I'm going about this the right way or if this is even possible? Thanks in advance!!!

var searchDist = 200;
var addresses = Intersects(FeatureSetById($map, "Primary_Address_3482"), Buffer( $feature, searchDist, "feet"));
var cnt = Count(addresses)
Console("Total Number of addresses within buffer: " + cnt);
var nearestaddress;
for (var f in addresses){
 var addressDist = Round(Distance(f, $feature, "feet"),2);
 Console(f.FULL_ADDR + ": " + " " + addressDist)
}

f.FULL_ADDR

1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

Hi peter.dalrymple ,

You are close. The distances are correctly reported to the console. The only thing you need is to get the nearest.

Try this:

var searchDist = 200;
var addresses = Intersects(FeatureSetById($map, "Primary_Address_3482"), Buffer( $feature, searchDist, "feet"));
var cnt = Count(addresses)
Console("Total Number of addresses within buffer: " + cnt);
var nearestaddress;
var min_dist = 250;
for (var f in addresses){
 var addressDist = Round(Distance(f, $feature, "feet"),2);
 if (addressDist < min_dist) {
     nearestaddress = f.FULL_ADDR;
     min_dist = addressDist;
 }
 Console(f.FULL_ADDR + ": " + " " + addressDist);
}

return nearestaddress;

View solution in original post

17 Replies
XanderBakker
Esri Esteemed Contributor

Hi peter.dalrymple ,

You are close. The distances are correctly reported to the console. The only thing you need is to get the nearest.

Try this:

var searchDist = 200;
var addresses = Intersects(FeatureSetById($map, "Primary_Address_3482"), Buffer( $feature, searchDist, "feet"));
var cnt = Count(addresses)
Console("Total Number of addresses within buffer: " + cnt);
var nearestaddress;
var min_dist = 250;
for (var f in addresses){
 var addressDist = Round(Distance(f, $feature, "feet"),2);
 if (addressDist < min_dist) {
     nearestaddress = f.FULL_ADDR;
     min_dist = addressDist;
 }
 Console(f.FULL_ADDR + ": " + " " + addressDist);
}

return nearestaddress;
PeterDalrymple
Occasional Contributor

Thanks Xander Bakker‌, that works great! I was struggling with that last bit.

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi peter.dalrymple ,

I'm glad it worked. If you have any doubt, please let me know and I will provide some more explanation.

0 Kudos
PeterDalrymple
Occasional Contributor

Hi Xander Bakker‌,

Do you have any suggestions as to how I might iterate the addresses chain, so that it grows the buffer if the cnt is less than 1? I've tried a couple of loops and if then statements, but the logic seems circular. Is this possible? Are there any examples you know of that could serve as a guide?

Thanks!

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi Peter Dalrymple ,

You can do that, but this could have a performance hit if you would have to do multiple buffers and intersects to get a result. Have you tried making the search distance larger instead?

Here is something you could try, although I haven't tested it and don't recommend doing this:

var searchDist = 200;
var maxloops = 10;
var factor = 2;

for (var i in maxloops) {
    var addresses = Intersects(FeatureSetById($map, "Primary_Address_3482"), Buffer( $feature, searchDist, "feet"));
    var cnt = Count(addresses)
    if (cnt > 0) {
        Console("Total Number of addresses within buffer: " + cnt);
        var nearestaddress;
        var min_dist = searchDist * 2;
        for (var f in addresses){
            var addressDist = Round(Distance(f, $feature, "feet"),2);
            if (addressDist < min_dist) {
                nearestaddress = f.FULL_ADDR;
                min_dist = addressDist;
            }
        Console(f.FULL_ADDR + ": " + " " + addressDist);
        }
        return nearestaddress;    
    }
    searchDist = searchDist * factor;
}

return "no results...";
0 Kudos
PeterDalrymple
Occasional Contributor

Thanks Xander Bakker‌,

That didn't work, but I'm not sure I could tell you exactly why.  Popup wants to return "no results..." even when there are intersecting features. I don't think I'll be going that route anyway, since the address result losses relevance once it's that far away. Returning a coordinate or a message is probably more effective in that case. 

Either way, it's informative to see how you would nest that logic. I haven't seen a lot of examples like that, so thank you!

Based upon your comments, I assume that performing multiple buffers and intersects is still less performant than returning and calculating distance for a 100-200 (or even 1000) feature list?

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi peter.dalrymple ,

I thinks so. Basically since it will make multiple requests to the server and that will probably result in a lower performance. Too bad to hear that it doesn't work, but I agree, it would probably not be the way to go.

0 Kudos
NaomiBegg2
Occasional Contributor III

Hi Xander Bakker‌ I'm trying to do this where it is looking within the same feature class to find the closest group next to it.  I've made the silly mistake of using the above code however now it just references itself as being the nearest (which makes sense!) most of the time the distances are 0 (again good), but sometimes they aren't (which is weird). 

How do I add a filter into the script so that it jumps over its own feature and only looks at the others within that layer?

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi njbegg ,

Can you share the expression that you have at this moment?

0 Kudos