-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
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
Unable to perform polygon boolean operation on a list of polygons simultaneously #29784
Comments
@Dr4kzor, in order to solve your issue, you first you need to make sure the tiles do overlap, having them adjacent might not be sufficient. If they do not overlap, you could grow them with Then, you could perform some sort of flood fill algorithm against your tiles to ensure connectivity. So there would be two cases: one type of merge that increases your overall merged polygons area and ones that do not contribute to the overall area. You would have to keep track of each visited tile. In the end, you'll get a set of merged areas (polygons) that way. But yes, having ability to add all polygons before doing a single merge operation would simplify your use case, and is actually possible under the hood, though I'm not sure whether it's worth it to have ability to add an array of polygons as it could potentially make the implementation/interface more complex. |
@avencherus responding to your comment, I feel like the implementation might need to be changed to cater more use cases. There's a notion of In this case, having clip_polygons_2d(polygons_subject : Array, polygons_clip : Array)
intersect_polygons_2d(polygons_subject : Array, polygons_clip : Array)
exclude_polygons_2d(polygons_subject : Array, polygons_clip : Array) Instead of: clip_polygons_2d(polygon_a : PoolVector2Array, polygon_b : PoolVector2Array)
intersect_polygons_2d(polygon_a : PoolVector2Array, polygon_b : PoolVector2Array)
exclude_polygons_2d(polygon_a : PoolVector2Array, polygon_b : PoolVector2Array) This is was I meant by additional complexity added to core, but if it worth it, these could be rewritten to operate on array of polygons rather than single polygons, one would have to use it like that: # Notice constructing additional arrays to merge single polygons
Geometry.clip_polygons_2d([polygon_a], [polygon_b]) As these methods return an array of polygons as a result of operation already, yeah this starts to make more sense to me to have this that way, so you could pass the result of operation to other methods as input quite easily. |
I see. If I understand, you'd have to load all your polygons into a subject array and feed them in that way. Leaving the clip array empty. You may have to break with the language of the api, because the complexity is in the implementation details and their concepts. Does an end user that wants to merge distant polygons need to first get familiar with the concepts of subject polygons and clip polygons? I think your concerns about the complexity of those two arrays of polygons is correct. Stuffing parameters into arrays does add a little bit of mental overhead, which would go away once you got familiar with how it was working. But needing to understand additional concepts about the back-end is going to add quite a bit of friction. If it was left with no documentation, it would be very time consuming to figure out how it was working, at least if you're like me and approaching it ignorant of the library. I imagine you could keep with the 1 to 1 polygon if you created multiple functions or additional parameters that changed the behavior. So here would be some ideas that are hopefully more specific, but I can't be too specific since I'm not familiar with the API and what you're having to wrangle together.
Or phrasing the same parameter differently.
Below are two more thoughts about signatures. The first just combines everything into the fewest points. the second one has clipping types as a parameter. Then most of the documentation about the clipping is contained in the TYPE/MODE constants.
|
This is not really a problem as the signature could be changed to accept subject polygons only for
These would lead to changing how the underlying library works or coming up with custom solutions which feels quite specific indeed. The logic behind those would certainly blow up (similarly to what I've done in the past via scripting). Passing an array would solve most of the use cases I believe. The approach with replacing single polygon parameters with arrays seems fine to me. I think it might be possible to accept
I thought about that but the user would find it more difficult to search for specific methods, and it's hard to come up with a generic name for polygon boolean operation, mixing up names like |
I think that the @Xrayez The Clipper library has a property called PreserveCollinear, if you are merging together the outlines of a NavigationPolygon then this option must be active because otherwise the resulting polygon won't be able to connect with his neighbours. Could it be possible to have it as an additional optional parameter? ( default to false ) |
@Daw11 I haven't used The new version of Clipper (10.0.0, beta) doesn't have these init options at all, so it could imply that those could be mere "hacks" in the 6.4.2. So if we're ever going to upgrade to the newest version at some point, those options would make no sense anymore. Perhaps But I think it wouldn't hurt to add this as optional parameter only for merge operation where this would make more sense. For that matter, an optional |
Good points. That was also a syntax mistake on my part, I was a bit fixated on showing all at once it would take constants, but yeah, ended up being an unintentional default parameter. XD |
@Xrayez I did a test and with PreserveCollinear at However I noticed that with version 6.4.2 I looked at the source code of version 10 and at first glance it seems that they don't remove the extra edges anymore. I think that it's disabled in version 6.4.2 because in that version it didn't always work. On a different topic, |
I think it doesn't matter for Clipper, or in fact similar is done already internally by sorting vertices according to Y coordinate as a requirement for Vatti algorithm:
|
I've created GeometryTools module with both Clipper 6.4.2 and 10.0.0 backends.
var polygons = [] # a list of polygons...
var params = PolyBooleanParameters.new()
params.preserve_collinear = true
params.strictly_simple = true # Also available.
var solution = GeometryTools2D.merge_multiple_polygons(polygons, [], params) Both options are ignored in |
Tbh I wish I could implement this within the engine, but the current Godot's philosophy is that the API must be kept simple, and these methods with so much parameters belong to a module, so I just consider closing all of the geometry-related PR's of mine unless they prove to be essential to Godot. |
I've opened a master proposal to handle all related stuff regarding this: godotengine/godot-proposals#913, please describe your use cases there if you really need this to be implemented in core, otherwise feel free to use GeometryTools module for now. 🙂 |
Godot version:
3.2, 4.0
Pertains to #28987.
Issue description:
Currently it's not as easy to perform polygon boolean operations with
Geometry
methods likemerge_polygons_2d
on a list of polygons. One has to use these methods in multiple iterations, for instance, to merge a list of polygons that may or may not be adjacent to each other, see this use case.Steps to reproduce:
@Dr4kzor, @avencherus
The text was updated successfully, but these errors were encountered: