Source code for fabex.strategies.waterline

from math import ceil


from ..utilities.chunk_utils import (
    chunks_refine,
    limit_chunks,
    sort_chunks,
)
from ..utilities.parent_utils import parent_child_distance
from ..utilities.shapely_utils import shapely_to_chunks


[docs] async def waterline(o): if o.optimisation.use_opencamlib: get_ambient(o) chunks = [] await oclGetWaterline(o, chunks) chunks = limit_chunks(chunks, o) if (o.movement.type == "CLIMB" and o.movement.spindle_rotation == "CW") or ( o.movement.type == "CONVENTIONAL" and o.movement.spindle_rotation == "CCW" ): for ch in chunks: ch.reverse() strategy.chunks_to_mesh(chunks, o) else: topdown = True chunks = [] await progress_async("Retrieving Object Slices") await prepare_area(o) layerstep = 1000000000 if o.use_layers: layerstep = floor(o.stepdown / o.slice_detail) if layerstep == 0: layerstep = 1 # for projection of filled areas layerstart = o.max.z # layerend = o.min.z # layers = [[layerstart, layerend]] ####################### nslices = ceil(abs((o.min_z - o.max_z) / o.slice_detail)) lastslice = spolygon.Polygon() # polyversion layerstepinc = 0 slicesfilled = 0 get_ambient(o) for h in range(0, nslices): layerstepinc += 1 slicechunks = [] # lower the layer by the skin value so the slice gets done at the tip of the tool z = o.min_z + h * o.slice_detail - o.skin if h == 0: z += 0.0000001 # if people do mill flat areas, this helps to reach those... # otherwise first layer would actually be one slicelevel above min z. islice = o.offset_image > z slicepolys = image_to_shapely(o, islice, with_border=True) poly = spolygon.Polygon() # polygversion lastchunks = [] for p in slicepolys.geoms: poly = poly.union(p) # polygversion TODO: why is this added? nchunks = shapely_to_chunks(p, z + o.skin) nchunks = limit_chunks(nchunks, o, force=True) lastchunks.extend(nchunks) slicechunks.extend(nchunks) if len(slicepolys.geoms) > 0: slicesfilled += 1 # if o.waterline_fill: layerstart = min(o.max_z, z + o.slice_detail) # layerend = max(o.min.z, z - o.slice_detail) # layers = [[layerstart, layerend]] ##################################### # fill top slice for normal and first for inverse, fill between polys if not lastslice.is_empty or ( o.inverse and not poly.is_empty and slicesfilled == 1 ): restpoly = None if not lastslice.is_empty: # between polys if o.inverse: restpoly = poly.difference(lastslice) else: restpoly = lastslice.difference(poly) # print('filling between') if (not o.inverse and poly.is_empty and slicesfilled > 0) or ( o.inverse and not poly.is_empty and slicesfilled == 1 ): # first slice fill restpoly = lastslice restpoly = restpoly.buffer( -o.distance_between_paths, resolution=o.optimisation.circle_detail ) fillz = z i = 0 while not restpoly.is_empty: nchunks = shapely_to_chunks(restpoly, fillz + o.skin) # project paths TODO: path projection during waterline is not working if o.waterline_project: nchunks = chunks_refine(nchunks, o) nchunks = await sample_chunks(o, nchunks, layers) nchunks = limit_chunks(nchunks, o, force=True) ######################### slicechunks.extend(nchunks) parent_child_distance(lastchunks, nchunks, o) lastchunks = nchunks # slicechunks.extend(polyToChunks(restpoly,z)) restpoly = restpoly.buffer( -o.distance_between_paths, resolution=o.optimisation.circle_detail ) i += 1 # print(i) i = 0 # fill layers and last slice, last slice with inverse is not working yet # - inverse millings end now always on 0 so filling ambient does have no sense. if ( (slicesfilled > 0 and layerstepinc == layerstep) or (not o.inverse and not poly.is_empty and slicesfilled == 1) or (o.inverse and poly.is_empty and slicesfilled > 0) ): fillz = z layerstepinc = 0 bound_rectangle = o.ambient restpoly = bound_rectangle.difference(poly) if o.inverse and poly.is_empty and slicesfilled > 0: restpoly = bound_rectangle.difference(lastslice) restpoly = restpoly.buffer( -o.distance_between_paths, resolution=o.optimisation.circle_detail ) i = 0 # 'GeometryCollection':#len(restpoly.boundary.coords)>0: while not restpoly.is_empty: # print(i) nchunks = shapely_to_chunks(restpoly, fillz + o.skin) ######################### nchunks = limit_chunks(nchunks, o, force=True) slicechunks.extend(nchunks) parent_child_distance(lastchunks, nchunks, o) lastchunks = nchunks restpoly = restpoly.buffer( -o.distance_between_paths, resolution=o.optimisation.circle_detail ) i += 1 percent = int(h / nslices * 100) await progress_async("Waterline Layers", percent) lastslice = poly if (o.movement.type == "CONVENTIONAL" and o.movement.spindle_rotation == "CCW") or ( o.movement.type == "CLIMB" and o.movement.spindle_rotation == "CW" ): for chunk in slicechunks: chunk.reverse() slicechunks = await sort_chunks(slicechunks, o) if topdown: slicechunks.reverse() # project chunks in between chunks.extend(slicechunks) if topdown: chunks.reverse() strategy.chunks_to_mesh(chunks, o)