Hi, I would to show the list of nearest substations in the popup of the areas that I'm drawing.
I've managed to get it in the console but I cannot return a list; it would be gret if i could display the first 3 from the nearest
var substat= FeatureSetByName($map,"OSM SUBSTATION",["operator"])
var searchDistance = 10;
var inrangesubstat = Intersects( substat, Buffer( $feature, searchDistance, "kilometers") );
var cnt = Count(inrangesubstat)
Console("Total Number of addresses within "+searchDistance+ "km buffer: " + cnt);
var min_dist = infinity;
for (var f in inrangesubstat){
var substDist = Round(Distance(f,$feature,"kilometers"),2);
if (substDist < min_dist) {
inrangesubstat = f.operator;
min_dist = substDist;
}
console(f.operator + ": " + " " + substDist);
}
return f.operator+": at " + " " + substDist+" km"
thanks
Solved! Go to Solution.
In that case, push the values into an array of objects ([operator, Name, distance]), sort them by distance (item 2 in the array) and write out the three smallest results.
// define Sort comparator returning IsEmpty as least values
function Comp(a,b) {
When(
IsEmpty(a[2]), -1,
IsEmpty(b[2]), 1,
IIf(a[2]>b[2],1,-1)
);
};
var substat= FeatureSetByName($map,"OSM_SUBSTATION",["operator","Name"])
var inrangesubstat = Intersects(substat, Buffer($feature, 10, "kilometers"));
// Cycle through the polygon features and find the nearest one
var geomArea=Geometry($feature)
var arr = Array(0);
var counter = 0;
for (var f in inrangesubstat){
var geomSub=Geometry(f)
var substDist = Round(Distance(geomArea,geomSub, "kilometers"),2);
arr[counter] = [f.operator, f.name, substDist];
counter++;
}
arr = Reverse(Sort(arr, Comp));
var lbl = '';
for (var k in arr){
if (k < 3) {
lbl = Concatenate([lbl, `${arr[k][2]} km: ${arr[k][0]}-${arr[k][1]}`], TextFormatting.NewLine);}
}
}
return lbl;
This is using the sorting method from this post.
Start with the Arcade documentation to get a better understanding of all the functions and how to use them.
I would also suggest the Esri Training site. They have several lessons (videos or web courses) that are free or could be covered by a maintenance agreement. They also have curated learning plans (such as this one) that are more guided.
Thanks for the answer, but the Orderby function is ordering the Substation operator name, I would to order it by substdistance, that is a variable calculated in the loop.
var substat= FeatureSetByName($map,"OSM_SUBSTATION",["operator","Name"])
var inrangesubstat = Intersects(substat, Buffer($feature, 10, "kilometers"));
// Cycle through the polygon features and find the nearest one
var min_dist = infinity;
var geomArea=Geometry($feature)
var nearestSubstat=null;
for (var f in inrangesubstat){
var geomSub=Geometry(f)
var substDist = Round(Distance(geomArea,geomSub, "kilometers"),2);
if (substDist <min_dist) {
min_dist=substDist
nearestSubstat = substDist+ "km: " + " " +f.operator+"-"+f.name
}
console(f.operator + ": " + " " + substDist);
}
return nearestSubstat
In that case, push the values into an array of objects ([operator, Name, distance]), sort them by distance (item 2 in the array) and write out the three smallest results.
// define Sort comparator returning IsEmpty as least values
function Comp(a,b) {
When(
IsEmpty(a[2]), -1,
IsEmpty(b[2]), 1,
IIf(a[2]>b[2],1,-1)
);
};
var substat= FeatureSetByName($map,"OSM_SUBSTATION",["operator","Name"])
var inrangesubstat = Intersects(substat, Buffer($feature, 10, "kilometers"));
// Cycle through the polygon features and find the nearest one
var geomArea=Geometry($feature)
var arr = Array(0);
var counter = 0;
for (var f in inrangesubstat){
var geomSub=Geometry(f)
var substDist = Round(Distance(geomArea,geomSub, "kilometers"),2);
arr[counter] = [f.operator, f.name, substDist];
counter++;
}
arr = Reverse(Sort(arr, Comp));
var lbl = '';
for (var k in arr){
if (k < 3) {
lbl = Concatenate([lbl, `${arr[k][2]} km: ${arr[k][0]}-${arr[k][1]}`], TextFormatting.NewLine);}
}
}
return lbl;
This is using the sorting method from this post.
Worked great! Thanks a lot
// define Sort comparator returning IsEmpty as least values
function Comp(a,b) {
When(
IsEmpty(a[2]), -1,
IsEmpty(b[2]), 1,
IIf(a[2]<b[2],1,-1)
);
};var substat= FeatureSetByName($map,"OSM_SUBSTATION",["operator","Name"])
var inrangesubstat = Intersects(substat, Buffer($feature, 10, "kilometers"));// Cycle through the polygon features and find the nearest one
var geomArea=Geometry($feature)
var arr = Array(0);
var counter = 0;
for (var f in inrangesubstat){
var geomSub=Geometry(f)
var substDist = Round(Distance(geomArea,geomSub, "kilometers"),2);
arr[counter] = [f.operator, f.name, substDist];
counter++;
}
arr = Reverse(Sort(arr, Comp));
var lbl = '';
for (var k in arr){
if (k < 3) {
lbl = Concatenate([lbl,`${arr[k][2]} km: ${arr[k][0]}-${arr[k][1]}`], TextFormatting.NewLine);}
}return lbl;
Ken I have a similar question. I have 2 feature layers in a map - situations, stores.
For the Situations popup I want to return any stores that are within a 2 mile radius but I can't seem to get it to work to even simply count the number stores.
Any thoughts?
What have you tried so far?
I started with this blog: https://www.esri.com/arcgis-blog/products/arcgis-online/data-management/your-arcade-questions-answer...
where I used the earthquake map listed there as basis - Nearby Cities - Closest to Furthest:
// Exclude the following calculation if the event
// magnitude is less than 3
if($feature.mag < 3) {
return ""
}
// Create a 250km buffer around the selected earthquake event
var buff = BufferGeodetic($feature, 250, 'kilometers')
// Return City Centres within 250km of what's selected
var portal = Portal("https://www.arcgis.com")
var cityLocations = FeatureSetByPortalItem(portal,"6996f03a1b364dbab4008d99380370ed", 0, ['CITY_NAME'])
var nearbyCities = Intersects(cityLocations, buff)
var cities = []
for(var f in nearbyCities){
var distance = DistanceGeodetic(f, $feature, "kilometers")
var city_distance = Dictionary("CityName",f.CITY_NAME,"Distance",distance)
cities[Count(cities)] = city_distance
}
function compareDistance(a,b){
if(a['Distance']<b['Distance'])
return -1;
if(a['Distance']>b['Distance'])
return 1;
return 0;
}
// Build the pop-up string
var popup = ''
cities = Sort(cities, compareDistance)
for(var city in cities){
popup += cities[city].CityName + ": " + ROUND(cities[city].Distance, 0) + "km" +
TextFormatting.NewLine
}
//return pop-up string
When(Count(cities) == 0, TextFormatting.NewLine + TextFormatting.NewLine +
"No major City Centres within 250km of event",
Count(cities) == 1, TextFormatting.NewLine + TextFormatting.NewLine +
"1 major City Centre within 250km of event" + TextFormatting.NewLine
+ popup,
TextFormatting.NewLine + TextFormatting.NewLine +
Count(cities) + " major City Centres within 250km of event" + TextFormatting.NewLine
+ popup)
From there I tried to swap in my stores dataset and commented out the < 3 magnitude. Both FeatureSetByName and FeatureSetById but keep ending with null values.
Have you used "console" to see what values are in various places? This helps you track down where your code is failing.
For example
Also, have you updated the variables used in the arrays to match the attributes in your services? For example, in the line
var city_distance = Dictionary("CityName",f.CITY_NAME,"Distance",distance)
does your data contain the field "CITY_NAME"?
Did not know about the console, very helpful. I am able to return the correct # of stores but it seems to be something within city_distance
The field City exists
// Exclude the following calculation if the event
// magnitude is less than 3
/*if($feature.mag < 3) {
return ""
}
*/
// Create a 250km buffer around the selected earthquake event
var buff = BufferGeodetic($feature, 2, 'miles')
// Return City Centres within 250km of what's selected
var portal = Portal("https://www.arcgis.com")
var cityLocations = FeatureSetByPortalItem(portal,"42a5957d3d7741399e279eea3cf1506b", 0, ['City'])
var nearbyCities = Intersects(cityLocations, buff)
var cities = []
//console(count(cityLocations)) returns correct
//console(count(cities)) returns 0
for(var f in nearbyCities){
var distance = DistanceGeodetic(f, $feature, "miles")
var city_distance = Dictionary("City",f.City,"Distance",distance)
cities[Count(cities)] = city_distance
}
//console(count(cities)) returns 0
function compareDistance(a,b){
if(a['Distance']<b['Distance'])
return -1;
if(a['Distance']>b['Distance'])
return 1;
return 0;
}
// Build the pop-up string
var popup = ''
cities = Sort(cities, compareDistance)
for(var city in cities){
popup += cities[city].CityName + ": " + ROUND(cities[city].Distance, 0) + "mi" +
TextFormatting.NewLine
}
//return pop-up string
When(Count(cities) == 0, TextFormatting.NewLine + TextFormatting.NewLine +
"No Stores within 2 miles of event",
Count(cities) == 1, TextFormatting.NewLine + TextFormatting.NewLine +
"1 Store within 2 miles of event" + TextFormatting.NewLine
+ popup,
TextFormatting.NewLine + TextFormatting.NewLine +
Count(cities) + " Stores within 2 miles of event" + TextFormatting.NewLine
+ popup)