Source code for cam.fillet

#-----------------------------------------------------------------------------
# Copyright 2012-2016 Claude Zervas
# email: claude@utlco.com
#-----------------------------------------------------------------------------
"""
Connect Line/Arc segments with a fillet arc.
"""
# Python 3 compatibility boilerplate
from __future__ import (absolute_import, division,
                        print_function, unicode_literals)
from future_builtins import *

# import logging

import geom

from geom import fillet


[docs]def fillet_path(path, radius, fillet_close=True, adjust_rotation=False, mark_fillet=False): """Attempt to insert a circular arc of the specified radius to blend adjacent path segments that have C0 or G0 continuity. Args: path: a list of geom.Line or geom.Arc segments. fillet_close: If True and the path is closed then add a terminating fillet. Default is False. adjust_rotation: If True adjust the A axis rotation hints to compensate for the offset caused by the fillet. mark_fillets: If True add an attribute to the fillet arc to mark it to ignore G1. Default is False. Returns: A new path with fillet arcs. If no fillets are created then the original path will be returned. """ if radius < geom.const.EPSILON or len(path) < 2: return path new_path = [] seg1 = path[0] for seg2 in path[1:]: new_segs = create_adjusted_fillet(seg1, seg2, radius, adjust_rotation=adjust_rotation, mark_fillet=mark_fillet) if new_segs: new_path.extend(new_segs[:-1]) seg2 = new_segs[-1] else: new_path.append(seg1) seg1 = seg2 new_path.append(seg1) # Close the path with a fillet if fillet_close and len(path) > 2 and path[0].p1 == path[-1].p2: new_segs = create_adjusted_fillet(new_path[-1], new_path[0], radius, adjust_rotation=adjust_rotation, mark_fillet=mark_fillet) if new_segs: new_path[-1] = new_segs[0] new_path.append(new_segs[1]) new_path[0] = new_segs[2] # Discard the path copy if no fillets were created... return new_path if len(new_path) > len(path) else path
[docs]def create_adjusted_fillet(seg1, seg2, radius, adjust_rotation=False, mark_fillet=False): """Try to create a fillet between two segments. Any GCode rendering hints attached to the segments will be preserved. Args: seg1: First segment, an Arc or a Line. seg2: Second segment, an Arc or a Line. radius: Fillet radius. adjust_rotation: If True adjust the A axis rotation hints to compensate for the offset caused by the fillet. mark_fillets: If True add an attribute to the fillet arc to mark it to ignore G1. Default is False. Returns: A tuple containing the adjusted segments and fillet arc (seg1, fillet_arc, seg2), or an empty tuple if the segments cannot be connected with a fillet arc (either they are too small, already G1 continuous, or are somehow degenerate.) """ if geom.segments_are_g1(seg1, seg2): return () farc = fillet.create_fillet_arc(seg1, seg2, radius) if farc is None: return () if mark_fillet: farc.ignore_g1 = True # Mark fillet as connecting two non-G1 segments if adjust_rotation: _adjust_fillet_rotation_hints(seg1, farc, seg2) new_segs = fillet.connect_fillet(seg1, farc, seg2) _copy_segment_attrs(seg1, new_segs[0]) _copy_segment_attrs(seg2, new_segs[2]) return new_segs
def _adjust_fillet_rotation_hints(seg1, farc, seg2): """Adjust the A axis rotation hints to compensate for the offset caused by a fillet arc. """ a1 = getattr(seg1, 'inline_start_angle', seg1.start_tangent_angle()) a2 = getattr(seg1, 'inline_end_angle', seg1.end_tangent_angle()) mu = 1.0 - seg1.mu(farc.p1) offset_angle = geom.calc_rotation(a1, a2) * mu if not geom.is_zero(offset_angle): seg1.inline_end_angle = a2 - offset_angle farc.inline_start_angle = seg1.inline_end_angle else: farc.inline_start_angle = a2 a1 = getattr(seg2, 'inline_start_angle', seg2.start_tangent_angle()) a2 = getattr(seg2, 'inline_end_angle', seg2.end_tangent_angle()) mu = seg2.mu(farc.p2) offset_angle = geom.calc_rotation(a1, a2) * mu if not geom.is_zero(offset_angle): seg2.inline_start_angle = a1 + offset_angle farc.inline_end_angle = seg2.inline_start_angle else: farc.inline_end_angle = a1 def _copy_segment_attrs(seg1, seg2): """Copy inline GCode rendering hints from seg1 to seg2.""" for name in vars(seg1): if name.startswith('inline_'): setattr(seg2, name, getattr(seg1, name))