Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

Hello! I am working on a project that requires plenty of (mostly 2D) polygon clipping and offsetting operations. I know that COMPAS already supports offsetting, however, it can get pretty messy when the resulting offset is a complex or concave polygon. I was wondering if you have considered adding such operations as native COMPAS functions or perhaps creating an extension wrapping functionality either from Shapely or Clipper2 libraries. I did some tries with these two, and the result in offsetting is much more consistent with what you'd get from running it in Rhino for instance (I used Pyclipper as a wrapper). The results are as follows:
In black you can see the original polygon, red the COMPAS offset, blue the Pyclipper, and green the Shapely offset.
image

You must be logged in to vote

Replies: 7 comments · 1 reply

Comment options

Hi,

Yes, that would indeed be useful. Ideally this would be done through the plugin mechanism. This means that we would define a bunch of pluggable functions in compas.geometry and then provide implementations using backends such as Shapely or Clipper by creating plugins for the pluggables.

Perhaps you can help get this started by compiling a list of useful pluggables?

You must be logged in to vote
0 replies
Comment options

My though exactly, so we can also offer an implementation using Rhino. I can compile a list of pluggables that is would be defined using one of the aforementioned libraries and post a new comment! I've been working with @baehrjo using shapely, and have already developed a few function in this direction.

You must be logged in to vote
0 replies
Comment options

Shapely defines the following methods for geometry clipping:

  • intersection
  • union
  • unary_union (more efficient with multiple geometries)
  • difference (a representation of the intersection of this object with the other geometric object)
  • symmetric_difference (Returns a representation of the points in this object not in the other geometric object, and the points in the other not in this geometric object)

For offset, it defines the buffer method. Additionally, @baehrjo has developed a function for a multi-offset, where a list of distances can be entered, one per polygon side, resulting in a non-uniform offset.
The buffer method could also be used to create a line and polyline thicken function, turning them into a polygon by offsetting them on both sides.

Wrapping these methods should be relatively straightforward, perhaps with the exception of handling multipolygons (a collection of polygons) and polygons with holes. In our workflow, a polygon with holes is represented as a tuple containing first the outer polygon and then any hole polygon or None, and a multipolygon is a tuple containing tuples of the previously defined polygons.

You must be logged in to vote
1 reply
@nmaslarinos
Comment options

Small update on the polygon translation between COMPAS and Shapely. After reviewing the data types native to Shapely, I would say that the COMPAS Polygon (and Polyline, Line etc) most closely resembles the Shapely LineString, as an order list of Points. Shapely Polygons are more related with a surface, as the can have holes, something that COMPAS Polygons don't support.

Comment options

check the prerelease of COMPAS 2.0 (latest changes on the main branch). some 2D booleans already implemented with shapely as backend...

You must be logged in to vote
0 replies
Comment options

from compas.geometry import Polygon, Translation

from compas_view2.app import App

a = Polygon.from_sides_and_radius_xy(4, 1.0)
b = Polygon.from_sides_and_radius_xy(4, 1.0)

b.transform(Translation.from_vector([0.5, 0, 0]))

c = a.boolean_intersection(b)
d = a.boolean_symmetric_difference(b)

viewer = App()
viewer.add(c)
for item in d:
    mesh = item.to_mesh(earclip=True)
    viewer.add(mesh, facecolor=(1, 0, 0), show_lines=False)
viewer.run()
You must be logged in to vote
0 replies
Comment options

It looks very exciting! Let me know if I could help somehow with other boolean or offset methods :)

You must be logged in to vote
0 replies
Comment options

#1163

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
💡
Ideas
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.