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
Solved! Go to Solution.
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...
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...
Thank you very much, Johannes! I didn't expect the solution so soon.
It works, fantastic!