Arch: Fix baseface generation for walls with a trace that self-intersects, has T-connections or that overlaps
This commit is contained in:
@@ -1351,7 +1351,7 @@ class _Wall(ArchComponent.Component):
|
||||
|
||||
if not DraftVecUtils.isNull(dvec):
|
||||
dvec.normalize()
|
||||
sh = None
|
||||
face = None
|
||||
|
||||
curAligns = aligns[0]
|
||||
off = obj.Offset.Value
|
||||
@@ -1399,7 +1399,7 @@ class _Wall(ArchComponent.Component):
|
||||
normal=normal,
|
||||
basewireOffset=off)
|
||||
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
face = DraftGeomUtils.bind(w1, w2, per_segment=True)
|
||||
|
||||
elif curAligns == "Right":
|
||||
dvec = dvec.negative()
|
||||
@@ -1440,7 +1440,7 @@ class _Wall(ArchComponent.Component):
|
||||
normal=normal,
|
||||
basewireOffset=off)
|
||||
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
face = DraftGeomUtils.bind(w1, w2, per_segment=True)
|
||||
|
||||
#elif obj.Align == "Center":
|
||||
elif curAligns == "Center":
|
||||
@@ -1473,18 +1473,16 @@ class _Wall(ArchComponent.Component):
|
||||
alignList=aligns,
|
||||
normal=normal,
|
||||
basewireOffset=off)
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
face = DraftGeomUtils.bind(w1, w2, per_segment=True)
|
||||
|
||||
del widths[0:edgeNum]
|
||||
del aligns[0:edgeNum]
|
||||
if sh:
|
||||
if face:
|
||||
|
||||
if layers and (layers[i] < 0):
|
||||
# layers with negative values are not drawn
|
||||
continue
|
||||
|
||||
sh.fix(0.1,0,1) # fixes self-intersecting wires
|
||||
f = Part.Face(sh)
|
||||
if baseface:
|
||||
|
||||
# To allow exportIFC.py to work properly on
|
||||
@@ -1505,14 +1503,14 @@ class _Wall(ArchComponent.Component):
|
||||
# - 1st finding : if a rectangle + 1 line, can't removesSplitter properly...
|
||||
# - 2nd finding : if 2 faces do not touch, can't form a shell; then, subsequently for remaining faces even though touch each faces, can't form a shell
|
||||
|
||||
baseface.append(f)
|
||||
baseface.append(face)
|
||||
# The above make Refine methods below (in else) useless, regardless removeSpitters yet to be improved for cases do not work well
|
||||
''' Whether layers or not, all baseface.append(f) '''
|
||||
''' Whether layers or not, all baseface.append(face) '''
|
||||
|
||||
else:
|
||||
baseface = [f]
|
||||
baseface = [face]
|
||||
|
||||
''' Whether layers or not, all baseface = [f] '''
|
||||
''' Whether layers or not, all baseface = [face] '''
|
||||
|
||||
if baseface:
|
||||
base,placement = self.rebase(baseface)
|
||||
|
||||
@@ -110,32 +110,58 @@ def is_coplanar(faces, tol=-1):
|
||||
isCoplanar = is_coplanar
|
||||
|
||||
|
||||
def bind(w1, w2):
|
||||
"""Bind 2 wires by their endpoints and returns a face."""
|
||||
if not w1 or not w2:
|
||||
print("DraftGeomUtils: unable to bind wires")
|
||||
return None
|
||||
def bind(w1, w2, per_segment=False):
|
||||
"""Bind 2 wires by their endpoints and returns a face.
|
||||
|
||||
if w1.isClosed() and w2.isClosed():
|
||||
d1 = w1.BoundBox.DiagonalLength
|
||||
d2 = w2.BoundBox.DiagonalLength
|
||||
if d1 > d2:
|
||||
# w2.reverse()
|
||||
return Part.Face([w1, w2])
|
||||
else:
|
||||
# w1.reverse()
|
||||
return Part.Face([w2, w1])
|
||||
else:
|
||||
If per_segment is True and the wires have the same number of edges, the
|
||||
wires are processed per segment: a separate face is created for each pair
|
||||
of edges (one from w1 and one from w2), and the faces are then fused. This
|
||||
avoids problems with walls based on wires that selfintersect, or that have
|
||||
a loop that ends in a T-connection (f.e. a wire shaped like a number 6).
|
||||
"""
|
||||
|
||||
def create_face(w1, w2):
|
||||
try:
|
||||
w3 = Part.LineSegment(w1.Vertexes[0].Point,
|
||||
w2.Vertexes[0].Point).toShape()
|
||||
w4 = Part.LineSegment(w1.Vertexes[-1].Point,
|
||||
w2.Vertexes[-1].Point).toShape()
|
||||
return Part.Face(Part.Wire(w1.Edges+[w3] + w2.Edges+[w4]))
|
||||
return Part.Face(Part.Wire(w1.Edges + [w3] + w2.Edges + [w4]))
|
||||
except Part.OCCError:
|
||||
print("DraftGeomUtils: unable to bind wires")
|
||||
return None
|
||||
|
||||
if not w1 or not w2:
|
||||
print("DraftGeomUtils: unable to bind wires")
|
||||
return None
|
||||
|
||||
if (per_segment
|
||||
and len(w1.Edges) > 1
|
||||
and len(w1.Edges) == len(w2.Edges)):
|
||||
faces = []
|
||||
for (edge1, edge2) in zip(w1.Edges, w2.Edges):
|
||||
face = create_face(edge1, edge2)
|
||||
if face is None:
|
||||
return None
|
||||
faces.append(face)
|
||||
# return concatenate(faces[0].fuse(faces[1:])) # Also works.
|
||||
return faces[0].fuse(faces[1:]).removeSplitter().Faces[0]
|
||||
elif w1.isClosed() and w2.isClosed():
|
||||
d1 = w1.BoundBox.DiagonalLength
|
||||
d2 = w2.BoundBox.DiagonalLength
|
||||
if d1 < d2:
|
||||
w1, w2 = w2, w1
|
||||
# return Part.Face(w1).cut(Part.Face(w2)).Faces[0] # Only works if wires do not self-intersect.
|
||||
try:
|
||||
face = Part.Face([w1, w2])
|
||||
face.fix(1e-7, 0, 1)
|
||||
return face
|
||||
except Part.OCCError:
|
||||
print("DraftGeomUtils: unable to bind wires")
|
||||
return None
|
||||
else:
|
||||
return create_face(w1, w2)
|
||||
|
||||
|
||||
def cleanFaces(shape):
|
||||
"""Remove inner edges from coplanar faces."""
|
||||
|
||||
Reference in New Issue
Block a user