diff --git a/src/Mod/Path/PathScripts/PathProfile.py b/src/Mod/Path/PathScripts/PathProfile.py index 6745b143e0..87ba301649 100644 --- a/src/Mod/Path/PathScripts/PathProfile.py +++ b/src/Mod/Path/PathScripts/PathProfile.py @@ -188,7 +188,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): # ml = 0 if obj.JoinType == 'Miter' else 2 rotation = 2 if obj.EnableRotation == 'Off' else 0 side = 0 if obj.UseComp else 2 - opType = self.getOperationType(obj) + opType = self._getOperationType(obj) if opType == 'Contour': side = 2 @@ -211,7 +211,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): obj.setEditorMode('AttemptInverseAngle', rotation) obj.setEditorMode('LimitDepthToFace', rotation) - def getOperationType(self, obj): + def _getOperationType(self, obj): if len(obj.Base) == 0: return 'Contour' @@ -286,23 +286,29 @@ class ObjectProfile(PathAreaOp.ObjectOp): return True def opUpdateDepths(self, obj): - obj.OpStartDepth = obj.OpStockZMax - obj.OpFinalDepth = obj.OpStockZMin + if hasattr(obj, 'Base') and obj.Base.__len__() == 0: + obj.OpStartDepth = obj.OpStockZMax + obj.OpFinalDepth = obj.OpStockZMin def areaOpShapes(self, obj): '''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.''' PathLog.track() shapes = [] - inaccessible = translate('PathProfileEdges', 'The selected edge(s) are inaccessible. If multiple, re-ordering selection might work.') baseSubsTuples = list() allTuples = list() edgeFaces = list() subCount = 0 + self.inaccessibleMsg = translate('PathProfile', 'The selected edge(s) are inaccessible. If multiple, re-ordering selection might work.') self.profileshape = list() # pylint: disable=attribute-defined-outside-init - self.offsetExtra = abs(obj.OffsetExtra.Value) + self.offsetExtra = obj.OffsetExtra.Value # abs(obj.OffsetExtra.Value) if PathLog.getLevel(PathLog.thisModule()) == 4: + for grpNm in ['tmpDebugGrp', 'tmpDebugGrp001']: + if hasattr(FreeCAD.ActiveDocument, grpNm): + for go in FreeCAD.ActiveDocument.getObject(grpNm).Group: + FreeCAD.ActiveDocument.removeObject(go.Name) + FreeCAD.ActiveDocument.removeObject(grpNm) self.tmpGrp = FreeCAD.ActiveDocument.addObject('App::DocumentObjectGroup', 'tmpDebugGrp') tmpGrpNm = self.tmpGrp.Name self.JOB = PathUtils.findParentJob(obj) @@ -321,8 +327,6 @@ class ObjectProfile(PathAreaOp.ObjectOp): shapes.extend(self._processEdges(obj)) if obj.Base and len(obj.Base) > 0: # The user has selected subobjects from the base. Process each. - isFace = False - isEdge = False if obj.EnableRotation != 'Off': for p in range(0, len(obj.Base)): (base, subsList) = obj.Base[p] @@ -332,12 +336,11 @@ class ObjectProfile(PathAreaOp.ObjectOp): if isinstance(shape, Part.Face): tup = self._analyzeFace(obj, base, sub, shape, subCount) allTuples.append(tup) - # Eif - # Efor + if subCount > 1: msg = translate('PathProfile', "Multiple faces in Base Geometry.") + " " msg += translate('PathProfile', "Depth settings will be applied to all faces.") - PathLog.warning(msg) + FreeCAD.Console.PrintWarning(msg) (Tags, Grps) = self.sortTuplesByIndex(allTuples, 2) # return (TagList, GroupList) subList = [] @@ -366,6 +369,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): for sub in subsList: shape = getattr(base.Shape, sub) + # only process faces here if isinstance(shape, Part.Face): faces.append(shape) if numpy.isclose(abs(shape.normalAt(0, 0).z), 1): # horizontal face @@ -382,8 +386,6 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Set initial Start and Final Depths and recalculate depthparams finDep = obj.FinalDepth.Value strDep = obj.StartDepth.Value - # if strDep > stock.Shape.BoundBox.ZMax: - # strDep = stock.Shape.BoundBox.ZMax startDepths.append(strDep) self.depthparams = self._customDepthParams(obj, strDep, finDep) @@ -409,18 +411,17 @@ class ObjectProfile(PathAreaOp.ObjectOp): finDep = profileshape.BoundBox.ZMin envDepthparams = self._customDepthParams(obj, strDep + 0.5, finDep) # only an envelope try: - # env = PathUtils.getEnvelope(base.Shape, subshape=profileshape, depthparams=envDepthparams) env = PathUtils.getEnvelope(profileshape, depthparams=envDepthparams) except Exception as ee: # pylint: disable=broad-except # PathUtils.getEnvelope() failed to return an object. - PathLog.error(translate('Path', 'Unable to create path for face(s).') + '\n{}'.format(ee)) + msg = translate('Path', 'Unable to create path for face(s).') + PathLog.error(msg + '\n{}'.format(ee)) else: tup = env, False, 'pathProfileFaces', angle, axis, strDep, finDep shapes.append(tup) elif obj.HandleMultipleFeatures == 'Individually': for shape in faces: - # profShape = Part.makeCompound([shape]) finalDep = obj.FinalDepth.Value custDepthparams = self.depthparams if obj.Side == 'Inside': @@ -429,7 +430,6 @@ class ObjectProfile(PathAreaOp.ObjectOp): finalDep = shape.BoundBox.ZMin custDepthparams = self._customDepthParams(obj, strDep + 0.5, finalDep) - # env = PathUtils.getEnvelope(base.Shape, subshape=profShape, depthparams=custDepthparams) env = PathUtils.getEnvelope(shape, depthparams=custDepthparams) tup = env, False, 'pathProfileFaces', angle, axis, strDep, finalDep shapes.append(tup) @@ -572,15 +572,15 @@ class ObjectProfile(PathAreaOp.ObjectOp): f.Placement = newPlace env = PathUtils.getEnvelope(base.Shape, subshape=f, depthparams=self.depthparams) # shapes.append((env, False)) - tup = env, False, 'ProfileEdges', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value + tup = env, False, 'Profile', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value shapes.append(tup) else: - PathLog.error(inaccessible) + PathLog.error(self.inaccessibleMsg) else: # Attempt open-edges profile if self.JOB.GeometryTolerance.Value == 0.0: msg = self.JOB.Label + '.GeometryTolerance = 0.0.' - msg += translate('PathProfileEdges', 'Please set to an acceptable value greater than zero.') + msg += translate('PathProfile', 'Please set to an acceptable value greater than zero.') PathLog.error(msg) else: cutWireObjs = False @@ -592,6 +592,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): os.Shape = flatWire os.purgeTouched() self.tmpGrp.addObject(os) + cutShp = self._getCutAreaCrossSection(obj, base, origWire, flatWire) if cutShp: cutWireObjs = self._extractPathWire(obj, base, flatWire, cutShp) @@ -603,9 +604,9 @@ class ObjectProfile(PathAreaOp.ObjectOp): tup = cW, False, 'OpenEdge', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value shapes.append(tup) else: - PathLog.error(inaccessible) + PathLog.error(self.inaccessibleMsg) else: - PathLog.error(inaccessible) + PathLog.error(self.inaccessibleMsg) # Eif # Eif # Efor @@ -664,9 +665,10 @@ class ObjectProfile(PathAreaOp.ObjectOp): extLenFwd = sdv - fdv if extLenFwd <= 0.0: msg = translate('PathProfile', - 'For open edges, select top edge and set Final Depth manually.') + 'For open edges, verify Final Depth for this operation.') FreeCAD.Console.PrintError(msg + '\n') - return False + # return False + extLenFwd = 0.1 WIRE = flatWire.Wires[0] numEdges = len(WIRE.Edges) @@ -686,10 +688,6 @@ class ObjectProfile(PathAreaOp.ObjectOp): cntr = vectDist.multiply(0.5).add(pb) R = diam / 2 - pl = FreeCAD.Placement() - pl.Rotation = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0) - pl.Base = FreeCAD.Vector(0, 0, 0) - # Obtain beginning point perpendicular points if blen > 0.1: bcp = begE.valueAt(begE.getParameterByLength(0.1)) # point returned 0.1 mm along edge @@ -738,7 +736,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): topComp = Part.makeCompound([cutArea.Faces[f] for f in topFc]) topComp.translate(FreeCAD.Vector(0, 0, fdv - topComp.BoundBox.ZMin)) # Translate face to final depth if len(botFc) > 1: - PathLog.debug('len(botFc) > 1') + # PathLog.debug('len(botFc) > 1') bndboxFace = Part.Face(extBndbox.Wires[0]) tmpFace = Part.Face(extBndbox.Wires[0]) for f in botFc: @@ -840,9 +838,17 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Add path stops at ends of wire cutShp = workShp.cut(pathStops) + if PathLog.getLevel(PathLog.thisModule()) == 4: + cs = FreeCAD.ActiveDocument.addObject('Part::Feature', 'tmpCutShape') + cs.Shape = cutShp + cs.recompute() + cs.purgeTouched() + self.tmpGrp.addObject(cs) + return cutShp def _checkTagIntersection(self, iTAG, eTAG, cutSide, tstObj): + PathLog.debug('_checkTagIntersection()') # Identify intersection of Common area and Interior Tags intCmn = tstObj.common(iTAG) @@ -880,10 +886,6 @@ class ObjectProfile(PathAreaOp.ObjectOp): cent0 = FreeCAD.Vector(frstVrt.X, frstVrt.Y, fdv) cent1 = FreeCAD.Vector(lstVrt.X, lstVrt.Y, fdv) - pl = FreeCAD.Placement() - pl.Rotation = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0) - pl.Base = FreeCAD.Vector(0, 0, 0) - # Calculate offset shape, containing cut region ofstShp = self._extractFaceOffset(obj, cutShp, False) @@ -891,7 +893,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): try: osArea = ofstShp.Area except Exception as ee: - PathLog.error('No area to offset shape returned.') + PathLog.error('No area to offset shape returned.\n{}'.format(ee)) return False if PathLog.getLevel(PathLog.thisModule()) == 4: @@ -941,7 +943,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): if w0 != w1: PathLog.warning('Offset wire endpoint indexes are not equal - w0, w1: {}, {}'.format(w0, w1)) - if PathLog.getLevel(PathLog.thisModule()) == 4: + if False and PathLog.getLevel(PathLog.thisModule()) == 4: PathLog.debug('min0i is {}.'.format(min0i)) PathLog.debug('min1i is {}.'.format(min1i)) PathLog.debug('NEAR0[{}] is {}.'.format(w0, NEAR0[w0])) @@ -978,7 +980,11 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Eif # Break offset loop into two wires - one of which is the desired profile path wire. - (edgeIdxs0, edgeIdxs1) = self._separateWireAtVertexes(mainWire, mainWire.Vertexes[vi0], mainWire.Vertexes[vi1]) + try: + (edgeIdxs0, edgeIdxs1) = self._separateWireAtVertexes(mainWire, mainWire.Vertexes[vi0], mainWire.Vertexes[vi1]) + except Exception as ee: + PathLog.error('Failed to identify offset edge.\n{}'.format(ee)) + return False edgs0 = list() edgs1 = list() for e in edgeIdxs0: @@ -1105,7 +1111,8 @@ class ObjectProfile(PathAreaOp.ObjectOp): chk4 = True FLGS[e] += v # Efor - PathLog.debug('_separateWireAtVertexes() FLGS: \n{}'.format(FLGS)) + + # PathLog.debug('_separateWireAtVertexes() FLGS: {}'.format(FLGS)) PRE = list() POST = list() @@ -1152,7 +1159,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): for e in range(0, lenFULL): f = PRE[e] if f == 1: - if begFlg is False: + if not begFlg: begFlg = True else: begIdx = e @@ -1184,7 +1191,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Efor # Eif - if PathLog.getLevel(PathLog.thisModule()) != 4: + if False and PathLog.getLevel(PathLog.thisModule()) == 4: PathLog.debug('grps[0]: {}'.format(grps[0])) PathLog.debug('grps[1]: {}'.format(grps[1])) PathLog.debug('wireIdxs[0]: {}'.format(wireIdxs[0])) @@ -1198,6 +1205,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): '''_makeCrossSection(shape, sliceZ, zHghtTrgt=None)... Creates cross-section objectc from shape. Translates cross-section to zHghtTrgt if available. Makes face shape from cross-section object. Returns face shape at zHghtTrgt.''' + PathLog.debug('_makeCrossSection()') # Create cross-section of shape and translate wires = list() slcs = shape.slice(FreeCAD.Vector(0, 0, 1), sliceZ) @@ -1212,6 +1220,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): return False def _makeExtendedBoundBox(self, wBB, bbBfr, zDep): + PathLog.debug('_makeExtendedBoundBox()') p1 = FreeCAD.Vector(wBB.XMin - bbBfr, wBB.YMin - bbBfr, zDep) p2 = FreeCAD.Vector(wBB.XMax + bbBfr, wBB.YMin - bbBfr, zDep) p3 = FreeCAD.Vector(wBB.XMax + bbBfr, wBB.YMax + bbBfr, zDep) @@ -1225,6 +1234,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): return Part.Face(Part.Wire([L1, L2, L3, L4])) def _makeIntersectionTags(self, useWire, numOrigEdges, fdv): + PathLog.debug('_makeIntersectionTags()') # Create circular probe tags around perimiter of wire extTags = list() intTags = list() @@ -1270,6 +1280,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): return (begInt, begExt, iTAG, eTAG) def _makeOffsetCircleTag(self, p1, p2, cutterRad, depth, lbl, reverse=False): + # PathLog.debug('_makeOffsetCircleTag()') pb = FreeCAD.Vector(p1.x, p1.y, 0.0) pe = FreeCAD.Vector(p2.x, p2.y, 0.0) @@ -1283,8 +1294,6 @@ class ObjectProfile(PathAreaOp.ObjectOp): perpE = FreeCAD.Vector(-1 * toMid.y, toMid.x, 0.0).multiply(-1 * cutFactor) # exterior tag extPnt = pb.add(toMid.add(perpE)) - pl = FreeCAD.Placement() - pl.Rotation = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0) # make exterior tag eCntr = extPnt.add(FreeCAD.Vector(0, 0, depth)) ecw = Part.Wire(Part.makeCircle((cutterRad / 2), eCntr).Edges[0]) @@ -1300,20 +1309,17 @@ class ObjectProfile(PathAreaOp.ObjectOp): return (intTag, extTag) def _makeStop(self, sType, pA, pB, lbl): + # PathLog.debug('_makeStop()') rad = self.radius ofstRad = self.ofstRadius extra = self.radius / 10 - pl = FreeCAD.Placement() - pl.Rotation = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0) - pl.Base = FreeCAD.Vector(0, 0, 0) - E = FreeCAD.Vector(pB.x, pB.y, 0) # endpoint C = FreeCAD.Vector(pA.x, pA.y, 0) # checkpoint lenEC = E.sub(C).Length if self.useComp is True or (self.useComp is False and self.offsetExtra != 0): - # 'L' stop shape and edge legend + # 'L' stop shape and edge map # --1-- # | | # 2 6 @@ -1325,15 +1331,15 @@ class ObjectProfile(PathAreaOp.ObjectOp): p1 = E if sType == 'BEG': p2 = self._makePerp2DVector(C, E, -0.25) # E1 - p3 = self._makePerp2DVector(p1, p2, ofstRad + 1 + extra) # E2 + p3 = self._makePerp2DVector(p1, p2, ofstRad + 1.0 + extra) # E2 p4 = self._makePerp2DVector(p2, p3, 0.25 + ofstRad + extra) # E3 - p5 = self._makePerp2DVector(p3, p4, 1 + extra) # E4 + p5 = self._makePerp2DVector(p3, p4, 1.0 + extra) # E4 p6 = self._makePerp2DVector(p4, p5, ofstRad + extra) # E5 elif sType == 'END': p2 = self._makePerp2DVector(C, E, 0.25) # E1 - p3 = self._makePerp2DVector(p1, p2, -1 * (ofstRad + 1 + extra)) # E2 + p3 = self._makePerp2DVector(p1, p2, -1 * (ofstRad + 1.0 + extra)) # E2 p4 = self._makePerp2DVector(p2, p3, -1 * (0.25 + ofstRad + extra)) # E3 - p5 = self._makePerp2DVector(p3, p4, -1 * (1 + extra)) # E4 + p5 = self._makePerp2DVector(p3, p4, -1 * (1.0 + extra)) # E4 p6 = self._makePerp2DVector(p4, p5, -1 * (ofstRad + extra)) # E5 p7 = E # E6 L1 = Part.makeLine(p1, p2) @@ -1344,7 +1350,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): L6 = Part.makeLine(p6, p7) wire = Part.Wire([L1, L2, L3, L4, L5, L6]) else: - # 'L' stop shape and edge legend + # 'L' stop shape and edge map # : # |----2-------| # 3 1