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:
@@ -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]))
|
||||
|
||||
Reference in New Issue
Block a user