def backSmaller(self, i): import DraftGeomUtils profilCurrent = self.findProfil(i) profilBack1 = self.findProfil(i - 1) dec = profilBack1["height"] / math.tan(math.radians(profilCurrent["angle"])) edgeRidgeOnPane = DraftGeomUtils.offset( profilCurrent["edge"], self.getPerpendicular(profilCurrent["vec"], profilCurrent["rot"], dec) ) ptInter1 = DraftGeomUtils.findIntersection( edgeRidgeOnPane, profilBack1["ridge"], infinite1=True, infinite2=True ) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter1[0]), profilCurrent["edge"].Vertexes[0].Point) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular(ptInter2, [profilCurrent["ridge"].Edges[0]], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) self.ptsPaneProject.append(FreeCAD.Vector(ptInterRidges)) self.ptsPaneProject.append(FreeCAD.Vector(ptInter1[0])) ptInterHipEave = DraftGeomUtils.findIntersection( edgeHip, profilCurrent["eave"], infinite1=True, infinite2=False ) if ptInterHipEave: self.ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave[0])) else: ptInterHipEave = DraftGeomUtils.findIntersection( edgeHip, profilBack1["eaveD"], infinite1=True, infinite2=True ) self.ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave[0])) self.ptsPaneProject.append(FreeCAD.Vector(profilCurrent["eave"].Vertexes[0].Point[0]))
def nextSmaller(self, i): print("Next : ht2 < ht1") profilCurrent = self.findProfil(i) profilNext1 = self.findProfil(i+1) dec = profilNext1["height"]/math.tan(math.radians(profilCurrent["angle"])) edgeRidgeOnPane = DraftGeomUtils.offset(profilCurrent["edge"],self.getPerpendicular(profilCurrent["vec"],profilCurrent["rot"],dec)) ptInter = DraftGeomUtils.findIntersection(profilNext1["ridge"],edgeRidgeOnPane,infinite1=True,infinite2=True,) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter[0]),profilCurrent["edge"].Vertexes[-1].Point) ptInterHipEave = DraftGeomUtils.findIntersection(edgeHip,profilCurrent["eave"],infinite1=True,infinite2=False,) if ptInterHipEave: print "a ",FreeCAD.Vector(ptInterHipEave[0]) self.ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave[0])) else: ptInterHipEave = DraftGeomUtils.findIntersection(edgeHip,profilNext1["eaveD"],infinite1=True,infinite2=True,) print "b ",FreeCAD.Vector(profilCurrent["eave"].Vertexes[-1].Point[0]) print "c ",FreeCAD.Vector(ptInterHipEave[0]) self.ptsPaneProject.append(FreeCAD.Vector(profilCurrent["eave"].Vertexes[-1].Point[0])) self.ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave[0])) print "d ",FreeCAD.Vector(ptInter[0]) self.ptsPaneProject.append(FreeCAD.Vector(ptInter[0])) ptInter = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular(ptInter, [profilCurrent["ridge"].Edges[0],], force=0) ptInterRidges = ptInter.add(vecInterRidges[0]) print "e ",FreeCAD.Vector(ptInterRidges) self.ptsPaneProject.append(FreeCAD.Vector(ptInterRidges))
def backSmaller(self, i): import DraftGeomUtils print("Back : ht0 < ht1") profilCurrent = self.findProfil(i) profilBack1 = self.findProfil(i - 1) dec = profilBack1["height"] / math.tan( math.radians(profilCurrent["angle"])) edgeRidgeOnPane = DraftGeomUtils.offset( profilCurrent["edge"], self.getPerpendicular(profilCurrent["vec"], profilCurrent["rot"], dec)) ptInter1 = DraftGeomUtils.findIntersection( edgeRidgeOnPane, profilBack1["ridge"], infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter1[0]), profilCurrent["edge"].Vertexes[0].Point) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular(ptInter2, [ profilCurrent["ridge"].Edges[0], ], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) print "a ", FreeCAD.Vector(ptInterRidges) print "b ", FreeCAD.Vector(ptInter1[0]) self.ptsPaneProject.append(FreeCAD.Vector(ptInterRidges)) self.ptsPaneProject.append(FreeCAD.Vector(ptInter1[0])) ptInterHipEave = DraftGeomUtils.findIntersection( edgeHip, profilCurrent["eave"], infinite1=True, infinite2=False, ) if ptInterHipEave: print "c ", FreeCAD.Vector(ptInterHipEave[0]) self.ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave[0])) else: ptInterHipEave = DraftGeomUtils.findIntersection( edgeHip, profilBack1["eaveD"], infinite1=True, infinite2=True, ) print "d ", FreeCAD.Vector(ptInterHipEave[0]) print "e ", FreeCAD.Vector( profilCurrent["eave"].Vertexes[0].Point[0]) self.ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave[0])) self.ptsPaneProject.append( FreeCAD.Vector(profilCurrent["eave"].Vertexes[0].Point[0]))
def nextSmaller(self, i): import DraftGeomUtils profilCurrent = self.findProfil(i) profilNext1 = self.findProfil(i + 1) dec = profilNext1["height"] / math.tan( math.radians(profilCurrent["angle"])) edgeRidgeOnPane = DraftGeomUtils.offset( profilCurrent["edge"], self.getPerpendicular(profilCurrent["vec"], profilCurrent["rot"], dec)) ptInter = DraftGeomUtils.findIntersection( profilNext1["ridge"], edgeRidgeOnPane, infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter[0]), profilCurrent["edge"].Vertexes[-1].Point) ptInterHipEave = DraftGeomUtils.findIntersection( edgeHip, profilCurrent["eave"], infinite1=True, infinite2=False, ) if ptInterHipEave: self.ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave[0])) else: ptInterHipEave = DraftGeomUtils.findIntersection( edgeHip, profilNext1["eaveD"], infinite1=True, infinite2=True, ) self.ptsPaneProject.append( FreeCAD.Vector(profilCurrent["eave"].Vertexes[-1].Point[0])) self.ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave[0])) self.ptsPaneProject.append(FreeCAD.Vector(ptInter[0])) ptInter = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular(ptInter, [ profilCurrent["ridge"].Edges[0], ], force=0) ptInterRidges = ptInter.add(vecInterRidges[0]) self.ptsPaneProject.append(FreeCAD.Vector(ptInterRidges))
def buildpathocc(self, obj, shape): """Build pocket Path using Native OCC algorithm.""" import Part import DraftGeomUtils from PathScripts.PathUtils import fmt, helicalPlunge, rampPlunge FreeCAD.Console.PrintMessage( translate("PathPocket", "Generating toolpath with OCC native offsets.\n")) # Build up the offset loops output = "" offsets = [] nextradius = (self.radius * 2) * (float(obj.StepOver) / 100) result = DraftGeomUtils.pocket2d(shape, nextradius) print "did we get something: " + str(result) while result: print "Adding " + str(len(result)) + " wires" offsets.extend(result) nextradius += (self.radius * 2) * (float(obj.StepOver) / 100) result = DraftGeomUtils.pocket2d(shape, nextradius) # revert the list so we start with the outer wires if obj.StartAt != 'Edge': offsets.reverse() plungePos = None rampEdge = None if obj.UseEntry: # Try to find an entry location toold = self.radius * 2 helixBounds = DraftGeomUtils.pocket2d( shape, self.radius * (1 + obj.HelixSize)) if helixBounds: rampD = obj.RampSize if obj.StartAt == 'Edge': plungePos = helixBounds[0].Edges[0].Vertexes[0].Point else: plungePos = offsets[0].Edges[0].Vertexes[0].Point # If it turns out this is invalid for some reason, nuke plungePos [perp, idx] = DraftGeomUtils.findPerpendicular( plungePos, shape.Edges) if not perp or perp.Length < self.radius * (1 + obj.HelixSize): plungePos = None FreeCAD.Console.PrintError( translate("PathPocket", "Helical Entry location not found.\n")) # FIXME: Really need to do a point-in-polygon operation to make sure this is within helixBounds # Or some math to prove that it has to be (doubt that's true) # Maybe reverse helixBounds and pick off that? if plungePos is None: # If we didn't find a place to helix, how about a ramp? FreeCAD.Console.PrintMessage( translate("PathPocket", "Attempting ramp entry.\n")) if (offsets[0].Edges[0].Length >= toold * rampD) and not ( isinstance(offsets[0].Edges[0].Curve, Part.Circle)): rampEdge = offsets[0].Edges[0] # The last edge also connects with the starting location- try that elif (offsets[0].Edges[-1].Length >= toold * rampD) and not ( isinstance(offsets[0].Edges[-1].Curve, Part.Circle)): rampEdge = offsets[0].Edges[-1] else: FreeCAD.Console.PrintError( translate("PathPocket", "Ramp Entry location not found.\n")) # print "Neither edge works: " + str(offsets[0].Edges[0]) + ", " + str(offsets[0].Edges[-1]) # FIXME: There's got to be a smarter way to find a place to ramp fastZPos = obj.ClearanceHeight.Value # For helix-ing/ramping, know where we were last time # FIXME: Can probably get this from the "machine"? lastZ = fastZPos startPoint = None for vpos in PathUtils.frange(obj.StartDepth.Value, obj.FinalDepth.Value, obj.StepDown, obj.FinishDepth.Value): first = True # loop over successive wires for currentWire in offsets: #output += PathUtils.convert(currentWire.Edges, "on", 1) last = None for edge in currentWire.Edges: if not last: # we set the base GO to our fast move to our starting pos if first: # If we can helix, do so if plungePos: output += helicalPlunge( plungePos, obj.RampAngle, vpos, lastZ, self.radius * 2, obj.HelixSize, self.horizFeed) # print output lastZ = vpos # Otherwise, see if we can ramp # FIXME: This could be a LOT smarter (eg, searching for a longer leg of the edge to ramp along) elif rampEdge: output += rampPlunge(rampEdge, obj.RampAngle, vpos, lastZ) lastZ = vpos # Otherwise, straight plunge... Don't want to, but sometimes you might not have a choice. # FIXME: At least not with the lazy ramp programming above... else: print "WARNING: Straight-plunging... probably not good, but we didn't find a place to helix or ramp" startPoint = edge.Vertexes[0].Point output += "G0 X" + fmt(startPoint.x) + " Y" + fmt(startPoint.y) +\ " Z" + fmt(fastZPos) + "\n" first = False # then move slow down to our starting point for our profile last = edge.Vertexes[0].Point output += "G1 X" + fmt(last.x) + " Y" + fmt( last.y) + " Z" + fmt(vpos) + "\n" # if isinstance(edge.Curve,Part.Circle): if DraftGeomUtils.geomType(edge) == "Circle": point = edge.Vertexes[-1].Point if point == last: # edges can come flipped point = edge.Vertexes[0].Point center = edge.Curve.Center relcenter = center.sub(last) v1 = last.sub(center) v2 = point.sub(center) if v1.cross(v2).z < 0: output += "G2" else: output += "G3" output += " X" + fmt(point.x) + " Y" + fmt( point.y) + " Z" + fmt(vpos) output += " I" + fmt(relcenter.x) + " J" + fmt( relcenter.y) + " K" + fmt(relcenter.z) output += "\n" last = point else: point = edge.Vertexes[-1].Point if point == last: # edges can come flipped point = edge.Vertexes[0].Point output += "G1 X" + fmt(point.x) + " Y" + fmt( point.y) + " Z" + fmt(vpos) + "\n" last = point # move back up output += "G1 Z" + fmt(fastZPos) + "\n" return output
def execute(self,obj): if obj.Base: tool = PathUtils.getLastTool(obj) if tool: radius = tool.Diameter/2 if radius < 0:# safe guard radius -= radius else: # temporary value, to be taken from the properties later on radius = 1 import Part, DraftGeomUtils if "Face" in obj.Base[1][0]: shape = getattr(obj.Base[0].Shape,obj.Base[1][0]) else: edges = [getattr(obj.Base[0].Shape,sub) for sub in obj.Base[1]] shape = Part.Wire(edges) print len(edges) # absolute coords, millimeters, cancel offsets output = "G90\nG21\nG40\n" # save tool if obj.ToolNumber > 0 and tool.ToolNumber != obj.ToolNumber: output += "M06 T" + str(tool.ToolNumber) + "\n" # build offsets offsets = [] nextradius = radius result = DraftGeomUtils.pocket2d(shape,nextradius) while result: #print "Adding " + str(len(result)) + " wires" offsets.extend(result) nextradius += radius result = DraftGeomUtils.pocket2d(shape,nextradius) # first move will be rapid, subsequent will be at feed rate first = True startPoint = None fastZPos = max(obj.StartDepth + 2, obj.RetractHeight) # revert the list so we start with the outer wires if obj.StartAt != 'Edge': offsets.reverse() # print "startDepth: " + str(obj.StartDepth) # print "finalDepth: " + str(obj.FinalDepth) # print "stepDown: " + str(obj.StepDown) # print "finishDepth" + str(obj.FinishDepth) # print "offsets:", len(offsets) def prnt(vlu): return str("%.4f" % round(vlu, 4)) #Fraction of tool radius our plunge helix is to be #FIXME: This should be configurable plungeR = 0.75 #(minimum) Fraction of tool DIAMETER to go back and forth while ramp-plunging #FIXME: This should be configurable #FIXME: The ramp plunging should maybe even be limited to this distance; I don't know what's best rampD = 0.75 #Total offset from the desired pocket edge is tool radius plus the plunge helix radius #Any point on these curves could be the center of a plunge helixBounds = DraftGeomUtils.pocket2d(shape, tool.Diameter / 2. * (1 + plungeR)) #Try to find a location to nicely plunge, starting with a helix, then ramp #Can't do it without knowledge of a tool plungePos = None rampEdge = None if not tool: raise Error("Ramp plunge location-finding requires a tool") return else: #Since we're going to start machining either the inner-most #edge or the outer (depending on StartAt setting), try to #plunge near that location if helixBounds: #Edge is easy- pick a point on helixBounds and go with it if obj.StartAt == 'Edge': plungePos = helixBounds[0].Edges[0].Vertexes[0].Point #Center is harder- use a point from the first offset, check if it works else: plungePos = offsets[0].Edges[0].Vertexes[0].Point #If it turns out this is invalid for some reason, nuke plungePos [perp,idx] = DraftGeomUtils.findPerpendicular(plungePos, shape.Edges) if not perp or perp.Length < tool.Diameter / 2. * (1 + plungeR): plungePos = None #FIXME: Really need to do a point-in-polygon operation to make sure this is within helixBounds #Or some math to prove that it has to be (doubt that's true) #Maybe reverse helixBounds and pick off that? #If we didn't find a place to helix, how about a ramp? if not plungePos: #Check first edge of our offsets if (offsets[0].Edges[0].Length >= tool.Diameter * rampD) and not (isinstance(offsets[0].Edges[0].Curve, Part.Circle)): rampEdge = offsets[0].Edges[0] #The last edge also connects with the starting location- try that elif (offsets[0].Edges[-1].Length >= tool.Diameter * rampD) and not (isinstance(offsets[0].Edges[-1].Curve, Part.Circle)): rampEdge = offsets[0].Edges[-1] else: print "Neither edge works: " + str(offsets[0].Edges[0]) + ", " + str(offsets[0].Edges[-1]) #FIXME: There's got to be a smarter way to find a place to ramp #Returns gcode to perform a rapid move def rapid(x=None, y=None, z=None): retstr = "G00" if (x != None) or (y != None) or (z != None): if (x != None): retstr += " X" + str("%.4f" % x) if (y != None): retstr += " Y" + str("%.4f" % y) if (z != None): retstr += " Z" + str("%.4f" % z) else: return "" return retstr + "\n" #Returns gcode to perform a linear feed def feed(x=None, y=None, z=None): global feedxy retstr = "G01 F" if(x == None) and (y == None): retstr += str("%.4f" % obj.HorizFeed) else: retstr += str("%.4f" % obj.VertFeed) if (x != None) or (y != None) or (z != None): if (x != None): retstr += " X" + str("%.4f" % x) if (y != None): retstr += " Y" + str("%.4f" % y) if (z != None): retstr += " Z" + str("%.4f" % z) else: return "" return retstr + "\n" #Returns gcode to perform an arc #Assumes XY plane or helix around Z #Don't worry about starting Z- assume that's dealt with elsewhere def arc(cx, cy, sx, sy, ex, ey, ez=None, ccw=False): #If start/end radii aren't within eps, abort eps = 0.01 if (math.sqrt((cx - sx)**2 + (cy - sy)**2) - math.sqrt((cx - ex)**2 + (cy - ey)**2)) >= eps: print "ERROR: Illegal arc: Stand and end radii not equal" return "" #Set [C]CW and feed retstr = "" if ccw: retstr += "G03 F" else: retstr += "G02 F" retstr += str(obj.HorizFeed) #End location retstr += " X" + str("%.4f" % ex) + " Y" + str("%.4f" % ey) #Helix if requested if ez != None: retstr += " Z" + str("%.4f" % ez) #Append center offsets retstr += " I" + str("%.4f" % (cx - sx)) + " J" + str("%.4f" % (cy - sy)) return retstr + "\n" #Returns gcode to helically plunge #destZ is the milling level #startZ is the height we can safely feed down to before helix-ing def helicalPlunge(plungePos, rampangle, destZ, startZ): helixCmds = "(START HELICAL PLUNGE)\n" if(plungePos == None): raise Error("Helical plunging requires a position!") return None if(not tool): raise Error("Helical plunging requires a tool!") return None helixX = plungePos.x + tool.Diameter/2. * plungeR helixY = plungePos.y; helixCirc = math.pi * tool.Diameter * plungeR dzPerRev = math.sin(rampangle/180. * math.pi) * helixCirc #Go to the start of the helix position helixCmds += rapid(helixX, helixY) helixCmds += rapid(z=startZ) #Helix as required to get to the requested depth lastZ = startZ curZ = max(startZ-dzPerRev, destZ) done = False while not done: done = (curZ == destZ) #NOTE: FreeCAD doesn't render this, but at least LinuxCNC considers it valid #helixCmds += arc(plungePos.x, plungePos.y, helixX, helixY, helixX, helixY, ez = curZ, ccw=True) #Use two half-helixes; FreeCAD renders that correctly, #and it fits with the other code breaking up 360-degree arcs helixCmds += arc(plungePos.x, plungePos.y, helixX, helixY, helixX - tool.Diameter * plungeR, helixY, ez = (curZ + lastZ)/2., ccw=True) helixCmds += arc(plungePos.x, plungePos.y, helixX - tool.Diameter * plungeR, helixY, helixX, helixY, ez = curZ, ccw=True) lastZ = curZ curZ = max(curZ - dzPerRev, destZ) return helixCmds #Returns commands to linearly ramp into a cut #FIXME: This ramps along the first edge, assuming it's long #enough, NOT just wiggling back and forth by ~0.75 * toolD. #Not sure if that's any worse, but it's simpler #FIXME: This code is untested def rampPlunge(edge, rampangle, destZ, startZ): rampCmds = "(START RAMP PLUNGE)\n" if(edge == None): raise Error("Ramp plunging requires an edge!") return None if(not tool): raise Error("Ramp plunging requires a tool!") sPoint = edge.Vertexes[0].Point ePoint = edge.Vertexes[1].Point #Evidently edges can get flipped- pick the right one in this case #FIXME: This is iffy code, based on what already existed in the "for vpos ..." loop below if ePoint == sPoint: #print "FLIP" ePoint = edge.Vertexes[-1].Point #print "Start: " + str(sPoint) + " End: " + str(ePoint) + " Zhigh: " + prnt(startZ) + " ZLow: " + prnt(destZ) rampDist = edge.Length rampDZ = math.sin(rampangle/180. * math.pi) * rampDist rampCmds += rapid(sPoint.x, sPoint.y) rampCmds += rapid(z=startZ) #Ramp down to the requested depth #FIXME: This might be an arc, so handle that as well lastZ = startZ curZ = max(startZ-rampDZ, destZ) done = False while not done: done = (curZ == destZ) #If it's an arc, handle it! if isinstance(edge.Curve,Part.Circle): raise Error("rampPlunge: Screw it, not handling an arc.") #Straight feed! Easy! else: rampCmds += feed(ePoint.x, ePoint.y, curZ) rampCmds += feed(sPoint.x, sPoint.y) lastZ = curZ curZ = max(curZ - rampDZ, destZ) return rampCmds #For helix-ing/ramping, know where we were last time #FIXME: Can probably get this from the "machine"? lastZ = fastZPos for vpos in frange(obj.StartDepth, obj.FinalDepth, obj.StepDown, obj.FinishDepth): # print "vpos: " + str(vpos) #Every for every depth we should helix down first = True # loop over successive wires for currentWire in offsets: # print "new line (offset)" last = None for edge in currentWire.Edges: # print "new edge" if not last: # we set the base GO to our fast move to our starting pos if first: #If we can helix, do so if plungePos: output += helicalPlunge(plungePos, 3, vpos, lastZ) #print output lastZ = vpos #Otherwise, see if we can ramp #FIXME: This could be a LOT smarter (eg, searching for a longer leg of the edge to ramp along) elif rampEdge: output += rampPlunge(rampEdge, 3, vpos, lastZ) lastZ = vpos #Otherwise, straight plunge... Don't want to, but sometimes you might not have a choice. #FIXME: At least not with the lazy ramp programming above... else: print "WARNING: Straight-plunging... probably not good, but we didn't find a place to helix or ramp" startPoint = edge.Vertexes[0].Point output += "G0 X" + prnt(startPoint.x) + " Y" + prnt(startPoint.y) +\ " Z" + prnt(fastZPos) + "\n" first = False #then move slow down to our starting point for our profile last = edge.Vertexes[0].Point output += "G1 X" + prnt(last.x) + " Y" + prnt(last.y) + " Z" + prnt(vpos) + "\n" #if isinstance(edge.Curve,Part.Circle): if DraftGeomUtils.geomType(edge) == "Circle": point = edge.Vertexes[-1].Point if point == last: # edges can come flipped point = edge.Vertexes[0].Point # print "flipped" center = edge.Curve.Center relcenter = center.sub(last) v1 = last.sub(center) v2 = point.sub(center) if v1.cross(v2).z < 0: output += "G2" else: output += "G3" output += " X" + prnt(point.x) + " Y" + prnt(point.y) + " Z" + prnt(vpos) output += " I" + prnt(relcenter.x) + " J" +prnt(relcenter.y) + " K" + prnt(relcenter.z) output += "\n" last = point else: point = edge.Vertexes[-1].Point if point == last: # edges can come flipped point = edge.Vertexes[0].Point output += "G1 X" + prnt(point.x) + " Y" + prnt(point.y) + " Z" + prnt(vpos) + "\n" last = point #move back up output += "G0 Z" + prnt(fastZPos) + "\n" # print output # path = Path.Path(output) # obj.Path = path if obj.Active: path = Path.Path(output) obj.Path = path obj.ViewObject.Visibility = True else: path = Path.Path("(inactive operation)") obj.Path = path obj.ViewObject.Visibility = False
def action(self, arg): """Handle the 3D scene events. This is installed as an EventCallback in the Inventor view. Parameters ---------- arg: dict Dictionary with strings that indicates the type of event received from the 3D view. """ import DraftGeomUtils plane = App.DraftWorkingPlane if arg["Type"] == "SoKeyboardEvent": if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) if (gui_tool_utils.hasMod(arg, gui_tool_utils.MODCONSTRAIN) and self.constrainSeg): dist = DraftGeomUtils.findPerpendicular(self.point, self.shape, self.constrainSeg[1]) else: dist = DraftGeomUtils.findPerpendicular(self.point, self.shape.Edges) if dist: self.ghost.on() if self.mode == "Wire": d = dist[0].negative() v1 = DraftGeomUtils.getTangent(self.shape.Edges[0], self.point) v2 = DraftGeomUtils.getTangent(self.shape.Edges[dist[1]], self.point) a = -DraftVecUtils.angle(v1, v2, plane.axis) self.dvec = DraftVecUtils.rotate(d, a, plane.axis) occmode = self.ui.occOffset.isChecked() utils.param.SetBool("Offset_OCC", occmode) _wire = DraftGeomUtils.offsetWire(self.shape, self.dvec, occ=occmode) self.ghost.update(_wire, forceclosed=occmode) elif self.mode == "BSpline": d = dist[0].negative() e = self.shape.Edges[0] basetan = DraftGeomUtils.getTangent(e, self.point) self.npts = [] for p in self.sel.Points: currtan = DraftGeomUtils.getTangent(e, p) a = -DraftVecUtils.angle(currtan, basetan, plane.axis) self.dvec = DraftVecUtils.rotate(d, a, plane.axis) self.npts.append(p.add(self.dvec)) self.ghost.update(self.npts) elif self.mode == "Circle": self.dvec = self.point.sub(self.center).Length self.ghost.setRadius(self.dvec) self.constrainSeg = dist self.linetrack.on() self.linetrack.p1(self.point) self.linetrack.p2(self.point.add(dist[0])) self.ui.setRadiusValue(dist[0].Length, unit="Length") else: self.dvec = None self.ghost.off() self.constrainSeg = None self.linetrack.off() self.ui.radiusValue.setText("off") self.ui.radiusValue.setFocus() self.ui.radiusValue.selectAll() if self.extendedCopy: if not gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): self.finish() gui_tool_utils.redraw3DView() elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): copymode = False occmode = self.ui.occOffset.isChecked() utils.param.SetBool("Offset_OCC", occmode) if (gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT) or self.ui.isCopy.isChecked()): copymode = True Gui.addModule("Draft") if self.npts: # _msg("offset:npts= " + str(self.npts)) _cmd = 'Draft.offset' _cmd += '(' _cmd += 'FreeCAD.ActiveDocument.' _cmd += self.sel.Name + ', ' _cmd += DraftVecUtils.toString(self.npts) + ', ' _cmd += 'copy=' + str(copymode) _cmd += ')' _cmd_list = ['offst = ' + _cmd, 'FreeCAD.ActiveDocument.recompute()'] self.commit(translate("draft", "Offset"), _cmd_list) elif self.dvec: if isinstance(self.dvec, float): delta = str(self.dvec) else: delta = DraftVecUtils.toString(self.dvec) _cmd = 'Draft.offset' _cmd += '(' _cmd += 'FreeCAD.ActiveDocument.' _cmd += self.sel.Name + ', ' _cmd += delta + ', ' _cmd += 'copy=' + str(copymode) + ', ' _cmd += 'occ=' + str(occmode) _cmd += ')' _cmd_list = ['offst = ' + _cmd, 'FreeCAD.ActiveDocument.recompute()'] self.commit(translate("draft", "Offset"), _cmd_list) if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): self.extendedCopy = True else: self.finish()
def buildpathocc(self, obj, shape): """Build pocket Path using Native OCC algorithm.""" import Part import DraftGeomUtils from PathScripts.PathUtils import fmt, helicalPlunge, rampPlunge, depth_params FreeCAD.Console.PrintMessage(translate("PathPocket", "Generating toolpath with OCC native offsets.\n")) extraoffset = obj.MaterialAllowance.Value # Build up the offset loops output = "" if obj.Comment != "": output += '(' + str(obj.Comment)+')\n' output += 'G0 Z' + fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n" offsets = [] nextradius = self.radius + extraoffset result = DraftGeomUtils.pocket2d(shape, nextradius) while result: offsets.extend(result) nextradius += (self.radius * 2) * (float(obj.StepOver)/100) result = DraftGeomUtils.pocket2d(shape, nextradius) # revert the list so we start with the outer wires if obj.StartAt != 'Edge': offsets.reverse() plungePos = None rampEdge = None if obj.UseEntry: # Try to find an entry location toold = self.radius*2 helixBounds = DraftGeomUtils.pocket2d(shape, self.radius * (1 + obj.HelixSize)) if helixBounds: rampD = obj.RampSize if obj.StartAt == 'Edge': plungePos = helixBounds[0].Edges[0].Vertexes[0].Point else: plungePos = offsets[0].Edges[0].Vertexes[0].Point # If it turns out this is invalid for some reason, nuke plungePos [perp, idx] = DraftGeomUtils.findPerpendicular(plungePos, shape.Edges) if not perp or perp.Length < self.radius * (1 + obj.HelixSize): plungePos = None FreeCAD.Console.PrintError(translate("PathPocket", "Helical Entry location not found.\n")) # FIXME: Really need to do a point-in-polygon operation to make sure this is within helixBounds # Or some math to prove that it has to be (doubt that's true) # Maybe reverse helixBounds and pick off that? if plungePos is None: # If we didn't find a place to helix, how about a ramp? FreeCAD.Console.PrintMessage(translate("PathPocket", "Attempting ramp entry.\n")) if (offsets[0].Edges[0].Length >= toold * rampD) and not (isinstance(offsets[0].Edges[0].Curve, Part.Circle)): rampEdge = offsets[0].Edges[0] # The last edge also connects with the starting location- try that elif (offsets[0].Edges[-1].Length >= toold * rampD) and not (isinstance(offsets[0].Edges[-1].Curve, Part.Circle)): rampEdge = offsets[0].Edges[-1] else: FreeCAD.Console.PrintError(translate("PathPocket", "Ramp Entry location not found.\n")) # print "Neither edge works: " + str(offsets[0].Edges[0]) + ", " + str(offsets[0].Edges[-1]) # FIXME: There's got to be a smarter way to find a place to ramp # For helix-ing/ramping, know where we were last time # FIXME: Can probably get this from the "machine"? lastZ = obj.ClearanceHeight.Value startPoint = None depthparams = depth_params( obj.ClearanceHeight.Value, obj.SafeHeight.Value, obj.StartDepth.Value, obj.StepDown, obj.FinishDepth.Value, obj.FinalDepth.Value) for vpos in depthparams.get_depths(): first = True # loop over successive wires for currentWire in offsets: last = None for edge in currentWire.Edges: if not last: # we set the base GO to our fast move to our starting pos if first: # If we can helix, do so if plungePos: output += helicalPlunge(plungePos, obj.RampAngle, vpos, lastZ, self.radius*2, obj.HelixSize, self.horizFeed) lastZ = vpos # Otherwise, see if we can ramp # FIXME: This could be a LOT smarter (eg, searching for a longer leg of the edge to ramp along) elif rampEdge: output += rampPlunge(rampEdge, obj.RampAngle, vpos, lastZ) lastZ = vpos # Otherwise, straight plunge... Don't want to, but sometimes you might not have a choice. # FIXME: At least not with the lazy ramp programming above... else: print "WARNING: Straight-plunging... probably not good, but we didn't find a place to helix or ramp" startPoint = edge.Vertexes[0].Point output += "G0 Z" + fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n" output += "G0 X" + fmt(startPoint.x) + " Y" + fmt(startPoint.y) +\ " Z" + fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.horizRapid) + "\n" first = False # then move slow down to our starting point for our profile last = edge.Vertexes[0].Point output += "G1 X" + fmt(last.x) + " Y" + fmt(last.y) + " Z" + fmt(vpos) + " F" + fmt(self.vertFeed) + "\n" if DraftGeomUtils.geomType(edge) == "Circle": point = edge.Vertexes[-1].Point if point == last: # edges can come flipped point = edge.Vertexes[0].Point center = edge.Curve.Center relcenter = center.sub(last) v1 = last.sub(center) v2 = point.sub(center) if v1.cross(v2).z < 0: output += "G2" else: output += "G3" output += " X" + fmt(point.x) + " Y" + fmt(point.y) + " Z" + fmt(vpos) output += " I" + fmt(relcenter.x) + " J" + fmt(relcenter.y) + " K" + fmt(relcenter.z) + " F" + fmt(self.horizFeed) output += "\n" last = point else: point = edge.Vertexes[-1].Point if point == last: # edges can come flipped point = edge.Vertexes[0].Point output += "G1 X" + fmt(point.x) + " Y" + fmt(point.y) + " Z" + fmt(vpos) + " F" + fmt(self.horizFeed) + "\n" last = point # move back up output += "G0 Z" + fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n" return output
def execute(self, obj): import Part, math, DraftGeomUtils pl = obj.Placement self.baseface = None base = None if obj.Base and obj.Angles: w = None if obj.Base.isDerivedFrom("Part::Feature"): if (obj.Base.Shape.Faces and obj.Face): w = obj.Base.Shape.Faces[obj.Face - 1].Wires[0] elif obj.Base.Shape.Wires: w = obj.Base.Shape.Wires[0] if w: if w.isClosed(): self.profilsDico = [] self.shps = [] self.subVolshps = [] heights = [] edges = DraftGeomUtils.sortEdges(w.Edges) l = len(edges) print("le contour contient " + str(l) + " aretes") for i in range(l): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(l): self.calcMissingData(i) for p in self.profilsDico: heights.append(p["height"]) obj.Heights = heights for i in range(l): edgesForward = edges[:] edgesForward.append(edges[0]) ptsPaneProject = [] profil0 = self.profilsDico[i - 1] profil1 = self.profilsDico[i] if i == l - 1: profil2 = self.profilsDico[0] else: profil2 = self.profilsDico[i + 1] vec0 = edges[i - 1].Vertexes[-1].Point.sub( edges[i - 1].Vertexes[0].Point) vec1 = edges[i].Vertexes[-1].Point.sub( edges[i].Vertexes[0].Point) vec2 = edgesForward[i + 1].Vertexes[-1].Point.sub( edgesForward[i + 1].Vertexes[0].Point) rotEdge0 = math.degrees(DraftVecUtils.angle(vec0)) rotEdge1 = math.degrees(DraftVecUtils.angle(vec1)) rotEdge2 = math.degrees(DraftVecUtils.angle(vec2)) edgeEave0 = DraftGeomUtils.offset( edges[i - 1], self.getPerpendicular( vec0, rotEdge0, profil0["overhang"]).negative()) edgeEave1 = DraftGeomUtils.offset( edges[i], self.getPerpendicular( vec1, rotEdge1, profil1["overhang"]).negative()) edgeEave2 = DraftGeomUtils.offset( edgesForward[i + 1], self.getPerpendicular( vec2, rotEdge2, profil2["overhang"]).negative()) pt0Eave1 = DraftGeomUtils.findIntersection( edgeEave0, edgeEave1, infinite1=True, infinite2=True, ) pt1Eave1 = DraftGeomUtils.findIntersection( edgeEave1, edgeEave2, infinite1=True, infinite2=True, ) edgeEave1 = DraftGeomUtils.edg( FreeCAD.Vector(pt0Eave1[0]), FreeCAD.Vector(pt1Eave1[0])) edgeRidge0 = DraftGeomUtils.offset( edges[i - 1], self.getPerpendicular(vec0, rotEdge0, profil0["run"])) edgeRidge1 = DraftGeomUtils.offset( edges[i], self.getPerpendicular(vec1, rotEdge1, profil1["run"])) edgeRidge2 = DraftGeomUtils.offset( edgesForward[i + 1], self.getPerpendicular(vec2, rotEdge2, profil2["run"])) midpoint = DraftGeomUtils.findMidpoint(edges[i]) pt0Edge1 = edges[i].Vertexes[0].Point pt1Edge1 = edges[i].Vertexes[-1].Point print("Analyse profil " + str(i)) if profil1["angle"] != 90.: if profil2["angle"] == 90.: print("situation a droite : pignon") ptsPaneProject.append( FreeCAD.Vector(pt1Eave1[0])) point = DraftGeomUtils.findIntersection( edgeRidge1, edgeEave2, infinite1=True, infinite2=True, ) ptsPaneProject.append(FreeCAD.Vector(point[0])) elif profil1["height"] == profil2["height"]: print("situation a droite : ht1 = ht2") ptInterRidges = DraftGeomUtils.findIntersection( edgeRidge1, edgeRidge2, infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInterRidges[0]), pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave1: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection( edgeHip, edgeEave2, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges[0])) elif profil1["height"] > profil2["height"]: print("situation a droite : ht1 > ht2") dec = profil2["height"] / math.tan( math.radians(profil1["angle"])) edgeRidge2OnPane = DraftGeomUtils.offset( edges[i], self.getPerpendicular(vec1, rotEdge1, dec)) ptInter1 = DraftGeomUtils.findIntersection( edgeRidge2, edgeRidge2OnPane, infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInter1[0]), pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave1: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection( edgeHip, edgeEave2, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append( FreeCAD.Vector(ptInter1[0])) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular( ptInter2, [ edgeRidge1.Edges[0], ], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges)) elif profil1["height"] < profil2["height"]: print("situation a droite : ht1 < ht2") dec = profil1["height"] / math.tan( math.radians(profil2["angle"])) edgeRidge2OnPane = DraftGeomUtils.offset( edgesForward[i + 1], self.getPerpendicular(vec2, rotEdge2, dec)) ptInter1 = DraftGeomUtils.findIntersection( edgeRidge1, edgeRidge2OnPane, infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInter1[0]), pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave1: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection( edgeHip, edgeEave2, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append( FreeCAD.Vector(ptInter1[0])) ptInterRidges = DraftGeomUtils.findIntersection( edgeRidge1, edgeRidge2, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges[0])) else: print("Cas de figure non pris en charge") if profil0["angle"] == 90.: print("situation a gauche : pignon") point = DraftGeomUtils.findIntersection( edgeRidge1, edgeEave0, infinite1=True, infinite2=True, ) ptsPaneProject.append(FreeCAD.Vector(point[0])) ptsPaneProject.append( FreeCAD.Vector(pt0Eave1[0])) elif profil0["height"] == profil1["height"]: print("situation a gauche : ht1 = ht0") edgeRidge0 = DraftGeomUtils.offset( edges[i - 1], self.getPerpendicular( vec0, rotEdge0, profil0["run"])) ptInterRidges = DraftGeomUtils.findIntersection( edgeRidge1, edgeRidge0, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges[0])) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInterRidges[0]), pt0Edge1) ptInterHipEave3 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave3: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection( edgeHip, edgeEave0, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append( FreeCAD.Vector(pt0Eave1[0])) elif profil1["height"] > profil0["height"]: print("situation a gauche : ht1 > ht0") dec = profil0["height"] / math.tan( math.radians(profil1["angle"])) edgeRidge0OnPane = DraftGeomUtils.offset( edges[i], self.getPerpendicular(vec1, rotEdge1, dec)) ptInter1 = DraftGeomUtils.findIntersection( edgeRidge0OnPane, edgeRidge0, infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInter1[0]), pt0Edge1) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular( ptInter2, [ edgeRidge1.Edges[0], ], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges)) ptsPaneProject.append( FreeCAD.Vector(ptInter1[0])) ptInterHipEave3 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave3: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection( edgeHip, edgeEave0, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append( FreeCAD.Vector(pt0Eave1[0])) elif profil1["height"] < profil0["height"]: print("situation a gauche : ht1 < ht0") dec = profil1["height"] / math.tan( math.radians(profil0["angle"])) edgeRidge0OnPane = DraftGeomUtils.offset( edges[i - 1], self.getPerpendicular(vec0, rotEdge0, dec)) ptInterRidges = DraftGeomUtils.findIntersection( edgeRidge0OnPane, edgeRidge1, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges[0])) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInterRidges[0]), pt0Edge1) ptInterHipEave3 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave3: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection( edgeHip, edgeEave0, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append( FreeCAD.Vector(pt0Eave1[0])) else: print("Cas de figure non pris en charge") ptsPaneProject = DraftVecUtils.removeDoubles( ptsPaneProject) print("ptsPaneProject", ptsPaneProject) print("Fin Analyse profil " + str(i)) self.profilsDico[i]["points"] = ptsPaneProject lp = len(ptsPaneProject) ptsPaneProject.append(ptsPaneProject[0]) edgesWire = [] for i in range(lp): edge = Part.makeLine(ptsPaneProject[i], ptsPaneProject[i + 1]) edgesWire.append(edge) wire = Part.Wire(edgesWire) d = wire.BoundBox.DiagonalLength thicknessV = profil1["thickness"] / (math.cos( math.radians(profil1["angle"]))) overhangV = profil1["overhang"] * math.tan( math.radians(profil1["angle"])) if wire.isClosed(): f = Part.Face(wire) f = f.extrude( FreeCAD.Vector( 0, 0, profil1["height"] + 2 * thicknessV + 2 * overhangV)) f.translate( FreeCAD.Vector(0.0, 0.0, -2 * overhangV)) ptsPaneProfil = [ FreeCAD.Vector(-profil1["overhang"], -overhangV, 0.0), FreeCAD.Vector(profil1["run"], profil1["height"], 0.0), FreeCAD.Vector(profil1["run"], profil1["height"] + thicknessV, 0.0), FreeCAD.Vector(-profil1["overhang"], -overhangV + thicknessV, 0.0) ] self.createProfilShape(ptsPaneProfil, midpoint, rotEdge1, vec1, profil1["run"], d, self.shps, f) ## subVolume shape ptsSubVolumeProfil = [ FreeCAD.Vector(-profil1["overhang"], -overhangV, 0.0), FreeCAD.Vector(profil1["run"], profil1["height"], 0.0), FreeCAD.Vector(profil1["run"], profil1["height"] + 10000, 0.0), FreeCAD.Vector(0.0, profil1["height"] + 10000, 0.0) ] self.createProfilShape(ptsSubVolumeProfil, midpoint, rotEdge1, vec1, profil1["run"], d, self.subVolshps, f) else: #TODO PIGNON pass ## SubVolume self.sub = self.subVolshps.pop() for s in self.subVolshps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl ## BaseVolume base = Part.makeCompound(self.shps) if not base.isNull(): if not DraftGeomUtils.isNull(pl): base.Placement = pl base = self.processSubShapes(obj, base) if base: if not base.isNull(): obj.Shape = base
def execute(self,obj): import Part, math, DraftGeomUtils pl = obj.Placement self.baseface = None base = None if obj.Base and obj.Angles: w = None if obj.Base.isDerivedFrom("Part::Feature"): if (obj.Base.Shape.Faces and obj.Face): w = obj.Base.Shape.Faces[obj.Face-1].Wires[0] elif obj.Base.Shape.Wires: w = obj.Base.Shape.Wires[0] if w: if w.isClosed(): self.profilsDico = [] self.shps = [] self.subVolshps = [] heights = [] edges = DraftGeomUtils.sortEdges(w.Edges) l = len(edges) print("le contour contient "+str(l)+" aretes") for i in range(l): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(l): self.calcMissingData(i) for p in self.profilsDico: heights.append(p["height"]) obj.Heights = heights for i in range(l): edgesForward = edges[:] edgesForward.append(edges[0]) ptsPaneProject=[] profil0 =self.profilsDico[i-1] profil1 =self.profilsDico[i] if i == l-1: profil2 =self.profilsDico[0] else: profil2 =self.profilsDico[i+1] vec0 = edges[i-1].Vertexes[-1].Point.sub(edges[i-1].Vertexes[0].Point) vec1 = edges[i].Vertexes[-1].Point.sub(edges[i].Vertexes[0].Point) vec2 = edgesForward[i+1].Vertexes[-1].Point.sub(edgesForward[i+1].Vertexes[0].Point) rotEdge0 = math.degrees(DraftVecUtils.angle(vec0)) rotEdge1 = math.degrees(DraftVecUtils.angle(vec1)) rotEdge2 = math.degrees(DraftVecUtils.angle(vec2)) edgeEave0 = DraftGeomUtils.offset(edges[i-1],self.getPerpendicular(vec0,rotEdge0,profil0["overhang"]).negative()) edgeEave1 = DraftGeomUtils.offset(edges[i],self.getPerpendicular(vec1,rotEdge1,profil1["overhang"]).negative()) edgeEave2 = DraftGeomUtils.offset(edgesForward[i+1],self.getPerpendicular(vec2,rotEdge2,profil2["overhang"]).negative()) pt0Eave1 = DraftGeomUtils.findIntersection(edgeEave0,edgeEave1,infinite1=True,infinite2=True,) pt1Eave1 = DraftGeomUtils.findIntersection(edgeEave1,edgeEave2,infinite1=True,infinite2=True,) edgeEave1 = DraftGeomUtils.edg(FreeCAD.Vector(pt0Eave1[0]),FreeCAD.Vector(pt1Eave1[0])) edgeRidge0 = DraftGeomUtils.offset(edges[i-1],self.getPerpendicular(vec0,rotEdge0,profil0["run"])) edgeRidge1 = DraftGeomUtils.offset(edges[i],self.getPerpendicular(vec1,rotEdge1,profil1["run"])) edgeRidge2 = DraftGeomUtils.offset(edgesForward[i+1],self.getPerpendicular(vec2,rotEdge2,profil2["run"])) midpoint = DraftGeomUtils.findMidpoint(edges[i]) pt0Edge1 = edges[i].Vertexes[0].Point pt1Edge1 = edges[i].Vertexes[-1].Point print("Analyse profil " + str(i)) if profil1["angle"] != 90.: if profil2["angle"] == 90. : print("situation a droite : pignon") ptsPaneProject.append(FreeCAD.Vector(pt1Eave1[0])) point = DraftGeomUtils.findIntersection(edgeRidge1,edgeEave2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(point[0])) elif profil1["height"] == profil2["height"] : print("situation a droite : ht1 = ht2") ptInterRidges = DraftGeomUtils.findIntersection(edgeRidge1,edgeRidge2,infinite1=True,infinite2=True,) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInterRidges[0]),pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave1: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection(edgeHip,edgeEave2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0])) elif profil1["height"] > profil2["height"]: print("situation a droite : ht1 > ht2") dec = profil2["height"]/math.tan(math.radians(profil1["angle"])) edgeRidge2OnPane = DraftGeomUtils.offset(edges[i],self.getPerpendicular(vec1,rotEdge1,dec)) ptInter1 = DraftGeomUtils.findIntersection(edgeRidge2,edgeRidge2OnPane,infinite1=True,infinite2=True,) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter1[0]),pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave1: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection(edgeHip,edgeEave2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append(FreeCAD.Vector(ptInter1[0])) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular(ptInter2, [edgeRidge1.Edges[0],], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges)) elif profil1["height"] < profil2["height"]: print("situation a droite : ht1 < ht2") dec = profil1["height"]/math.tan(math.radians(profil2["angle"])) edgeRidge2OnPane = DraftGeomUtils.offset(edgesForward[i+1],self.getPerpendicular(vec2,rotEdge2,dec)) ptInter1 = DraftGeomUtils.findIntersection(edgeRidge1,edgeRidge2OnPane,infinite1=True,infinite2=True,) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter1[0]),pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave1: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection(edgeHip,edgeEave2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append(FreeCAD.Vector(ptInter1[0])) ptInterRidges = DraftGeomUtils.findIntersection(edgeRidge1,edgeRidge2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0])) else: print("Cas de figure non pris en charge") if profil0["angle"] == 90. : print("situation a gauche : pignon") point = DraftGeomUtils.findIntersection(edgeRidge1,edgeEave0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(point[0])) ptsPaneProject.append(FreeCAD.Vector(pt0Eave1[0])) elif profil0["height"] == profil1["height"]: print("situation a gauche : ht1 = ht0") edgeRidge0 = DraftGeomUtils.offset(edges[i-1],self.getPerpendicular(vec0,rotEdge0,profil0["run"])) ptInterRidges = DraftGeomUtils.findIntersection(edgeRidge1,edgeRidge0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0])) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInterRidges[0]),pt0Edge1) ptInterHipEave3 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave3: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection(edgeHip,edgeEave0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append(FreeCAD.Vector(pt0Eave1[0])) elif profil1["height"] > profil0["height"]: print("situation a gauche : ht1 > ht0") dec = profil0["height"]/math.tan(math.radians(profil1["angle"])) edgeRidge0OnPane = DraftGeomUtils.offset(edges[i],self.getPerpendicular(vec1,rotEdge1,dec)) ptInter1 = DraftGeomUtils.findIntersection(edgeRidge0OnPane,edgeRidge0,infinite1=True,infinite2=True,) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter1[0]),pt0Edge1) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular(ptInter2, [edgeRidge1.Edges[0],], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges)) ptsPaneProject.append(FreeCAD.Vector(ptInter1[0])) ptInterHipEave3 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave3: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection(edgeHip,edgeEave0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append(FreeCAD.Vector(pt0Eave1[0])) elif profil1["height"] < profil0["height"]: print("situation a gauche : ht1 < ht0") dec = profil1["height"]/math.tan(math.radians(profil0["angle"])) edgeRidge0OnPane = DraftGeomUtils.offset(edges[i-1],self.getPerpendicular(vec0,rotEdge0,dec)) ptInterRidges = DraftGeomUtils.findIntersection(edgeRidge0OnPane,edgeRidge1,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0])) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInterRidges[0]),pt0Edge1) ptInterHipEave3 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave3: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection(edgeHip,edgeEave0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append(FreeCAD.Vector(pt0Eave1[0])) else: print("Cas de figure non pris en charge") ptsPaneProject = DraftVecUtils.removeDoubles(ptsPaneProject) print("ptsPaneProject",ptsPaneProject) print("Fin Analyse profil " + str(i)) self.profilsDico[i]["points"] = ptsPaneProject lp = len(ptsPaneProject) ptsPaneProject.append(ptsPaneProject[0]) edgesWire = [] for i in range(lp): edge = Part.makeLine(ptsPaneProject[i],ptsPaneProject[i+1]) edgesWire.append(edge) wire = Part.Wire(edgesWire) d = wire.BoundBox.DiagonalLength thicknessV = profil1["thickness"]/(math.cos(math.radians(profil1["angle"]))) overhangV = profil1["overhang"]*math.tan(math.radians(profil1["angle"])) if wire.isClosed(): f = Part.Face(wire) f = f.extrude(FreeCAD.Vector(0,0,profil1["height"]+2*thicknessV+2*overhangV)) f.translate(FreeCAD.Vector(0.0,0.0,-2*overhangV)) ptsPaneProfil=[FreeCAD.Vector(-profil1["overhang"],-overhangV,0.0),FreeCAD.Vector(profil1["run"],profil1["height"],0.0),FreeCAD.Vector(profil1["run"],profil1["height"]+thicknessV,0.0),FreeCAD.Vector(-profil1["overhang"],-overhangV+thicknessV,0.0)] self.createProfilShape (ptsPaneProfil, midpoint, rotEdge1, vec1, profil1["run"], d, self.shps, f) ## subVolume shape ptsSubVolumeProfil=[FreeCAD.Vector(-profil1["overhang"],-overhangV,0.0),FreeCAD.Vector(profil1["run"],profil1["height"],0.0),FreeCAD.Vector(profil1["run"],profil1["height"]+10000,0.0),FreeCAD.Vector(0.0,profil1["height"]+10000,0.0)] self.createProfilShape (ptsSubVolumeProfil, midpoint, rotEdge1, vec1, profil1["run"], d, self.subVolshps, f) else: #TODO PIGNON pass ## SubVolume self.sub = self.subVolshps.pop() for s in self.subVolshps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl ## BaseVolume base = Part.makeCompound(self.shps) if not base.isNull(): if not DraftGeomUtils.isNull(pl): base.Placement = pl base = self.processSubShapes(obj,base) if base: if not base.isNull(): obj.Shape = base