mikedh / pocketing

Fill 2D regions with traversals for generating tool paths
MIT License
24 stars 2 forks source link

contour_parallel does not work with polygons #1

Open LuisVinTM opened 1 year ago

LuisVinTM commented 1 year ago

Hello,

I am using Trimesh to work on STL files, generating slices at different Z heights et then generating a surfacing toolpath for CNC Milling. contour_parallel.py looks perfect for my purpose, however it doesnt work : When i use the function to generate a toolpath on polygon or multipolygon it gives the error "'MultiPolygon' object has no attribute 'exterior'" I am thinking maybe it is a problem due to new shapely versions?

Thanks!

JayasinghePasan commented 1 month ago

Hello,

I am using Trimesh to work on STL files, generating slices at different Z heights et then generating a surfacing toolpath for CNC Milling. contour_parallel.py looks perfect for my purpose, however it doesnt work : When i use the function to generate a toolpath on polygon or multipolygon it gives the error "'MultiPolygon' object has no attribute 'exterior'" I am thinking maybe it is a problem due to new shapely versions?

Thanks!

Hi, I'm also facing this issue, Did you find any solution?

JayasinghePasan commented 4 weeks ago

Replace the offset_graph() function at the pocketing/polygons.py with the function below. It should work :)

def offset_graph(polygon, distance, min_area=1e-3):
    """
    Generate a graph from a polygon offset inwards until
    the polygon is consumed.

    Parameters
    -------------
    polygon : shapely.geometry.Polygon
        Source geometry to offset
    distance : float
        Distance each step will be offset by
    min_area : float
        Polygons smaller than this will be
        considered fully consumed

    Returns
    -------------
    graph : networkx.DiGraph
        Topology of offsets
    offsets : dict
        The actual offset geometry for each node
        {node key : shapely.geometry.Polygon}
    """

    # make sure distance is negative
    distance = -np.abs(distance)
    # generate the graph of offset polygons
    g = nx.DiGraph()
    # which polygons need to be visited
    queue = collections.deque([polygon])
    # store the polygons at each offset level
    offsets = {}

    while len(queue) > 0:
        current = queue.pop()
        current_index = hash(current)
        offsets[current_index] = current
        buffered = current.buffer(distance)

        # If buffered is a MultiPolygon, process each part
        if isinstance(buffered, MultiPolygon):
            for part in buffered.geoms:
                if part.area >= min_area:
                    part = Polygon(shell=part.exterior.coords, holes=[i.coords for i in current.interiors])
                    g.add_edge(current_index, hash(part))
                    queue.append(part)
        elif isinstance(buffered, Polygon):
            if buffered.area >= min_area:
                buffered = Polygon(shell=buffered.exterior.coords, holes=[i.coords for i in current.interiors])
                g.add_edge(current_index, hash(buffered))
                queue.append(buffered)

    return g, offsets