def __init__(self, edge, tag, i, segm, maxZ): debugEdge(edge, 'MapWireToTag(%.2f, %.2f, %.2f)' % (i.x, i.y, i.z)) self.tag = tag self.segm = segm self.maxZ = maxZ if PathGeom.pointsCoincide(edge.valueAt(edge.FirstParameter), i): tail = edge self.commands = [] debugEdge(tail, '.........=') elif PathGeom.pointsCoincide(edge.valueAt(edge.LastParameter), i): debugEdge(edge, '++++++++ .') self.commands = PathGeom.cmdsForEdge(edge, segm=segm) tail = None else: e, tail = PathGeom.splitEdgeAt(edge, i) debugEdge(e, '++++++++ .') self.commands = PathGeom.cmdsForEdge(e, segm=segm) debugEdge(tail, '.........-') self.initialEdge = edge self.tail = tail self.edges = [] self.entry = i if tail: PathLog.debug("MapWireToTag(%s - %s)" % (i, tail.valueAt(tail.FirstParameter))) else: PathLog.debug("MapWireToTag(%s - )" % i) self.complete = False self.haveProblem = False
def commandsForEdges(self): global failures if self.edges: try: shape = self.shell().common(self.tag.solid) commands = [] rapid = None for e, flip in self.orderAndFlipEdges(self.cleanupEdges(shape.Edges)): debugEdge(e, '++++++++ %s' % ('<' if flip else '>'), False) p1 = e.valueAt(e.FirstParameter) p2 = e.valueAt(e.LastParameter) if self.tag.isSquare and (PathGeom.isRoughly(p1.z, self.maxZ) or p1.z > self.maxZ) and (PathGeom.isRoughly(p2.z, self.maxZ) or p2.z > self.maxZ): rapid = p1 if flip else p2 else: if rapid: commands.append(Path.Command('G0', {'X': rapid.x, 'Y': rapid.y, 'Z': rapid.z})) rapid = None commands.extend(PathGeom.cmdsForEdge(e, False, False, self.segm)) if rapid: commands.append(Path.Command('G0', {'X': rapid.x, 'Y': rapid.y, 'Z': rapid.z})) rapid = None return commands except Exception as e: PathLog.error("Exception during processing tag @(%.2f, %.2f) (%s) - disabling the tag" % (self.tag.x, self.tag.y, e.args[0])) #traceback.print_exc(e) self.tag.enabled = False commands = [] for e in self.edges: commands.extend(PathGeom.cmdsForEdge(e)) failures.append(self) return commands return []
def commandsForEdges(self): global failures if self.edges: try: shape = self.shell().common(self.tag.solid) commands = [] rapid = None for e, flip in self.orderAndFlipEdges(self.cleanupEdges(shape.Edges)): debugEdge(e, '++++++++ %s' % ('<' if flip else '>'), False) p1 = e.valueAt(e.FirstParameter) p2 = e.valueAt(e.LastParameter) if self.tag.isSquare and (PathGeom.isRoughly(p1.z, self.maxZ) or p1.z > self.maxZ) and (PathGeom.isRoughly(p2.z, self.maxZ) or p2.z > self.maxZ): rapid = p1 if flip else p2 else: if rapid: commands.append(Path.Command('G0', {'X': rapid.x, 'Y': rapid.y, 'Z': rapid.z})) rapid = None commands.extend(PathGeom.cmdsForEdge(e, False, False, self.segm, hSpeed = self.hSpeed, vSpeed = self.vSpeed)) if rapid: commands.append(Path.Command('G0', {'X': rapid.x, 'Y': rapid.y, 'Z': rapid.z})) rapid = None return commands except Exception as e: PathLog.error("Exception during processing tag @(%.2f, %.2f) (%s) - disabling the tag" % (self.tag.x, self.tag.y, e.args[0])) #if sys.version_info.major < 3: # traceback.print_exc(e) #else: # traceback.print_exc() self.tag.enabled = False commands = [] for e in self.edges: commands.extend(PathGeom.cmdsForEdge(e, hSpeed = self.hSpeed, vSpeed = self.vSpeed)) failures.append(self) return commands return []
def __init__(self, edge, tag, i, segm, maxZ, hSpeed, vSpeed): debugEdge(edge, 'MapWireToTag(%.2f, %.2f, %.2f)' % (i.x, i.y, i.z)) self.tag = tag self.segm = segm self.maxZ = maxZ self.hSpeed = hSpeed self.vSpeed = vSpeed if PathGeom.pointsCoincide(edge.valueAt(edge.FirstParameter), i): tail = edge self.commands = [] debugEdge(tail, '.........=') elif PathGeom.pointsCoincide(edge.valueAt(edge.LastParameter), i): debugEdge(edge, '++++++++ .') self.commands = PathGeom.cmdsForEdge(edge, segm=segm, hSpeed = self.hSpeed, vSpeed = self.vSpeed) tail = None else: e, tail = PathGeom.splitEdgeAt(edge, i) debugEdge(e, '++++++++ .') self.commands = PathGeom.cmdsForEdge(e, segm=segm, hSpeed = self.hSpeed, vSpeed = self.vSpeed) debugEdge(tail, '.........-') self.initialEdge = edge self.tail = tail self.edges = [] self.entry = i if tail: PathLog.debug("MapWireToTag(%s - %s)" % (i, tail.valueAt(tail.FirstParameter))) else: PathLog.debug("MapWireToTag(%s - )" % i) self.complete = False self.haveProblem = False
def buildpathocc(self, obj, wires, zValues, rel=False): '''buildpathocc(obj, wires, zValues, rel=False) ... internal helper function to generate engraving commands.''' PathLog.track(obj.Label, len(wires), zValues) for wire in wires: offset = wire # reorder the wire if hasattr(obj, 'StartVertex'): offset = DraftGeomUtils.rebaseWire(offset, obj.StartVertex) edges = copy.copy(offset.Edges) last = None for z in zValues: if last: if rel: self.commandlist.append(Path.Command('G1', {'X': last.x, 'Y': last.y, 'Z': last.z - z, 'F': self.vertFeed})) else: self.commandlist.append(Path.Command('G1', {'X': last.x, 'Y': last.y, 'Z': z, 'F': self.vertFeed})) for edge in edges: if not last: # we set the first move to our first point last = edge.Vertexes[0].Point if len(offset.Edges) > 1: ve = edge.Vertexes[-1] e2 = offset.Edges[1] if not PathGeom.pointsCoincide(ve.Point, e2.Vertexes[0].Point) and not PathGeom.pointsCoincide(ve.Point, e2.Vertexes[-1].Point): PathLog.debug("flip first edge") last = edge.Vertexes[-1].Point else: PathLog.debug("original first edge") else: PathLog.debug("not enough edges to flip") self.commandlist.append(Path.Command('G0', {'X': last.x, 'Y': last.y, 'Z': obj.ClearanceHeight.Value, 'F': self.horizRapid})) self.commandlist.append(Path.Command('G0', {'X': last.x, 'Y': last.y, 'Z': obj.SafeHeight.Value, 'F': self.vertRapid})) if rel: self.commandlist.append(Path.Command('G1', {'X': last.x, 'Y': last.y, 'Z': last.z - z, 'F': self.vertFeed})) else: self.commandlist.append(Path.Command('G1', {'X': last.x, 'Y': last.y, 'Z': z, 'F': self.vertFeed})) if PathGeom.pointsCoincide(last, edge.Vertexes[0].Point): for cmd in PathGeom.cmdsForEdge(edge): self.appendCommand(cmd, z, rel) last = edge.Vertexes[-1].Point else: for cmd in PathGeom.cmdsForEdge(edge, True): self.appendCommand(cmd, z, rel) last = edge.Vertexes[0].Point self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid})) if self.commandlist: self.commandlist.pop()
def buildpathocc(self, obj, wires, zValues, relZ=False, forward=True, start_idx=0): '''buildpathocc(obj, wires, zValues, relZ=False) ... internal helper function to generate engraving commands.''' PathLog.track(obj.Label, len(wires), zValues) for wire in wires: offset = wire # reorder the wire if hasattr(obj, 'StartVertex'): start_idx = obj.StartVertex edges = copy.copy(PathOpTools.orientWire(offset, forward).Edges) edges = Part.sortEdges(edges)[0]; last = None for z in zValues: PathLog.debug(z) if last: self.appendCommand(Path.Command('G1', {'X': last.x, 'Y': last.y, 'Z': last.z}), z, relZ, self.vertFeed) first = True if start_idx > len(edges)-1: start_idx = len(edges)-1 edges = edges[start_idx:] + edges[:start_idx] for edge in edges: PathLog.debug("points: {} -> {}".format(edge.Vertexes[0].Point, edge.Vertexes[-1].Point)) PathLog.debug("valueat {} -> {}".format(edge.valueAt(edge.FirstParameter), edge.valueAt(edge.LastParameter))) if first and (not last or not wire.isClosed()): PathLog.debug('processing first edge entry') # we set the first move to our first point last = edge.Vertexes[0].Point self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid})) self.commandlist.append(Path.Command('G0', {'X': last.x, 'Y': last.y, 'F': self.horizRapid})) self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid})) self.appendCommand(Path.Command('G1', {'X': last.x, 'Y': last.y, 'Z': last.z}), z, relZ, self.vertFeed) first = False if PathGeom.pointsCoincide(last, edge.valueAt(edge.FirstParameter)): #if PathGeom.pointsCoincide(last, edge.Vertexes[0].Point): for cmd in PathGeom.cmdsForEdge(edge): self.appendCommand(cmd, z, relZ, self.horizFeed) last = edge.Vertexes[-1].Point else: for cmd in PathGeom.cmdsForEdge(edge, True): self.appendCommand(cmd, z, relZ, self.horizFeed) last = edge.Vertexes[0].Point self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
def test42(self): '''Verify ellipsis results in a proper segmentation of G1 commands.''' ellipse = Part.Edge(Part.Ellipse()) cmds = PathGeom.cmdsForEdge(ellipse) # let's make sure all commands are G1 and there are more than 20 of those self.assertGreater(len(cmds), 20) self.assertTrue(all([cmd.Name == 'G1' for cmd in cmds]))
def cutWire(edges): path = [] path.append(Path.Command("G0 Z{}".format(obj.SafeHeight.Value))) e = edges[0] p = e.valueAt(e.FirstParameter) path.append(Path.Command("G0 X{} Y{} Z{}".format(p.x, p.y, obj.SafeHeight.Value))) hSpeed = obj.ToolController.HorizFeed.Value vSpeed = obj.ToolController.VertFeed.Value path.append(Path.Command("G1 X{} Y{} Z{} F{}".format(p.x, p.y, p.z, vSpeed))) for e in edges: path.extend(PathGeom.cmdsForEdge(e, hSpeed=hSpeed, vSpeed=vSpeed)) return path
def buildpathocc(self, obj, wires, zValues, relZ=False): '''buildpathocc(obj, wires, zValues, relZ=False) ... internal helper function to generate engraving commands.''' PathLog.track(obj.Label, len(wires), zValues) for wire in wires: offset = wire # reorder the wire if hasattr(obj, 'StartVertex'): offset = DraftGeomUtils.rebaseWire(offset, obj.StartVertex) edges = copy.copy(PathOpTools.orientWire(offset).Edges) last = None for z in zValues: if last: self.appendCommand(Path.Command('G1', {'X': last.x, 'Y': last.y, 'Z': last.z}), z, relZ, self.vertFeed) first = True for edge in edges: if first and (not last or not wire.isClosed()): # we set the first move to our first point last = edge.Vertexes[0].Point self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid})) self.commandlist.append(Path.Command('G0', {'X': last.x, 'Y': last.y, 'F': self.horizRapid})) self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid})) self.appendCommand(Path.Command('G1', {'Z': last.z}), z, relZ, self.vertFeed) first = False if PathGeom.pointsCoincide(last, edge.Vertexes[0].Point): for cmd in PathGeom.cmdsForEdge(edge): self.appendCommand(cmd, z, relZ, self.horizFeed) last = edge.Vertexes[-1].Point else: for cmd in PathGeom.cmdsForEdge(edge, True): self.appendCommand(cmd, z, relZ, self.horizFeed) last = edge.Vertexes[0].Point self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
def createPath(self, obj, pathData, tags): PathLog.track() commands = [] lastEdge = 0 lastTag = 0 # sameTag = None t = 0 # inters = None edge = None segm = 50 if hasattr(obj, 'SegmentationFactor'): segm = obj.SegmentationFactor if segm <= 0: segm = 50 obj.SegmentationFactor = 50 self.mappers = [] mapper = None while edge or lastEdge < len(pathData.edges): PathLog.debug("------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags))) if not edge: edge = pathData.edges[lastEdge] debugEdge( edge, "======= new edge: %d/%d" % (lastEdge, len(pathData.edges))) lastEdge += 1 # sameTag = None if mapper: mapper.add(edge) if mapper.mappingComplete(): commands.extend(mapper.commands) edge = mapper.tail mapper = None else: edge = None if edge: tIndex = (t + lastTag) % len(tags) t += 1 i = tags[tIndex].intersects(edge, edge.FirstParameter) if i and self.isValidTagStartIntersection(edge, i): mapper = MapWireToTag(edge, tags[tIndex], i, segm, pathData.maxZ) self.mappers.append(mapper) edge = mapper.tail if not mapper and t >= len(tags): # gone through all tags, consume edge and move on if edge: debugEdge(edge, '++++++++') if pathData.rapid.isRapid(edge): v = edge.Vertexes[1] if not commands and PathGeom.isRoughly( 0, v.X) and PathGeom.isRoughly( 0, v.Y) and not PathGeom.isRoughly(0, v.Z): # The very first move is just to move to ClearanceHeight commands.append(Path.Command('G0', {'Z': v.Z})) else: commands.append( Path.Command('G0', { 'X': v.X, 'Y': v.Y, 'Z': v.Z })) else: commands.extend(PathGeom.cmdsForEdge(edge, segm=segm)) edge = None t = 0 lastCmd = Path.Command('G0', {'X': 0.0, 'Y': 0.0, 'Z': 0.0}) outCommands = [] tc = PathDressup.toolController(obj.Base) horizFeed = tc.HorizFeed.Value vertFeed = tc.VertFeed.Value horizRapid = tc.HorizRapid.Value vertRapid = tc.VertRapid.Value for cmd in commands: params = cmd.Parameters zVal = params.get('Z', None) zVal2 = lastCmd.Parameters.get('Z', None) zVal = zVal and round(zVal, 8) zVal2 = zVal2 and round(zVal2, 8) if cmd.Name in ['G1', 'G2', 'G3', 'G01', 'G02', 'G03']: if False and zVal is not None and zVal2 != zVal: params['F'] = vertFeed else: params['F'] = horizFeed lastCmd = cmd elif cmd.Name in ['G0', 'G00']: if zVal is not None and zVal2 != zVal: params['F'] = vertRapid else: params['F'] = horizRapid lastCmd = cmd outCommands.append(Path.Command(cmd.Name, params)) return Path.Path(outCommands)
def createCommands(self, obj, edges): commands = [] for edge in edges: israpid = False for redge in self.rapids: if PathGeom.edgesMatch(edge, redge): israpid = True if israpid: v = edge.valueAt(edge.LastParameter) commands.append(Path.Command('G0', {'X': v.x, 'Y': v.y, 'Z': v.z})) else: commands.extend(PathGeom.cmdsForEdge(edge)) lastCmd = Path.Command('G0', {'X': 0.0, 'Y': 0.0, 'Z': 0.0}) outCommands = [] tc = PathDressup.toolController(obj.Base) horizFeed = tc.HorizFeed.Value vertFeed = tc.VertFeed.Value if obj.RampFeedRate == "Horizontal Feed Rate": rampFeed = tc.HorizFeed.Value elif obj.RampFeedRate == "Vertical Feed Rate": rampFeed = tc.VertFeed.Value else: rampFeed = obj.CustomFeedRate.Value horizRapid = tc.HorizRapid.Value vertRapid = tc.VertRapid.Value for cmd in commands: params = cmd.Parameters zVal = params.get('Z', None) zVal2 = lastCmd.Parameters.get('Z', None) xVal = params.get('X', None) xVal2 = lastCmd.Parameters.get('X', None) yVal2 = lastCmd.Parameters.get('Y', None) yVal = params.get('Y', None) zVal = zVal and round(zVal, 8) zVal2 = zVal2 and round(zVal2, 8) if cmd.Name in ['G1', 'G2', 'G3', 'G01', 'G02', 'G03']: if zVal is not None and zVal2 != zVal: if PathGeom.isRoughly(xVal, xVal2) and PathGeom.isRoughly(yVal, yVal2): # this is a straight plunge params['F'] = vertFeed else: # this is a ramp params['F'] = rampFeed else: params['F'] = horizFeed lastCmd = cmd elif cmd.Name in ['G0', 'G00']: if zVal is not None and zVal2 != zVal: params['F'] = vertRapid else: params['F'] = horizRapid lastCmd = cmd outCommands.append(Path.Command(cmd.Name, params)) return Path.Path(outCommands)
def execute(self): if ( not self.baseOp or not self.baseOp.isDerivedFrom("Path::Feature") or not self.baseOp.Path ): return None if len(self.baseOp.Path.Commands) == 0: PathLog.warning("No Path Commands for %s" % self.baseOp.Label) return [] tc = PathDressup.toolController(self.baseOp) self.safeHeight = float(PathUtil.opProperty(self.baseOp, "SafeHeight")) self.clearanceHeight = float( PathUtil.opProperty(self.baseOp, "ClearanceHeight") ) self.strG0ZsafeHeight = Path.Command( # was a Feed rate with G1 "G0", {"Z": self.safeHeight, "F": tc.VertRapid.Value} ) self.strG0ZclearanceHeight = Path.Command("G0", {"Z": self.clearanceHeight}) cmd = self.baseOp.Path.Commands[0] pos = cmd.Placement.Base # bogus m/c position to create first edge bogusX = True bogusY = True commands = [cmd] lastExit = None for cmd in self.baseOp.Path.Commands[1:]: if cmd.Name in PathGeom.CmdMoveAll: if bogusX: bogusX = "X" not in cmd.Parameters if bogusY: bogusY = "Y" not in cmd.Parameters edge = PathGeom.edgeForCmd(cmd, pos) if edge: inside = edge.common(self.boundary).Edges outside = edge.cut(self.boundary).Edges if not self.inside: # UI "inside boundary" param tmp = inside inside = outside outside = tmp # it's really a shame that one cannot trust the sequence and/or # orientation of edges if 1 == len(inside) and 0 == len(outside): PathLog.track(_vstr(pos), _vstr(lastExit), " + ", cmd) # cmd fully included by boundary if lastExit: if not ( bogusX or bogusY ): # don't insert false paths based on bogus m/c position commands.extend( self.boundaryCommands( lastExit, pos, tc.VertFeed.Value ) ) lastExit = None commands.append(cmd) pos = PathGeom.commandEndPoint(cmd, pos) elif 0 == len(inside) and 1 == len(outside): PathLog.track(_vstr(pos), _vstr(lastExit), " - ", cmd) # cmd fully excluded by boundary if not lastExit: lastExit = pos pos = PathGeom.commandEndPoint(cmd, pos) else: PathLog.track( _vstr(pos), _vstr(lastExit), len(inside), len(outside), cmd ) # cmd pierces boundary while inside or outside: ie = [e for e in inside if PathGeom.edgeConnectsTo(e, pos)] PathLog.track(ie) if ie: e = ie[0] LastPt = e.valueAt(e.LastParameter) flip = PathGeom.pointsCoincide(pos, LastPt) newPos = e.valueAt(e.FirstParameter) if flip else LastPt # inside edges are taken at this point (see swap of inside/outside # above - so we can just connect the dots ... if lastExit: if not (bogusX or bogusY): commands.extend( self.boundaryCommands( lastExit, pos, tc.VertFeed.Value ) ) lastExit = None PathLog.track(e, flip) if not ( bogusX or bogusY ): # don't insert false paths based on bogus m/c position commands.extend( PathGeom.cmdsForEdge( e, flip, False, 50, tc.HorizFeed.Value, tc.VertFeed.Value, ) ) inside.remove(e) pos = newPos lastExit = newPos else: oe = [ e for e in outside if PathGeom.edgeConnectsTo(e, pos) ] PathLog.track(oe) if oe: e = oe[0] ptL = e.valueAt(e.LastParameter) flip = PathGeom.pointsCoincide(pos, ptL) newPos = ( e.valueAt(e.FirstParameter) if flip else ptL ) # outside edges are never taken at this point (see swap of # inside/outside above) - so just move along ... outside.remove(e) pos = newPos else: PathLog.error("huh?") import Part Part.show(Part.Vertex(pos), "pos") for e in inside: Part.show(e, "ei") for e in outside: Part.show(e, "eo") raise Exception("This is not supposed to happen") # Eif # Eif # Ewhile # Eif # pos = PathGeom.commandEndPoint(cmd, pos) # Eif else: PathLog.track("no-move", cmd) commands.append(cmd) if lastExit: commands.extend(self.boundaryCommands(lastExit, None, tc.VertFeed.Value)) lastExit = None PathLog.track(commands) return Path.Path(commands)
def cmds(center, radius, up=True): norm = Vector(0, 0, 1) if up else Vector(0, 0, -1) return PathGeom.cmdsForEdge( Part.Edge(Part.Circle(center, norm, radius)))[0]
def createPath(self, obj, pathData, tags): PathLog.track() commands = [] lastEdge = 0 lastTag = 0 # sameTag = None t = 0 # inters = None edge = None segm = 50 if hasattr(obj, 'SegmentationFactor'): segm = obj.SegmentationFactor if segm <= 0: segm = 50 obj.SegmentationFactor = 50 self.mappers = [] mapper = None tc = PathDressup.toolController(obj.Base) horizFeed = tc.HorizFeed.Value vertFeed = tc.VertFeed.Value horizRapid = tc.HorizRapid.Value vertRapid = tc.VertRapid.Value while edge or lastEdge < len(pathData.edges): PathLog.debug("------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags))) if not edge: edge = pathData.edges[lastEdge] debugEdge(edge, "======= new edge: %d/%d" % (lastEdge, len(pathData.edges))) lastEdge += 1 # sameTag = None if mapper: mapper.add(edge) if mapper.mappingComplete(): commands.extend(mapper.commands) edge = mapper.tail mapper = None else: edge = None if edge: tIndex = (t + lastTag) % len(tags) t += 1 i = tags[tIndex].intersects(edge, edge.FirstParameter) if i and self.isValidTagStartIntersection(edge, i): mapper = MapWireToTag(edge, tags[tIndex], i, segm, pathData.maxZ, hSpeed = horizFeed, vSpeed = vertFeed) self.mappers.append(mapper) edge = mapper.tail if not mapper and t >= len(tags): # gone through all tags, consume edge and move on if edge: debugEdge(edge, '++++++++') if pathData.rapid.isRapid(edge): v = edge.Vertexes[1] if not commands and PathGeom.isRoughly(0, v.X) and PathGeom.isRoughly(0, v.Y) and not PathGeom.isRoughly(0, v.Z): # The very first move is just to move to ClearanceHeight commands.append(Path.Command('G0', {'Z': v.Z, 'F': horizRapid})) else: commands.append(Path.Command('G0', {'X': v.X, 'Y': v.Y, 'Z': v.Z, 'F': vertRapid})) else: commands.extend(PathGeom.cmdsForEdge(edge, segm=segm, hSpeed = horizFeed, vSpeed = vertFeed)) edge = None t = 0 return Path.Path(commands)
def cmds(pa, pb, pc, flip): return PathGeom.cmdsForEdge(Part.Edge(Part.Arc(pa, pb, pc)), flip)[0]
def buildpathocc(self, obj, wires, zValues, relZ=False, forward=True, start_idx=0): """buildpathocc(obj, wires, zValues, relZ=False) ... internal helper function to generate engraving commands.""" PathLog.track(obj.Label, len(wires), zValues) decomposewires = [] for wire in wires: decomposewires.extend(PathOpTools.makeWires(wire.Edges)) wires = decomposewires for wire in wires: # offset = wire # reorder the wire if hasattr(obj, "StartVertex"): start_idx = obj.StartVertex edges = wire.Edges # edges = copy.copy(PathOpTools.orientWire(offset, forward).Edges) # PathLog.track("wire: {} offset: {}".format(len(wire.Edges), len(edges))) # edges = Part.sortEdges(edges)[0] # PathLog.track("edges: {}".format(len(edges))) last = None for z in zValues: PathLog.debug(z) if last: self.appendCommand( Path.Command("G1", { "X": last.x, "Y": last.y, "Z": last.z }), z, relZ, self.vertFeed, ) first = True if start_idx > len(edges) - 1: start_idx = len(edges) - 1 edges = edges[start_idx:] + edges[:start_idx] for edge in edges: PathLog.debug("points: {} -> {}".format( edge.Vertexes[0].Point, edge.Vertexes[-1].Point)) PathLog.debug("valueat {} -> {}".format( edge.valueAt(edge.FirstParameter), edge.valueAt(edge.LastParameter), )) if first and (not last or not wire.isClosed()): PathLog.debug("processing first edge entry") # we set the first move to our first point last = edge.Vertexes[0].Point self.commandlist.append( Path.Command( "G0", { "Z": obj.ClearanceHeight.Value, "F": self.vertRapid }, )) self.commandlist.append( Path.Command("G0", { "X": last.x, "Y": last.y, "F": self.horizRapid })) self.commandlist.append( Path.Command("G0", { "Z": obj.SafeHeight.Value, "F": self.vertRapid })) self.appendCommand( Path.Command("G1", { "X": last.x, "Y": last.y, "Z": last.z }), z, relZ, self.vertFeed, ) first = False if PathGeom.pointsCoincide( last, edge.valueAt(edge.FirstParameter)): # if PathGeom.pointsCoincide(last, edge.Vertexes[0].Point): for cmd in PathGeom.cmdsForEdge(edge): self.appendCommand(cmd, z, relZ, self.horizFeed) last = edge.Vertexes[-1].Point else: for cmd in PathGeom.cmdsForEdge(edge, True): self.appendCommand(cmd, z, relZ, self.horizFeed) last = edge.Vertexes[0].Point self.commandlist.append( Path.Command("G0", { "Z": obj.ClearanceHeight.Value, "F": self.vertRapid }))
def createCommands(self, obj, edges): commands = [] for edge in edges: israpid = False for redge in self.rapids: if PathGeom.edgesMatch(edge, redge): israpid = True if israpid: v = edge.valueAt(edge.LastParameter) commands.append( Path.Command("G0", { "X": v.x, "Y": v.y, "Z": v.z })) else: commands.extend(PathGeom.cmdsForEdge(edge)) lastCmd = Path.Command("G0", {"X": 0.0, "Y": 0.0, "Z": 0.0}) outCommands = [] tc = PathDressup.toolController(obj.Base) horizFeed = tc.HorizFeed.Value vertFeed = tc.VertFeed.Value if obj.RampFeedRate == "Horizontal Feed Rate": rampFeed = tc.HorizFeed.Value elif obj.RampFeedRate == "Vertical Feed Rate": rampFeed = tc.VertFeed.Value elif obj.RampFeedRate == "Ramp Feed Rate": rampFeed = math.sqrt( pow(tc.VertFeed.Value, 2) + pow(tc.HorizFeed.Value, 2)) else: rampFeed = obj.CustomFeedRate.Value horizRapid = tc.HorizRapid.Value vertRapid = tc.VertRapid.Value for cmd in commands: params = cmd.Parameters zVal = params.get("Z", None) zVal2 = lastCmd.Parameters.get("Z", None) xVal = params.get("X", None) xVal2 = lastCmd.Parameters.get("X", None) yVal2 = lastCmd.Parameters.get("Y", None) yVal = params.get("Y", None) zVal = zVal and round(zVal, 8) zVal2 = zVal2 and round(zVal2, 8) if cmd.Name in ["G1", "G2", "G3", "G01", "G02", "G03"]: if zVal is not None and zVal2 != zVal: if PathGeom.isRoughly(xVal, xVal2) and PathGeom.isRoughly( yVal, yVal2): # this is a straight plunge params["F"] = vertFeed else: # this is a ramp params["F"] = rampFeed else: params["F"] = horizFeed lastCmd = cmd elif cmd.Name in ["G0", "G00"]: if zVal is not None and zVal2 != zVal: params["F"] = vertRapid else: params["F"] = horizRapid lastCmd = cmd outCommands.append(Path.Command(cmd.Name, params)) return Path.Path(outCommands)
def createPath(self, obj, pathData, tags): PathLog.track() commands = [] lastEdge = 0 lastTag = 0 # sameTag = None t = 0 # inters = None edge = None segm = 50 if hasattr(obj, 'SegmentationFactor'): segm = obj.SegmentationFactor if segm <= 0: segm = 50 obj.SegmentationFactor = 50 self.mappers = [] mapper = None while edge or lastEdge < len(pathData.edges): PathLog.debug("------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags))) if not edge: edge = pathData.edges[lastEdge] debugEdge(edge, "======= new edge: %d/%d" % (lastEdge, len(pathData.edges))) lastEdge += 1 # sameTag = None if mapper: mapper.add(edge) if mapper.mappingComplete(): commands.extend(mapper.commands) edge = mapper.tail mapper = None else: edge = None if edge: tIndex = (t + lastTag) % len(tags) t += 1 i = tags[tIndex].intersects(edge, edge.FirstParameter) if i and self.isValidTagStartIntersection(edge, i): mapper = MapWireToTag(edge, tags[tIndex], i, segm, pathData.maxZ) self.mappers.append(mapper) edge = mapper.tail if not mapper and t >= len(tags): # gone through all tags, consume edge and move on if edge: debugEdge(edge, '++++++++') if pathData.rapid.isRapid(edge): v = edge.Vertexes[1] if not commands and PathGeom.isRoughly(0, v.X) and PathGeom.isRoughly(0, v.Y) and not PathGeom.isRoughly(0, v.Z): # The very first move is just to move to ClearanceHeight commands.append(Path.Command('G0', {'Z': v.Z})) else: commands.append(Path.Command('G0', {'X': v.X, 'Y': v.Y, 'Z': v.Z})) else: commands.extend(PathGeom.cmdsForEdge(edge, segm=segm)) edge = None t = 0 lastCmd = Path.Command('G0', {'X': 0.0, 'Y': 0.0, 'Z': 0.0}) outCommands = [] tc = PathDressup.toolController(obj.Base) horizFeed = tc.HorizFeed.Value vertFeed = tc.VertFeed.Value horizRapid = tc.HorizRapid.Value vertRapid = tc.VertRapid.Value for cmd in commands: params = cmd.Parameters zVal = params.get('Z', None) zVal2 = lastCmd.Parameters.get('Z', None) zVal = zVal and round(zVal, 8) zVal2 = zVal2 and round(zVal2, 8) if cmd.Name in ['G1', 'G2', 'G3', 'G01', 'G02', 'G03']: if False and zVal is not None and zVal2 != zVal: params['F'] = vertFeed else: params['F'] = horizFeed lastCmd = cmd elif cmd.Name in ['G0', 'G00']: if zVal is not None and zVal2 != zVal: params['F'] = vertRapid else: params['F'] = horizRapid lastCmd = cmd outCommands.append(Path.Command(cmd.Name, params)) return Path.Path(outCommands)
def cmds(center, radius, up = True): norm = Vector(0, 0, 1) if up else Vector(0, 0, -1) return PathGeom.cmdsForEdge(Part.Edge(Part.Circle(center, norm, radius)))[0]
def execute(self, obj): if not obj.Base or not obj.Base.isDerivedFrom('Path::Feature') or not obj.Base.Path: return tc = PathDressup.toolController(obj.Base) if len(obj.Base.Path.Commands) > 0: self.safeHeight = float(PathUtil.opProperty(obj.Base, 'SafeHeight')) self.clearanceHeight = float(PathUtil.opProperty(obj.Base, 'ClearanceHeight')) boundary = obj.Stock.Shape cmd = obj.Base.Path.Commands[0] pos = cmd.Placement.Base commands = [cmd] lastExit = None for cmd in obj.Base.Path.Commands[1:]: if cmd.Name in PathGeom.CmdMoveAll: edge = PathGeom.edgeForCmd(cmd, pos) inside = edge.common(boundary).Edges outside = edge.cut(boundary).Edges if not obj.Inside: t = inside inside = outside outside = t # it's really a shame that one cannot trust the sequence and/or # orientation of edges if 1 == len(inside) and 0 == len(outside): PathLog.track(_vstr(pos), _vstr(lastExit), ' + ', cmd) # cmd fully included by boundary if lastExit: commands.extend(self.boundaryCommands(obj, lastExit, pos, tc.VertFeed.Value)) lastExit = None commands.append(cmd) pos = PathGeom.commandEndPoint(cmd, pos) elif 0 == len(inside) and 1 == len(outside): PathLog.track(_vstr(pos), _vstr(lastExit), ' - ', cmd) # cmd fully excluded by boundary if not lastExit: lastExit = pos pos = PathGeom.commandEndPoint(cmd, pos) else: PathLog.track(_vstr(pos), _vstr(lastExit), len(inside), len(outside), cmd) # cmd pierces boundary while inside or outside: ie = [e for e in inside if PathGeom.edgeConnectsTo(e, pos)] PathLog.track(ie) if ie: e = ie[0] ptL = e.valueAt(e.LastParameter) flip = PathGeom.pointsCoincide(pos, ptL) newPos = e.valueAt(e.FirstParameter) if flip else ptL # inside edges are taken at this point (see swap of inside/outside # above - so we can just connect the dots ... if lastExit: commands.extend(self.boundaryCommands(obj, lastExit, pos, tc.VertFeed.Value)) lastExit = None PathLog.track(e, flip) commands.extend(PathGeom.cmdsForEdge(e, flip, False)) inside.remove(e) pos = newPos lastExit = newPos else: oe = [e for e in outside if PathGeom.edgeConnectsTo(e, pos)] PathLog.track(oe) if oe: e = oe[0] ptL = e.valueAt(e.LastParameter) flip = PathGeom.pointsCoincide(pos, ptL) newPos = e.valueAt(e.FirstParameter) if flip else ptL # outside edges are never taken at this point (see swap of # inside/oustide above) - so just move along ... outside.remove(e) pos = newPos else: PathLog.error('huh?') import Part Part.show(Part.Vertex(pos), 'pos') for e in inside: Part.show(e, 'ei') for e in outside: Part.show(e, 'eo') raise Exception('This is not supposed to happen') #pos = PathGeom.commandEndPoint(cmd, pos) else: PathLog.track('no-move', cmd) commands.append(cmd) if lastExit: commands.extend(self.boundaryCommands(obj, lastExit, None, tc.VertFeed.Value)) lastExit = None else: PathLog.warning("No Path Commands for %s" % obj.Base.Label) commands = [] PathLog.track(commands) obj.Path = Path.Path(commands)