Arcade: Get paths array from feature — why so much overhead?

1714
7
03-04-2022 01:35 PM
Labels (1)
Bud
by
Notable Contributor

Esri has a calculation attribute rule expression on GitHub called Set Ms to Index. The script loops through polyline vertices and updates the M-Values.

var current_line_geo = Geometry($feature);
var line_geo =  Dictionary(Text(current_line_geo));
var paths = line_geo['paths'];
for (var path_idx in paths){
    for (var vert_idx in paths[path_idx]){


That script works, but I'm having trouble understanding all the prep work that's involved -- for converting the feature's geometry into an array:

Feature —> Geometry —> Text —> Dictionary (type) —> Paths array (array is a key/value pair within dict)

That seems like a lot of overhead just to get at the vertices. Would someone be able to explain why all of those steps are needed — or if it can be simplified?

Thanks!

Tags (1)
7 Replies
KimGarbade
Occasional Contributor III

An Esri person would probably know the specifics, but I would imagine its just the way the objects are structures.

You need Geometry to get the "shape" of the feature.  This is probably stored in a blob or geometry data type, so you have to convert it to Text to use it later.  That text is probably formatted as JSON or some other format that can hold more than just the X,Y data of the object's shape,  so it has to be converted to a Dictionary (see below - generated by labeling simple test features with "line_geo" stolen from your first two lines of of code in your original post)

KimGarbade_0-1646431193763.png

we can see the dictionary contains an array called "paths" that stores the feature's coordinates.  So to reference that you have to pull it out of there...hence paths.

Sort of makes sense.  I image its to keep Arcade on the "Simple" side.  To reference Geometry objects directly you would probably have to use something more like ArcObjects and object oriented programming... 

.  

Bud
by
Notable Contributor

For cases where we don’t need to update paths, I wonder if something simpler could work instead:

 for (var part in Geometry($feature).paths) {
    var line_part = Geometry($feature).paths[part]

I’m not sure if I understood that correctly though.


Source:  ESRI’s GitHub of Arcade expressions - CreatePointsAlongLine

Related: Are Arcade geometry subtypes immutable? (i.e. point, polyline, polygon)

0 Kudos
MikeMillerGIS
Esri Frequent Contributor

Strongly advise against call Geometry in a loop, declare a variable outside and set that to the geometry.

Edit: I fixed this example so it does not call geo in a loop - Source:  ESRI’s GitHub of Arcade expressions - CreatePointsAlongLine

var geo = Geometry($feature);
for (var part in geo.paths) {
    var line_part = geo.paths[part]

Geometry are immutable, so you cannot change the X,Y,Z,M of one, but a trick is to convert the geometry to text and then to a dict, then you can edit the shape and return it to update the feature.  If you are not modify the geometry, then you do not need to do it.

var current_line_geo = Geometry($feature);
var line_geo =  Dictionary(Text(current_line_geo));
var paths = line_geo['paths'];
for (var path_idx in paths){
    for (var vert_idx in paths[path_idx]){

To understand paths versus just a list of vertices(or is it vertex's), lines can be multipart, each part is a path, each path is composed of 2 or more vertices. 

Hope that helps

Bud
by
Notable Contributor
0 Kudos
DrewDowling
Occasional Contributor III

Here is a great code sample for looping through polyline segments and getting the midpoint.It really helped me understand the structure in arcade

https://community.esri.com/t5/arcgis-online-questions/how-to-get-the-mid-point-x-y-of-a-polyline-seg... 

Bud
by
Notable Contributor

This example might be helpful to some people: Arcade Code Review: Set polyline M-values to cumulative length of line

 

Bud
by
Notable Contributor

For future reference, when my organization moves from Pro 2.6.8 to Pro 3.2(?):

...copy your geoemtry(can do this by calling Dictionary(geo) on it, prior to 3.2, you need to call Dictionary(Text(geo))).

Arcade modify only Z geometry

0 Kudos