diff --git a/src/Mod/Arch/ArchPanel.py b/src/Mod/Arch/ArchPanel.py index 64ff205b7d..18d96be44b 100644 --- a/src/Mod/Arch/ArchPanel.py +++ b/src/Mod/Arch/ArchPanel.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,Draft,ArchComponent,DraftVecUtils,ArchCommands,math +import FreeCAD,Draft,ArchComponent,DraftVecUtils,ArchCommands,math, Part from FreeCAD import Vector if FreeCAD.GuiUp: import FreeCADGui @@ -374,7 +374,7 @@ class _Panel(ArchComponent.Component): if self.clone(obj): return - import Part, DraftGeomUtils + import Part #, DraftGeomUtils # base tests if obj.Base: @@ -415,7 +415,7 @@ class _Panel(ArchComponent.Component): if obj.Base: base = obj.Base.Shape.copy() if not base.Solids: - p = FreeCAD.Placement(obj.Base.Placement) + # p = FreeCAD.Placement(obj.Base.Placement) if base.Faces: baseprofile = base if not normal: @@ -515,7 +515,7 @@ class _Panel(ArchComponent.Component): base = self.vol.common(base) base = base.removeSplitter() if not base: - FreeCAD.Console.PrintError(transpate("Arch","Error computing shape of ")+obj.Label+"\n") + FreeCAD.Console.PrintError(translate("Arch","Error computing shape of ")+obj.Label+"\n") return False if base and (obj.Sheets > 1) and normal and thickness: @@ -558,7 +558,7 @@ class _ViewProviderPanel(ArchComponent.ViewProviderComponent): vobj.ShapeColor = ArchCommands.getDefaultColor("Panel") def getIcon(self): - import Arch_rc + #import Arch_rc if hasattr(self,"Object"): if hasattr(self.Object,"CloneOf"): if self.Object.CloneOf: @@ -723,13 +723,12 @@ class PanelCut(Draft._DraftObject): obj.Shape = base obj.Placement = pl - def getWires(self,obj): - + def getWires(self, obj): + """getWires(obj): returns a tuple containing 3 shapes that define the panel outline, the panel holes, and tags (engravings): (outline,holes,tags). Any of these can be None if nonexistent""" - tag = None outl = None inl = None @@ -742,6 +741,8 @@ class PanelCut(Draft._DraftObject): tag = self.tag.copy() if tag: tag.Placement = obj.Placement.multiply(tag.Placement) + + outl = self.outline.copy() outl.Placement = obj.Placement.multiply(outl.Placement) if len(outl.Wires) > 1: # separate outline @@ -753,11 +754,11 @@ class PanelCut(Draft._DraftObject): ow = w if ow: inl = Part.Compound([w for w in outl.Wires if w.hashCode() != ow.hashCode()]) - outl = ow + outl = Part.Compound([ow]) else: inl = None - outl = outl.Wires[0] - return (outl,inl,tags) + outl = Part.Compound([outl.Wires[0]]) + return (outl, inl, tag) class ViewProviderPanelCut(Draft._ViewProviderDraft): "a view provider for the panel cut object" @@ -889,10 +890,10 @@ class PanelSheet(Draft._DraftObject): obj.FillRatio = int((subarea/area)*100) def getOutlines(self,obj,transform=False): - """getOutlines(obj,transform=False): returns a list of wires that define the + """getOutlines(obj,transform=False): returns a list of compounds whose wires define the outlines of the panels in this sheet. If transform is True, the placement of the sheet will be added to each wire""" - + outp = [] for p in obj.Group: ispanel = False @@ -914,10 +915,10 @@ class PanelSheet(Draft._DraftObject): return outp def getHoles(self,obj,transform=False): - """getHoles(obj,transform=False): returns a list of wires that define the + """getHoles(obj,transform=False): returns a list of compound whose wires define the holes contained in the panels in this sheet. If transform is True, the placement of the sheet will be added to each wire""" - + outp = [] for p in obj.Group: if hasattr(p,"Proxy"): @@ -931,21 +932,25 @@ class PanelSheet(Draft._DraftObject): return outp def getTags(self,obj,transform=False): - """getTags(obj,transform=False): returns a list of wires that define the - tags (engravings) contained in the panels in this sheet. If transform is - True, the placement of the sheet will be added to each wire. Warning, the - wires returned by this function may not be closed, depending on the font""" - + """getTags(obj,transform=False): returns a list of compounds whose wires define the + tags (engravings) contained in the panels in this sheet and the sheet intself. + If transform is True, the placement of the sheet will be added to each wire. + Warning, the wires returned by this function may not be closed, + depending on the font""" + outp = [] for p in obj.Group: if hasattr(p,"Proxy"): if hasattr(p.Proxy,"getWires"): w = p.Proxy.getWires(p) - if w[1]: - w = w[1] + if w[2]: + w = w[2] if transform: w.Placement = obj.Placement.multiply(w.Placement) outp.append(w) + if self.sheettag is not None: + outp.append(self.sheettag) + return outp diff --git a/src/Mod/Path/Gui/Resources/panels/ProfileEdit.ui b/src/Mod/Path/Gui/Resources/panels/ProfileEdit.ui index ada29ee2a1..5964a1104e 100644 --- a/src/Mod/Path/Gui/Resources/panels/ProfileEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/ProfileEdit.ui @@ -327,53 +327,6 @@ - - - - - 0 - - - 0 - - - - - Use End Point - - - - - - - Use Start Point - - - - - - - Use Compensation - - - - - - - Process Holes - - - - - - - Process Perimeter - - - - - - @@ -420,6 +373,54 @@ + + + + + + + Process Perimeter + + + + + + + Process Holes + + + + + + + Use End Point + + + + + + + Use Start Point + + + + + + + Use Compensation + + + + + + + Process Circles + + + + + + diff --git a/src/Mod/Path/PathScripts/PathContour.py b/src/Mod/Path/PathScripts/PathContour.py index 395ca476f3..8ea6483c0d 100644 --- a/src/Mod/Path/PathScripts/PathContour.py +++ b/src/Mod/Path/PathScripts/PathContour.py @@ -34,7 +34,7 @@ import ArchPanel LOG_MODULE = 'PathContour' PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) -PathLog.trackModule('PathContour') +#PathLog.trackModule('PathContour') if FreeCAD.GuiUp: import FreeCADGui diff --git a/src/Mod/Path/PathScripts/PathEngrave.py b/src/Mod/Path/PathScripts/PathEngrave.py index bd3fc032f9..6ab7b183f8 100644 --- a/src/Mod/Path/PathScripts/PathEngrave.py +++ b/src/Mod/Path/PathScripts/PathEngrave.py @@ -116,7 +116,6 @@ class ObjectPathEngrave: baseobject = parentJob.Base if baseobject is None: return - try: if baseobject.isDerivedFrom('Sketcher::SketchObject') or \ baseobject.isDerivedFrom('Part::Part2DObject'): @@ -132,31 +131,14 @@ class ObjectPathEngrave: output += self.buildpathocc(obj, wires) elif isinstance(baseobject.Proxy, ArchPanel.PanelSheet): # process the sheet - baseobject.Proxy.execute(baseobject) - ss = baseobject.Proxy.sheettag - ss.Placement = baseobject.Placement.multiply(ss.Placement) - - output += "G0 Z" + PathUtils.fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n" - for w in ss.Wires: - tempedges = PathUtils.cleanedges(w.Edges, 0.5) - wires.append(Part.Wire(tempedges)) - if obj.Algorithm == "OCC Native": - output += self.buildpathocc(obj, wires) - - for subobj in baseobject.Group: # process the group of panels - if isinstance(subobj.Proxy, ArchPanel.PanelCut): - subobj.Proxy.execute(subobj) - - if hasattr(subobj.Proxy, "tag"): - ss = subobj.Proxy.tag - ss.Placement = subobj.Placement.multiply(ss.Placement) - - output += "G0 Z" + PathUtils.fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n" - for w in ss.Wires: - tempedges = PathUtils.cleanedges(w.Edges, 0.5) - wires.append(Part.Wire(tempedges)) - if obj.Algorithm == "OCC Native": - output += self.buildpathocc(obj, wires) + shapes = baseobject.Proxy.getTags(baseobject) + for shape in shapes: + output += "G0 Z" + PathUtils.fmt(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n" + for w in shape.Wires: + tempedges = PathUtils.cleanedges(w.Edges, 0.5) + wires.append(Part.Wire(tempedges)) + if obj.Algorithm == "OCC Native": + output += self.buildpathocc(obj, wires) else: raise ValueError('Unknown baseobject type for engraving') diff --git a/src/Mod/Path/PathScripts/PathProfile.py b/src/Mod/Path/PathScripts/PathProfile.py index 013ab802b4..440117ff65 100644 --- a/src/Mod/Path/PathScripts/PathProfile.py +++ b/src/Mod/Path/PathScripts/PathProfile.py @@ -26,13 +26,15 @@ import FreeCAD import Path import numpy import TechDraw +import ArchPanel + from FreeCAD import Vector from PathScripts import PathUtils from PathScripts.PathUtils import depth_params import PathScripts.PathLog as PathLog LOG_MODULE = 'PathProfile' -PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) +PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE) # PathLog.trackModule('PathProfile') if FreeCAD.GuiUp: @@ -99,6 +101,7 @@ class ObjectProfile: obj.addProperty("App::PropertyDistance", "OffsetExtra", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Extra value to stay away from final profile- good for roughing toolpath")) obj.addProperty("App::PropertyBool", "processHoles", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Profile holes as well as the outline")) obj.addProperty("App::PropertyBool", "processPerimeter", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Profile the outline")) + obj.addProperty("App::PropertyBool", "processCircles", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Profile round holes")) obj.Proxy = self @@ -109,8 +112,7 @@ class ObjectProfile: return None def onChanged(self, obj, prop): - if prop == "UserLabel": - obj.Label = obj.UserLabel + " :" + obj.ToolDescription + pass def addprofilebase(self, obj, ss, sub=""): baselist = obj.Base @@ -271,6 +273,40 @@ print "y - " + str(point.y) edgelist = Part.__sortEdges__(edgelist) output += self._buildPathLibarea(obj, edgelist, False) + else: #Try to build targets frorm the job base + parentJob = PathUtils.findParentJob(obj) + if parentJob is None: + return + baseobject = parentJob.Base + if baseobject is None: + return + + if hasattr(baseobject, "Proxy"): + if isinstance(baseobject.Proxy, ArchPanel.PanelSheet): # process the sheet + if obj.processPerimeter: + shapes = baseobject.Proxy.getOutlines(baseobject, transform=False) + for shape in shapes: + for wire in shape.Wires: + edgelist = wire.Edges + edgelist = Part.__sortEdges__(edgelist) + PathLog.debug("Processing panel perimeter. edges found: {}".format(len(edgelist))) + try: + output += self._buildPathLibarea(obj, edgelist, isHole=False) + except: + FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") + + shapes = baseobject.Proxy.getHoles(baseobject, transform=False) + for shape in shapes: + for wire in shape.Wires: + drillable = PathUtils.isDrillable(baseobject.Proxy, wire) + if (drillable and obj.processCircles) or (not drillable and obj.processHoles): + edgelist = wire.Edges + edgelist = Part.__sortEdges__(edgelist) + try: + output += self._buildPathLibarea(obj, edgelist, isHole=True) + except: + FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") + if obj.Active: path = Path.Path(output) obj.Path = path @@ -442,6 +478,8 @@ class TaskPanel: self.obj.processHoles = self.form.processHoles.isChecked() if hasattr(self.obj, "processPerimeter"): self.obj.processPerimeter = self.form.processPerimeter.isChecked() + if hasattr(self.obj, "processCircles"): + self.obj.processCircles = self.form.processCircles.isChecked() if hasattr(self.obj, "ToolController"): PathLog.debug("name: {}".format(self.form.uiToolController.currentText())) tc = PathUtils.findToolController(self.obj, self.form.uiToolController.currentText()) @@ -462,6 +500,7 @@ class TaskPanel: self.form.useEndPoint.setChecked(self.obj.UseEndPoint) self.form.processHoles.setChecked(self.obj.processHoles) self.form.processPerimeter.setChecked(self.obj.processPerimeter) + self.form.processCircles.setChecked(self.obj.processCircles) index = self.form.cutSide.findText( self.obj.Side, QtCore.Qt.MatchFixedString) @@ -602,6 +641,7 @@ class TaskPanel: self.form.rollRadius.editingFinished.connect(self.getFields) self.form.processHoles.clicked.connect(self.getFields) self.form.processPerimeter.clicked.connect(self.getFields) + self.form.processCircles.clicked.connect(self.getFields) self.setFields() diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index 39894499bf..13b56a71e5 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -93,6 +93,7 @@ def isDrillable(obj, candidate): if (round(face.ParameterRange[0], 8) == 0.0) and (round(face.ParameterRange[1], 8) == round(math.pi * 2, 8)): for edge in face.Edges: # Find seam edge and check if aligned to Z axis. if (isinstance(edge.Curve, Part.Line)): + PathLog.debug("candidate is a circle") v0 = edge.Vertexes[0].Point v1 = edge.Vertexes[1].Point if (v1.sub(v0).x == 0) and (v1.sub(v0).y == 0): @@ -103,16 +104,19 @@ def isDrillable(obj, candidate): if obj.isInside(lsp, 0, False) or obj.isInside(lep, 0, False): drillable = False # eliminate elliptical holes - elif abs(face.BoundBox.XLength - face.BoundBox.YLength) > 0.05: + elif not hasattr(face.Surface, "Radius"): #abs(face.BoundBox.XLength - face.BoundBox.YLength) > 0.05: drillable = False else: drillable = True else: for edge in candidate.Edges: - if (isinstance(edge.Curve, Part.Circle)): - if abs(edge.BoundBox.XLength - edge.BoundBox.YLength) > 0.05: + if isinstance(edge.Curve, Part.Circle) and edge.isClosed(): + PathLog.debug("candidate is a circle or ellipse") + if not hasattr(edge.Curve, "Radius"): #bbdiff > 0.05: + PathLog.debug("No radius. Ellipse.") drillable = False else: + PathLog.debug("Has Radius, Circle") drillable = True return drillable