Added doc strings to operations.
This commit is contained in:
committed by
Yorik van Havre
parent
d57fb7bd33
commit
684b4f6e7e
@@ -28,14 +28,13 @@ import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathOp as PathOp
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
|
||||
from PathScripts.PathUtils import depth_params
|
||||
from PathScripts.PathUtils import makeWorkplane
|
||||
from PathScripts.PathUtils import waiting_effects
|
||||
from PySide import QtCore
|
||||
|
||||
__title__ = "Base class for PathArea based operations."
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Base class and properties for Path.Area based operations."
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
@@ -48,11 +47,22 @@ def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
class ObjectOp(PathOp.ObjectOp):
|
||||
'''Base class for all Path.Area based operations.
|
||||
Provides standard features including debugging properties AreaParams,
|
||||
PathParams and removalshape, all hidding.
|
||||
The main reason for existance is to implement the standard interface
|
||||
to Path.Area so subclasses only have to provide the shapes for the
|
||||
operations.'''
|
||||
|
||||
def opFeatures(self, obj):
|
||||
'''opFeatures(obj) ... returns the base features supported by all Path.Area based operations.
|
||||
The standard feature list is OR'ed with the return value of areaOpFeatures().
|
||||
Do not overwrite, implement areaOpFeatures(obj) instead.'''
|
||||
return PathOp.FeatureTool | PathOp.FeatureDepths | PathOp.FeatureStepDown | PathOp.FeatureHeights | PathOp.FeatureStartPoint | self.areaOpFeatures(obj)
|
||||
|
||||
def initOperation(self, obj):
|
||||
'''initOperation(obj) ... sets up standard Path.Area properties and calls initAreaOp().
|
||||
Do not overwrite, overwrite initAreaOp(obj) instead.'''
|
||||
PathLog.track()
|
||||
|
||||
# Debugging
|
||||
@@ -66,6 +76,8 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
self.initAreaOp(obj)
|
||||
|
||||
def areaOpShapeForDepths(self, obj):
|
||||
'''areaOpShapeForDepths(obj) ... returns the shape used to make an initial calculation for the depths being used.
|
||||
The default implementation retuns the job's Base.Shape'''
|
||||
job = PathUtils.findParentJob(obj)
|
||||
if job and job.Base:
|
||||
PathLog.debug("job=%s base=%s shape=%s" % (job, job.Base, job.Base.Shape))
|
||||
@@ -77,9 +89,15 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
return None
|
||||
|
||||
def areaOpOnChanged(self, obj, prop):
|
||||
'''areaOpOnChanged(obj, porp) ... overwrite to process operation specific changes to properties.
|
||||
Can safely be overwritten by subclasses.'''
|
||||
pass
|
||||
|
||||
def opOnChanged(self, obj, prop):
|
||||
'''opOnChanged(obj, prop) ... base implemenation of the notification framework - do not overwrite.
|
||||
The base implementation takes a stab at determining Heights and Depths if the operations's Base
|
||||
changes.
|
||||
Do not overwrite, overwrite areaOpOnChanged(obj, prop) instead.'''
|
||||
#PathLog.track(obj.Label, prop)
|
||||
if prop in ['AreaParams', 'PathParams', 'removalshape']:
|
||||
obj.setEditorMode(prop, 2)
|
||||
@@ -124,6 +142,10 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
self.areaOpOnChanged(obj, prop)
|
||||
|
||||
def opSetDefaultValues(self, obj):
|
||||
'''opSetDefaultValues(obj) ... base implementation, do not overwrite.
|
||||
The base implementation sets the depths and heights based on the
|
||||
areaOpShapeForDepths() return value.
|
||||
Do not overwrite, overwrite areaOpSetDefaultValues(obj) instead.'''
|
||||
PathLog.info("opSetDefaultValues(%s)" % (obj.Label))
|
||||
if PathOp.FeatureDepths & self.opFeatures(obj):
|
||||
try:
|
||||
@@ -159,10 +181,16 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
|
||||
self.areaOpSetDefaultValues(obj)
|
||||
|
||||
def areaOpSetDefaultValues(self, obj):
|
||||
'''areaOpSetDefaultValues(obj) ... overwrite to set initial values of operation specific properties.
|
||||
Can safely be overwritten by subclasses.'''
|
||||
pass
|
||||
|
||||
def _buildPathArea(self, obj, baseobject, isHole, start, getsim):
|
||||
'''_buildPathArea(obj, baseobject, isHole, start, getsim) ... internal function.'''
|
||||
PathLog.track()
|
||||
area = Path.Area()
|
||||
area.setPlane(makeWorkplane(baseobject))
|
||||
area.setPlane(PathUtils.makeWorkplane(baseobject))
|
||||
area.add(baseobject)
|
||||
|
||||
areaParams = self.areaOpAreaParams(obj, isHole)
|
||||
@@ -211,10 +239,18 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
return pp, simobj
|
||||
|
||||
def opExecute(self, obj, getsim=False):
|
||||
'''opExecute(obj, getsim=False) ... implementation of Path.Area ops.
|
||||
determines the parameters for _buildPathArea().
|
||||
Do not overwrite, implement
|
||||
areaOpAreaParams(obj, isHole) ... op specific area param dictionary
|
||||
areaOpPathParams(obj, isHole) ... op specific path param dictionary
|
||||
areaOpShapes(obj) ... the shape for path area to process
|
||||
areaOpUseProjection(obj) ... return true if operation can use projection
|
||||
instead.'''
|
||||
PathLog.track()
|
||||
self.endVector = None
|
||||
|
||||
self.depthparams = depth_params(
|
||||
self.depthparams = PathUtils.depth_params(
|
||||
clearance_height=obj.ClearanceHeight.Value,
|
||||
safe_height=obj.SafeHeight.Value,
|
||||
start_depth=obj.StartDepth.Value,
|
||||
@@ -241,3 +277,22 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
FreeCAD.Console.PrintError("Something unexpected happened. Check project and tool config.")
|
||||
|
||||
return sims
|
||||
|
||||
def areaOpAreaParams(self, obj, isHole):
|
||||
'''areaOpAreaParams(obj, isHole) ... return operation specific area parameters in a dictionary.
|
||||
Note that the resulting parameters are stored in the property AreaParams.
|
||||
Must be overwritten by subclasses.'''
|
||||
pass
|
||||
def areaOpPathParams(self, obj, isHole):
|
||||
'''areaOpPathParams(obj, isHole) ... return operation specific path parameters in a dictionary.
|
||||
Note that the resulting parameters are stored in the property PathParams.
|
||||
Must be overwritten by subclasses.'''
|
||||
pass
|
||||
def areaOpShapes(self, obj):
|
||||
'''areaOpShapes(obj) ... return all shapes to be processed by Path.Area for this op.
|
||||
Must be overwritten by subclasses.'''
|
||||
pass
|
||||
def areaOpUseProjection(self, obj):
|
||||
'''areaOpUseProcjection(obj) ... return True if the operation can use procjection, defaults to False.
|
||||
Can safely be overwritten by subclasses.'''
|
||||
return False
|
||||
|
||||
@@ -33,6 +33,11 @@ import sys
|
||||
|
||||
from PySide import QtCore
|
||||
|
||||
__title__ = "Path Circular Holes Base Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Base class an implementation for operations on circular holes."
|
||||
|
||||
# Qt tanslation handling
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
@@ -42,18 +47,32 @@ if True:
|
||||
PathLog.trackModule(PathLog.thisModule())
|
||||
|
||||
class ObjectOp(PathOp.ObjectOp):
|
||||
'''Base class for proxy objects of all operations on circular holes.'''
|
||||
|
||||
def opFeatures(self, obj):
|
||||
'''opFeatures(obj) ... calls circularHoleFeatures(obj) and ORs in the standard features required for processing circular holes.
|
||||
Do not overwrite, implement circularHoleFeatures(obj) instead'''
|
||||
return PathOp.FeatureTool | PathOp.FeatureDepths | PathOp.FeatureHeights | PathOp.FeatureBaseFaces | self.circularHoleFeatures(obj)
|
||||
|
||||
def initOperation(self, obj):
|
||||
'''initOperation(obj) ... adds Disabled properties and calls initCircularHoleOperation(obj).
|
||||
Do not overwrite, implement initCircularHoleOperation(obj) instead.'''
|
||||
obj.addProperty("App::PropertyStringList", "Disabled", "Base", QtCore.QT_TRANSLATE_NOOP("Path", "List of disabled features"))
|
||||
self.initCircularHoleOperation(obj)
|
||||
|
||||
def baseIsArchPanel(self, obj, base):
|
||||
'''baseIsArchPanel(obj, base) ... return true if op deals with an Arch.Panel.'''
|
||||
return hasattr(base, "Proxy") and isinstance(base.Proxy, ArchPanel.PanelSheet)
|
||||
|
||||
def getArchPanelEdge(self, obj, base, sub):
|
||||
'''getArchPanelEdge(obj, base, sub) ... helper function to identify a specific edge of an Arch.Panel.
|
||||
Edges are identified by 3 numbers:
|
||||
<holeId>.<wireId>.<edgeId>
|
||||
Let's say the edge is specified as "3.2.7", then the 7th edge of the 2nd wire in the 3rd hole returned
|
||||
by the panel sheet is the edge returned.
|
||||
Obviously this is as fragile as can be, but currently the best we can do while the panel sheets
|
||||
hide the actual features from Path and they can't be referenced directly.
|
||||
'''
|
||||
ids = string.split(sub, '.')
|
||||
holeId = int(ids[0])
|
||||
wireId = int(ids[1])
|
||||
@@ -68,6 +87,7 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
return edge
|
||||
|
||||
def holeDiameter(self, obj, base, sub):
|
||||
'''holeDiameter(obj, base, sub) ... returns the diameter of the specified hole.'''
|
||||
if self.baseIsArchPanel(obj, base):
|
||||
edge = self.getArchPanelEdge(obj, base, sub)
|
||||
return edge.BoundBox.XLength
|
||||
@@ -80,6 +100,8 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
return shape.BoundBox.XLength
|
||||
|
||||
def holePosition(self, obj, base, sub):
|
||||
'''holePosition(obj, base, sub) ... returns a Vector for the position defined by the given features.
|
||||
Note that the value for Z is set to 0.'''
|
||||
if self.baseIsArchPanel(obj, base):
|
||||
edge = self.getArchPanelEdge(obj, base, sub)
|
||||
center = edge.Curve.Center
|
||||
@@ -98,10 +120,17 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
PathLog.error('This is bad')
|
||||
|
||||
def isHoleEnabled(self, obj, base, sub):
|
||||
'''isHoleEnabled(obj, base, sub) ... return true if hole is enabled.'''
|
||||
name = "%s.%s" % (base.Name, sub)
|
||||
return not name in obj.Disabled
|
||||
|
||||
def opExecute(self, obj):
|
||||
'''opExecute(obj) ... processes all Base features and Locations and collects
|
||||
them in a list of positions and radii which is then passed to circularHoleExecute(obj, holes).
|
||||
If no Base geometries and no Locations are present, the job's Base is inspected and all
|
||||
drillable features are added to Base. In this case appropriate values for depths are also
|
||||
calculated and assigned.
|
||||
Do not overwrite, implement circularHoleExecute(obj, holes) instead.'''
|
||||
PathLog.track()
|
||||
|
||||
def haveLocations(self, obj):
|
||||
@@ -145,7 +174,16 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
if len(holes) > 0:
|
||||
self.circularHoleExecute(obj, holes)
|
||||
|
||||
def circularHoleExecute(self, obj, holes):
|
||||
'''circularHoleExecute(obj, holes) ... implement processing of holes.
|
||||
holes is a list of dictionaries with 'x', 'y' and 'r' specified for each hole.
|
||||
Note that for Vertexes, non-circular Edges and Locations r=0.
|
||||
Must be overwritten by subclasses.'''
|
||||
pass
|
||||
|
||||
def opOnChanged(self, obj, prop):
|
||||
'''opOnChange(obj, prop) ... implements depth calculation if Base changes.
|
||||
Do not overwrite.'''
|
||||
if 'Base' == prop and not 'Restore' in obj.State and obj.Base:
|
||||
features = []
|
||||
for base, subs in obj.Base:
|
||||
@@ -159,6 +197,12 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
self.setupDepthsFrom(obj, features, job.Base)
|
||||
|
||||
def setupDepthsFrom(self, obj, features, baseobject):
|
||||
'''setupDepthsFrom(obj, features, baseobject) ... determins the min and max Z values necessary.
|
||||
Note that the algorithm calculates "safe" values,
|
||||
it determines the highest top Z value of all features
|
||||
and it also determines the highest bottom Z value of all features.
|
||||
The result is that all features can be drilled safely and the operation
|
||||
does not drill deeper than any of the features requires.'''
|
||||
zmax = None
|
||||
zmin = None
|
||||
if not self.baseIsArchPanel(obj, baseobject):
|
||||
@@ -174,6 +218,7 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
self.setDepths(obj, zmax, zmin, baseobject.Shape.BoundBox)
|
||||
|
||||
def setDepths(self, obj, zmax, zmin, bb):
|
||||
'''setDepths(obj, zmax, zmin, bb) ... set properties according to the provided values.'''
|
||||
PathLog.track(obj.Label, zmax, zmin, bb)
|
||||
if zmax is None:
|
||||
zmax = bb.ZMax
|
||||
@@ -191,6 +236,7 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
obj.FinalDepth = zmin
|
||||
|
||||
def findHoles(self, obj, baseobject):
|
||||
'''findHoles(obj, baseobject) ... inspect baseobject and identify all features that resemble a straight cricular hole.'''
|
||||
shape = baseobject.Shape
|
||||
PathLog.track('obj: {} shape: {}'.format(obj, shape))
|
||||
holelist = []
|
||||
|
||||
@@ -35,13 +35,17 @@ import PathScripts.PathUtils as PathUtils
|
||||
from PathScripts.PathUtils import fmt, waiting_effects
|
||||
from PySide import QtCore
|
||||
|
||||
__title__ = "Path Drilling Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Path Drilling operation."
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
PathLog.trackModule(PathLog.thisModule())
|
||||
else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
"""Path Drilling object and FreeCAD command"""
|
||||
|
||||
# Qt tanslation handling
|
||||
def translate(context, text, disambig=None):
|
||||
@@ -49,13 +53,14 @@ def translate(context, text, disambig=None):
|
||||
|
||||
|
||||
class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
||||
'''Proxy object for Drilling operation.'''
|
||||
|
||||
def circularHoleFeatures(self, obj):
|
||||
# drilling works on anything
|
||||
'''circularHoleFeatures(obj) ... drilling works on anything, turn on all Base geometries and Locations.'''
|
||||
return PathOp.FeatureBaseGeometry | PathOp.FeatureLocations
|
||||
|
||||
def initCircularHoleOperation(self, obj):
|
||||
|
||||
'''initCircularHoleOperation(obj) ... add drilling specific properties to obj.'''
|
||||
obj.addProperty("App::PropertyLength", "PeckDepth", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "Incremental Drill depth before retracting to clear chips"))
|
||||
obj.addProperty("App::PropertyBool", "PeckEnabled", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "Enable pecking"))
|
||||
obj.addProperty("App::PropertyFloat", "DwellTime", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "The time to dwell between peck cycles"))
|
||||
@@ -67,6 +72,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
||||
obj.addProperty("App::PropertyDistance", "RetractHeight", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "The height where feed starts and height during retract tool when path is finished"))
|
||||
|
||||
def circularHoleExecute(self, obj, holes):
|
||||
'''circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.'''
|
||||
PathLog.track()
|
||||
|
||||
self.commandlist.append(Path.Command("(Begin Drilling)"))
|
||||
@@ -111,6 +117,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
||||
self.commandlist.append(Path.Command('G80'))
|
||||
|
||||
def setDepths(self, obj, zmax, zmin, bb):
|
||||
'''setDepths(obj, zmax, zmin, bb) ... call base implementation and set RetractHeight accordingly.'''
|
||||
super(self.__class__, self).setDepths(obj, zmax, zmin, bb)
|
||||
if zmax is not None:
|
||||
obj.RetractHeight = zmax + 1.0
|
||||
@@ -118,9 +125,11 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
||||
obj.RetractHeight = 6.0
|
||||
|
||||
def opSetDefaultValues(self, obj):
|
||||
'''opSetDefaultValues(obj) ... set default value for RetractHeight'''
|
||||
obj.RetractHeight = 10
|
||||
|
||||
def opOnChanged(self, obj, prop):
|
||||
'''opOnChanged(obj, prop) ... if Locations changed, check if depths should be calculated.'''
|
||||
super(self.__class__, self).opOnChanged(obj, prop)
|
||||
if prop == 'Locations' and not 'Restore' in obj.State and obj.Locations and not obj.Base:
|
||||
if not hasattr(self, 'baseobject'):
|
||||
@@ -129,6 +138,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
||||
self.setupDepthsFrom(obj, [], job.Base)
|
||||
|
||||
def Create(name):
|
||||
'''Create(name) ... Creates and returns a Drilling operation.'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectDrilling(obj)
|
||||
return obj
|
||||
|
||||
@@ -33,7 +33,7 @@ import PathScripts.PathUtils as PathUtils
|
||||
|
||||
from PySide import QtCore
|
||||
|
||||
"""Path Engrave object and FreeCAD command"""
|
||||
__doc__ = "Class and implementation of Path Engrave operation"
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
@@ -47,14 +47,18 @@ def translate(context, text, disambig=None):
|
||||
|
||||
|
||||
class ObjectEngrave(PathOp.ObjectOp):
|
||||
'''Proxy class for Engrave operation.'''
|
||||
|
||||
def opFeatures(self, obj):
|
||||
'''opFeatures(obj) ... return all standard features and edges based geomtries'''
|
||||
return PathOp.FeatureTool | PathOp.FeatureDepths | PathOp.FeatureHeights | PathOp.FeatureStepDown | PathOp.FeatureBaseEdges;
|
||||
|
||||
def initOperation(self, obj):
|
||||
'''initOperation(obj) ... create engraving specific properties.'''
|
||||
obj.addProperty("App::PropertyInteger", "StartVertex", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The vertex index to start the path from"))
|
||||
|
||||
def opExecute(self, obj):
|
||||
'''opExecute(obj) ... process engraving operation'''
|
||||
PathLog.track()
|
||||
|
||||
zValues = []
|
||||
@@ -107,6 +111,7 @@ class ObjectEngrave(PathOp.ObjectOp):
|
||||
PathLog.error(translate("Path", "The Job Base Object has no engraveable element. Engraving operation will produce no output."))
|
||||
|
||||
def buildpathocc(self, obj, wires, zValues):
|
||||
'''buildpathocc(obj, wires, zValues) ... internal helper function to generate engraving commands.'''
|
||||
PathLog.track()
|
||||
|
||||
output = ""
|
||||
@@ -175,6 +180,7 @@ class ObjectEngrave(PathOp.ObjectOp):
|
||||
return output
|
||||
|
||||
def opSetDefaultValues(self, obj):
|
||||
'''opSetDefaultValues(obj) ... set depths for engraving'''
|
||||
job = PathUtils.findParentJob(obj)
|
||||
if job and job.Base:
|
||||
bb = job.Base.Shape.BoundBox
|
||||
@@ -189,6 +195,7 @@ class ObjectEngrave(PathOp.ObjectOp):
|
||||
obj.StepDown = obj.StartDepth.Value - obj.FinalDepth.Value
|
||||
|
||||
def Create(name):
|
||||
'''Create(name) ... Creates and returns a Engrave operation.'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectEngrave(obj)
|
||||
return obj
|
||||
|
||||
@@ -34,19 +34,21 @@ import PathScripts.PathUtils as PathUtils
|
||||
from PathUtils import fmt
|
||||
from PySide import QtCore
|
||||
|
||||
"""Helix Drill object and FreeCAD command"""
|
||||
__doc__ = "Class and implementation of Helix Drill operation"
|
||||
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
class ObjectHelix(PathCircularHoleBase.ObjectOp):
|
||||
'''Proxy class for Helix operations.'''
|
||||
|
||||
def circularHoleFeatures(self, obj):
|
||||
'''circularHoleFeatures(obj) ... enable features supported by Helix.'''
|
||||
return PathOp.FeatureStepDown | PathOp.FeatureBaseEdges | PathOp.FeatureBaseFaces | PathOp.FeatureBasePanels
|
||||
|
||||
def initCircularHoleOperation(self, obj):
|
||||
# Basic
|
||||
'''initCircularHoleOperation(obj) ... create helix specific properties.'''
|
||||
obj.addProperty("App::PropertyEnumeration", "Direction", "Helix Drill", translate("PathHelix", "The direction of the circular cuts, clockwise (CW), or counter clockwise (CCW)"))
|
||||
obj.Direction = ['CW', 'CCW']
|
||||
|
||||
@@ -56,6 +58,7 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp):
|
||||
obj.addProperty("App::PropertyLength", "StepOver", "Helix Drill", translate("PathHelix", "Radius increment (must be smaller than tool diameter)"))
|
||||
|
||||
def circularHoleExecute(self, obj, holes):
|
||||
'''circularHoleExecute(obj, holes) ... generate helix commands for each hole in holes'''
|
||||
PathLog.track()
|
||||
self.commandlist.append(Path.Command('(helix cut operation)'))
|
||||
|
||||
@@ -70,18 +73,10 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp):
|
||||
PathLog.debug(output)
|
||||
|
||||
def helix_cut(self, obj, x0, y0, r_out, r_in, dr):
|
||||
"""
|
||||
x0, y0:
|
||||
coordinates of center
|
||||
r_out, r_in: floats
|
||||
radial range, cut from outer radius r_out in layers of dr to inner radius r_in
|
||||
zmax, zmin: floats
|
||||
z-range, cut from zmax in layers of dz down to zmin
|
||||
safe_z: float
|
||||
safety layer height
|
||||
tool_diameter: float
|
||||
Width of tool
|
||||
"""
|
||||
'''helix_cut(obj, x0, y0, r_out, r_in, dr) ... generate helix commands for specified hole.
|
||||
x0, y0: coordinates of center
|
||||
r_out, r_in: outer and inner radius of the hole
|
||||
dr: step over radius value'''
|
||||
from numpy import ceil, linspace
|
||||
|
||||
if (obj.StartDepth.Value <= obj.FinalDepth.Value):
|
||||
@@ -199,6 +194,7 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp):
|
||||
obj.StepOver = 100
|
||||
|
||||
def Create(name):
|
||||
'''Create(name) ... Creates and returns a Helix operation.'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectHelix(obj)
|
||||
return obj
|
||||
|
||||
@@ -50,17 +50,18 @@ def translate(context, text, disambig=None):
|
||||
__title__ = "Path Mill Face Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
"""Path Face object and FreeCAD command"""
|
||||
__doc__ = "Class and implementation of Mill Facing operation."
|
||||
|
||||
|
||||
class ObjectFace(PathAreaOp.ObjectOp):
|
||||
'''Proxy object for Mill Facing operation.'''
|
||||
|
||||
def areaOpFeatures(self, obj):
|
||||
'''areaOpFeatures(obj) ... mill facing uses FinishDepth and is based on faces.'''
|
||||
return PathOp.FeatureBaseFaces | PathOp.FeatureFinishDepth
|
||||
|
||||
def initAreaOp(self, obj):
|
||||
|
||||
'''initAreaOp(obj) ... create operation specific properties'''
|
||||
# Face Properties
|
||||
obj.addProperty("App::PropertyEnumeration", "CutMode", "Face", QtCore.QT_TRANSLATE_NOOP("App::Property", "The direction that the toolpath should go around the part ClockWise CW or CounterClockWise CCW"))
|
||||
obj.CutMode = ['Climb', 'Conventional']
|
||||
@@ -79,6 +80,7 @@ class ObjectFace(PathAreaOp.ObjectOp):
|
||||
|
||||
|
||||
def areaOpOnChanged(self, obj, prop):
|
||||
'''areaOpOnChanged(obj, prop) ... facing specific depths calculation.'''
|
||||
PathLog.track(prop)
|
||||
if prop == "StepOver" and obj.StepOver == 0:
|
||||
obj.StepOver = 1
|
||||
@@ -94,9 +96,11 @@ class ObjectFace(PathAreaOp.ObjectOp):
|
||||
obj.FinalDepth = d.start_depth
|
||||
|
||||
def areaOpUseProjection(self, obj):
|
||||
'''areaOpUseProjection(obj) ... return False'''
|
||||
return False
|
||||
|
||||
def areaOpAreaParams(self, obj, isHole):
|
||||
'''areaOpAreaPrams(obj, isHole) ... return dictionary with mill facing area parameters'''
|
||||
params = {}
|
||||
params['Fill'] = 0
|
||||
params['Coplanar'] = 0
|
||||
@@ -115,6 +119,7 @@ class ObjectFace(PathAreaOp.ObjectOp):
|
||||
return params
|
||||
|
||||
def areaOpPathParams(self, obj, isHole):
|
||||
'''areaOpPathPrams(obj, isHole) ... return dictionary with mill facing path parameters'''
|
||||
params = {}
|
||||
params['feedrate'] = self.horizFeed
|
||||
params['feedrate_v'] = self.vertFeed
|
||||
@@ -128,6 +133,7 @@ class ObjectFace(PathAreaOp.ObjectOp):
|
||||
return params
|
||||
|
||||
def areaOpShapes(self, obj):
|
||||
'''areaOpShapes(obj) ... return top face'''
|
||||
# Facing is done either against base objects
|
||||
if obj.Base:
|
||||
PathLog.debug("obj.Base: {}".format(obj.Base))
|
||||
@@ -160,6 +166,7 @@ class ObjectFace(PathAreaOp.ObjectOp):
|
||||
return [(env, False)]
|
||||
|
||||
def areaOpSetDefaultValues(self, obj):
|
||||
'''areaOpSetDefaultValues(obj) ... initialize mill facing properties'''
|
||||
obj.StepOver = 50
|
||||
obj.ZigZagAngle = 45.0
|
||||
|
||||
@@ -173,6 +180,7 @@ class ObjectFace(PathAreaOp.ObjectOp):
|
||||
obj.FinalDepth = d.start_depth
|
||||
|
||||
def Create(name):
|
||||
'''Create(name) ... Creates and returns a Mill Facing operation.'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectFace(obj)
|
||||
return obj
|
||||
|
||||
@@ -33,6 +33,7 @@ from PySide import QtCore
|
||||
__title__ = "Base class for all operations."
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Base class and properties implemenation for all Path operations."
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
@@ -44,21 +45,48 @@ else:
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
FeatureTool = 0x0001
|
||||
FeatureDepths = 0x0002
|
||||
FeatureHeights = 0x0004
|
||||
FeatureStartPoint = 0x0008
|
||||
FeatureFinishDepth = 0x0010
|
||||
FeatureStepDown = 0x0020
|
||||
FeatureBaseVertexes = 0x0100
|
||||
FeatureBaseEdges = 0x0200
|
||||
FeatureBaseFaces = 0x0400
|
||||
FeatureBasePanels = 0x0800
|
||||
FeatureLocations = 0x1000
|
||||
FeatureTool = 0x0001 # ToolController
|
||||
FeatureDepths = 0x0002 # FinalDepth, StartDepth
|
||||
FeatureHeights = 0x0004 # ClearanceHeight, SafeHeight
|
||||
FeatureStartPoint = 0x0008 # StartPoint
|
||||
FeatureFinishDepth = 0x0010 # FinishDepth
|
||||
FeatureStepDown = 0x0020 # StepDown
|
||||
FeatureBaseVertexes = 0x0100 # Base
|
||||
FeatureBaseEdges = 0x0200 # Base
|
||||
FeatureBaseFaces = 0x0400 # Base
|
||||
FeatureBasePanels = 0x0800 # Base
|
||||
FeatureLocations = 0x1000 # Locations
|
||||
|
||||
FeatureBaseGeometry = FeatureBaseVertexes | FeatureBaseFaces | FeatureBaseEdges | FeatureBasePanels
|
||||
|
||||
class ObjectOp(object):
|
||||
'''
|
||||
Base class for proxy objects of all Path operations.
|
||||
|
||||
Use this class as a base class for new operations. It provides properties
|
||||
and some functionality for the standard properties each operation supports.
|
||||
By OR'ing features from the feature list an operation can select which ones
|
||||
of the standard features it requires and/or supports.
|
||||
|
||||
The currently supported features are:
|
||||
FeatureTool ... Use of a ToolController
|
||||
FeatureDepths ... Depths, for start, final
|
||||
FeatureHeights ... Heights, safe and clearance
|
||||
FeatureStartPoint ... Supports setting a start point
|
||||
FeatureFinishDepth ... Operation supports a finish depth
|
||||
FeatureStepDown ... Support for step down
|
||||
FeatureBaseVertexes ... Base geometry support for vertexes
|
||||
FeatureBaseEdges ... Base geometry support for edges
|
||||
FeatureBaseFaces ... Base geometry support for faces
|
||||
FeatureBasePanels ... Base geometry support for Arch.Panels
|
||||
FeatureLocations ... Base location support
|
||||
|
||||
The base class handles all base API and forwards calls to subclasses with
|
||||
an op prefix. For instance, an op is not expected to overwrite onChanged(),
|
||||
but implement the function opOnChanged().
|
||||
If a base class overwrites a base API function it should call the super's
|
||||
implementation - otherwise the base functionality might be broken.
|
||||
'''
|
||||
|
||||
def __init__(self, obj):
|
||||
PathLog.track()
|
||||
@@ -102,22 +130,49 @@ class ObjectOp(object):
|
||||
self.setDefaultValues(obj)
|
||||
|
||||
def __getstate__(self):
|
||||
'''__getstat__(self) ... called when receiver is saved.
|
||||
Can safely be overwritten by subclasses.'''
|
||||
return None
|
||||
|
||||
def __setstate__(self, state):
|
||||
'''__getstat__(self) ... called when receiver is restored.
|
||||
Can safely be overwritten by subclasses.'''
|
||||
return None
|
||||
|
||||
def opFeatures(self, obj):
|
||||
'''opFeatures(obj) ... returns the OR'ed list of features used and supported by the operation.
|
||||
The default implementation returns "FeatureTool | FeatureDeptsh | FeatureHeights | FeatureStartPoint"
|
||||
Should be overwritten by subclasses.'''
|
||||
return FeatureTool | FeatureDepths | FeatureHeights | FeatureStartPoint | FeatureBaseGeometry | FeatureFinishDepth
|
||||
def opOnChanged(self, obj, prop):
|
||||
|
||||
def initOperation(self, obj):
|
||||
'''initOperation(obj) ... implement to create additional properties.
|
||||
Should be overwritten by subclasses.'''
|
||||
pass
|
||||
|
||||
def opOnChanged(self, obj, prop):
|
||||
'''opOnChanged(obj, prop) ... overwrite to process property changes.
|
||||
This is a callback function that is invoked each time a property of the
|
||||
receiver is assigned a value. Note that the FC framework does not
|
||||
distinguish between assigning a different value and assigning the same
|
||||
value again.
|
||||
Can safely be overwritten by subclasses.'''
|
||||
pass
|
||||
|
||||
def opSetDefaultValues(self, obj):
|
||||
'''opSetDefaultValues(obj) ... overwrite to set initial default values.
|
||||
Called after the reciever has been fully created with all properties.
|
||||
Can safely be overwritten by subclasses.'''
|
||||
pass
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
'''onChanged(obj, prop) ... base implementation of the FC notification framework.
|
||||
Do not overwrite, overwrite opOnChanged() instead.'''
|
||||
self.opOnChanged(obj, prop)
|
||||
|
||||
def setDefaultValues(self, obj, callOp = True):
|
||||
def setDefaultValues(self, obj):
|
||||
'''setDefaultValues(obj) ... base implementation.
|
||||
Do not overwrite, overwrite opSetDefaultValues() instead.'''
|
||||
PathUtils.addToJob(obj)
|
||||
|
||||
obj.Active = True
|
||||
@@ -145,6 +200,24 @@ class ObjectOp(object):
|
||||
|
||||
@waiting_effects
|
||||
def execute(self, obj):
|
||||
'''execute(obj) ... base implementation - do not overwrite!
|
||||
Verifies that the operation is assigned to a job and that the job also has a valid Base.
|
||||
It also sets the following instance variables that can and should be safely be used by
|
||||
implementation of opExecute():
|
||||
self.baseobject ... Base object of the Job itself
|
||||
self.vertFeed ... vertical feed rate of assigned tool
|
||||
self.vertRapid ... vertical rapid rate of assigned tool
|
||||
self.horizFeed ... horizontal feed rate of assigned tool
|
||||
self.horizRapid ... norizontal rapid rate of assigned tool
|
||||
self.tool ... the actual tool being used
|
||||
self.radius ... the main radius of the tool being used
|
||||
self.commandlist ... a list for collecting all commands produced by the operation
|
||||
|
||||
Once everything is validated and above variables are set the implementation calls
|
||||
opExectue(obj) - which is expected to add the generated commands to self.commandlist
|
||||
Finally the base implementation adds a rapid move to clearance height and assigns
|
||||
the receiver's Path property from the command list.
|
||||
'''
|
||||
PathLog.track()
|
||||
|
||||
if not obj.Active:
|
||||
@@ -188,8 +261,9 @@ class ObjectOp(object):
|
||||
|
||||
result = self.opExecute(obj)
|
||||
|
||||
# Let's finish by rapid to clearance...just for safety
|
||||
self.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))
|
||||
if FeatureHeights & self.opFeatures(obj):
|
||||
# Let's finish by rapid to clearance...just for safety
|
||||
self.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))
|
||||
|
||||
path = Path.Path(self.commandlist)
|
||||
obj.Path = path
|
||||
|
||||
@@ -31,7 +31,7 @@ import PathScripts.PathOp as PathOp
|
||||
from PathScripts import PathUtils
|
||||
from PySide import QtCore
|
||||
|
||||
"""Path Pocket object and FreeCAD command"""
|
||||
__doc__ = "Class and implementation of the Pocket operation."
|
||||
|
||||
if True:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
@@ -45,11 +45,14 @@ def translate(context, text, disambig=None):
|
||||
|
||||
|
||||
class ObjectPocket(PathAreaOp.ObjectOp):
|
||||
'''Proxy object for Pocket operation.'''
|
||||
|
||||
def areaOpFeatures(self, obj):
|
||||
'''areaOpFeatures(obj) ... Pockets have a FinishDepth and work on Faces'''
|
||||
return PathOp.FeatureBaseFaces | PathOp.FeatureFinishDepth
|
||||
|
||||
def initAreaOp(self, obj):
|
||||
'''initAreaOp(obj) ... create pocket specific properties.'''
|
||||
PathLog.track()
|
||||
|
||||
# Pocket Properties
|
||||
@@ -65,9 +68,11 @@ class ObjectPocket(PathAreaOp.ObjectOp):
|
||||
obj.addProperty("App::PropertyBool", "MinTravel", "Pocket", QtCore.QT_TRANSLATE_NOOP("App::Property", "Use 3D Sorting of Path"))
|
||||
|
||||
def areaOpUseProjection(self, obj):
|
||||
'''areaOpUseProjection(obj) ... return False'''
|
||||
return False
|
||||
|
||||
def areaOpAreaParams(self, obj, isHole):
|
||||
'''areaOpAreaParams(obj, isHole) ... return dictionary with pocket's area parameters'''
|
||||
params = {}
|
||||
params['Fill'] = 0
|
||||
params['Coplanar'] = 0
|
||||
@@ -84,6 +89,7 @@ class ObjectPocket(PathAreaOp.ObjectOp):
|
||||
return params
|
||||
|
||||
def areaOpPathParams(self, obj, isHole):
|
||||
'''areaOpAreaParams(obj, isHole) ... return dictionary with pocket's path parameters'''
|
||||
params = {}
|
||||
|
||||
# if MinTravel is turned on, set path sorting to 3DSort
|
||||
@@ -94,6 +100,7 @@ class ObjectPocket(PathAreaOp.ObjectOp):
|
||||
return params
|
||||
|
||||
def areaOpShapes(self, obj):
|
||||
'''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
|
||||
PathLog.track()
|
||||
|
||||
if obj.Base:
|
||||
@@ -120,11 +127,13 @@ class ObjectPocket(PathAreaOp.ObjectOp):
|
||||
return removalshapes
|
||||
|
||||
def areaOpSetDefaultValues(self, obj):
|
||||
'''areaOpSetDefaultValues(obj) ... set default values'''
|
||||
obj.StepOver = 100
|
||||
obj.ZigZagAngle = 45
|
||||
|
||||
|
||||
def Create(name):
|
||||
'''Create(name) ... Creates and returns a Pocket operation.'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectPocket(obj)
|
||||
return obj
|
||||
|
||||
@@ -29,7 +29,10 @@ import PathScripts.PathOp as PathOp
|
||||
|
||||
from PySide import QtCore
|
||||
|
||||
"""Path Profile from base features"""
|
||||
__title__ = "Path Contour Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Base class and implementation for Path profile operations."
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
@@ -49,13 +52,17 @@ def translate(context, text, disambig=None):
|
||||
__title__ = "Path Profile Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Base class and properties for all profile operations."
|
||||
|
||||
"""Path Profile object and FreeCAD command for operating on sets of features"""
|
||||
|
||||
|
||||
class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
'''Base class for proxy objects of all profile operations.'''
|
||||
|
||||
def initAreaOp(self, obj):
|
||||
'''initAreaOp(obj) ... creates all profile specific properties.
|
||||
Do not overwrite.'''
|
||||
# Profile Properties
|
||||
obj.addProperty("App::PropertyEnumeration", "Side", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Side of edge that tool should cut"))
|
||||
obj.Side = ['Outside', 'Inside'] # side of profile that cutter is on in relation to direction of profile
|
||||
@@ -70,6 +77,8 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
obj.setEditorMode('MiterLimit', 2)
|
||||
|
||||
def areaOpOnChanged(self, obj, prop):
|
||||
'''areaOpOnChanged(obj, prop) ... updates Side and MiterLimit visibility depending on changed properties.
|
||||
Do not overwrite.'''
|
||||
if prop == "UseComp":
|
||||
if not obj.UseComp:
|
||||
obj.setEditorMode('Side', 2)
|
||||
@@ -83,6 +92,8 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
obj.setEditorMode('MiterLimit', 2)
|
||||
|
||||
def areaOpAreaParams(self, obj, isHole):
|
||||
'''areaOpAreaParams(obj, isHole) ... returns dictionary with area parameters.
|
||||
Do not overwrite.'''
|
||||
params = {}
|
||||
params['Fill'] = 0
|
||||
params['Coplanar'] = 0
|
||||
@@ -106,6 +117,8 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
return params
|
||||
|
||||
def areaOpPathParams(self, obj, isHole):
|
||||
'''areaOpPathParams(obj, isHole) ... returns dictionary with path parameters.
|
||||
Do not overwrite.'''
|
||||
params = {}
|
||||
|
||||
# Reverse the direction for holes
|
||||
@@ -122,9 +135,12 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
return params
|
||||
|
||||
def areaOpUseProjection(self, obj):
|
||||
'''areaOpUseProjection(obj) ... returns True'''
|
||||
return True
|
||||
|
||||
def areaOpSetDefaultValues(self, obj):
|
||||
'''areaOpSetDefaultValues(obj) ... sets default values.
|
||||
Do not overwrite.'''
|
||||
obj.Side = "Outside"
|
||||
obj.OffsetExtra = 0.0
|
||||
obj.Direction = "CW"
|
||||
|
||||
@@ -50,27 +50,33 @@ def translate(context, text, disambig=None):
|
||||
__title__ = "Path Contour Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
"""Path Contour object and FreeCAD command"""
|
||||
__doc__ = "Implementation of the Contour operation."
|
||||
|
||||
|
||||
class ObjectContour(PathProfileBase.ObjectProfile):
|
||||
'''Proxy object for Contour operations.'''
|
||||
|
||||
def baseObject(self):
|
||||
'''baseObject() ... returns super of receiver
|
||||
Used to call base implementation in overwritten functions.'''
|
||||
return super(self.__class__, self)
|
||||
|
||||
def areaOpFeatures(self, obj):
|
||||
'''areaOpFeatures(obj) ... returns 0, Contour only requires the base profile features.'''
|
||||
return 0
|
||||
|
||||
def initAreaOp(self, obj):
|
||||
'''initAreaOp(obj) ... call super's implementation and hide Side property.'''
|
||||
self.baseObject().initAreaOp(obj)
|
||||
obj.setEditorMode('Side', 2) # it's always outside
|
||||
|
||||
def areaOpSetDefaultValues(self, obj):
|
||||
'''areaOpSetDefaultValues(obj) ... call super's implementation and set Side="Outside".'''
|
||||
self.baseObject().areaOpSetDefaultValues(obj)
|
||||
obj.Side = 'Outside'
|
||||
|
||||
def areaOpShapes(self, obj):
|
||||
'''areaOpShapes(obj) ... return envelope over the job's Base.Shape or all Arch.Panel shapes.'''
|
||||
if obj.UseComp:
|
||||
self.commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"))
|
||||
else:
|
||||
@@ -96,6 +102,7 @@ class ObjectContour(PathProfileBase.ObjectProfile):
|
||||
return params
|
||||
|
||||
def Create(name):
|
||||
'''Create(name) ... Creates and returns a Contour operation.'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectContour(obj)
|
||||
return obj
|
||||
|
||||
@@ -54,19 +54,23 @@ def translate(context, text, disambig=None):
|
||||
__title__ = "Path Profile Edges Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
"""Path Profile object and FreeCAD command for operating on sets of edges"""
|
||||
__doc__ = "Path Profile operation based on edges."
|
||||
|
||||
|
||||
class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
'''Proxy object for Profile operations based on edges.'''
|
||||
|
||||
def baseObject(self):
|
||||
'''baseObject() ... returns super of receiver
|
||||
Used to call base implementation in overwritten functions.'''
|
||||
return super(self.__class__, self)
|
||||
|
||||
def areaOpFeatures(self, obj):
|
||||
'''areaOpFeatures(obj) ... add support for edge base geometry.'''
|
||||
return PathOp.FeatureBaseEdges
|
||||
|
||||
def areaOpShapes(self, obj):
|
||||
'''areaOpShapes(obj) ... returns envelope for all wires formed by the base edges.'''
|
||||
PathLog.track()
|
||||
|
||||
if obj.UseComp:
|
||||
@@ -97,6 +101,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
return shapes
|
||||
|
||||
def Create(name):
|
||||
'''Create(name) ... Creates and returns a Profile based on edges operation.'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectProfile(obj)
|
||||
return obj
|
||||
|
||||
@@ -43,19 +43,27 @@ PathLog.trackModule(PathLog.thisModule())
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
__title__ = "Path Profile Operation"
|
||||
__title__ = "Path Profile Faces Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
"""Path Profile object and FreeCAD command"""
|
||||
__doc__ = "Path Profile operation based on faces."
|
||||
|
||||
|
||||
class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
'''Proxy object for Profile operations based on faces.'''
|
||||
|
||||
def baseObject(self):
|
||||
'''baseObject() ... returns super of receiver
|
||||
Used to call base implementation in overwritten functions.'''
|
||||
return super(self.__class__, self)
|
||||
|
||||
def areaOpFeatures(self, obj):
|
||||
'''baseObject() ... returns super of receiver
|
||||
Used to call base implementation in overwritten functions.'''
|
||||
return PathOp.FeatureBaseFaces
|
||||
|
||||
def initAreaOp(self, obj):
|
||||
'''initAreaOp(obj) ... adds properties for hole, circle and perimeter processing.'''
|
||||
# Face specific Properties
|
||||
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"))
|
||||
@@ -63,17 +71,8 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
|
||||
self.baseObject().initAreaOp(obj)
|
||||
|
||||
def areaOpSetDefaultValues(self, obj):
|
||||
self.baseObject().areaOpSetDefaultValues(obj)
|
||||
|
||||
obj.processHoles = False
|
||||
obj.processCircles = False
|
||||
obj.processPerimeter = True
|
||||
|
||||
def areaOpFeatures(self, obj):
|
||||
return PathOp.FeatureBaseFaces
|
||||
|
||||
def areaOpShapes(self, obj):
|
||||
'''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
|
||||
if obj.UseComp:
|
||||
self.commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"))
|
||||
else:
|
||||
@@ -130,7 +129,16 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
|
||||
return shapes
|
||||
|
||||
def areaOpSetDefaultValues(self, obj):
|
||||
'''areaOpSetDefaultValues(obj) ... sets default values for hole, circle and perimeter processing.'''
|
||||
self.baseObject().areaOpSetDefaultValues(obj)
|
||||
|
||||
obj.processHoles = False
|
||||
obj.processCircles = False
|
||||
obj.processPerimeter = True
|
||||
|
||||
def Create(name):
|
||||
'''Create(name) ... Creates and returns a Profile based on faces operation.'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectProfile(obj)
|
||||
return obj
|
||||
|
||||
Reference in New Issue
Block a user