Merge branch 'FreeCAD:master' into patharray_multibase
This commit is contained in:
@@ -171,7 +171,7 @@ class ObjectJob:
|
||||
obj.Stock.ViewObject.Visibility = False
|
||||
|
||||
def setupSetupSheet(self, obj):
|
||||
if not hasattr(obj, 'SetupSheet'):
|
||||
if not getattr(obj, 'SetupSheet', None):
|
||||
obj.addProperty('App::PropertyLink', 'SetupSheet', 'Base', QtCore.QT_TRANSLATE_NOOP('PathJob', 'SetupSheet holding the settings for this job'))
|
||||
obj.SetupSheet = PathSetupSheet.Create()
|
||||
if obj.SetupSheet.ViewObject:
|
||||
@@ -223,53 +223,58 @@ class ObjectJob:
|
||||
PathLog.track(obj.Label, arg2)
|
||||
doc = obj.Document
|
||||
|
||||
# the first to tear down are the ops, they depend on other resources
|
||||
PathLog.debug('taking down ops: %s' % [o.Name for o in self.allOperations()])
|
||||
while obj.Operations.Group:
|
||||
op = obj.Operations.Group[0]
|
||||
if not op.ViewObject or not hasattr(op.ViewObject.Proxy, 'onDelete') or op.ViewObject.Proxy.onDelete(op.ViewObject, ()):
|
||||
PathUtil.clearExpressionEngine(op)
|
||||
doc.removeObject(op.Name)
|
||||
obj.Operations.Group = []
|
||||
doc.removeObject(obj.Operations.Name)
|
||||
obj.Operations = None
|
||||
if getattr(obj, 'Operations', None):
|
||||
# the first to tear down are the ops, they depend on other resources
|
||||
PathLog.debug('taking down ops: %s' % [o.Name for o in self.allOperations()])
|
||||
while obj.Operations.Group:
|
||||
op = obj.Operations.Group[0]
|
||||
if not op.ViewObject or not hasattr(op.ViewObject.Proxy, 'onDelete') or op.ViewObject.Proxy.onDelete(op.ViewObject, ()):
|
||||
PathUtil.clearExpressionEngine(op)
|
||||
doc.removeObject(op.Name)
|
||||
obj.Operations.Group = []
|
||||
doc.removeObject(obj.Operations.Name)
|
||||
obj.Operations = None
|
||||
|
||||
# stock could depend on Model, so delete it first
|
||||
if obj.Stock:
|
||||
if getattr(obj, 'Stock', None):
|
||||
PathLog.debug('taking down stock')
|
||||
PathUtil.clearExpressionEngine(obj.Stock)
|
||||
doc.removeObject(obj.Stock.Name)
|
||||
obj.Stock = None
|
||||
|
||||
# base doesn't depend on anything inside job
|
||||
for base in obj.Model.Group:
|
||||
PathLog.debug("taking down base %s" % base.Label)
|
||||
self.removeBase(obj, base, False)
|
||||
obj.Model.Group = []
|
||||
doc.removeObject(obj.Model.Name)
|
||||
obj.Model = None
|
||||
if getattr(obj, 'Model', None):
|
||||
for base in obj.Model.Group:
|
||||
PathLog.debug("taking down base %s" % base.Label)
|
||||
self.removeBase(obj, base, False)
|
||||
obj.Model.Group = []
|
||||
doc.removeObject(obj.Model.Name)
|
||||
obj.Model = None
|
||||
|
||||
# Tool controllers might refer to either legacy tool or toolbit
|
||||
PathLog.debug('taking down tool controller')
|
||||
for tc in obj.Tools.Group:
|
||||
if hasattr(tc.Tool, "Proxy"):
|
||||
PathUtil.clearExpressionEngine(tc.Tool)
|
||||
doc.removeObject(tc.Tool.Name)
|
||||
PathUtil.clearExpressionEngine(tc)
|
||||
tc.Proxy.onDelete(tc)
|
||||
doc.removeObject(tc.Name)
|
||||
obj.Tools.Group = []
|
||||
doc.removeObject(obj.Tools.Name)
|
||||
obj.Tools = None
|
||||
if getattr(obj, 'Tools', None):
|
||||
PathLog.debug('taking down tool controller')
|
||||
for tc in obj.Tools.Group:
|
||||
if hasattr(tc.Tool, "Proxy"):
|
||||
PathUtil.clearExpressionEngine(tc.Tool)
|
||||
doc.removeObject(tc.Tool.Name)
|
||||
PathUtil.clearExpressionEngine(tc)
|
||||
tc.Proxy.onDelete(tc)
|
||||
doc.removeObject(tc.Name)
|
||||
obj.Tools.Group = []
|
||||
doc.removeObject(obj.Tools.Name)
|
||||
obj.Tools = None
|
||||
|
||||
# SetupSheet
|
||||
PathUtil.clearExpressionEngine(obj.SetupSheet)
|
||||
doc.removeObject(obj.SetupSheet.Name)
|
||||
obj.SetupSheet = None
|
||||
if getattr(obj, 'SetupSheet', None):
|
||||
PathUtil.clearExpressionEngine(obj.SetupSheet)
|
||||
doc.removeObject(obj.SetupSheet.Name)
|
||||
obj.SetupSheet = None
|
||||
|
||||
return True
|
||||
|
||||
def fixupOperations(self, obj):
|
||||
if obj.Operations.ViewObject:
|
||||
if getattr(obj.Operations, 'ViewObject', None):
|
||||
try:
|
||||
obj.Operations.ViewObject.DisplayMode
|
||||
except Exception: # pylint: disable=broad-except
|
||||
@@ -409,7 +414,7 @@ class ObjectJob:
|
||||
return None
|
||||
|
||||
def execute(self, obj):
|
||||
if hasattr(obj, 'Operations'):
|
||||
if getattr(obj, 'Operations', None):
|
||||
obj.Path = obj.Operations.Path
|
||||
self.getCycleTime()
|
||||
|
||||
@@ -457,6 +462,11 @@ class ObjectJob:
|
||||
self.obj.Operations.Group = group
|
||||
op.Path.Center = self.obj.Operations.Path.Center
|
||||
|
||||
def nextToolNumber(self):
|
||||
# returns the next available toolnumber in the job
|
||||
group = self.obj.Tools.Group
|
||||
return sorted([t.ToolNumber for t in group])[-1] + 1
|
||||
|
||||
def addToolController(self, tc):
|
||||
group = self.obj.Tools.Group
|
||||
PathLog.debug("addToolController(%s): %s" % (tc.Label, [t.Label for t in group]))
|
||||
@@ -479,8 +489,11 @@ class ObjectJob:
|
||||
ops.append(op)
|
||||
for sub in op.Group:
|
||||
collectBaseOps(sub)
|
||||
for op in self.obj.Operations.Group:
|
||||
collectBaseOps(op)
|
||||
|
||||
if getattr(self.obj, 'Operations', None) and getattr(self.obj.Operations, 'Group', None):
|
||||
for op in self.obj.Operations.Group:
|
||||
collectBaseOps(op)
|
||||
|
||||
return ops
|
||||
|
||||
def setCenterOfRotation(self, center):
|
||||
|
||||
@@ -27,11 +27,11 @@ import math
|
||||
import traceback
|
||||
from pivy import coin
|
||||
from PySide import QtCore, QtGui
|
||||
import json
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
import PathGui as PGui # ensure Path/Gui/Resources are loaded
|
||||
import PathScripts.PathJob as PathJob
|
||||
import PathScripts.PathJobCmd as PathJobCmd
|
||||
import PathScripts.PathJobDlg as PathJobDlg
|
||||
@@ -520,7 +520,7 @@ class StockFromExistingEdit(StockEdit):
|
||||
stock = self.form.stockExisting.itemData(self.form.stockExisting.currentIndex())
|
||||
if not (hasattr(obj.Stock, 'Objects') and len(obj.Stock.Objects) == 1 and obj.Stock.Objects[0] == stock):
|
||||
if stock:
|
||||
stock = PathJob.createResourceClone(obj, stock, self.StockLabelPrefix , 'Stock')
|
||||
stock = PathJob.createResourceClone(obj, stock, self.StockLabelPrefix, 'Stock')
|
||||
stock.ViewObject.Visibility = True
|
||||
PathStock.SetupStockObject(stock, PathStock.StockType.Unknown)
|
||||
stock.Proxy.execute(stock)
|
||||
@@ -546,7 +546,7 @@ class StockFromExistingEdit(StockEdit):
|
||||
index = -1
|
||||
for i, solid in enumerate(self.candidates(obj)):
|
||||
self.form.stockExisting.addItem(solid.Label, solid)
|
||||
label="{}-{}".format(self.StockLabelPrefix, solid.Label)
|
||||
label = "{}-{}".format(self.StockLabelPrefix, solid.Label)
|
||||
|
||||
if label == stockName:
|
||||
index = i
|
||||
@@ -864,13 +864,33 @@ class TaskPanel:
|
||||
self.toolControllerSelect()
|
||||
|
||||
def toolControllerAdd(self):
|
||||
# adding a TC from a toolbit directly.
|
||||
# Try to find a tool number from the currently selected lib. Otherwise
|
||||
# use next available number
|
||||
|
||||
if PathPreferences.toolsUseLegacyTools():
|
||||
PathToolLibraryEditor.CommandToolLibraryEdit().edit(self.obj, self.updateToolController)
|
||||
else:
|
||||
tools = PathToolBitGui.LoadTools()
|
||||
|
||||
curLib = PathPreferences.lastFileToolLibrary()
|
||||
|
||||
library = None
|
||||
if curLib is not None:
|
||||
with open(curLib) as fp:
|
||||
library = json.load(fp)
|
||||
|
||||
for tool in tools:
|
||||
tc = PathToolControllerGui.Create(name=tool.Label, tool=tool)
|
||||
toolNum = self.obj.Proxy.nextToolNumber()
|
||||
if library is not None:
|
||||
for toolBit in library['tools']:
|
||||
|
||||
if toolBit['path'] == tool.File:
|
||||
toolNum = toolBit['nr']
|
||||
|
||||
tc = PathToolControllerGui.Create(name=tool.Label, tool=tool, toolNumber=toolNum)
|
||||
self.obj.Proxy.addToolController(tc)
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
self.updateToolController()
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@ class Extension(object):
|
||||
self.sub = sub
|
||||
self.length = length
|
||||
self.direction = direction
|
||||
self.extFaces = list()
|
||||
|
||||
self.wire = None
|
||||
|
||||
@@ -197,7 +198,22 @@ class Extension(object):
|
||||
|
||||
return self._getDirectedNormal(e0.valueAt(midparam), normal.normalize())
|
||||
|
||||
def getExtensionFaces(self, extensionWire):
|
||||
'''getExtensionFace(extensionWire)...
|
||||
A public helper method to retrieve the requested extension as a face,
|
||||
rather than a wire becuase 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
|
||||
and sub element provided at class instantiation, as a closed wire. If no closed wire
|
||||
is possible, a `None` value is returned.'''
|
||||
PathLog.track()
|
||||
if PathGeom.isRoughly(0, self.length.Value) or not self.sub:
|
||||
PathLog.debug("no extension, length=%.2f, sub=%s" % (self.length.Value, self.sub))
|
||||
@@ -233,7 +249,9 @@ class Extension(object):
|
||||
e2 = Part.makeLine(edge.valueAt(edge.LastParameter), e3.valueAt(e3.LastParameter))
|
||||
return Part.Wire([e0, edge, e2, e3])
|
||||
|
||||
return Part.Wire([e3])
|
||||
extWire = Part.Wire([e3])
|
||||
self.extFaces = [self._makeCircularExtFace(edge, extWire)]
|
||||
return extWire
|
||||
|
||||
# the extension is bigger than the hole - so let's just cover the whole hole
|
||||
if endPoints(edge):
|
||||
@@ -258,6 +276,25 @@ class Extension(object):
|
||||
|
||||
return extendWire(feature, sub, self.length.Value)
|
||||
|
||||
def _makeCircularExtFace(self, 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))
|
||||
extWireFace = Part.Face(extWire)
|
||||
extWireFace.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - extWireFace.BoundBox.ZMin))
|
||||
|
||||
if extWireFace.Area >= edgeFace.Area:
|
||||
extensionFace = extWireFace.cut(edgeFace)
|
||||
else:
|
||||
extensionFace = edgeFace.cut(extWireFace)
|
||||
extensionFace.translate(FreeCAD.Vector(0.0, 0.0, edge.BoundBox.ZMin))
|
||||
|
||||
return extensionFace
|
||||
# Eclass
|
||||
|
||||
|
||||
class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
'''Proxy object for Pocket operation.'''
|
||||
@@ -385,9 +422,9 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
||||
for ext in self.getExtensions(obj):
|
||||
wire = ext.getWire()
|
||||
if wire:
|
||||
face = Part.Face(wire)
|
||||
self.horiz.append(face)
|
||||
self.exts.append(face)
|
||||
for face in ext.getExtensionFaces(wire):
|
||||
self.horiz.append(face)
|
||||
self.exts.append(face)
|
||||
|
||||
# Place all self.horiz faces into same working plane
|
||||
for h in self.horiz:
|
||||
|
||||
@@ -75,6 +75,7 @@ class _Extension(object):
|
||||
hnt = coin.SoShapeHints()
|
||||
|
||||
if not ext is None:
|
||||
numVert = list() # track number of verticies in each polygon face
|
||||
try:
|
||||
wire = ext.getWire()
|
||||
except FreeCAD.Base.FreeCADError:
|
||||
@@ -86,8 +87,22 @@ class _Extension(object):
|
||||
p2 = list(reversed(p1))
|
||||
polygon = [(p.x, p.y, p.z) for p in (p0 + p2)]
|
||||
else:
|
||||
poly = [p for p in wire.discretize(Deflection=0.02)][:-1]
|
||||
polygon = [(p.x, p.y, p.z) for p in poly]
|
||||
if ext.extFaces:
|
||||
# Create polygon for each extension face in compound extensions
|
||||
allPolys = list()
|
||||
extFaces = ext.getExtensionFaces(wire)
|
||||
for f in extFaces:
|
||||
pCnt = 0
|
||||
for w in f.Wires:
|
||||
poly = [p for p in w.discretize(Deflection=0.01)]
|
||||
pCnt += len(poly)
|
||||
allPolys.extend(poly)
|
||||
numVert.append(pCnt)
|
||||
polygon = [(p.x, p.y, p.z) for p in allPolys]
|
||||
else:
|
||||
# poly = [p for p in wire.discretize(Deflection=0.02)][:-1]
|
||||
poly = [p for p in wire.discretize(Deflection=0.02)]
|
||||
polygon = [(p.x, p.y, p.z) for p in poly]
|
||||
crd.point.setValues(polygon)
|
||||
else:
|
||||
return None
|
||||
@@ -98,6 +113,10 @@ class _Extension(object):
|
||||
hnt.faceType = coin.SoShapeHints.UNKNOWN_FACE_TYPE
|
||||
hnt.vertexOrdering = coin.SoShapeHints.CLOCKWISE
|
||||
|
||||
if numVert:
|
||||
# Transfer vertex counts for polygon faces
|
||||
fce.numVertices.setValues(tuple(numVert))
|
||||
|
||||
sep.addChild(pos)
|
||||
sep.addChild(mat)
|
||||
sep.addChild(hnt)
|
||||
@@ -222,7 +241,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
|
||||
|
||||
if obj.ExtensionCorners != self.form.extendCorners.isChecked():
|
||||
self.form.extendCorners.toggle()
|
||||
self.defaultLength.updateSpinBox()
|
||||
self.updateQuantitySpinBoxes()
|
||||
self.extensions = obj.Proxy.getExtensions(obj) # pylint: disable=attribute-defined-outside-init
|
||||
self.setExtensions(self.extensions)
|
||||
|
||||
@@ -341,11 +360,15 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
|
||||
|
||||
self.form.extensionTree.blockSignals(False)
|
||||
|
||||
def updateQuantitySpinBoxes(self, index = None):
|
||||
self.defaultLength.updateSpinBox()
|
||||
|
||||
def updateData(self, obj, prop):
|
||||
PathLog.track(obj.Label, prop, self.blockUpdateData)
|
||||
if not self.blockUpdateData:
|
||||
if prop in ['Base', 'ExtensionLengthDefault']:
|
||||
self.setExtensions(obj.Proxy.getExtensions(obj))
|
||||
self.updateQuantitySpinBoxes()
|
||||
|
||||
def restoreSelection(self, selection):
|
||||
PathLog.track()
|
||||
@@ -458,6 +481,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage):
|
||||
self.form.buttonClear.clicked.connect(self.extensionsClear)
|
||||
self.form.buttonDisable.clicked.connect(self.extensionsDisable)
|
||||
self.form.buttonEnable.clicked.connect(self.extensionsEnable)
|
||||
self.form.defaultLength.editingFinished.connect(self.updateQuantitySpinBoxes)
|
||||
|
||||
self.model.itemChanged.connect(self.updateItemEnabled)
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import math
|
||||
from lazy_loader.lazy_loader import LazyLoader
|
||||
Part = LazyLoader('Part', globals(), 'Part')
|
||||
Arcs = LazyLoader('draftgeoutils.arcs', globals(), 'draftgeoutils.arcs')
|
||||
PathGeom = LazyLoader('PathScripts.PathGeom', globals(), 'PathScripts.PathGeom')
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui = LazyLoader('FreeCADGui', globals(), 'FreeCADGui')
|
||||
|
||||
@@ -159,7 +160,7 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
'CustomPoint1': FreeCAD.Vector(0.0, 0.0, 0.0),
|
||||
'ExtendPathStart': 0.0,
|
||||
'Reference1': 'Center of Mass',
|
||||
'CustomPoint2': FreeCAD.Vector(10.0, 10.0, 0.0),
|
||||
'CustomPoint2': FreeCAD.Vector(0.0, 0.0, 0.0),
|
||||
'ExtendPathEnd': 0.0,
|
||||
'Reference2': 'Center of Mass',
|
||||
'LayerMode': 'Multi-pass',
|
||||
@@ -353,6 +354,7 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
self.arcMidPnt = None
|
||||
self.arcRadius = 0.0
|
||||
self.newRadius = 0.0
|
||||
self.featureDetails = ["", ""]
|
||||
self.isDebug = False if PathLog.getLevel(PathLog.thisModule()) != 4 else True
|
||||
self.showDebugObjects = False
|
||||
self.stockZMin = self.job.Stock.Shape.BoundBox.ZMin
|
||||
@@ -433,35 +435,41 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
# Use custom inputs here
|
||||
p1 = obj.CustomPoint1
|
||||
p2 = obj.CustomPoint2
|
||||
if p1.z == p2.z:
|
||||
if p1 == p2:
|
||||
msg = translate('PathSlot',
|
||||
'Custom points are identical.')
|
||||
FreeCAD.Console.PrintError(msg + '\n')
|
||||
return False
|
||||
elif p1.z == p2.z:
|
||||
pnts = (p1, p2)
|
||||
featureCount = 2
|
||||
else:
|
||||
msg = translate('PathSlot',
|
||||
'Custom points not at same Z height.')
|
||||
FreeCAD.Console.PrintError(msg + '\n')
|
||||
return False
|
||||
|
||||
baseGeom = obj.Base[0]
|
||||
base, subsList = baseGeom
|
||||
self.base = base
|
||||
|
||||
featureCount = len(subsList)
|
||||
if featureCount == 1:
|
||||
PathLog.debug('Reference 1: {}'.format(obj.Reference1))
|
||||
sub1 = subsList[0]
|
||||
shape_1 = getattr(base.Shape, sub1)
|
||||
self.shape1 = shape_1
|
||||
pnts = self._processSingle(obj, shape_1, sub1)
|
||||
else:
|
||||
PathLog.debug('Reference 1: {}'.format(obj.Reference1))
|
||||
PathLog.debug('Reference 2: {}'.format(obj.Reference2))
|
||||
sub1 = subsList[0]
|
||||
sub2 = subsList[1]
|
||||
shape_1 = getattr(base.Shape, sub1)
|
||||
shape_2 = getattr(base.Shape, sub2)
|
||||
self.shape1 = shape_1
|
||||
self.shape2 = shape_2
|
||||
pnts = self._processDouble(obj, shape_1, sub1, shape_2, sub2)
|
||||
baseGeom = obj.Base[0]
|
||||
base, subsList = baseGeom
|
||||
self.base = base
|
||||
|
||||
featureCount = len(subsList)
|
||||
if featureCount == 1:
|
||||
PathLog.debug('Reference 1: {}'.format(obj.Reference1))
|
||||
sub1 = subsList[0]
|
||||
shape_1 = getattr(base.Shape, sub1)
|
||||
self.shape1 = shape_1
|
||||
pnts = self._processSingle(obj, shape_1, sub1)
|
||||
else:
|
||||
PathLog.debug('Reference 1: {}'.format(obj.Reference1))
|
||||
PathLog.debug('Reference 2: {}'.format(obj.Reference2))
|
||||
sub1 = subsList[0]
|
||||
sub2 = subsList[1]
|
||||
shape_1 = getattr(base.Shape, sub1)
|
||||
shape_2 = getattr(base.Shape, sub2)
|
||||
self.shape1 = shape_1
|
||||
self.shape2 = shape_2
|
||||
pnts = self._processDouble(obj, shape_1, sub1, shape_2, sub2)
|
||||
|
||||
if not pnts:
|
||||
return False
|
||||
@@ -608,21 +616,26 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
PathLog.debug('_finishLine() Perp, featureCnt == 2')
|
||||
if perpZero:
|
||||
(p1, p2) = pnts
|
||||
pnts = self._makePerpendicular(p1, p2, 10.0) # 10.0 offset below
|
||||
initPerpDist = p1.sub(p2).Length
|
||||
pnts = self._makePerpendicular(p1, p2, initPerpDist) # 10.0 offset below
|
||||
else:
|
||||
# Modify path points if user selected two parallel edges
|
||||
if (featureCnt == 2 and self.shapeType1 == 'Edge' and
|
||||
self.shapeType2 == 'Edge' and self._isParallel(self.dYdX1, self.dYdX2)):
|
||||
(p1, p2) = pnts
|
||||
edg1_len = self.shape1.Length
|
||||
edg2_len = self.shape2.Length
|
||||
set_length = max(edg1_len, edg2_len)
|
||||
pnts = self._makePerpendicular(p1, p2, 10.0 + set_length) # 10.0 offset below
|
||||
if edg1_len != edg2_len:
|
||||
msg = obj.Label + ' '
|
||||
msg += translate('PathSlot',
|
||||
'Verify slot path start and end points.')
|
||||
FreeCAD.Console.PrintWarning(msg + '\n')
|
||||
self.shapeType2 == 'Edge'):
|
||||
if self.featureDetails[0] == "arc" and self.featureDetails[1] == "arc":
|
||||
perpZero = False
|
||||
elif self._isParallel(self.dYdX1, self.dYdX2):
|
||||
PathLog.debug('_finishLine() StE, featureCnt == 2 // edges')
|
||||
(p1, p2) = pnts
|
||||
edg1_len = self.shape1.Length
|
||||
edg2_len = self.shape2.Length
|
||||
set_length = max(edg1_len, edg2_len)
|
||||
pnts = self._makePerpendicular(p1, p2, 10.0 + set_length) # 10.0 offset below
|
||||
if edg1_len != edg2_len:
|
||||
msg = obj.Label + ' '
|
||||
msg += translate('PathSlot',
|
||||
'Verify slot path start and end points.')
|
||||
FreeCAD.Console.PrintWarning(msg + '\n')
|
||||
else:
|
||||
perpZero = False
|
||||
|
||||
@@ -712,21 +725,30 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
pnts = False
|
||||
norm = shape_1.normalAt(0.0, 0.0)
|
||||
PathLog.debug('{}.normalAt(): {}'.format(sub1, norm))
|
||||
if norm.z == 1 or norm.z == -1:
|
||||
pnts = self._processSingleHorizFace(obj, shape_1)
|
||||
elif norm.z == 0:
|
||||
faceType = self._getVertFaceType(shape_1)
|
||||
if faceType:
|
||||
(geo, shp) = faceType
|
||||
if geo == 'Face':
|
||||
pnts = self._processSingleComplexFace(obj, shp)
|
||||
if geo == 'Wire':
|
||||
pnts = self._processSingleVertFace(obj, shp)
|
||||
if geo == 'Edge':
|
||||
pnts = self._processSingleVertFace(obj, shp)
|
||||
|
||||
if PathGeom.isRoughly(shape_1.BoundBox.ZMax, shape_1.BoundBox.ZMin):
|
||||
# Horizontal face
|
||||
if norm.z == 1 or norm.z == -1:
|
||||
pnts = self._processSingleHorizFace(obj, shape_1)
|
||||
elif norm.z == 0:
|
||||
faceType = self._getVertFaceType(shape_1)
|
||||
if faceType:
|
||||
(geo, shp) = faceType
|
||||
if geo == 'Face':
|
||||
pnts = self._processSingleComplexFace(obj, shp)
|
||||
if geo == 'Wire':
|
||||
pnts = self._processSingleVertFace(obj, shp)
|
||||
if geo == 'Edge':
|
||||
pnts = self._processSingleVertFace(obj, shp)
|
||||
else:
|
||||
if len(shape_1.Edges) == 4:
|
||||
pnts = self._processSingleHorizFace(obj, shape_1)
|
||||
else:
|
||||
pnts = self._processSingleComplexFace(obj, shape_1)
|
||||
|
||||
if not pnts:
|
||||
msg = translate('PathSlot',
|
||||
'The selected face is not oriented horizontally or vertically.')
|
||||
'The selected face is inaccessible.')
|
||||
FreeCAD.Console.PrintError(msg + '\n')
|
||||
return False
|
||||
|
||||
@@ -862,16 +884,16 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
def _processSingleComplexFace(self, obj, shape):
|
||||
"""Determine slot path endpoints from a single complex face."""
|
||||
PathLog.debug('_processSingleComplexFace()')
|
||||
PNTS = list()
|
||||
pnts = list()
|
||||
|
||||
def zVal(V):
|
||||
return V.z
|
||||
def zVal(p):
|
||||
return p.z
|
||||
|
||||
for E in shape.Wires[0].Edges:
|
||||
p = self._findLowestEdgePoint(E)
|
||||
PNTS.append(p)
|
||||
PNTS.sort(key=zVal)
|
||||
return (PNTS[0], PNTS[1])
|
||||
pnts.append(p)
|
||||
pnts.sort(key=zVal)
|
||||
return (pnts[0], pnts[1])
|
||||
|
||||
def _processSingleVertFace(self, obj, shape):
|
||||
"""Determine slot path endpoints from a single vertically oriented face
|
||||
@@ -925,7 +947,7 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
# Check that all Z values are equal (isRoughly same)
|
||||
if (abs(z1 - z2) > tolrnc or
|
||||
abs(z1 - z3) > tolrnc ):
|
||||
# abs(z2 - z3) > tolrnc): 3rd test redundant.
|
||||
# abs(z2 - z3) > tolrnc): 3rd test redundant.
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -1182,6 +1204,9 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
p = self._getHighestPoint(shape)
|
||||
|
||||
elif cat == 'Edge':
|
||||
featDetIdx = pNum - 1
|
||||
if shape.Curve.TypeId == 'Part::GeomCircle':
|
||||
self.featureDetails[featDetIdx] = "arc"
|
||||
# calculate slope between end vertexes
|
||||
v0 = shape.Edges[0].Vertexes[0]
|
||||
v1 = shape.Edges[0].Vertexes[1]
|
||||
@@ -1309,13 +1334,13 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
|
||||
def _isParallel(self, dYdX1, dYdX2):
|
||||
"""Determine if two orientation vectors are parallel."""
|
||||
# if dYdX1.add(dYdX2).Length == 0:
|
||||
# return True
|
||||
# if ((dYdX1.x + dYdX2.x) / 2.0 == dYdX1.x and
|
||||
# (dYdX1.y + dYdX2.y) / 2.0 == dYdX1.y):
|
||||
# return True
|
||||
# return False
|
||||
return (dYdX1.cross(dYdX2) == FreeCAD.Vector(0,0,0) )
|
||||
# if dYdX1.add(dYdX2).Length == 0:
|
||||
# return True
|
||||
# if ((dYdX1.x + dYdX2.x) / 2.0 == dYdX1.x and
|
||||
# (dYdX1.y + dYdX2.y) / 2.0 == dYdX1.y):
|
||||
# return True
|
||||
# return False
|
||||
|
||||
def _makePerpendicular(self, p1, p2, length):
|
||||
"""_makePerpendicular(p1, p2, length)...
|
||||
@@ -1367,7 +1392,7 @@ class ObjectSlot(PathOp.ObjectOp):
|
||||
def _findLowestEdgePoint(self, E):
|
||||
zMin = E.BoundBox.ZMin
|
||||
eLen = E.Length
|
||||
L0 = 0
|
||||
L0 = 0.0
|
||||
L1 = eLen
|
||||
p0 = None
|
||||
p1 = None
|
||||
|
||||
@@ -186,7 +186,7 @@ class _Geometry(object):
|
||||
def _calculate_depth(MIC, geom):
|
||||
# given a maximum inscribed circle (MIC) and tool angle,
|
||||
# return depth of cut relative to zStart.
|
||||
depth = geom.start - round(MIC / geom.scale, 4)
|
||||
depth = geom.start - round(MIC * geom.scale, 4)
|
||||
PathLog.debug('zStart value: {} depth: {}'.format(geom.start, depth))
|
||||
|
||||
return max(depth, geom.stop)
|
||||
|
||||
Reference in New Issue
Block a user