Select to view content in your preferred language

Create polylines of sertain length with attribute rules

802
2
Jump to solution
04-03-2022 01:50 PM
ОльгаПинчук
New Contributor

Hi,

I have an editing task on the portal to create polyline features in the feature service , that will have aliquot (integer) length in meters (like 1m, 2m, 3m, etc). I know, it is possible to do with ArcGIS Pro, but I need this option on the portal.

It means that user will not be able to create the line with length 2.5 meters and 3.8 meters, only 2 and 4 m.

I thought it is possible to do with attribute rules and geometry functions in Arcade, but didn't find the right function for this. 

Probably, there are some other ways to make this operation posible during editing on the portal.

Thank you

 

0 Kudos
1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

There isn't a dedicated function for that, but you can do it using a little math and array manipulation:

// get the new distance of the polyline
// we should make sure it isn't zero.
var old_length = Length(Geometry($feature), "meters")
var new_length = Max(1, Round(old_length))  // 4.2 -> 4; 4.5 -> 5; 0.1 -> 1

// we want to change the geometry of the $feature, which means changing the 
// paths attribute, where the points are stored.
// this is an array, and arrays can't be changed, so we have to copy all
// points except the last one (because we want to change that) into a new array.
var path = Geometry($feature).paths[0]
var new_path = []
for(var p = 0; p < Count(path)-1; p++) {
    Push(new_path, [path[p].x, path[p].y])
}
// we only change the last segment of the polyline, so we have to get the 
// new length and the angle of that segment
var last_length = Distance(path[-2], path[-1])
var new_last_length = last_length + (new_length - old_length)
var a = Angle(path[-2], path[-1]) * PI / 180  // degrees to radians

// now we can use simple trigonometry to calculate the new last point and
// append it to the array.
Push(new_path, [
    new_path[-1][0] + new_last_length * Cos(a),  // new_x = old_x + distance * cos(angle)
    new_path[-1][1] + new_last_length * Sin(a)   // new_y = old_x + distance * sin(angle)
    ])

// and then we convert the point array to a polyline and return that.
return Polyline({"paths": [new_path], "spatialReference": Geometry($feature).spatialReference})

 

Use this expression as a Calculation Attribute Rule on the Shape field, triggers: Insert and Update.

 

This will change the last segment of the polyline to make the polyline an integer length. Well, almost: there seem to be some rounding errors...

JohannesLindner_0-1649052835353.pngJohannesLindner_1-1649052850182.png

JohannesLindner_2-1649052877984.png

 

 


Have a great day!
Johannes

View solution in original post

2 Replies
JohannesLindner
MVP Frequent Contributor

There isn't a dedicated function for that, but you can do it using a little math and array manipulation:

// get the new distance of the polyline
// we should make sure it isn't zero.
var old_length = Length(Geometry($feature), "meters")
var new_length = Max(1, Round(old_length))  // 4.2 -> 4; 4.5 -> 5; 0.1 -> 1

// we want to change the geometry of the $feature, which means changing the 
// paths attribute, where the points are stored.
// this is an array, and arrays can't be changed, so we have to copy all
// points except the last one (because we want to change that) into a new array.
var path = Geometry($feature).paths[0]
var new_path = []
for(var p = 0; p < Count(path)-1; p++) {
    Push(new_path, [path[p].x, path[p].y])
}
// we only change the last segment of the polyline, so we have to get the 
// new length and the angle of that segment
var last_length = Distance(path[-2], path[-1])
var new_last_length = last_length + (new_length - old_length)
var a = Angle(path[-2], path[-1]) * PI / 180  // degrees to radians

// now we can use simple trigonometry to calculate the new last point and
// append it to the array.
Push(new_path, [
    new_path[-1][0] + new_last_length * Cos(a),  // new_x = old_x + distance * cos(angle)
    new_path[-1][1] + new_last_length * Sin(a)   // new_y = old_x + distance * sin(angle)
    ])

// and then we convert the point array to a polyline and return that.
return Polyline({"paths": [new_path], "spatialReference": Geometry($feature).spatialReference})

 

Use this expression as a Calculation Attribute Rule on the Shape field, triggers: Insert and Update.

 

This will change the last segment of the polyline to make the polyline an integer length. Well, almost: there seem to be some rounding errors...

JohannesLindner_0-1649052835353.pngJohannesLindner_1-1649052850182.png

JohannesLindner_2-1649052877984.png

 

 


Have a great day!
Johannes
ОльгаПинчук
New Contributor

Thank you very much, Johannes! I didn't expect the solution so soon.

It works, fantastic!

0 Kudos