Hello
I am trying to add an indicator to my dashboard which shows the hectares of where two polygons weblayers intersect. ie the hectares of sugarcane in treatment areas. I am new to arcade so a little unsure whats the best way to go about it. The final feature set I would like to have the TA name, TA hectares, (from the TA weblayer) and the hectares in sugarcane (intersection calculation).
// Access data layers from portal
var port = Portal( 'http://www.argis.com')
var TA = FeatureSetByPortalItem(Port, 'itemid', 0)
var sugar = FeatureSetByPortalItem(Port,'itemid', 0)
//Create empty dictionary
var sugarDict = {
Fields:[
{name: “TA Name”, type:esriFieldString”},
{name: “TA Ha”, type:esriFieldDouble”},
{name: “TA Sugar”, type:esriFieldDouble”},
],
Geometry type: '',
Features: [],
};
// calculate area of sugarcane in Treatment area - below works fine in pop up
var intlayer = Intersects(TA, sugar);
var intcount = Count(intlayer);
var sugarinTA = 0;
if(intcount > 0){
for(var sugararea in intlayer){
sugarinTA += Area(Intersection(TA, sugararea),"hectares")
}
}
// Loop through and store attributes in dictionary - not sure how to do this
for (var t in TA){
var feat = {
attributes: {
TA Name: t["name"],
TA Ha: t["Area_ha"],
for (var s in sugarinTA){
var feat = {
attributes: {
TA Sugar: s["sugarinTA"],
}
}
} Push(features,feat);
Thank you so much for your help
Solved! Go to Solution.
// Access data layers from portal
var port = Portal( 'http://www.argis.com')
var fsTa = FeatureSetByPortalItem(port, 'itemid', 0)
var fsSugar = FeatureSetByPortalItem(port,'itemid', 0)
//Create empty dictionary
var sugarDict = {
fields:[
{name: "TA_Name", type: "esriFieldTypeString"},
{name: "TA_Ha", type: "esriFieldTypeDouble"},
{name: "TA_Sugar", type: "esriFieldTypeDouble"},
],
geometryType: "",
features: [],
}
// loop over the treatment area features
for(var ta in fsTa) {
// get the intersecting sugar areas
var intSugar = Intersects(fsSugar, ta)
// loop over those features and get the sum of the intersections
var sugarArea = 0
for(var s in intSugar) {
sugarArea += Area(Intersection(s, ta), "hectares")
}
// append to the output dict
var f = {attributes: {TA_Name: ta.Name, TA_Ha: Area(ta, "hectares"), TA_Sugar: sugarArea}}
Push(sugarDict.features, f)
}
// convert to Featureset and return
return Featureset(Text(sugarDict))
To format code:
I have added another layer area intersect, it appears as a field but it isn't calculating the intersect area
That's because you put the intersection with the WHA features into a separate loop. They get calculated and then overwritten without being stored in the output dict.
I would also like to group the phases
Fortunately, that is quite simple in this case. I used When() to get a default value if the phase is in neither of those groups (eg when it's null).
// blablabla
// loop over the treatment area features
for(var ta in fsTa) {
// get the intersecting sugar area
var intSugar = Intersects(fsSugar, ta)
var sugarArea = 0
for(var s in intSugar) {
sugarArea += AreaGeodetic(Intersection(s, ta), "hectares")
}
// get the intersecting WHA area
var intWHA = Intersects(fsWHA, ta)
var WHAArea = 0
for(var w in intWHA) {
WHAArea += AreaGeodetic(Intersection(w, ta), "hectares")
}
// calculate the status value
var status = When(Includes([1, 2, 3, 4], ta.Phase), "Status 1", ta.Phase == 5, "Status 2", "Default")
// append to the output dict
var f = {attributes: {TA_Status: status, TA_Ha: AreaGeodetic(ta, "hectares"), TA_Sugar: sugarArea, TA_WHA: WHAArea}}
Push(combinedDict.features, f)
}
// convert to Featureset and return
return Featureset(Text(combinedDict))
Loop through Rounds - would grouping it like above allow me to loop through the rounds and buffer and union them??
No, it's a little more complicated. Buffer(), Union(), and Area() don't work on Featuresets, only on singular Features/Geometries (or arrays in case of Union), so you need two loops:
Something like this should work:
// we don't need GroupBy, we just need the distinct values of the group field
var treatmentRounds = Distinct(fsTreatment, "Round_Num")
// outer loop over the rounds
for(var treatRound in treatmentRounds) {
// filter the Featureset
var roundNum = treatRound.Round_Num
var query = "Round_Num " + Iif(roundNum == null, "IS NULL", "= @roundNum")
var filtered = Filter(fsTreatment, query)
// inner loop over the filtered features
var buffer_geometries = []
for(var f in filtered) {
// buffer the geometry and append it to the array
Push(buffer_geometries, Buffer(f, 5, "meters"))
}
// union all those buffers into one geometry
var union_geometry = Union(buffer_geometries)
// create the new output feature
var f = {attributes: {Round_Treat: roundNum, Area_Treat: AreaGeodetic(union_geometry, "hectares")}}
Push(TreatmentDict.features, f)
}
return Featureset(Text(TreatmentDict))
// Access data layers from portal
var port = Portal( 'http://www.argis.com')
var fsTa = FeatureSetByPortalItem(port, 'itemid', 0)
var fsSugar = FeatureSetByPortalItem(port,'itemid', 0)
//Create empty dictionary
var sugarDict = {
fields:[
{name: "TA_Name", type: "esriFieldTypeString"},
{name: "TA_Ha", type: "esriFieldTypeDouble"},
{name: "TA_Sugar", type: "esriFieldTypeDouble"},
],
geometryType: "",
features: [],
}
// loop over the treatment area features
for(var ta in fsTa) {
// get the intersecting sugar areas
var intSugar = Intersects(fsSugar, ta)
// loop over those features and get the sum of the intersections
var sugarArea = 0
for(var s in intSugar) {
sugarArea += Area(Intersection(s, ta), "hectares")
}
// append to the output dict
var f = {attributes: {TA_Name: ta.Name, TA_Ha: Area(ta, "hectares"), TA_Sugar: sugarArea}}
Push(sugarDict.features, f)
}
// convert to Featureset and return
return Featureset(Text(sugarDict))
Legendary ! That worked perfectly.
I have added another layer area intersect, it appears as a field but it isn't calculating the intersect area. I have added it below.
I would also like to group the phases, they are 1,2,3,4,5. and I would like to group them into two categories (5) and (1,2,3,4)
Thank you so much for your help
var port = Portal( 'https://qgsp.maps.arcgis.com/')
var fsTa = FeatureSetByPortalItem(port, 'item', 0)
var fsWHA = FeatureSetByPortalItem(port,'item', 0)
var fsSugar = FeatureSetByPortalItem(port,'item', 0)
//Create empty dictionary
var CombinedDict = {
fields:[
{name: "TA_Status", type: "esriFieldTypeString"},
{name: "TA_Ha", type: "esriFieldTypeDouble"},
{name: "TA_WHA", type: "esriFieldTypeDouble"},
{name: "TA_Sugar", type: "esriFieldTypeDouble"},
],
geometryType: "",
features: [],
}
// loop over the treatment area features
for(var t in fsTa) {
// get the intersecting sugar areas
var intWHA = Intersects(fsWHA, t)
// loop over those features and get the sum of the intersections
var WHAArea = 0
for(var w in intWHA) {
WHAArea += AreaGeodetic(Intersection(w, t), "hectares")
}
// loop over the treatment area features
for(var ta in fsTa) {
// get the intersecting sugar areas
var intSugar = Intersects(fsSugar, ta)
// loop over those features and get the sum of the intersections
var sugarArea = 0
for(var s in intSugar) {
sugarArea += Area(Intersection(s, ta), "hectares")
}
// append to the output dict
var f = {attributes: {TA_Status:ta.Phase, TA_Ha: AreaGeodetic(ta, "hectares"), TA_WHA: WHAArea,TA_Sugar: sugarArea}}
Push(CombinedDict.features, f)
}
// convert to Featureset and return
return Featureset(Text(CombinedDict))}
To format code:
I have added another layer area intersect, it appears as a field but it isn't calculating the intersect area
That's because you put the intersection with the WHA features into a separate loop. They get calculated and then overwritten without being stored in the output dict.
I would also like to group the phases
Fortunately, that is quite simple in this case. I used When() to get a default value if the phase is in neither of those groups (eg when it's null).
// blablabla
// loop over the treatment area features
for(var ta in fsTa) {
// get the intersecting sugar area
var intSugar = Intersects(fsSugar, ta)
var sugarArea = 0
for(var s in intSugar) {
sugarArea += AreaGeodetic(Intersection(s, ta), "hectares")
}
// get the intersecting WHA area
var intWHA = Intersects(fsWHA, ta)
var WHAArea = 0
for(var w in intWHA) {
WHAArea += AreaGeodetic(Intersection(w, ta), "hectares")
}
// calculate the status value
var status = When(Includes([1, 2, 3, 4], ta.Phase), "Status 1", ta.Phase == 5, "Status 2", "Default")
// append to the output dict
var f = {attributes: {TA_Status: status, TA_Ha: AreaGeodetic(ta, "hectares"), TA_Sugar: sugarArea, TA_WHA: WHAArea}}
Push(combinedDict.features, f)
}
// convert to Featureset and return
return Featureset(Text(combinedDict))
Thank you very much 🙂 Your help is greatly appreciated! thanks for showing me how to add code also.
I couldnt see a dissolve function or option in the buffer function. Is it possible to buffer and dissolve overlapping buffers? I would like to Group a weblayer by Rounds, buffer each round and calculate the area in my dashboard element.
Thank you 🙂
Thank you!
Ok Im trying to give it a go. Would you use a group by to separate the web layer by rounds? (there is a round field) then loop through with a buffer then a union then area? The final featureset would just have area in hectares for each round
// Access data layers from portal
var port = Portal( 'https://arcgis.com/')
var fsTreatment = FeatureSetByPortalItem(port, 'itemID', 0)
//Create empty dictionary
var TreatmentDict = {
fields:[
{name: "Round_Treat", type: "esriFieldTypeString"},
{name: "Area_Treat", type: "esriFieldTypeDouble"},
],
geometryType: "",
features: [],
}
// Group feature set by round
Var treatmentround = GroupBy(fstreatment,'Round_Num',COUNT)
//Loop through Rounds - would grouping it like above allow me to loop through the rounds and buffer and union them??
// buffer group 5m
var treatbuff = BufferGeodetic(treatmentround, 5,'meters')
// union to dissolve
var treatunion = Union(treatbuff)
// calculate area treated
var AreaTreated = AreaGeodetic(treatunion, "hectares")
// append to the output dict
var f = {attributes: {Round_Treat: .Round_num , Area_Treat: AreaTreated }}
Push(TreatmentDict.features, f)
}
// convert to Featureset and return
return Featureset(Text(TreatmentDict))
Loop through Rounds - would grouping it like above allow me to loop through the rounds and buffer and union them??
No, it's a little more complicated. Buffer(), Union(), and Area() don't work on Featuresets, only on singular Features/Geometries (or arrays in case of Union), so you need two loops:
Something like this should work:
// we don't need GroupBy, we just need the distinct values of the group field
var treatmentRounds = Distinct(fsTreatment, "Round_Num")
// outer loop over the rounds
for(var treatRound in treatmentRounds) {
// filter the Featureset
var roundNum = treatRound.Round_Num
var query = "Round_Num " + Iif(roundNum == null, "IS NULL", "= @roundNum")
var filtered = Filter(fsTreatment, query)
// inner loop over the filtered features
var buffer_geometries = []
for(var f in filtered) {
// buffer the geometry and append it to the array
Push(buffer_geometries, Buffer(f, 5, "meters"))
}
// union all those buffers into one geometry
var union_geometry = Union(buffer_geometries)
// create the new output feature
var f = {attributes: {Round_Treat: roundNum, Area_Treat: AreaGeodetic(union_geometry, "hectares")}}
Push(TreatmentDict.features, f)
}
return Featureset(Text(TreatmentDict))
Hi @JohannesLindner,
I am trying to do something similar by intersecting two polygon layers to get the area of the resulting intersections.
So far I have:
var p = Portal('https://csparks.maps.arcgis.com')
var itemid = '617b93e023cc463d862f5e6836d9a8d1'
var layerid = 0
var fs1 = (FeatureSetByPortalItem(p, itemid, layerid, ['*'], true))
var itemid2 = '91196d5c9aaf4144be3a0be62de8d524'
var layerid2 = 0
var fs2 = (FeatureSetByPortalItem(p, itemid2, layerid2, ['*'], true))
var Dict = {
fields:[
{name:"park", type: "esriFieldTypeString"},
{name: "space", type: "esriFieldTypeDouble"},
],
geometryType:"",
features:[],
}
var i = 0
for (var block in fs2){
var intersect = Intersects(fs1, block)
var cnt = Count(intersect)
var riskArea = 0
for (var r in intersect){
riskArea += Area(Intersection(r, block), "hectares")
}
var feat = {
attributes: {
park: block ['UNITNAME'],
space: Round(riskArea, 2)
}}
Push(Dict.features, feat)
}
i++;
return FeatureSet (Text(Dict))
I am able to successfully get the count of each intersect if I do:
var feat = {
attributes: {
park: block ['UNITNAME'],
space: Text(cnt)
}}
but then when I add lines 22, 23, and 24 I end up getting "Test execution error: Unknown Error. Verify test data."
Thank you!