@turf/boolean-contains: Add MultiPolygon support for non-polygon types#3010
Conversation
|
Thanks heaps for putting this together @rexxars. To some of your questions:
We asked ourselves this recently, and discovered some performance differences for what should be equivalent approaches. Before pressing ahead, we wanted to understand why that was happening first. Though yes, ideally we would have a single implementation that served both operations.
Generally speaking, we try to have each package export a single function (helpers and meta being the exceptions). Any other packages that do that is doing so probably because we've never had a good place to keep common code in the monorepo. We're half way through adding an internal code only package. Suspect between your two PRs there might be some good candidates? |
Curious! Not a blocker for this PR, was just curious about the context around it
Many of the same methods are implemented in
For reference, these are all the (currently) exported methods from
I could see the rationale for exporting the
Yes, that appears correct. |
|
I would guess it's mostly historical "just in case" exporting. Can you see any drawbacks to the below as a plan:
Not asking you to commit to any of this beyond what you've already done. Just making the most of your recent perusal of those two packages. |
|
Yep, happy with that plan. If I could be slightly selfish, I'd love to have this merged and released and then do some follow-up PRs to address point 2-4 (happy to help with this and more, but they're not backwards incompatible changes). I'm trying to use this library in groq-js (for our geo functions) and that would unblock that work :) |
a320a79 to
abb5048
Compare
mfedderly
left a comment
There was a problem hiding this comment.
A quick look makes me think there's at least one logic bug in this PR, and the fact that we've got within and contains as completely separate implementations seems a little rough. I wonder if we should revisit this from a "we should just mirror de9im's implementation" angle before continuing to maintain both of these packages in their current state. I'm not convinced that either of these implementations are actually spec-complaint at the moment.
Thoughts?
abb5048 to
f093628
Compare
mfedderly
left a comment
There was a problem hiding this comment.
Sorry, I think I missed another case that will need some attention, but this time in the MultiLineString implementation.
As an aside: these tests are fantastic (thank you!), and you should totally take credit in the contributors section of package.json if you'd like to.
| return false; | ||
| } | ||
| } | ||
| return true; |
There was a problem hiding this comment.
I think that this has a similar false negative problem with a MultiLineString where the first one is on a border and the second one is at least partly inside.
As an aside I looked at the de9im package's implementation of this and they just check the line centroids which makes me a little uncomfortable.
One thing they do seem to do nicely though is upgrade to the Multi equivalents to keep the implementation a little tidier. I think part of why this implementation is tough is because you can't actually reuse the isLineInPoly in this way because of the nuance of a multi check actually allowing some border-only geometries along the way.
…n-MultiPolygon check Per DE-9IM, contains(a, b) requires that no point of b lies in the exterior of a and that at least one point of b's interior lies in the interior of a. isMultiLineStringInMultiPolygon required every line to individually have an interior segment, so a MultiLineString with one line on a polygon boundary and another line in the interior was incorrectly rejected. Split isLineInPoly into a lineInPolyStatus helper that classifies a line as outside/boundary/interior against a polygon (isLineInPoly behavior is unchanged). The MultiLineString check now rejects only if a line touches the exterior, and accepts only if at least one line has a segment strictly in some polygon's interior. Adds true/false fixtures for the boundary-plus-interior and all-boundary cases, both validated against JSTS.
Yep, you were right - my apologies. I was requiring every line to have an interior segment, when the "at least one interior point" condition should apply across the MultiLineString as a whole. A line lying entirely on a boundary is fine, as long as one of its siblings "dips into" the interior. I've pushed a fix. Since Added fixtures for both the boundary-plus-interior case (true) and the all-lines-on-boundary case (false), and both agree with JSTS.
Same - a centroid of a line that wanders in and out of a polygon can land pretty much anywhere, so I steered away from that approach. One thing worth noting: a line spanning two polygons that touch at a single point would still return false here, since each line is checked against individual polygons rather than the union. Can't happen for properly disjoint MultiPolygons, so I'd suggest deferring that to the de9im-alignment follow-up, maybe? If not, let me know and I can take a stab at it here.
Thanks! I'm already in there based on another PR I did earlier, I believe :) |

Extends
booleanContainsto support MultiPolygon as the containing geometry for additional geometry types. Previously,booleanContains(MultiPolygon, X)only worked when X was a Polygon.New supported combinations:
Follows DE-9IM "contains" semantics:
Questions:
booleanContainsdocumentation states booleanContains(a, b) is equivalent to booleanWithin(b, a) - if that's true, why doesbooleanWithinnot import thebooleanContainsmodule and swap the argument order instead of redefining all the logic?@private(such ascompareCoords). I wasn't sure if I should export the new helper methods or not, and if they should be marked as private