Select to view content in your preferred language

Is line on polygon boundary flag

1025
6
Jump to solution
01-18-2023 05:54 AM
Jake_S
by Esri Contributor
Esri Contributor

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.

Example.jpg

Thanks in advance!

~jake

0 Kudos
2 Solutions

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

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

  • each vertex of the line touches the polygon
  • there are no polygon vertices that do not touch the line inbetween vertices that do

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_0-1674207686255.png

 

 

 


Have a great day!
Johannes

View solution in original post

Jake_S
by Esri Contributor
Esri Contributor

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

View solution in original post

0 Kudos
6 Replies
JohannesLindner
MVP Frequent Contributor

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

Have a great day!
Johannes
Jake_S
by Esri Contributor
Esri Contributor

Thanks for the input. Unfortunately this doesn't give the output I'm looking for

JS_Esri_0-1674135420003.png

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

 

0 Kudos
MikeMillerGIS
Esri Frequent Contributor
Jake_S
by Esri Contributor
Esri Contributor

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

0 Kudos
JohannesLindner
MVP Frequent Contributor

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

  • each vertex of the line touches the polygon
  • there are no polygon vertices that do not touch the line inbetween vertices that do

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_0-1674207686255.png

 

 

 


Have a great day!
Johannes
Jake_S
by Esri Contributor
Esri Contributor

@JohannesLindner @MikeMillerGIS  Very much appreciate your assistance on this!

0 Kudos