Is it possible to create a rule that flags polylines if it intersects along the boundary of a polygon.
I know I can get this if it intersects anywhere with Intersects(). Yet trying to create it if the line runs along the boundary.
Thanks in advance!
~jake
Solved! Go to Solution.
OK, so using the geometries to do this turns out to be a bit more complicated than Touches()...
A line completely lies on a polygon's boundary if
Maybe it can be done easier, but that's the way it worked for my test cases...
// get all intersecting polygons
var polygons = FeaturesetByName($datastore, "TestPolygons")
var i_polygons = Intersects(polygons, $feature)
for(var i_poly in i_polygons) {
// check if each vertex of $feature is on boundary
// if not, go to the next i_poly
var vertices = Geometry($feature).paths[0]
var vertices_on_boundary = true
for(var v in vertices) {
if(!Touches(vertices[v], i_poly)) {
vertices_on_boundary = false
break
}
}
if(!vertices_on_boundary) { continue }
// check if there are polygon vertices that do not touch the line inbetween vertices that do
// if not, the line coincides with the polygon boundary
var vertices = Geometry(i_poly).rings[0]
var status = "not touching"
for(var v in vertices) {
if(Intersects(vertices[v], $feature)) {
if(status == "not touching") { status = "touching" }
if(status == "not touching anymore") { status = "error"; break }
} else {
if(status == "touching") { status = "not touching anymore" }
}
}
if(status != "error") { return 1 }
}
return 0
But it can be done much, muuuuch easier with @MikeMillerGIS 's suggestion of Relate. The DE-9IM model is completely new to me, but I found the right expression quite fast by drawing the matrix.
var polygons = FeaturesetByName($datastore, "TestPolygons")
var i_polygons = Intersects(polygons, $feature)
for(var i_poly in i_polygons) {
if(Relate(i_poly, $feature, "FF*TT*FF*")) { return 1 }
}
return 0
Mike,
Thanks for the suggestion. I think this might work but the documentation for this and Dimensionally Extended 9-Intersection Model is very lacking in general. Have you used this before?
~jake
Try Touches().
Can't test right now, but something like this could work:
// load polygons
var polygons = FeaturesetByName(...)
// get intersecting polygons
var i_polygons = Intersects(polygons, $feature)
// return 1 at the first touching polygon
for(var i_poly in i_polygons) {
if(Touches(i_poly, $feature)) { return 1}
}
// else return 0
return 0
Thanks for the input. Unfortunately this doesn't give the output I'm looking for
I applied the rule to the Parcel Lines to check if the line was on the PlatIndex boundary (which is a polygon) for ease of viability. As you can see the non-intersecting (red) feature works as expected but the other (green) indicates its on the boundary. I'm looking to get a contiguous overlap.
A collogue and I came up with this code below but I cant get past the 3rd line of code " var vertBndry = Geometry(polygonFeature).rings[0];" returning an error of "unexpected null". I may not be able to get the rings of an intersected polygon feature. If use the the same logic on a polygon feature class "var vertBndry = Geometry($feature).rings[0];" it works just fine. Not sure if there is a limitation to the applied feature.
The idea of this script convert polygon rings to line segments and check the vertices of the parcel line against the ring lines. If all the vertices of the parcel line fall on the converted ring lines it is on the boundary.
var polygonFeature = Intersects(FeatureSetByName($datastore, 'PlatIndex'),$feature)
var vertFeat = Geometry($feature).paths[0][0];
var vertBndry = Geometry(polygonFeature).rings[0];
var cnt_vertFeat= count(vertFeat);
var cnt_vertBndry = count(vertBndry) // number of verticies in ring
if (vertFeat > 1 && vertBndry > 1) {
for (var vb = 0; vb < cnt_vertBndry; vb++) {
var polylineJSON = {
"paths": [vb, vb+1],
"spatialReference": { "wkid": 3857 }
};
var line = Polyline(polylineJSON);
var onbndry = 1
for (var vf = 0; vf < cntVert; vf++){
var intCnt = Intersects(point(verts[vf]),line)
onbndry = 0
if (intCnt<1) {
break
}
}
if (onbndry==1) {
return onbndry
}
}
return onbndry
}
return 0
Any thoughts? How to get past the error or any other possible alternatives?
Thanks Johannes!
~jake
Jake,
Take a look at https://developers.arcgis.com/arcade/function-reference/geometry_functions/#relate
Mike,
Thanks for the suggestion. I think this might work but the documentation for this and Dimensionally Extended 9-Intersection Model is very lacking in general. Have you used this before?
~jake
OK, so using the geometries to do this turns out to be a bit more complicated than Touches()...
A line completely lies on a polygon's boundary if
Maybe it can be done easier, but that's the way it worked for my test cases...
// get all intersecting polygons
var polygons = FeaturesetByName($datastore, "TestPolygons")
var i_polygons = Intersects(polygons, $feature)
for(var i_poly in i_polygons) {
// check if each vertex of $feature is on boundary
// if not, go to the next i_poly
var vertices = Geometry($feature).paths[0]
var vertices_on_boundary = true
for(var v in vertices) {
if(!Touches(vertices[v], i_poly)) {
vertices_on_boundary = false
break
}
}
if(!vertices_on_boundary) { continue }
// check if there are polygon vertices that do not touch the line inbetween vertices that do
// if not, the line coincides with the polygon boundary
var vertices = Geometry(i_poly).rings[0]
var status = "not touching"
for(var v in vertices) {
if(Intersects(vertices[v], $feature)) {
if(status == "not touching") { status = "touching" }
if(status == "not touching anymore") { status = "error"; break }
} else {
if(status == "touching") { status = "not touching anymore" }
}
}
if(status != "error") { return 1 }
}
return 0
But it can be done much, muuuuch easier with @MikeMillerGIS 's suggestion of Relate. The DE-9IM model is completely new to me, but I found the right expression quite fast by drawing the matrix.
var polygons = FeaturesetByName($datastore, "TestPolygons")
var i_polygons = Intersects(polygons, $feature)
for(var i_poly in i_polygons) {
if(Relate(i_poly, $feature, "FF*TT*FF*")) { return 1 }
}
return 0
@JohannesLindner @MikeMillerGIS Very much appreciate your assistance on this!