Source code for fabex.strategies.outline_fill

from ..bridges import use_bridges

from ..utilities.chunk_utils import (
    chunks_refine,
    chunks_to_mesh,
    connect_chunks_low,
    sample_chunks,
    sort_chunks,
)
from ..utilities.logging_utils import log
from ..utilities.operation_utils import (
    get_layers,
    get_move_and_spin,
)
from ..utilities.parent_utils import parent_child_distance
from ..utilities.shapely_utils import shapely_to_chunks
from ..utilities.silhouette_utils import get_operation_silhouette
from ..utilities.simple_utils import progress


[docs] async def outline_fill(o): log.info("~ Strategy: Outline Fill ~") get_operation_silhouette(o) climb_CW, climb_CCW, conventional_CW, conventional_CCW = get_move_and_spin(o) minx, miny, minz, maxx, maxy, maxz = o.min.x, o.min.y, o.min.z, o.max.x, o.max.y, o.max.z pathchunks = [] zlevel = 1 polys = o.silhouette.geoms chunks = [] for p in polys: p = p.buffer(-o.distance_between_paths / 10, o.optimisation.circle_detail) # first, move a bit inside, because otherwise the border samples go crazy very often changin between # hit/non hit and making too many jumps in the path. chunks.extend(shapely_to_chunks(p, 0)) pathchunks.extend(chunks) lastchunks = chunks firstchunks = chunks approxn = (min(maxx - minx, maxy - miny) / o.distance_between_paths) / 2 i = 0 for porig in polys: p = porig while not p.is_empty: p = p.buffer(-o.distance_between_paths, o.optimisation.circle_detail) if not p.is_empty: nchunks = shapely_to_chunks(p, zlevel) if o.movement.insideout == "INSIDEOUT": parent_child_distance(lastchunks, nchunks, o) else: parent_child_distance(nchunks, lastchunks, o) pathchunks.extend(nchunks) lastchunks = nchunks percent = int(i / approxn * 100) progress("Outlining Polygons ", percent) i += 1 pathchunks.reverse() if not o.inverse: # dont do ambient for inverse milling lastchunks = firstchunks for p in polys: d = o.distance_between_paths steps = o.ambient_radius / o.distance_between_paths for a in range(0, int(steps)): dist = d if a == int(o.cutter_diameter / 2 / o.distance_between_paths): if o.optimisation.use_exact: dist += o.optimisation.pixsize * 0.85 # this is here only because silhouette is still done with zbuffer method, # even if we use bullet collisions. else: dist += o.optimisation.pixsize * 2.5 p = p.buffer(dist, o.optimisation.circle_detail) if not p.is_empty: nchunks = shapely_to_chunks(p, zlevel) if o.movement.insideout == "INSIDEOUT": parent_child_distance(nchunks, lastchunks, o) else: parent_child_distance(lastchunks, nchunks, o) pathchunks.extend(nchunks) lastchunks = nchunks if o.movement.insideout == "OUTSIDEIN": pathchunks.reverse() for chunk in pathchunks: if o.movement.insideout == "OUTSIDEIN": chunk.reverse() if climb_CW or conventional_CCW: chunk.reverse() pathSamples = chunks_refine(pathchunks, o) pathSamples = await sort_chunks(pathSamples, o) chunks = [] layers = get_layers(o, o.max_z, o.min.z) log.info(f"Sampling Object: {o.name}") chunks.extend(await sample_chunks(o, pathSamples, layers)) log.info("Sampling Finished Successfully") log.info("Sorting") chunks = await sort_chunks(chunks, o) chunks = await connect_chunks_low(chunks, o) if o.movement.ramp: for ch in chunks: ch.ramp_zig_zag(ch.zstart, None, o) if o.use_bridges: log.info(chunks) for bridge_chunk in chunks: use_bridges(bridge_chunk, o) chunks_to_mesh(chunks, o)