From 8130b57945da620239652cf993d56259bc6c002a Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Thu, 21 Jun 2018 16:31:24 -0700 Subject: [PATCH] Moved functions out of class for simpler testability --- src/Mod/Path/PathScripts/PathChamfer.py | 94 +++++++++++++++---------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathChamfer.py b/src/Mod/Path/PathScripts/PathChamfer.py index 84e6e698b8..59c5964cc5 100644 --- a/src/Mod/Path/PathScripts/PathChamfer.py +++ b/src/Mod/Path/PathScripts/PathChamfer.py @@ -30,6 +30,7 @@ import PathScripts.PathLog as PathLog import PathScripts.PathOp as PathOp import math +from PathScripts.PathGeom import PathGeom from PySide import QtCore if False: @@ -42,6 +43,59 @@ else: def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) +def removeInsideEdges(edges, shape, offset): + # An edge is considered to be inside of shape if the mid point is inside + # Of the remaining edges we take the longest wire to be the engraving side + # Looking for a circle with the start vertex as center marks and end + # starting from there follow the edges until a circle with the end vertex as center is found + # if the traversed edges include any oof the remainig from above, all those edges are remaining + # this is to also include edges which might partially be inside shape + # if they need to be discarded, split, that should happen in a post process + # Depending on the Axis of the circle, and which side remains we know if the wire needs to be flipped + def isInside(edge): + if shape.Shape.isInside(edge.Vertexes[0].Point, offset/2, True) and shape.Shape.isInside(edge.Vertexes[-1].Point, offset/2, True): + return True + return False + remaining = [e for e in edges if not isInside(e)] + # of the ones remaining, the first and the last are the end offsets + allFirst = [e.firstVertex().Point for e in remaining] + allLast = [e.lastVertex().Point for e in remaining] + first = [f for f in allFirst if not f in allLast][0] + last = [l for l in allLast if not l in allFirst][0] + #return [e for e in remaining if not PathGeom.pointsCoincide(e.firstVertex().Point, first) and not PathGeom.pointsCoincide(e.lastVertex().Point, last)] + return remaining + +def orientWireForClimbMilling(w): + face = Part.Face(w) + cw = 'Forward' == obj.ToolController.SpindleDir + wcw = 0 < face.Surface.Axis.z + if cw != wcw: + PathLog.track('flip wire') + # This works because Path creation will flip the edges accordingly + return Part.Wire([e for e in reversed(w.Edges)]) + PathLog.track('no flip', cw, wcw) + return w + +def offsetWire(obj, wire, base, offset): + PathLog.track(obj.Label) + + w = wire.makeOffset2D(offset) + if wire.isClosed(): + if not base.Shape.isInside(w.Edges[0].Vertexes[0].Point, offset/2, True): + return orientWireForClimbMilling(w) + w = wire.makeOffset2D(-offset) + return orientWireForClimbMilling(w) + + edges = removeInsideEdges(w.Edges, base, offset) + if not edges: + w = wire.makeOffset2D(-offset) + edges = removeInsideEdges(w.Edges, base, offset) + points = [] + for e in edges: + points + # determine the start point + return Part.Wire(edges) + class ObjectChamfer(PathEngraveBase.ObjectOp): '''Proxy class for Chamfer operation.''' @@ -79,51 +133,15 @@ class ObjectChamfer(PathEngraveBase.ObjectOp): basewires.extend(sub.Wires) else: basewires.append(Part.Wire(sub.Edges)) + self.edges = edges for edgelist in Part.sortEdges(edges): basewires.append(Part.Wire(edgelist)) for w in self.adjustWirePlacement(obj, base, basewires): - wires.append(self.offsetWire(obj, w, base, offset)) + wires.append(offsetWire(obj, w, base, offset)) self.wires = wires self.buildpathocc(obj, wires, [depth], True) - def offsetWire(self, obj, wire, base, offset): - PathLog.track(obj.Label) - - def removeInsideEdges(edges): - def isInside(edge): - for v in edge.Vertexes: - if base.Shape.isInside(v.Point, offset/2, True): - return True - return False - result = [] - return [e for e in edges if not isInside(e)] - - def orientWireForClimbMilling(w): - face = Part.Face(w) - cw = 'Forward' == obj.ToolController.SpindleDir - wcw = 0 < face.Surface.Axis.z - if cw != wcw: - PathLog.track('flip wire') - # This works because Path creation will flip the edges accordingly - return Part.Wire([e for e in reversed(w.Edges)]) - PathLog.track('no flip', cw, wcw) - return w - - w = wire.makeOffset2D(offset) - if wire.isClosed(): - if not base.Shape.isInside(w.Edges[0].Vertexes[0].Point, offset/2, True): - return orientWireForClimbMilling(w) - w = wire.makeOffset2D(-offset) - return orientWireForClimbMilling(w) - - edges = removeInsideEdges(w.Edges) - if edges: - return Part.Wire(edges) - w = wire.makeOffset2D(-offset) - edges = removeInsideEdges(w.Edges) - return Part.Wire(edges) - def opSetDefaultValues(self, obj): obj.Width = '1 mm' obj.ExtraDepth = '0.1 mm'