Fixes for depths and AttemptInverseAngle
Depth correction to obj.FinalDepth.Value in single feature operations Fix AttemptInverseAngle to be uni-directional Clean up debug and other user provided feedback
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
# with axis & rotation toggles and associated min/max values
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
import Path
|
||||
import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathOp as PathOp
|
||||
@@ -36,8 +37,6 @@ import Draft
|
||||
# from PathScripts.PathUtils import waiting_effects
|
||||
from PySide import QtCore
|
||||
import math
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
|
||||
__title__ = "Base class for PathArea based operations."
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
@@ -45,8 +44,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Base class and properties for Path.Area based operations."
|
||||
__contributors__ = "mlampert [FreeCAD], russ4262 (Russell Johnson)"
|
||||
__createdDate__ = "2017"
|
||||
__scriptVersion__ = "2e testing"
|
||||
__lastModified__ = "2019-06-12 06:28 CST"
|
||||
__scriptVersion__ = "2f testing"
|
||||
__lastModified__ = "2019-06-12 14:12 CST"
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
@@ -54,7 +53,6 @@ if False:
|
||||
else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
|
||||
# Qt translation handling
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
@@ -233,8 +231,6 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
obj.FinalDepth.Value = finalDepth
|
||||
obj.OpStartDepth.Value = startDepth
|
||||
obj.OpFinalDepth.Value = finalDepth
|
||||
# obj.OpStartDepth.UserString = str(startDepth) + ' mm' # Read-only
|
||||
# obj.OpFinalDepth.UserString = str(finalDepth) + ' mm' # Read-only
|
||||
|
||||
if obj.EnableRotation != 'Off':
|
||||
if self.initOpFinalDepth is None:
|
||||
@@ -380,8 +376,8 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
if obj.StartDepth.Value == obj.OpStartDepth.Value:
|
||||
obj.StartDepth.Value = self.strDep
|
||||
|
||||
# Create visual axises for debugging purposes.
|
||||
if PathLog.getLevel() == 2:
|
||||
# Create visual axises when debugging.
|
||||
if PathLog.getLevel(PathLog.thisModule()) == 4:
|
||||
self.visualAxis()
|
||||
else:
|
||||
self.strDep = obj.StartDepth.Value
|
||||
@@ -564,12 +560,12 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
|
||||
return [(xRotRad, yRotRad, zRotRad), (clrOfst, safOfst)]
|
||||
|
||||
def pocketRotationAnalysis(self, obj, norm, surf, prnt):
|
||||
'''pocketRotationAnalysis(self, obj, norm, surf, prnt)
|
||||
def faceRotationAnalysis(self, obj, norm, surf):
|
||||
'''faceRotationAnalysis(self, obj, norm, surf)
|
||||
Determine X and Y independent rotation necessary to make normalAt = Z=1 (0,0,1) '''
|
||||
PathLog.track()
|
||||
|
||||
praInfo = "pocketRotationAnalysis() in PathAreaOp.py"
|
||||
praInfo = "faceRotationAnalysis() in PathAreaOp.py"
|
||||
rtn = False
|
||||
axis = 'X'
|
||||
orientation = 'X'
|
||||
@@ -677,8 +673,8 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
else:
|
||||
praInfo += "\n - ... NO rotation triggered"
|
||||
|
||||
if prnt is True:
|
||||
PathLog.info("praInfo: " + str(praInfo))
|
||||
PathLog.debug("\n" + str(praInfo))
|
||||
|
||||
return (rtn, angle, axis, praInfo)
|
||||
|
||||
def guiMessage(self, title, msg, show=False):
|
||||
@@ -722,6 +718,7 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
zAx = 'zAxCyl'
|
||||
FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup","visualAxis")
|
||||
FreeCADGui.ActiveDocument.getObject('visualAxis').Visibility = False
|
||||
vaGrp = FreeCAD.ActiveDocument.getObject("visualAxis")
|
||||
|
||||
FreeCAD.ActiveDocument.addObject("Part::Cylinder", xAx)
|
||||
cyl = FreeCAD.ActiveDocument.getObject(xAx)
|
||||
@@ -730,11 +727,11 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
cyl.Height = 0.01
|
||||
cyl.Placement = FreeCAD.Placement(FreeCAD.Vector(0,0,0),FreeCAD.Rotation(FreeCAD.Vector(0,1,0),90))
|
||||
cyl.purgeTouched()
|
||||
FreeCAD.ActiveDocument.getObject("visualAxis").addObject(cyl)
|
||||
cylGui = FreeCADGui.ActiveDocument.getObject(xAx)
|
||||
cylGui.ShapeColor = (0.667,0.000,0.000)
|
||||
cylGui.Transparency = 80
|
||||
cylGui.Transparency = 85
|
||||
cylGui.Visibility = False
|
||||
vaGrp.addObject(cyl)
|
||||
|
||||
FreeCAD.ActiveDocument.addObject("Part::Cylinder", yAx)
|
||||
cyl = FreeCAD.ActiveDocument.getObject(yAx)
|
||||
@@ -742,12 +739,12 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
cyl.Radius = self.yRotRad
|
||||
cyl.Height = 0.01
|
||||
cyl.Placement = FreeCAD.Placement(FreeCAD.Vector(0,0,0),FreeCAD.Rotation(FreeCAD.Vector(1,0,0),90))
|
||||
FreeCAD.ActiveDocument.getObject("visualAxis").addObject(cyl)
|
||||
cyl.purgeTouched()
|
||||
cylGui = FreeCADGui.ActiveDocument.getObject(yAx)
|
||||
cylGui.ShapeColor = (0.000,0.667,0.000)
|
||||
cylGui.Transparency = 80
|
||||
cylGui.Transparency = 85
|
||||
cylGui.Visibility = False
|
||||
vaGrp.addObject(cyl)
|
||||
|
||||
if False:
|
||||
FreeCAD.ActiveDocument.addObject("Part::Cylinder", zAx)
|
||||
@@ -755,18 +752,19 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
cyl.Label = zAx
|
||||
cyl.Radius = self.yRotRad
|
||||
cyl.Height = 0.01
|
||||
cyl.Placement = FreeCAD.Placement(FreeCAD.Vector(0,0,0),FreeCAD.Rotation(FreeCAD.Vector(1,0,0),90))
|
||||
FreeCAD.ActiveDocument.getObject("visualAxis").addObject(cyl)
|
||||
# cyl.Placement = FreeCAD.Placement(FreeCAD.Vector(0,0,0),FreeCAD.Rotation(FreeCAD.Vector(1,0,0),90))
|
||||
cyl.purgeTouched()
|
||||
cylGui = FreeCADGui.ActiveDocument.getObject(zAx)
|
||||
cylGui.ShapeColor = (0.000,0.000,0.498)
|
||||
cylGui.Transparency = 80
|
||||
cylGui.Transparency = 85
|
||||
cylGui.Visibility = False
|
||||
vaGrp.addObject(cyl)
|
||||
|
||||
|
||||
def useRotJobClones(self, cloneName):
|
||||
if FreeCAD.ActiveDocument.getObject('rotJobClones'):
|
||||
if cloneName == 'Delete':
|
||||
if PathLog.getLevel() != 2:
|
||||
if PathLog.getLevel(PathLog.thisModule()) < 4:
|
||||
for cln in FreeCAD.ActiveDocument.getObject('rotJobClones').Group:
|
||||
FreeCAD.ActiveDocument.removeObject(cln.Name)
|
||||
FreeCAD.ActiveDocument.removeObject('rotJobClones')
|
||||
@@ -854,7 +852,7 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
clnStock.purgeTouched()
|
||||
return (clnBase, angle, clnStock, tag)
|
||||
|
||||
def applyInverseAngle(self, obj, clnBase, clnStock, axis, angle):
|
||||
def applyInverseAngle(self, obj, clnBase, clnStock, axis, angle):
|
||||
if axis == 'X':
|
||||
vect = FreeCAD.Vector(1, 0, 0)
|
||||
elif axis == 'Y':
|
||||
@@ -864,12 +862,11 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
clnStock = Draft.rotate(clnStock, (-2 * angle), center=FreeCAD.Vector(0.0, 0.0, 0.0), axis=vect, copy=False)
|
||||
clnBase.purgeTouched()
|
||||
clnStock.purgeTouched()
|
||||
if obj.InverseAngle is False:
|
||||
obj.InverseAngle = True
|
||||
else:
|
||||
obj.InverseAngle = False
|
||||
# Update property and angle values
|
||||
obj.InverseAngle = True
|
||||
angle = -1 * angle
|
||||
PathLog.debug(" --Rotated to InverseAngle.")
|
||||
|
||||
PathLog.info(translate("Path", "Rotated to inverse angle."))
|
||||
return (clnBase, clnStock, angle)
|
||||
|
||||
def calculateStartFinalDepths(self, obj, shape, stock):
|
||||
|
||||
@@ -50,8 +50,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Class and implementation of shape based Pocket operation."
|
||||
__contributors__ = "mlampert [FreeCAD], russ4262 (Russell Johnson)"
|
||||
__created__ = "2017"
|
||||
__scriptVersion__ = "2e testing"
|
||||
__lastModified__ = "2019-06-11 14:30 CST"
|
||||
__scriptVersion__ = "2f testing"
|
||||
__lastModified__ = "2019-06-12 14:12 CST"
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
@@ -100,7 +100,7 @@ def extendWire(feature, wire, length):
|
||||
try:
|
||||
off2D = wire.makeOffset2D(length)
|
||||
except Exception as e:
|
||||
PathLog.error("error: extendWire() off2D")
|
||||
PathLog.error("extendWire(): wire.makeOffset2D()")
|
||||
PathLog.error(e)
|
||||
return False
|
||||
else:
|
||||
@@ -112,7 +112,7 @@ def extendWire(feature, wire, length):
|
||||
try:
|
||||
l0 = (ePts[0] - endPts[0]).Length
|
||||
except Exception as ee:
|
||||
PathLog.error("error: extendWire() l0")
|
||||
PathLog.error("extendWire(): (ePts[0] - endPts[0]).Length")
|
||||
PathLog.error(ee)
|
||||
return False
|
||||
else:
|
||||
@@ -174,7 +174,7 @@ class Extension(object):
|
||||
try:
|
||||
normal = tangent.cross(FreeCAD.Vector(0, 0, 1)).normalize()
|
||||
except:
|
||||
PathLog.error(translate('PathPocket', 'Unable to getDirection(wire).'))
|
||||
PathLog.error('getDirection(): tangent.cross(FreeCAD.Vector(0, 0, 1)).normalize()')
|
||||
return None
|
||||
else:
|
||||
poffPlus = e0.valueAt(midparam) + 0.01 * normal
|
||||
@@ -252,6 +252,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
|
||||
def clasifySub(self, bs, sub):
|
||||
face = bs.Shape.getElement(sub)
|
||||
|
||||
def planarFaceFromExtrusionEdges(clsd):
|
||||
useFace = 'useFaceName'
|
||||
minArea = 0.0
|
||||
@@ -262,7 +263,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
# Create planar face from edge
|
||||
mFF = Part.Face(Part.Wire(Part.__sortEdges__([edg])))
|
||||
if mFF.isNull():
|
||||
PathLog.debug(' -Face(Part.Wire()) failed')
|
||||
PathLog.debug('Face(Part.Wire()) failed')
|
||||
else:
|
||||
mFF.translate(FreeCAD.Vector(0, 0, face.BoundBox.ZMin - mFF.BoundBox.ZMin))
|
||||
tmpFace = FreeCAD.ActiveDocument.addObject('Part::Feature', fName).Shape = mFF
|
||||
@@ -334,11 +335,11 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
msg += "\n<br>Bottom of pocket might be non-planar and/or not normal to spindle axis."
|
||||
msg += "\n<br>\n<br><i>3D pocket bottom is NOT available in this operation</i>."
|
||||
msg = translate('Path', msg)
|
||||
PathLog.error(msg)
|
||||
PathLog.info(msg)
|
||||
title = translate('Path', 'Depth Warning')
|
||||
self.guiMessage(title, msg, False)
|
||||
else:
|
||||
PathLog.error("Could not create a planar face from edges in {}.".format(sub))
|
||||
PathLog.error(translate("Path", "Failed to create a planar face from edges in {}.".format(sub)))
|
||||
else:
|
||||
PathLog.debug('type() == OTHER')
|
||||
PathLog.debug(' -type(face.Surface): {}'.format(type(face.Surface)))
|
||||
@@ -357,17 +358,17 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
(base, subsList) = obj.Base[p]
|
||||
go = False
|
||||
|
||||
# First, check all subs collectively for loop of faces
|
||||
if len(subsList) > 2:
|
||||
# Check for loop of faces
|
||||
(go, norm, surf) = self.checkForFacesLoop(base, subsList)
|
||||
|
||||
if go is True:
|
||||
PathLog.debug("Common Surface.Axis value found for loop faces.")
|
||||
PathLog.debug("Common Surface.Axis or normalAt() value found for loop faces.")
|
||||
rtn = False
|
||||
(rtn, angle, axis, praInfo) = self.pocketRotationAnalysis(obj, norm, surf, prnt=True)
|
||||
subCount += 1
|
||||
(rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
|
||||
|
||||
if rtn is True:
|
||||
(clnBase, angle, clnStock, tag) = self.applyRotationalAnalysis(obj, base, angle, axis, len(subsList))
|
||||
(clnBase, angle, clnStock, tag) = self.applyRotationalAnalysis(obj, base, angle, axis, subCount)
|
||||
|
||||
# Verify faces are correctly oriented - InverseAngle might be necessary
|
||||
PathLog.debug("Checking if faces are oriented correctly after rotation...")
|
||||
@@ -378,21 +379,25 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
rtn = False
|
||||
break
|
||||
if rtn is False:
|
||||
if obj.AttemptInverseAngle is True:
|
||||
if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
|
||||
(clnBase, clnStock, angle) = self.applyInverseAngle(obj, clnBase, clnStock, axis, angle)
|
||||
else:
|
||||
PathLog.error(" --Consider toggling the InverseAngle property and recomputing the operation.")
|
||||
PathLog.info(translate("Path", "Consider toggling the InverseAngle property and recomputing the operation."))
|
||||
|
||||
tup = clnBase, subsList, angle, axis, clnStock
|
||||
else:
|
||||
PathLog.error(" -Error with pocketRotationAnalysis()")
|
||||
PathLog.debug("No rotation used")
|
||||
axis = 'X'
|
||||
angle = 0.0
|
||||
stock = PathUtils.findParentJob(obj).Stock
|
||||
tup = base, subsList, angle, axis, stock
|
||||
# Eif
|
||||
allTuples.append(tup)
|
||||
baseSubsTuples.append(tup)
|
||||
# Eif
|
||||
|
||||
if go is False:
|
||||
PathLog.debug("Will process subs individually ...")
|
||||
PathLog.debug(translate('Path', "Processing subs individually ..."))
|
||||
for sub in subsList:
|
||||
subCount += 1
|
||||
if 'Face' in sub:
|
||||
@@ -401,26 +406,26 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
PathLog.debug(translate('Path', "Base Geometry sub: {}".format(sub)))
|
||||
face = base.Shape.getElement(sub)
|
||||
(norm, surf) = self.getFaceNormAndSurf(face)
|
||||
(rtn, angle, axis, praInfo)= self.pocketRotationAnalysis(obj, norm, surf, prnt=True)
|
||||
(rtn, angle, axis, praInfo)= self.faceRotationAnalysis(obj, norm, surf)
|
||||
|
||||
if rtn is True:
|
||||
(clnBase, angle, clnStock, tag) = self.applyRotationalAnalysis(obj, base, angle, axis, subCount)
|
||||
# Verify faces are correctly oriented - InverseAngle might be necessary
|
||||
faceIA = clnBase.Shape.getElement(sub)
|
||||
(norm, surf) = self.getFaceNormAndSurf(faceIA)
|
||||
(rtn, praAngle, praAxis, praInfo) = self.pocketRotationAnalysis(obj, norm, surf, prnt=False)
|
||||
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
|
||||
if rtn is True:
|
||||
PathLog.error(" --Face not aligned after initial rotation.")
|
||||
if obj.AttemptInverseAngle is True:
|
||||
PathLog.debug("Face not aligned after initial rotation.")
|
||||
if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
|
||||
(clnBase, clnStock, angle) = self.applyInverseAngle(obj, clnBase, clnStock, axis, angle)
|
||||
else:
|
||||
PathLog.error(" --Consider toggling the InverseAngle property and recomputing the operation.")
|
||||
PathLog.info(translate("Path", "Consider toggling the InverseAngle property and recomputing the operation."))
|
||||
else:
|
||||
PathLog.debug(" --Face appears to be oriented correctly.")
|
||||
PathLog.debug("Face appears to be oriented correctly.")
|
||||
|
||||
tup = clnBase, [sub], angle, axis, clnStock
|
||||
else:
|
||||
PathLog.debug(str(sub) + ": no rotation used")
|
||||
PathLog.debug(str(sub) + ": No rotation used")
|
||||
axis = 'X'
|
||||
angle = 0.0
|
||||
stock = PathUtils.findParentJob(obj).Stock
|
||||
@@ -430,7 +435,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
baseSubsTuples.append(tup)
|
||||
else:
|
||||
ignoreSub = base.Name + '.' + sub
|
||||
PathLog.error(translate('Path', "Selected object is not a face. Ignoring: {}".format(ignoreSub)))
|
||||
PathLog.error(translate('Path', "Selected feature is not a Face. Ignoring: {}".format(ignoreSub)))
|
||||
# Eif
|
||||
# Efor
|
||||
# Efor
|
||||
@@ -464,6 +469,13 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
if clasifySub(self, subBase, sub) is False:
|
||||
PathLog.error(translate('PathPocket', 'Pocket does not support shape %s.%s') % (subBase.Label, sub))
|
||||
|
||||
# Determine final depth as highest value of bottom boundbox of vertical face,
|
||||
# in case of uneven faces on bottom
|
||||
vFinDep = self.vert[0].BoundBox.ZMin
|
||||
for vFace in self.vert:
|
||||
if vFace.BoundBox.ZMin > vFinDep:
|
||||
vFinDep = vFace.BoundBox.ZMin
|
||||
# Determine if vertical faces for a loop: Extract planar loop wire as new horizontal face.
|
||||
self.vertical = PathGeom.combineConnectedShapes(self.vert)
|
||||
self.vWires = [TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1)) for shape in self.vertical]
|
||||
for wire in self.vWires:
|
||||
@@ -476,7 +488,12 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
# title = translate("Path", "Face Selection Warning")
|
||||
# self.guiMessage(title, msg, True)
|
||||
else:
|
||||
face.translate(FreeCAD.Vector(0, 0, vFinDep - face.BoundBox.ZMin))
|
||||
self.horiz.append(face)
|
||||
msg = translate('Path', 'Verify final depth of pocket shaped by vertical faces.')
|
||||
PathLog.error(msg)
|
||||
title = translate('Path', 'Depth Warning')
|
||||
self.guiMessage(title, msg, False)
|
||||
|
||||
# add faces for extensions
|
||||
self.exts = []
|
||||
@@ -507,13 +524,16 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
for face in self.horizontal:
|
||||
# extrude all faces up to StartDepth and those are the removal shapes
|
||||
(strDep, finDep) = self.calculateStartFinalDepths(obj, face, stock)
|
||||
# PathLog.debug("Extent depths are str: {}, and fin: {}".format(strDep, finDep))
|
||||
extent = FreeCAD.Vector(0, 0, strDep - finDep)
|
||||
self.removalshapes.append((face.removeSplitter().extrude(extent), False, 'pathPocketShape', angle, axis, strDep, finDep))
|
||||
PathLog.debug("Extent depths are str: {}, and fin: {}".format(strDep, finDep))
|
||||
# Efor face
|
||||
# Efor
|
||||
|
||||
# Adjust obj.FinalDepth.Value as needed.
|
||||
if subCount == 1:
|
||||
obj.FinalDepth.Value = finDep
|
||||
else: # process the job base object as a whole
|
||||
PathLog.debug('Processing... whole base')
|
||||
PathLog.debug(translate("Path", 'Processing model as a whole ...'))
|
||||
finDep = obj.FinalDepth.Value
|
||||
strDep = obj.StartDepth.Value
|
||||
self.outlines = [Part.Face(TechDraw.findShapeOutline(base.Shape, 1, FreeCAD.Vector(0, 0, 1))) for base in self.model]
|
||||
@@ -589,7 +609,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
wireName = 'tmpWire' + str(fCnt)
|
||||
wr = Part.Wire(Part.__sortEdges__(base.Shape.getElement(sub).Edges))
|
||||
if wr.isNull():
|
||||
PathLog.error('Now wire created from {}'.format(sub))
|
||||
PathLog.debug('No wire created from {}'.format(sub))
|
||||
return (False, 0, 0)
|
||||
else:
|
||||
tmpWire = FreeCAD.ActiveDocument.addObject('Part::Feature', wireName).Shape = wr
|
||||
@@ -624,12 +644,14 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
else:
|
||||
return round(val, 8)
|
||||
|
||||
# Sub Surface.Axis values of faces
|
||||
# Vector of (0, 0, 0) will suggests a loop
|
||||
for sub in subsList:
|
||||
if 'Face' in sub:
|
||||
fCnt += 1
|
||||
saSum = saSum.add(base.Shape.getElement(sub).Surface.Axis)
|
||||
# PathLog.debug("saSum: {}".format(saSum))
|
||||
|
||||
# Minimim of three faces required for loop to exist
|
||||
if fCnt < 3:
|
||||
go = False
|
||||
|
||||
@@ -704,18 +726,20 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
if (rnded.y > 0.0 or rnded.z > 0.0) and vertLoopFace is None:
|
||||
vertLoopFace = fc
|
||||
saTotal = saTotal.add(rnded)
|
||||
# PathLog.debug(" -saTotal: {}".format(saTotal))
|
||||
|
||||
if saTotal == FreeCAD.Vector(0.0, 0.0, 0.0):
|
||||
if vertLoopFace is not None:
|
||||
go = True
|
||||
|
||||
if go is True:
|
||||
(norm, surf) = self.getFaceNormAndSurf(vertLoopFace)
|
||||
else:
|
||||
PathLog.debug(translate('Path', ' -Can not identify loop.'))
|
||||
PathLog.debug(translate('Path', 'Can not identify loop.'))
|
||||
|
||||
if delTempNameList > 0:
|
||||
for tmpNm in tempNameList:
|
||||
FreeCAD.ActiveDocument.removeObject(tmpNm)
|
||||
|
||||
return (go, norm, surf)
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,14 @@ import numpy
|
||||
# from PathScripts.PathUtils import depth_params
|
||||
from PySide import QtCore
|
||||
|
||||
__title__ = "Path Profile Faces Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Path Profile operation based on faces."
|
||||
__created__ = "2014"
|
||||
__scriptVersion__ = "2f testing"
|
||||
__lastModified__ = "2019-06-12 14:12 CST"
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
PathLog.trackModule(PathLog.thisModule())
|
||||
@@ -46,14 +54,6 @@ else:
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
__title__ = "Path Profile Faces Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Path Profile operation based on faces."
|
||||
__created__ = "2014"
|
||||
__scriptVersion__ = "2e testing"
|
||||
__lastModified__ = "2019-06-11 14:30 CST"
|
||||
|
||||
|
||||
class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
'''Proxy object for Profile operations based on faces.'''
|
||||
@@ -99,6 +99,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
|
||||
shapes = []
|
||||
self.profileshape = []
|
||||
finalDepths = []
|
||||
|
||||
baseSubsTuples = []
|
||||
subCount = 0
|
||||
@@ -114,25 +115,24 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
if isinstance(shape, Part.Face):
|
||||
rtn = False
|
||||
(norm, surf) = self.getFaceNormAndSurf(shape)
|
||||
(rtn, angle, axis, praInfo)= self.pocketRotationAnalysis(obj, norm, surf, prnt=True)
|
||||
PathLog.info("praInfo: \n" + str(praInfo))
|
||||
(rtn, angle, axis, praInfo)= self.faceRotationAnalysis(obj, norm, surf)
|
||||
if rtn is True:
|
||||
(clnBase, angle, clnStock, tag) = self.applyRotationalAnalysis(obj, base, angle, axis, subCount)
|
||||
# Verify faces are correctly oriented - InverseAngle might be necessary
|
||||
faceIA = getattr(clnBase.Shape, sub)
|
||||
(norm, surf) = self.getFaceNormAndSurf(faceIA)
|
||||
(rtn, praAngle, praAxis, praInfo) = self.pocketRotationAnalysis(obj, norm, surf, prnt=False)
|
||||
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)
|
||||
if rtn is True:
|
||||
PathLog.error(" --Face not aligned after initial rotation.")
|
||||
if obj.AttemptInverseAngle is True:
|
||||
PathLog.error(translate("Path", "Face appears misaligned after initial rotation."))
|
||||
if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
|
||||
(clnBase, clnStock, angle) = self.applyInverseAngle(obj, clnBase, clnStock, axis, angle)
|
||||
else:
|
||||
msg = "Consider toggling the 'InverseAngle' property and recomputing."
|
||||
msg = translate("Path", "Consider toggling the 'InverseAngle' property and recomputing.")
|
||||
PathLog.error(msg)
|
||||
title = 'Rotation Warning'
|
||||
self.guiMessage(title, msg, False)
|
||||
# title = translate("Path", 'Rotation Warning')
|
||||
# self.guiMessage(title, msg, False)
|
||||
else:
|
||||
PathLog.debug(" --Face appears to be oriented correctly.")
|
||||
PathLog.debug("Face appears to be oriented correctly.")
|
||||
|
||||
tup = clnBase, sub, tag, angle, axis, clnStock
|
||||
else:
|
||||
@@ -151,7 +151,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
msg = "Multiple faces in Base Geometry."
|
||||
msg += " Depth settings will be applied to all faces."
|
||||
msg = translate("Path", msg)
|
||||
PathLog.error(msg)
|
||||
PathLog.warning(msg)
|
||||
#title = translate("Path", "Depth Warning")
|
||||
#self.guiMessage(title, msg)
|
||||
(Tags, Grps) = self.sortTuplesByIndex(allTuples, 2) # return (TagList, GroupList)
|
||||
@@ -164,7 +164,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
baseSubsTuples.append(pair)
|
||||
# Efor
|
||||
else:
|
||||
PathLog.info("Use Rotation feature(property) is 'Off'.")
|
||||
PathLog.info(translate("Path", "EnableRotation property is 'Off'."))
|
||||
stock = PathUtils.findParentJob(obj).Stock
|
||||
for (base, subList) in obj.Base:
|
||||
baseSubsTuples.append((base, subList, 0.0, 'X', stock))
|
||||
@@ -192,8 +192,10 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
f = Part.makeFace(wire, 'Part::FaceMakerSimple')
|
||||
drillable = PathUtils.isDrillable(shape, wire)
|
||||
if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
|
||||
PathLog.track()
|
||||
# Recalculate depthparams
|
||||
(strDep, finDep) = self.calculateStartFinalDepths(obj, shape, stock)
|
||||
finalDepths.append(finDep)
|
||||
PathLog.debug("Adjusted face depths strDep: {}, and finDep: {}".format(self.strDep, self.finDep))
|
||||
finish_step = obj.FinishDepth.Value if hasattr(obj, "FinishDepth") else 0.0
|
||||
self.depthparams = PathUtils.depth_params(
|
||||
@@ -205,7 +207,6 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
final_depth=finDep, #obj.FinalDepth.Value,
|
||||
user_depths=None)
|
||||
env = PathUtils.getEnvelope(shape, subshape=f, depthparams=self.depthparams)
|
||||
PathLog.track()
|
||||
# shapes.append((env, True))
|
||||
tup = env, True, 'pathProfileFaces', angle, axis, strDep, finDep
|
||||
shapes.append(tup)
|
||||
@@ -219,6 +220,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
if profileshape:
|
||||
# Recalculate depthparams
|
||||
(strDep, finDep) = self.calculateStartFinalDepths(obj, profileshape, stock)
|
||||
finalDepths.append(finDep)
|
||||
PathLog.debug("Adjusted face depths strDep: {}, and finDep: {}".format(self.strDep, self.finDep))
|
||||
finish_step = obj.FinishDepth.Value if hasattr(obj, "FinishDepth") else 0.0
|
||||
self.depthparams = PathUtils.depth_params(
|
||||
@@ -235,7 +237,8 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
try:
|
||||
env = PathUtils.getEnvelope(base.Shape, subshape=profileshape, depthparams=self.depthparams)
|
||||
except Exception as ee:
|
||||
PathLog.error(translate('Path', 'getEnvelope() failed to return an object.'))
|
||||
# PathUtils.getEnvelope() failed to return an object.
|
||||
PathLog.error(translate('Path', 'Unable to create path for face(s).'))
|
||||
else:
|
||||
# shapes.append((env, False))
|
||||
tup = env, False, 'pathProfileFaces', angle, axis, strDep, finDep
|
||||
@@ -244,6 +247,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
for shape in faces:
|
||||
# Recalculate depthparams
|
||||
(strDep, finDep) = self.calculateStartFinalDepths(obj, shape, stock)
|
||||
finalDepths.append(finDep)
|
||||
finish_step = obj.FinishDepth.Value if hasattr(obj, "FinishDepth") else 0.0
|
||||
self.depthparams = PathUtils.depth_params(
|
||||
clearance_height=obj.ClearanceHeight.Value,
|
||||
@@ -257,7 +261,11 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
tup = env, False, 'pathProfileFaces', angle, axis, strDep, finDep
|
||||
shapes.append(tup)
|
||||
# Eif
|
||||
# Efor
|
||||
|
||||
# adjust FinalDepth as needed
|
||||
finalDepth = min(finalDepths)
|
||||
if obj.FinalDepth.Value < finalDepth:
|
||||
obj.FinalDepth.Value = finalDepth
|
||||
else: # Try to build targets from the job base
|
||||
if 1 == len(self.model) and hasattr(self.model[0], "Proxy"):
|
||||
if isinstance(self.model[0].Proxy, ArchPanel.PanelSheet): # process the sheet
|
||||
@@ -295,7 +303,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
||||
obj.processPerimeter = True
|
||||
obj.ReverseDirection = False
|
||||
obj.InverseAngle = False
|
||||
obj.AttemptInverseAngle = False
|
||||
obj.AttemptInverseAngle = True
|
||||
obj.B_AxisErrorOverride = False
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user