Select to view content in your preferred language

Return the bearing of a polygon edge based on selection using Arcade

1009
6
Jump to solution
09-13-2021 11:00 AM
Jake_S
by Esri Contributor
Esri Contributor

Greetings folks,

Looking to be able to return the bearing of the side of a polygon based on a interaction.

I have a carto points feature class that I want to populate its F_ANGLE field with the bearing of the side in which intersects with a polygon. We use that bearing to change the symbology rotation. Any help would be great. 

The image below shows a polygon and a point with symblogy interacting. I'd like to get the bearing of that intersection

JS_Esri_1-1631555847574.png

I have got this working for an intersection of a line feature but not a polygon (image below). 

JS_Esri_0-1631555492520.png

Code for the intersection of lines is below, replacing the feature with a polygon does not work. Looking for someone with a bit more coding knowledge for some help

 

 

 

 

 

 

 

var LinesFC = Intersects(FeatureSetByName($datastore, "Lines", ['objectid', ''], false), $feature)
if (Count(LinesFC) > 0) {
    var line = first(LinesFC)
    var geom = Geometry(line)
    var pt0 = geom.paths[0][0]
    var brg = Bearing(pt0, Geometry($feature))
    if (brg > 90 && brg <= 360) {
        return (450 - brg)
    } 
    return (90 - brg)
}
return null

 

 

 

 

 

 

 

Thanks in advanced.

-JS

0 Kudos
1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

 

var PolyFC =Intersects(FeatureSetByName($datastore, "gewaesserkataster_sde.GWK_SDE_ADMIN.poly"), $feature)

// return early if no intersecting polygon is found
// doing it this way saves you from indenting everything in your if block
if(PolyFC == null || Count(PolyFC) == 0) {
  return null
}

// lines have the "paths" attribute, for polygons that's "rings"
var poly = First(PolyFC)
var geom = Geometry(poly)
var pt0 = geom.rings[0][0]
var brg = Bearing(pt0, Geometry($feature))
if (brg > 90 && brg <= 360) {
  return (450 - brg)
} 
return (90 - brg)

// if that works for you, cool.
// I got really inconsistent results when testing this on irregular polygons, though, 
// so I'd go with something like this:

var poly = First(PolyFC)
var vertices = Geometry(poly).rings[0]
var sr = Geometry(poly).spatialReference
// loop through the vertices
for(var r=0; r<Count(vertices)-1; r++) {
  // create a line segment between 2 adjacent vertices
  var p0 = vertices[r]
  var p1 = vertices[r+1]
  var line = Polyline({"paths": [[ [p0.x, p0.y], [p1.x, p1.y] ]], "spatialReference": sr})
  // do nothing if $feature doesn't intersect that line segment
  if(Disjoint($feature, line)) {
    continue
  }
  // return the bearing of the line segment
  var brg = Bearing(p0, p1)
  if (brg > 90 && brg <= 360) {
    return (450 - brg)
  } 
  return (90 - brg)
}
// if you land here, the feature intersects a polygon, but none of its edges
return null

 


Have a great day!
Johannes

View solution in original post

6 Replies
BillFox
MVP Frequent Contributor

Maybe something in this tool set Reporting COGO descriptions 

0 Kudos
JohannesLindner
MVP Frequent Contributor

 

var PolyFC =Intersects(FeatureSetByName($datastore, "gewaesserkataster_sde.GWK_SDE_ADMIN.poly"), $feature)

// return early if no intersecting polygon is found
// doing it this way saves you from indenting everything in your if block
if(PolyFC == null || Count(PolyFC) == 0) {
  return null
}

// lines have the "paths" attribute, for polygons that's "rings"
var poly = First(PolyFC)
var geom = Geometry(poly)
var pt0 = geom.rings[0][0]
var brg = Bearing(pt0, Geometry($feature))
if (brg > 90 && brg <= 360) {
  return (450 - brg)
} 
return (90 - brg)

// if that works for you, cool.
// I got really inconsistent results when testing this on irregular polygons, though, 
// so I'd go with something like this:

var poly = First(PolyFC)
var vertices = Geometry(poly).rings[0]
var sr = Geometry(poly).spatialReference
// loop through the vertices
for(var r=0; r<Count(vertices)-1; r++) {
  // create a line segment between 2 adjacent vertices
  var p0 = vertices[r]
  var p1 = vertices[r+1]
  var line = Polyline({"paths": [[ [p0.x, p0.y], [p1.x, p1.y] ]], "spatialReference": sr})
  // do nothing if $feature doesn't intersect that line segment
  if(Disjoint($feature, line)) {
    continue
  }
  // return the bearing of the line segment
  var brg = Bearing(p0, p1)
  if (brg > 90 && brg <= 360) {
    return (450 - brg)
  } 
  return (90 - brg)
}
// if you land here, the feature intersects a polygon, but none of its edges
return null

 


Have a great day!
Johannes
Jake_S
by Esri Contributor
Esri Contributor

Thanks for your efforts here!!!! 

Unfortunately the solutions you provided an error by the arcade compiler (see below line 3)

JS_Esri_0-1631626084748.png

I have seen this error before. the solution was to get a count of the initial FeatureSetByName intersection as seen below in line #2. Yet still gets an error with the geometry statement. 

JS_Esri_1-1631626326291.png

Where are you testing this? I am implementing this as as an Attribute rule on a enterprise geodatabase frim ArcGIS Pro 2.6.6. I wonder if there is an difference in environments.

Again you are a gem!

0 Kudos
JohannesLindner
MVP Frequent Contributor

Line 1: Try changing the boolean parameter (includeGeometry) to true.

https://developers.arcgis.com/arcade/function-reference/data_functions/#featuresetbyname

 


Have a great day!
Johannes
0 Kudos
Jake_S
by Esri Contributor
Esri Contributor

Oh man how did I miss that!!! Genius. @JohannesLindner you are my hero! I saw the same issue with inconsistent results with the first code but the second is working as expected! 

0 Kudos
JohannesLindner
MVP Frequent Contributor

Also, I'm on 2.6.3, Enterprise GDB, so no big differences there.


Have a great day!
Johannes