Path: Improve FindUnifiedRegion class

Improvements now identify cases where selected faces create a closed loop that creates an internal closed wire to not be processed.
Remove unnecessary comments.
Add debug statements.
This commit is contained in:
Russell Johnson
2020-06-05 00:10:56 -05:00
parent c53435cc91
commit 3c87e48b3b

View File

@@ -101,12 +101,6 @@ class PathGeometryGenerator:
self._prepareConstants()
def _prepareConstants(self):
# Apply drop cutter extra offset and set the max and min XY area of the operation
# xmin = self.shape.BoundBox.XMin
# xmax = self.shape.BoundBox.XMax
# ymin = self.shape.BoundBox.YMin
# ymax = self.shape.BoundBox.YMax
# Compute weighted center of mass of all faces combined
if self.pattern in ['Circular', 'CircularZigZag', 'Spiral']:
if self.obj.PatternCenterAt == 'CenterOfMass':
@@ -235,20 +229,6 @@ class PathGeometryGenerator:
centRot = FreeCAD.Vector(0.0, 0.0, 0.0) # Bottom left corner of face/selection/model
cAng = math.atan(self.deltaX / self.deltaY) # BoundaryBox angle
# Determine end points and create top lines
# x1 = centRot.x - self.halfDiag
# x2 = centRot.x + self.halfDiag
# diag = None
# if self.obj.CutPatternAngle == 0 or self.obj.CutPatternAngle == 180:
# diag = self.deltaY
# elif self.obj.CutPatternAngle == 90 or self.obj.CutPatternAngle == 270:
# diag = self.deltaX
# else:
# perpDist = math.cos(cAng - math.radians(self.obj.CutPatternAngle)) * self.deltaC
# diag = perpDist
# y1 = centRot.y + diag
# y2 = y1
# Create end points for set of lines to intersect with cross-section face
pntTuples = list()
for lc in range((-1 * (self.halfPasses - 1)), self.halfPasses + 1):
@@ -721,7 +701,7 @@ class ProcessSelectedFaces:
if cont:
lenIfL = len(ifL)
if self.obj.InternalFeaturesCut is False:
if not self.obj.InternalFeaturesCut:
if lenIfL == 0:
PathLog.debug(' -No internal features saved.')
else:
@@ -737,7 +717,6 @@ class ProcessSelectedFaces:
ofstVal = self._calculateOffsetValue(isHole=True)
intOfstShp = extractFaceOffset(casL, ofstVal, self.wpc)
mIFS.append(intOfstShp)
# faceOfstShp = faceOfstShp.cut(intOfstShp)
mFS = [faceOfstShp]
# Eif
@@ -1885,6 +1864,7 @@ class FindUnifiedRegions:
count[1] += 1
def _groupEdgesByLength(self):
PathLog.debug('_groupEdgesByLength()')
cont = True
threshold = self.geomToler
grp = list()
@@ -1935,6 +1915,7 @@ class FindUnifiedRegions:
self.idGroups.append(grp)
def _identifySharedEdgesByLength(self, grp):
PathLog.debug('_identifySharedEdgesByLength()')
holds = list()
cont = True
specialIndexes = []
@@ -1994,6 +1975,7 @@ class FindUnifiedRegions:
self.noSharedEdges = False
def _extractWiresFromEdges(self):
PathLog.debug('_extractWiresFromEdges()')
DATA = self.edgeData
holds = list()
lastEdge = None
@@ -2092,16 +2074,34 @@ class FindUnifiedRegions:
cont = False
# Ewhile
if len(LOOPS) > 0:
numLoops = len(LOOPS)
PathLog.debug(' -numLoops: {}.'.format(numLoops))
if numLoops > 0:
FACES = list()
for Edges in LOOPS:
for li in range(0, numLoops):
Edges = LOOPS[li]
#for e in Edges:
# self._showShape(e, 'Loop_{}_Edge'.format(li))
wire = Part.Wire(Part.__sortEdges__(Edges))
if wire.isClosed():
face = Part.Face(wire)
# This simple Part.Face() method fails to catch
# wires with tangent closed wires, or an external
# wire with one or more internal tangent wires.
# face = Part.Face(wire)
# This method works with the complex tangent
# closed wires mentioned above.
extWire = wire.extrude(FreeCAD.Vector(0.0, 0.0, 2.0))
wireSolid = Part.makeSolid(extWire)
extdBBFace1 = makeExtendedBoundBox(wireSolid.BoundBox, 5.0, wireSolid.BoundBox.ZMin + 1.0)
extdBBFace2 = makeExtendedBoundBox(wireSolid.BoundBox, 5.0, wireSolid.BoundBox.ZMin + 1.0)
inverse = extdBBFace1.cut(wireSolid)
face = extdBBFace2.cut(inverse)
self.REGIONS.append(face)
self.REGIONS.sort(key=faceArea, reverse=True)
def _identifyInternalFeatures(self):
PathLog.debug('_identifyInternalFeatures()')
remList = list()
for (top, fcIdx) in self.topFaces:
@@ -2123,6 +2123,7 @@ class FindUnifiedRegions:
self.REGIONS.pop(ri)
def _processNestedRegions(self):
PathLog.debug('_processNestedRegions()')
cont = True
hold = list()
Ids = list()
@@ -2224,6 +2225,7 @@ class FindUnifiedRegions:
def getUnifiedRegions(self):
'''getUnifiedRegions()... Returns a list of unified regions from list
of tuples (faceShape, faceIndex) received at instantiation of the class object.'''
PathLog.debug('getUnifiedRegions()')
self.INTERNALS = list()
if len(self.FACES) == 0:
msg = translate('PathSurfaceSupport',
@@ -2233,7 +2235,6 @@ class FindUnifiedRegions:
self._extractTopFaces()
lenFaces = len(self.topFaces)
PathLog.debug('getUnifiedRegions() lenFaces: {}.'.format(lenFaces))
if lenFaces == 0:
return []
@@ -2245,22 +2246,12 @@ class FindUnifiedRegions:
lenWrs = len(topFace.Wires)
if lenWrs > 1:
for w in range(1, lenWrs):
# Any internal wires need to be flattened
# before appending to self.INTERNALS
# A problem exists that inner wires are not all recognized as wires.
# Some are single circular edges.
# Face.Edges.__len_() - Face.OuterWire.Edges.__len__() = edges for inner wire(s)
# extWire = getExtrudedShape(wr)
# wCS = getCrossSection(extWire)
# wCS.translate(FreeCAD.Vector(0.0, 0.0, wr.BoundBox.ZMin))
wr = topFace.Wires[w]
self.INTERNALS.append(Part.Face(wr))
# Flatten face and extract outer wire, then convert to face
extWire = getExtrudedShape(topFace)
wCS = getCrossSection(extWire)
if wCS:
wCS.translate(FreeCAD.Vector(0.0, 0.0, topFace.BoundBox.ZMin))
face = Part.Face(wCS)
return [face]
else:
@@ -2273,8 +2264,8 @@ class FindUnifiedRegions:
# process multiple top faces, unifying if possible
self._fuseTopFaces()
# for F in self.fusedFaces.Faces:
# self._showShape(F, 'TopFaceFused')
for F in self.fusedFaces.Faces:
self._showShape(F, 'TopFaceFused')
self._getEdgesData()
self._groupEdgesByLength()
@@ -2282,7 +2273,7 @@ class FindUnifiedRegions:
self._identifySharedEdgesByLength(grp)
if self.noSharedEdges:
PathLog.debug('No shared edges by length detected.\n')
PathLog.debug('No shared edges by length detected.')
return [topFace for (topFace, fcIdx) in self.topFaces]
else:
# Delete shared edges from edgeData list
@@ -2293,8 +2284,8 @@ class FindUnifiedRegions:
self._extractWiresFromEdges()
self._identifyInternalFeatures()
self._processNestedRegions()
for ri in range(0, len(self.REGIONS)):
self._showShape(self.REGIONS[ri], 'UnifiedRegion_{}'.format(ri))
# for ri in range(0, len(self.REGIONS)):
# self._showShape(self.REGIONS[ri], 'UnifiedRegion_{}'.format(ri))
return self.REGIONS
@@ -2308,3 +2299,18 @@ class FindUnifiedRegions:
FreeCAD.Console.PrintError(msg + '\n')
return False
# Eclass
# Support functions
def makeExtendedBoundBox(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)
p4 = FreeCAD.Vector(wBB.XMin - bbBfr, wBB.YMax + bbBfr, zDep)
L1 = Part.makeLine(p1, p2)
L2 = Part.makeLine(p2, p3)
L3 = Part.makeLine(p3, p4)
L4 = Part.makeLine(p4, p1)
return Part.Face(Part.Wire([L1, L2, L3, L4]))