Black - Job

Holding tag black

Feature extension black

Dressup boundary and dogbone black
This commit is contained in:
sliptonic
2022-01-24 14:16:14 -06:00
parent 3c8b65aee4
commit 946944e1de
11 changed files with 1593 additions and 608 deletions

View File

@@ -28,7 +28,8 @@ import math
# lazily loaded modules
from lazy_loader.lazy_loader import LazyLoader
PathUtils = LazyLoader('PathScripts.PathUtils', globals(), 'PathScripts.PathUtils')
PathUtils = LazyLoader("PathScripts.PathUtils", globals(), "PathScripts.PathUtils")
from PySide import QtCore
@@ -47,7 +48,7 @@ def translate(context, text, disambig=None):
def endPoints(edgeOrWire):
'''endPoints(edgeOrWire) ... return the first and last point of the wire or the edge, assuming the argument is not a closed wire.'''
"""endPoints(edgeOrWire) ... return the first and last point of the wire or the edge, assuming the argument is not a closed wire."""
if Part.Wire == type(edgeOrWire):
# edges = edgeOrWire.Edges
pts = [e.valueAt(e.FirstParameter) for e in edgeOrWire.Edges]
@@ -69,7 +70,7 @@ def endPoints(edgeOrWire):
def includesPoint(p, pts):
'''includesPoint(p, pts) ... answer True if the collection of pts includes the point p'''
"""includesPoint(p, pts) ... answer True if the collection of pts includes the point p"""
for pt in pts:
if PathGeom.pointsCoincide(p, pt):
return True
@@ -78,11 +79,13 @@ def includesPoint(p, pts):
def selectOffsetWire(feature, wires):
'''selectOffsetWire(feature, wires) ... returns the Wire in wires which is does not intersect with feature'''
"""selectOffsetWire(feature, wires) ... returns the Wire in wires which is does not intersect with feature"""
closest = None
for w in wires:
dist = feature.distToShape(w)[0]
if closest is None or dist > closest[0]: # pylint: disable=unsubscriptable-object
if (
closest is None or dist > closest[0]
): # pylint: disable=unsubscriptable-object
closest = (dist, w)
if closest is not None:
@@ -92,19 +95,23 @@ def selectOffsetWire(feature, wires):
def extendWire(feature, wire, length):
'''extendWire(wire, length) ... return a closed Wire which extends wire by length'''
"""extendWire(wire, length) ... return a closed Wire which extends wire by length"""
PathLog.track(length)
if not length or length == 0:
return None
try:
off2D = wire.makeOffset2D(length)
except FreeCAD.Base.FreeCADError as ee:
return None
endPts = endPoints(wire) # Assumes wire is NOT closed
if endPts:
edges = [e for e in off2D.Edges if Part.Circle != type(e.Curve) or not includesPoint(e.Curve.Center, endPts)]
edges = [
e
for e in off2D.Edges
if Part.Circle != type(e.Curve) or not includesPoint(e.Curve.Center, endPts)
]
wires = [Part.Wire(e) for e in Part.sortEdges(edges)]
offset = selectOffsetWire(feature, wires)
ePts = endPoints(offset)
@@ -127,12 +134,14 @@ def extendWire(feature, wire, length):
def createExtension(obj, extObj, extFeature, extSub):
return Extension(obj,
extObj,
extFeature,
extSub,
obj.ExtensionLengthDefault,
Extension.DirectionNormal)
return Extension(
obj,
extObj,
extFeature,
extSub,
obj.ExtensionLengthDefault,
Extension.DirectionNormal,
)
def readObjExtensionFeature(obj):
@@ -142,7 +151,7 @@ def readObjExtensionFeature(obj):
for extObj, features in obj.ExtensionFeature:
for sub in features:
extFeature, extSub = sub.split(':')
extFeature, extSub = sub.split(":")
extensions.append((extObj.Name, extFeature, extSub))
return extensions
@@ -154,7 +163,7 @@ def getExtensions(obj):
for extObj, features in obj.ExtensionFeature:
for sub in features:
extFeature, extSub = sub.split(':')
extFeature, extSub = sub.split(":")
extensions.append(createExtension(obj, extObj, extFeature, extSub))
i = i + 1
return extensions
@@ -167,11 +176,14 @@ def setExtensions(obj, extensions):
class Extension(object):
DirectionNormal = 0
DirectionX = 1
DirectionY = 2
DirectionX = 1
DirectionY = 2
def __init__(self, op, obj, feature, sub, length, direction):
PathLog.debug("Extension(%s, %s, %s, %.2f, %s" % (obj.Label, feature, sub, length, direction))
PathLog.debug(
"Extension(%s, %s, %s, %.2f, %s"
% (obj.Label, feature, sub, length, direction)
)
self.op = op
self.obj = obj
self.feature = feature
@@ -197,8 +209,16 @@ class Extension(object):
off = self.length.Value * direction
e2.translate(off)
e2 = PathGeom.flipEdge(e2)
e1 = Part.Edge(Part.LineSegment(e0.valueAt(e0.LastParameter), e2.valueAt(e2.FirstParameter)))
e3 = Part.Edge(Part.LineSegment(e2.valueAt(e2.LastParameter), e0.valueAt(e0.FirstParameter)))
e1 = Part.Edge(
Part.LineSegment(
e0.valueAt(e0.LastParameter), e2.valueAt(e2.FirstParameter)
)
)
e3 = Part.Edge(
Part.LineSegment(
e2.valueAt(e2.LastParameter), e0.valueAt(e0.FirstParameter)
)
)
wire = Part.Wire([e0, e1, e2, e3])
self.wire = wire
return wire
@@ -206,8 +226,8 @@ class Extension(object):
return extendWire(feature, Part.Wire([e0]), self.length.Value)
def _getEdgeNumbers(self):
if 'Wire' in self.sub:
numbers = [nr for nr in self.sub[5:-1].split(',')]
if "Wire" in self.sub:
numbers = [nr for nr in self.sub[5:-1].split(",")]
else:
numbers = [self.sub[4:]]
@@ -235,7 +255,7 @@ class Extension(object):
e0 = wire.Edges[0]
midparam = e0.FirstParameter + 0.5 * (e0.LastParameter - e0.FirstParameter)
tangent = e0.tangentAt(midparam)
PathLog.track('tangent', tangent, self.feature, self.sub)
PathLog.track("tangent", tangent, self.feature, self.sub)
normal = tangent.cross(FreeCAD.Vector(0, 0, 1))
if PathGeom.pointsCoincide(normal, FreeCAD.Vector(0, 0, 0)):
return None
@@ -243,21 +263,21 @@ class Extension(object):
return self._getDirectedNormal(e0.valueAt(midparam), normal.normalize())
def getExtensionFaces(self, extensionWire):
'''getExtensionFace(extensionWire)...
"""getExtensionFace(extensionWire)...
A public helper method to retrieve the requested extension as a face,
rather than a wire because some extensions require a face shape
for definition that allows for two wires for boundary definition.
'''
"""
if self.extFaces:
return self.extFaces
return [Part.Face(extensionWire)]
def getWire(self):
'''getWire()... Public method to retrieve the extension area, pertaining to the feature
"""getWire()... Public method to retrieve the extension area, pertaining to the feature
and sub element provided at class instantiation, as a closed wire. If no closed wire
is possible, a `None` value is returned.'''
is possible, a `None` value is returned."""
if self.sub[:6] == "Avoid_":
feature = self.obj.Shape.getElement(self.feature)
@@ -281,9 +301,9 @@ class Extension(object):
return self._getRegularWire()
def _getRegularWire(self):
'''_getRegularWire()... Private method to retrieve the extension area, pertaining to the feature
"""_getRegularWire()... Private method to retrieve the extension area, pertaining to the feature
and sub element provided at class instantiation, as a closed wire. If no closed wire
is possible, a `None` value is returned.'''
is possible, a `None` value is returned."""
PathLog.track()
length = self.length.Value
@@ -314,11 +334,23 @@ class Extension(object):
# assuming the offset produces a valid circle - go for it
if r > 0:
e3 = Part.makeCircle(r, circle.Center, circle.Axis, edge.FirstParameter * 180 / math.pi, edge.LastParameter * 180 / math.pi)
e3 = Part.makeCircle(
r,
circle.Center,
circle.Axis,
edge.FirstParameter * 180 / math.pi,
edge.LastParameter * 180 / math.pi,
)
if endPoints(edge):
# need to construct the arc slice
e0 = Part.makeLine(edge.valueAt(edge.FirstParameter), e3.valueAt(e3.FirstParameter))
e2 = Part.makeLine(edge.valueAt(edge.LastParameter), e3.valueAt(e3.LastParameter))
e0 = Part.makeLine(
edge.valueAt(edge.FirstParameter),
e3.valueAt(e3.FirstParameter),
)
e2 = Part.makeLine(
edge.valueAt(edge.LastParameter),
e3.valueAt(e3.LastParameter),
)
return Part.Wire([e0, edge, e2, e3])
extWire = Part.Wire([e3])
@@ -358,7 +390,7 @@ class Extension(object):
off2D = sub.makeOffset2D(length)
except FreeCAD.Base.FreeCADError as ee:
return None
if isOutside:
self.extFaces = [Part.Face(off2D).cut(featFace)]
else:
@@ -369,9 +401,9 @@ class Extension(object):
return extendWire(feature, sub, length)
def _getOutlineWire(self):
'''_getOutlineWire()... Private method to retrieve an extended outline extension area,
"""_getOutlineWire()... Private method to retrieve an extended outline extension area,
pertaining to the feature and sub element provided at class instantiation, as a closed wire.
If no closed wire is possible, a `None` value is returned.'''
If no closed wire is possible, a `None` value is returned."""
PathLog.track()
baseShape = self.obj.Shape
@@ -411,10 +443,10 @@ class Extension(object):
return None
def _getWaterlineWire(self):
'''_getWaterlineWire()... Private method to retrieve a waterline extension area,
"""_getWaterlineWire()... Private method to retrieve a waterline extension area,
pertaining to the feature and sub element provided at class instantiation, as a closed wire.
Only waterline faces touching source face are returned as part of the waterline extension area.
If no closed wire is possible, a `None` value is returned.'''
If no closed wire is possible, a `None` value is returned."""
PathLog.track()
msg = translate("PathFeatureExtensions", "Waterline error")
@@ -451,9 +483,9 @@ class Extension(object):
return None
def _makeCircularExtFace(self, edge, extWire):
'''_makeCircularExtensionFace(edge, extWire)...
"""_makeCircularExtensionFace(edge, extWire)...
Create proper circular extension face shape. Incoming edge is expected to be a circle.
'''
"""
# Add original outer wire to cut faces if necessary
edgeFace = Part.Face(Part.Wire([edge]))
edgeFace.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - edgeFace.BoundBox.ZMin))
@@ -467,37 +499,60 @@ class Extension(object):
extensionFace.translate(FreeCAD.Vector(0.0, 0.0, edge.BoundBox.ZMin))
return extensionFace
# Eclass
def initialize_properties(obj):
"""initialize_properties(obj)... Adds feature properties to object argument"""
if not hasattr(obj, 'ExtensionLengthDefault'):
obj.addProperty('App::PropertyDistance', 'ExtensionLengthDefault', 'Extension', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'Default length of extensions.'))
if not hasattr(obj, 'ExtensionFeature'):
obj.addProperty('App::PropertyLinkSubListGlobal', 'ExtensionFeature', 'Extension', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'List of features to extend.'))
if not hasattr(obj, 'ExtensionCorners'):
obj.addProperty('App::PropertyBool', 'ExtensionCorners', 'Extension', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'When enabled connected extension edges are combined to wires.'))
if not hasattr(obj, "ExtensionLengthDefault"):
obj.addProperty(
"App::PropertyDistance",
"ExtensionLengthDefault",
"Extension",
QtCore.QT_TRANSLATE_NOOP(
"PathPocketShape", "Default length of extensions."
),
)
if not hasattr(obj, "ExtensionFeature"):
obj.addProperty(
"App::PropertyLinkSubListGlobal",
"ExtensionFeature",
"Extension",
QtCore.QT_TRANSLATE_NOOP("PathPocketShape", "List of features to extend."),
)
if not hasattr(obj, "ExtensionCorners"):
obj.addProperty(
"App::PropertyBool",
"ExtensionCorners",
"Extension",
QtCore.QT_TRANSLATE_NOOP(
"PathPocketShape",
"When enabled connected extension edges are combined to wires.",
),
)
obj.ExtensionCorners = True
obj.setEditorMode('ExtensionFeature', 2)
obj.setEditorMode("ExtensionFeature", 2)
def set_default_property_values(obj, job):
"""set_default_property_values(obj, job) ... set default values for feature properties"""
obj.ExtensionCorners = True
obj.setExpression('ExtensionLengthDefault', 'OpToolDiameter / 2.0')
obj.setExpression("ExtensionLengthDefault", "OpToolDiameter / 2.0")
def SetupProperties():
"""SetupProperties()... Returns list of feature property names"""
setup = ['ExtensionLengthDefault', 'ExtensionFeature',
'ExtensionCorners']
setup = ["ExtensionLengthDefault", "ExtensionFeature", "ExtensionCorners"]
return setup
# Extend outline face generation function
def getExtendOutlineFace(base_shape, face, extension, remHoles=False, offset_tolerance=1e-4):
def getExtendOutlineFace(
base_shape, face, extension, remHoles=False, offset_tolerance=1e-4
):
"""getExtendOutlineFace(obj, base_shape, face, extension, remHoles) ...
Creates an extended face for the pocket, taking into consideration lateral
collision with the greater base shape.
@@ -513,11 +568,9 @@ def getExtendOutlineFace(base_shape, face, extension, remHoles=False, offset_tol
"""
# Make offset face per user-specified extension distance so as to allow full clearing of face where possible.
offset_face = PathUtils.getOffsetArea(face,
extension,
removeHoles=remHoles,
plane=face,
tolerance=offset_tolerance)
offset_face = PathUtils.getOffsetArea(
face, extension, removeHoles=remHoles, plane=face, tolerance=offset_tolerance
)
if not offset_face:
PathLog.error("Failed to offset a selected face.")
return None
@@ -540,9 +593,11 @@ def getExtendOutlineFace(base_shape, face, extension, remHoles=False, offset_tol
for f in available.Faces:
bbx = f.BoundBox
zNorm = abs(f.normalAt(0.0, 0.0).z)
if (PathGeom.isRoughly(zNorm, 1.0) and
PathGeom.isRoughly(bbx.ZMax - bbx.ZMin, 0.0) and
PathGeom.isRoughly(bbx.ZMin, face.BoundBox.ZMin)):
if (
PathGeom.isRoughly(zNorm, 1.0)
and PathGeom.isRoughly(bbx.ZMax - bbx.ZMin, 0.0)
and PathGeom.isRoughly(bbx.ZMin, face.BoundBox.ZMin)
):
if bbx.ZMin < zmin:
bottom_faces.append(f)
@@ -561,6 +616,7 @@ def getExtendOutlineFace(base_shape, face, extension, remHoles=False, offset_tol
PathLog.error("No bottom face for extend outline.")
return None
# Waterline extension face generation function
def getWaterlineFace(base_shape, face):
"""getWaterlineFace(base_shape, face) ...
@@ -580,8 +636,11 @@ def getWaterlineFace(base_shape, face):
step_down=math.floor(faceHeight - baseBB.ZMin + 2.0),
z_finish_step=0.0,
final_depth=baseBB.ZMin,
user_depths=None)
env = PathUtils.getEnvelope(partshape=base_shape, subshape=None, depthparams=depthparams)
user_depths=None,
)
env = PathUtils.getEnvelope(
partshape=base_shape, subshape=None, depthparams=depthparams
)
# Get top face(s) of envelope at face height
rawList = list()
for f in env.Faces:
@@ -589,7 +648,9 @@ def getWaterlineFace(base_shape, face):
rawList.append(f)
# make compound and extrude downward
rawComp = Part.makeCompound(rawList)
rawCompExtNeg = rawComp.extrude(FreeCAD.Vector(0.0, 0.0, baseBB.ZMin - faceHeight - 1.0))
rawCompExtNeg = rawComp.extrude(
FreeCAD.Vector(0.0, 0.0, baseBB.ZMin - faceHeight - 1.0)
)
# Cut off bottom of base shape at face height
topSolid = base_shape.cut(rawCompExtNeg)