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!
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)
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...
.
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)
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
Here is a great code sample for looping through polyline segments and getting the midpoint.It really helped me understand the structure in arcade
This example might be helpful to some people: Arcade Code Review: Set polyline M-values to cumulative length of line