-
Notifications
You must be signed in to change notification settings - Fork 347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GEOSOffsetCurve_r returns multipart geometries for simple single line input curve #477
Comments
|
Do you know if this works on earlier versions of GEOS? joinStyle = 1 is ROUND, which is the default, and most robust to compute, so that probably removes one possible cause. |
|
The offset curve implementation is quite complex, so this could be a challenge to debug. The code uses overlay ( It will be useful to add |
|
Actually, on further investigation it doesn't appear to be a regression at all, and can be reproduced back in 3.7.0! |
Well, that's good news and bad news! Perhaps an improved offset curve algorithm is called for. |
|
Indeed. It's one of the places where GEOS functionality is > JTS functionality still, right? Not many of those now that JTS has GeometryFixer. |
|
Yes, OffsetCurve is in GEOS but not in JTS. Mainly because I couldn't
think of an algorithm that was robust enough. :). Perhaps its time to
revisit that. Or work on fixing the GEOS code (although not sure the
fundamental approach is fixable).
JTS does have an ability to generate "raw" offset curves, coming out of the
buffer code. And ironically that works fine for the geometry in this
issue. As it will for any line which is "smooth enough" (without very
acute angles relative to the offset distance). Perhaps there is a way to
detect this situation, and use the simpler & more robust code if so.
…On Fri, Sep 10, 2021 at 11:00 AM Paul Ramsey ***@***.***> wrote:
Indeed. It's one of the places where GEOS functionality is > JTS
functionality still, right? Not many of those now that JTS has
GeometryFixer.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#477 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA25SXLA7W6LIVTLJ5OI6ELUBJBUDANCNFSM5DBC4IMQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
|
Worth reading through https://github.com/libgeos/geos/blob/main/src/operation/buffer/BufferBuilder.cpp#L131 to see the current hack. It's amazing it works! Anyways, retrofitting it into the new snaprounder might make it magically work on this case. |
Yes, have read through the code. Agreed it is amazing that it works - except when it doesn't! The code actually uses snapping overlay, not snap-rounding (the distinction being that snapping snaps to the existing vertices, whereas snap-rounding snaps to a precision grid, and hence changes all vertices.). It's possible that using OverlayNG with the |
|
I was wondering whether snap-rounding might not be better precisely because it's a bigger hammer. |
|
Well, some research required. Here's an alternative. My understanding of the current algorithm is:
Now, in step 3 the intersection is really being used as a way of selecting line segments from the raw offset curve. Using intersection is likely to run up against all kinds of internal optimization/robustness mitigation issues. Potentially instead this could be done by a query using a distance tolerance (possible followed by a shortest-path pruning). This might be more robust and amenable to tuning. |
|
Some further investigation on this. I tried out the idea mentioned above of simply checking if the raw offset curve has any self-intersections and if not return it. This works for the case and distance (= 1) on this issue. However, it doesn't work on that case for distance = 2! So not sure if it's really worth adding that to the code. I'm still keen on the idea of extracting portions of the full buffer curve based on a distance test (and some other logic). That will be the next prototype, so stay tuned. |
|
Thank you @dr-jts , it's great to hear that you're investigating this! (I'd love to assist, but I don't have any useful input to make here 😆 ) |
|
Happy to get involved, @nyalldawson . Offset curves have been on the JTS roadmap for far too long, so it's time to get them sorted out. One way you can perhaps help is by providing some ideas / feedback on the semantics of offset curve generation in more complicated cases. (Do you have requirements from projects you work on? Or do you have any examples from other GIS systems which produce offset curves? ) In particular, I need to decide on the following questions:
|
I guess I would expect this: but honestly in the case of a self-intersecting line I'd say that any semi-reasonable output is ok.
This is a really tricky one. I don't think a single part input should ever result in a multi-part output for this operation. So I think the output in this case should be: |
|
Thanks for the feedback, @nyalldawson. I can see the argument for having the offset curve "loop back on itself" if the input does. However, that has some tricky technical challenges that I'm not sure can be overcome at the moment. But it's worth thinking about. It's also the behaviour implemented in various papers and other systems I've seen, which makes me wonder if there's reasons for that. As for not including extra loops, that seems totally reasonable to me. It might be worth making this an option, with the single-line value being the default. |
Fair enough! Like I said, I think it's entirely reasonable to output any semi-plausible curve in this circumstance. I guess another reasonable option could just be this: (i.e. drop all loops first, then do the offset) |
|
This issue will be fixed when locationtech/jts#810 is ported to GEOS. |
|
Thanks @dr-jts -- that's fantastic news! |
|
This should be fixed by #530. @nyalldawson Are you able to verify? |
|
This still true as of 0a32f15, @nyalldawson? |
|
I'll give this a test ASAP -- just back from leave this week and got a bit of catching up to do! |
|
@nyalldawson Any chance to test this? |
|
@nyalldawson ping? |
|
Closed by #530 |
GEOSOffsetCurve_r used to return a wrong result for some simple single lines (described in libgeos/geos#477). This has been fixed in GEOS 3.11. Update the test to check with the correct result and use the previous result as fallback for the previous GEOS versions.
GEOSOffsetCurve_r used to return a wrong result for some simple single lines (described in libgeos/geos#477). This has been fixed in GEOS 3.11. Update the test to check with the correct result and use the previous result as fallback for the previous GEOS versions.
GEOSOffsetCurve_r used to return a wrong result for some simple single lines (described in libgeos/geos#477). This has been fixed in GEOS 3.11. Update the test to check with the correct result and use the previous result as fallback for the previous GEOS versions.





Given the input linestring:
Attempt to offset this curve using GEOSOffsetCurve_r, with the parameters:
width: 1
quadsegs: 8
joinStyle: 1
mitreLimit: 5
The result is a multi line string, with a segment of the line missing:
Shown below, where green = original line, blue = offset result showing the gap in the middle of the line:
(tested on GEOS 3.9)
The text was updated successfully, but these errors were encountered: