Path: usecomp setting toggles the availability of the side property

This commit is contained in:
sliptonic
2017-06-02 16:00:41 -05:00
committed by Yorik van Havre
parent 0766a7387f
commit cc4abd21b9
7 changed files with 194 additions and 172 deletions

View File

@@ -33,8 +33,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>381</height>
<width>285</width>
<height>277</height>
</rect>
</property>
<attribute name="icon">
@@ -111,8 +111,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>381</height>
<width>120</width>
<height>96</height>
</rect>
</property>
<attribute name="icon">
@@ -178,8 +178,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>381</height>
<width>154</width>
<height>68</height>
</rect>
</property>
<attribute name="icon">
@@ -343,13 +343,6 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Roll Radius</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="Gui::InputField" name="extraOffset">
<property name="minimum">
@@ -360,16 +353,6 @@
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="Gui::InputField" name="rollRadius">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="unit" stdset="0">
<string notr="true">mm</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -390,13 +373,6 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="useEndPoint">
<property name="text">
<string>Use End Point</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="useStartPoint">
<property name="text">

View File

@@ -34,8 +34,8 @@ from PathScripts.PathUtils import waiting_effects
from PathScripts.PathUtils import makeWorkplane
LOG_MODULE = 'PathContour'
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
#PathLog.trackModule('PathContour')
PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE)
PathLog.trackModule('PathContour')
FreeCAD.setLogLevel('Path.Area', 0)
if FreeCAD.GuiUp:
@@ -77,9 +77,9 @@ class ObjectContour:
obj.addProperty("App::PropertyEnumeration", "Direction", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "The direction that the toolpath should go around the part ClockWise CW or CounterClockWise CCW"))
obj.Direction = ['CW', 'CCW'] # this is the direction that the Contour runs
obj.addProperty("App::PropertyBool", "UseComp", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if using Cutter Radius Compensation"))
obj.addProperty("App::PropertyEnumeration", "Side", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Side of edge that tool should cut"))
obj.Side = ['Left', 'Right', 'On'] # side of profile that cutter is on in relation to direction of profile
obj.setEditorMode('Side', 2) # hide
# obj.addProperty("App::PropertyEnumeration", "Side", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Side of edge that tool should cut"))
# obj.Side = ['Left', 'Right'] # side of profile that cutter is on in relation to direction of profile
# obj.setEditorMode('Side', 2) # hide
obj.addProperty("App::PropertyDistance", "OffsetExtra", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Extra value to stay away from final Contour- good for roughing toolpath"))
@@ -94,8 +94,11 @@ class ObjectContour:
def onChanged(self, obj, prop):
pass
# if prop in ['ClearanceHeight', 'StartPoint']:
# obj.StartPoint.z = obj.ClearanceHeight.Value
# if prop == "UseComp":
# if not obj.UseComp:
# obj.setEditorMode('Side', 2)
# else:
# obj.setEditorMode('Side', 0)
def setDepths(proxy, obj):
PathLog.track()
@@ -171,22 +174,22 @@ class ObjectContour:
PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector))
self.endVector = end_vector
if True:
from PathScripts.PathUtils import CollisionTester
parentJob = PathUtils.findParentJob(obj)
if parentJob is None:
pass
base = parentJob.Base
if base is None:
pass
# if True:
# from PathScripts.PathUtils import CollisionTester
# parentJob = PathUtils.findParentJob(obj)
# if parentJob is None:
# pass
# base = parentJob.Base
# if base is None:
# pass
profileparams['Thicken'] = True #{'Fill':0, 'Coplanar':0, 'Project':True, 'SectionMode':2, 'Thicken':True}
profileparams['ToolRadius']= self.radius - self.radius *.005
profile.setParams(**profileparams)
sec = profile.makeSections(heights=[0.0])[0].getShape()
cutPath = sec.extrude(FreeCAD.Vector(0,0,baseobject.BoundBox.ZMax))
c = CollisionTester()
c.getCollisionSim(base.Shape, cutPath)
# profileparams['Thicken'] = True #{'Fill':0, 'Coplanar':0, 'Project':True, 'SectionMode':2, 'Thicken':True}
# profileparams['ToolRadius']= self.radius - self.radius *.005
# profile.setParams(**profileparams)
# sec = profile.makeSections(heights=[0.0])[0].getShape()
# cutPath = sec.extrude(FreeCAD.Vector(0,0,baseobject.BoundBox.ZMax))
# c = CollisionTester()
# c.getCollisionSim(base.Shape, cutPath)
return pp
@@ -194,6 +197,12 @@ class ObjectContour:
PathLog.track()
self.endVector = None
if not obj.Active:
path = Path.Path("(inactive operation)")
obj.Path = path
obj.ViewObject.Visibility = False
return
commandlist = []
toolLoad = obj.ToolController
@@ -244,22 +253,16 @@ class ObjectContour:
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
else:
bb = baseobject.Shape.BoundBox
env = PathUtils.getEnvelope(partshape=baseobject.Shape, stockheight=bb.ZLength + (obj.StartDepth.Value-bb.ZMax))
env = PathUtils.getEnvelope(partshape=baseobject.Shape, subshape=None, stockheight=bb.ZLength + (obj.StartDepth.Value-bb.ZMax))
try:
commandlist.extend(self._buildPathArea(obj, env, start=obj.StartPoint).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
if obj.Active:
path = Path.Path(commandlist)
obj.Path = path
if obj.ViewObject:
obj.ViewObject.Visibility = True
else:
path = Path.Path("(inactive operation)")
obj.Path = path
obj.ViewObject.Visibility = False
path = Path.Path(commandlist)
obj.Path = path
obj.ViewObject.Visibility = True
class _ViewProviderContour:

View File

@@ -226,6 +226,12 @@ class ObjectFace:
def execute(self, obj):
PathLog.track()
if not obj.Active:
path = Path.Path("(inactive operation)")
obj.Path = path
obj.ViewObject.Visibility = False
return
commandlist = []
toolLoad = obj.ToolController
@@ -288,18 +294,12 @@ class ObjectFace:
try:
commandlist.extend(self._buildPathArea(obj, env).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintWarning(translate("Path_MillFace", "The selected settings did not produce a valid path.\n"))
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError(translate("Path_MillFace", "The selected settings did not produce a valid path.\n"))
if obj.Active:
path = Path.Path(commandlist)
obj.Path = path
if obj.ViewObject:
obj.ViewObject.Visibility = True
else:
path = Path.Path("(inactive operation)")
obj.Path = path
obj.ViewObject.Visibility = False
path = Path.Path(commandlist)
obj.Path = path
obj.ViewObject.Visibility = True
class _CommandSetFaceStartPoint:

View File

@@ -37,14 +37,16 @@ if FreeCAD.GuiUp:
"""Path Pocket object and FreeCAD command"""
LOG_MODULE = 'PathPocket'
PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE)
PathLog.trackModule('PathPocket')
FreeCAD.setLogLevel('Path.Area',0)
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
#PathLog.trackModule('PathPocket')
FreeCAD.setLogLevel('Path.Area', 0)
# Qt tanslation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class ObjectPocket:
def __init__(self, obj):
@@ -75,7 +77,6 @@ class ObjectPocket:
obj.addProperty("App::PropertyEnumeration", "OffsetPattern", "Face", QtCore.QT_TRANSLATE_NOOP("App::Property", "clearing pattern to use"))
obj.OffsetPattern = ['ZigZag', 'Offset', 'Spiral', 'ZigZagOffset', 'Line', 'Grid', 'Triangle']
# Start Point Properties
obj.addProperty("App::PropertyVector", "StartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "The start point of this path"))
obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if specifying a Start Point"))
@@ -163,11 +164,11 @@ class ObjectPocket:
return None
@waiting_effects
def _buildPathArea(self, obj, baseobject):
def _buildPathArea(self, obj, envelopeshape):
PathLog.track()
pocket = Path.Area()
pocket.setPlane(Part.makeCircle(10))
pocket.add(baseobject)
pocket.add(envelopeshape)
stepover = (self.radius * 2) * (float(obj.StepOver)/100)
@@ -205,16 +206,11 @@ class ObjectPocket:
'resume_height': obj.StepDown.Value,
'retraction': obj.ClearanceHeight.Value}
# if obj.UseStartPoint is True and obj.StartPoint is not None:
# params['start'] = obj.StartPoint
pp = Path.fromShapes(**params)
PathLog.debug("Generating Path with params: {}".format(params))
PathLog.debug(pp)
return pp
def execute(self, obj):
PathLog.track()
commandlist = []
@@ -225,6 +221,13 @@ class ObjectPocket:
obj.ViewObject.Visibility = False
return
parentJob = PathUtils.findParentJob(obj)
if parentJob is None:
return
baseobject = parentJob.Base
if baseobject is None:
return
toolLoad = obj.ToolController
if toolLoad is None or toolLoad.ToolNumber == 0:
FreeCAD.Console.PrintError("No Tool Controller is selected. We need a tool to build a Path.")
@@ -251,25 +254,20 @@ class ObjectPocket:
edges = [getattr(b[0].Shape, sub) for sub in b[1]]
shape = Part.makeFace(edges, 'Part::FaceMakerSimple')
env = PathUtils.getEnvelope(shape, obj.StartDepth)
env = PathUtils.getEnvelope(baseobject.Shape, subshape=shape, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, env.cut(b[0].Shape)).Commands)
commandlist.extend(self._buildPathArea(obj, env.cut(baseobject.Shape)).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a pocket path. Check project and tool config.")
else: # process the job base object as a whole
PathLog.debug("processing the whole job base object")
parentJob = PathUtils.findParentJob(obj)
if parentJob is None:
return
baseobject = parentJob.Base
if baseobject is None:
return
env = PathUtils.getEnvelope(baseobject.Shape, obj.StartDepth)
env = PathUtils.getEnvelope(baseobject.Shape, subshape=None, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, env.cut(baseobject.Shape)).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a pocket path. Check project and tool config.")
path = Path.Path(commandlist)
@@ -362,7 +360,7 @@ class CommandPathPocket:
FreeCADGui.doCommand('obj.ToolController = PathScripts.PathUtils.findToolController(obj)')
FreeCAD.ActiveDocument.commitTransaction()
#FreeCAD.ActiveDocument.recompute()
# FreeCAD.ActiveDocument.recompute()
FreeCADGui.doCommand('obj.ViewObject.startEditing()')
@@ -403,6 +401,8 @@ class TaskPanel:
self.obj.UseStartPoint = self.form.useStartPoint.isChecked()
if hasattr(self.obj, "CutMode"):
self.obj.CutMode = str(self.form.cutMode.currentText())
if hasattr(self.obj, "OffsetPattern"):
self.obj.OffsetPattern = str(self.form.offsetpattern.currentText())
if hasattr(self.obj, "ZigZagAngle"):
self.obj.ZigZagAngle = FreeCAD.Units.Quantity(self.form.zigZagAngle.text()).Value
if hasattr(self.obj, "StepOver"):
@@ -425,11 +425,12 @@ class TaskPanel:
self.form.zigZagAngle.setText(FreeCAD.Units.Quantity(self.obj.ZigZagAngle, FreeCAD.Units.Angle).UserString)
self.form.stepOverPercent.setValue(self.obj.StepOver)
# index = self.form.algorithmSelect.findText(self.obj.Algorithm, QtCore.Qt.MatchFixedString)
# if index >= 0:
# self.form.algorithmSelect.blockSignals(True)
# self.form.algorithmSelect.setCurrentIndex(index)
# self.form.algorithmSelect.blockSignals(False)
index = self.form.offsetpattern.findText(
self.obj.OffsetPattern, QtCore.Qt.MatchFixedString)
if index >= 0:
self.form.offsetpattern.blockSignals(True)
self.form.offsetpattern.setCurrentIndex(index)
self.form.offsetpattern.blockSignals(False)
index = self.form.cutMode.findText(
self.obj.CutMode, QtCore.Qt.MatchFixedString)

View File

@@ -34,7 +34,7 @@ import PathScripts.PathLog as PathLog
LOG_MODULE = 'PathProfile'
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
# PathLog.trackModule('PathProfile')
PathLog.trackModule('PathProfile')
FreeCAD.setLogLevel('Path.Area', 0)
if FreeCAD.GuiUp:
@@ -76,7 +76,7 @@ class ObjectProfile:
# Profile Properties
obj.addProperty("App::PropertyEnumeration", "Side", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Side of edge that tool should cut"))
obj.Side = ['Left', 'Right', 'On'] # side of profile that cutter is on in relation to direction of profile
obj.Side = ['Left', 'Right'] # side of profile that cutter is on in relation to direction of profile
obj.addProperty("App::PropertyEnumeration", "Direction", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "The direction that the toolpath should go around the part ClockWise CW or CounterClockWise CCW"))
obj.Direction = ['CW', 'CCW'] # this is the direction that the profile runs
obj.addProperty("App::PropertyBool", "UseComp", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if using Cutter Radius Compensation"))
@@ -94,7 +94,11 @@ class ObjectProfile:
return None
def onChanged(self, obj, prop):
pass
if prop == "UseComp":
if not obj.UseComp:
obj.setEditorMode('Side', 2)
else:
obj.setEditorMode('Side', 0)
def addprofilebase(self, obj, ss, sub=""):
baselist = obj.Base
@@ -135,22 +139,29 @@ class ObjectProfile:
obj.Base = baselist
self.execute(obj)
def _buildPathArea(self, obj, baseobject, isHole, start=None):
def _buildPathArea(self, obj, baseobject, isHole=False, start=None):
PathLog.track()
profile = Path.Area()
profile.setPlane(Part.makeCircle(10))
profile.add(baseobject)
profileparams = {'Fill': 0,
'Coplanar': 0,
'Coplanar': 2,
'Offset': 0.0,
'SectionCount': -1}
offsetval = 0
if obj.UseComp:
if isHole:
profileparams['Offset'] = 0 - self.radius+obj.OffsetExtra.Value
else:
profileparams['Offset'] = self.radius+obj.OffsetExtra.Value
offsetval = self.radius+obj.OffsetExtra.Value
if obj.Side == 'Right':
offsetval = 0 - offsetval
if isHole:
offsetval = 0 - offsetval
profileparams['Offset'] = offsetval
profile.setParams(**profileparams)
# PathLog.debug("About to profile with params: {}".format(profileparams))
@@ -175,7 +186,7 @@ class ObjectProfile:
'resume_height': obj.StepDown.Value,
'retraction': obj.ClearanceHeight.Value}
# Reverse the direction for holes
#Reverse the direction for holes
if isHole:
direction = "CW" if obj.Direction == "CCW" else "CCW"
else:
@@ -197,8 +208,14 @@ class ObjectProfile:
def execute(self, obj):
import Part
commandlist = []
if not obj.Active:
path = Path.Path("(inactive operation)")
obj.Path = path
obj.ViewObject.Visibility = False
return
commandlist = []
toolLoad = obj.ToolController
if toolLoad is None or toolLoad.ToolNumber == 0:
FreeCAD.Console.PrintError("No Tool Controller is selected. We need a tool to build a Path.")
@@ -222,7 +239,14 @@ class ObjectProfile:
else:
commandlist.append(Path.Command("(Uncompensated Tool Path)"))
if obj.Base:
parentJob = PathUtils.findParentJob(obj)
if parentJob is None:
return
baseobject = parentJob.Base
if baseobject is None:
return
if obj.Base: # The user has selected subobjects from the base. Process each.
holes = []
faces = []
for b in obj.Base:
@@ -233,46 +257,34 @@ class ObjectProfile:
if numpy.isclose(abs(shape.normalAt(0, 0).z), 1): # horizontal face
holes += shape.Wires[1:]
else:
print ("found a base object which is not a face. Can't continue.")
FreeCAD.Console.PrintWarning ("found a base object which is not a face. Can't continue.")
return
if obj.processHoles:
for wire in holes:
f = Part.makeFace(wire, 'Part::FaceMakerSimple')
drillable = PathUtils.isDrillable(baseobject.Shape, wire)
if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
# shift the compound to the bottom of the base object for
# proper sectioning
zShift = b[0].Shape.BoundBox.ZMin - f.BoundBox.ZMin
newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), f.Placement.Rotation)
f.Placement = newPlace
env = PathUtils.getEnvelope(f, obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=True, start=None).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=True, start=None).Commands)
except Exception as e:
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
profileshape = Part.makeCompound(faces)
zShift = b[0].Shape.BoundBox.ZMin - profileshape.BoundBox.ZMin
newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), profileshape.Placement.Rotation)
profileshape.Placement = newPlace
if len(faces) > 0:
profileshape = Part.makeCompound(faces)
if obj.processPerimeter:
env = PathUtils.getEnvelope(profileshape, obj.StartDepth)
env = PathUtils.getEnvelope(baseobject.Shape, subshape=profileshape, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=False, start=None).Commands)
commandlist.extend(self._buildPathArea(obj, baseobject=env, start=None).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
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
else: # Try to build targets from the job base
if hasattr(baseobject, "Proxy"):
if isinstance(baseobject.Proxy, ArchPanel.PanelSheet): # process the sheet
if obj.processPerimeter:
@@ -280,11 +292,11 @@ class ObjectProfile:
for shape in shapes:
for wire in shape.Wires:
f = Part.makeFace(wire, 'Part::FaceMakerSimple')
env = PathUtils.getEnvelope(f, obj.StartDepth)
env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=False, start=None).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
shapes = baseobject.Proxy.getHoles(baseobject, transform=True)
@@ -293,22 +305,16 @@ class ObjectProfile:
drillable = PathUtils.isDrillable(baseobject.Proxy, wire)
if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
f = Part.makeFace(wire, 'Part::FaceMakerSimple')
env = PathUtils.getEnvelope(f, obj.StartDepth)
env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=True, start=None).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
if obj.Active:
path = Path.Path(commandlist)
obj.Path = path
obj.ViewObject.Visibility = True
else:
path = Path.Path("(inactive operation)")
obj.Path = path
obj.ViewObject.Visibility = False
path = Path.Path(commandlist)
obj.Path = path
obj.ViewObject.Visibility = True
class _ViewProviderProfile:

View File

@@ -28,6 +28,7 @@ import Part
from PathScripts import PathUtils
from PathScripts.PathUtils import depth_params
from DraftGeomUtils import findWires
from DraftGeomUtils import isReallyClosed
import PathScripts.PathLog as PathLog
from PathScripts.PathUtils import waiting_effects
@@ -92,7 +93,11 @@ class ObjectProfile:
return None
def onChanged(self, obj, prop):
pass
if prop == "UseComp":
if not obj.UseComp:
obj.setEditorMode('Side', 2)
else:
obj.setEditorMode('Side', 0)
def addprofilebase(self, obj, ss, sub=""):
baselist = obj.Base
@@ -218,6 +223,12 @@ class ObjectProfile:
obj.ViewObject.Visibility = False
return
parentJob = PathUtils.findParentJob(obj)
if parentJob is None:
return
baseobject = parentJob.Base
if baseobject is None:
return
toolLoad = obj.ToolController
if toolLoad is None or toolLoad.ToolNumber == 0:
@@ -235,12 +246,12 @@ class ObjectProfile:
self.radius = tool.Diameter/2
commandlist.append(Path.Command("(" + obj.Label + ")"))
if obj.UseComp:
commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"))
else:
commandlist.append(Path.Command("(Uncompensated Tool Path)"))
if obj.Base:
wires = []
@@ -258,14 +269,14 @@ class ObjectProfile:
zShift = b[0].Shape.BoundBox.ZMin - f.BoundBox.ZMin
newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), f.Placement.Rotation)
f.Placement = newPlace
env = PathUtils.getEnvelope(f, obj.StartDepth)
env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth)
try:
# commandlist.extend(self._buildPathArea(obj, wire).Commands)
commandlist.extend(self._buildPathArea(obj, baseobject=env, start=None).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
path = Path.Path(commandlist)
@@ -492,6 +503,14 @@ class TaskPanel:
if not selection[0].SubObjects[0].ShapeType == "Edge":
FreeCAD.Console.PrintError(translate("PathProject", "Please select one or more edges from the Base model\n"))
return
try:
theWire = Part.Wire(sel.SubObjects)
except:
FreeCAD.Console.PrintError(translate("PathProject", "The selected edges don't form a closed loop\n"))
return
if not isReallyClosed(theWire):
FreeCAD.Console.PrintError(translate("PathProject", "The selected edges don't form a closed loop\n"))
return
for i in sel.SubElementNames:
self.obj.Proxy.addprofilebase(self.obj, sel.Object, i)

View File

@@ -38,7 +38,7 @@ from PySide import QtGui
LOG_MODULE = 'PathUtils'
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
PathLog.trackModule('PathUtils')
#PathLog.trackModule('PathUtils')
FreeCAD.setLogLevel('Path.Area', 0)
def waiting_effects(function):
@@ -236,34 +236,51 @@ def makeWorkplane(shape):
return c
def getEnvelope(partshape, stockheight=None):
def getEnvelope(partshape, subshape=None, stockheight=None):
'''
getEnvelop(partshape, stockheight=None)
getEnvelope(partshape, stockheight=None)
returns a shape corresponding to the partshape silhouette extruded to height.
if stockheight is given, the returned shape is extruded to that height otherwise the returned shape
is the height of the original shape boundbox
partshape = solid object
stockheight = float
stockheight = float - Absolute Z height of the top of material before cutting.
'''
PathLog.track(partshape, stockheight)
area = Path.Area(Fill=1, Coplanar=0).add(partshape)
# loc = FreeCAD.Vector(partshape.BoundBox.Center.x,
# partshape.BoundBox.Center.y,
# partshape.BoundBox.ZMin)
area.setPlane(makeWorkplane(partshape))
sec = area.makeSections(heights=[1.0], project=True)[0].getShape()
PathLog.track(partshape, subshape, stockheight)
# if partshape.Volume == 0.0: #Not a 3D object
# return None
if subshape is not None:
if isinstance(subshape, Part.Face):
PathLog.debug('processing a face')
sec = Part.makeCompound([subshape])
else:
area = Path.Area(Fill=2, Coplanar=0).add(subshape)
area.setPlane(makeWorkplane(partshape))
PathLog.debug("About to section with params: {}".format(area.getParams()))
sec = area.makeSections(heights=[0.0], project=True)[0].getShape()
zShift = partshape.BoundBox.ZMin - subshape.BoundBox.ZMin
PathLog.debug('partshapeZmin: {}, subshapeZMin: {}, zShift: {}'.format(partshape.BoundBox.ZMin, subshape.BoundBox.ZMin, zShift))
newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), sec.Placement.Rotation)
sec.Placement = newPlace
else:
area = Path.Area(Fill=2, Coplanar=0).add(partshape)
area.setPlane(makeWorkplane(partshape))
sec = area.makeSections(heights=[0.0], project=True)[0].getShape()
if stockheight is not None:
eLength = float(stockheight)-partshape.BoundBox.ZMin
PathLog.debug('boundbox zMIN: {} elength: {}'.format(partshape.BoundBox.ZMin, eLength))
envelopeshape = sec.extrude(FreeCAD.Vector(0, 0, eLength))
else:
envelopeshape = sec.extrude(FreeCAD.Vector(0, 0, partshape.BoundBox.ZLength))
if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG:
removalshape=FreeCAD.ActiveDocument.addObject("Part::Feature","RemovedMaterial")
removalshape=FreeCAD.ActiveDocument.addObject("Part::Feature","Envelope")
removalshape.Shape = envelopeshape
return envelopeshape
def reverseEdge(e):
if geomType(e) == "Circle":
arcstpt = e.valueAt(e.FirstParameter)