ArchWall_DraftGeomUtils Multi-Width support added
Discussion:- https://forum.freecadweb.org/viewtopic.php?f=23&t=36772&p=319829#p319829
This commit is contained in:
committed by
Yorik van Havre
parent
bbdbe0e491
commit
b7907e0fd8
@@ -534,6 +534,11 @@ class _Wall(ArchComponent.Component):
|
||||
obj.addProperty("App::PropertyLength","Length","Wall",QT_TRANSLATE_NOOP("App::Property","The length of this wall. Not used if this wall is based on an underlying object"))
|
||||
if not "Width" in lp:
|
||||
obj.addProperty("App::PropertyLength","Width","Wall",QT_TRANSLATE_NOOP("App::Property","The width of this wall. Not used if this wall is based on a face"))
|
||||
|
||||
# To be combined into Width when PropertyLengthList is available
|
||||
if not "WidthsOfWall" in lp:
|
||||
obj.addProperty("App::PropertyFloatList","WidthsOfWall","Wall",QT_TRANSLATE_NOOP("App::Property","The widths of each segment of wall (The 1st value override 'Width' attribute for 1st segment of wall; if a value is zero, 1st value of 'WidthsOfWall' attribute will be followed)")) # see DraftGeomUtils.offsetwire()
|
||||
|
||||
if not "Height" in lp:
|
||||
obj.addProperty("App::PropertyLength","Height","Wall",QT_TRANSLATE_NOOP("App::Property","The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid"))
|
||||
if not "Align" in lp:
|
||||
@@ -790,7 +795,19 @@ class _Wall(ArchComponent.Component):
|
||||
# multifuses not considered here
|
||||
return data
|
||||
length = obj.Length.Value
|
||||
width = obj.Width.Value
|
||||
|
||||
# TODO currently layers were not supported when len(basewires) > 0
|
||||
width = 0
|
||||
if obj.WidthsOfWall:
|
||||
if obj.WidthsOfWall[0]:
|
||||
width = obj.WidthsOfWall[0]
|
||||
if not width:
|
||||
if obj.Width:
|
||||
width = obj.Width.Value
|
||||
else:
|
||||
print("Width or Widths Of Wall [0] should not be 0")
|
||||
return
|
||||
|
||||
height = obj.Height.Value
|
||||
if not height:
|
||||
for p in obj.InList:
|
||||
@@ -861,7 +878,8 @@ class _Wall(ArchComponent.Component):
|
||||
for c in Part.sortEdges(cluster):
|
||||
self.basewires.append(Part.Wire(c))
|
||||
|
||||
if self.basewires and width:
|
||||
if self.basewires: # and width: # width already tested earlier...
|
||||
|
||||
if (len(self.basewires) == 1) and layers:
|
||||
self.basewires = [self.basewires[0] for l in layers]
|
||||
layeroffset = 0
|
||||
@@ -886,7 +904,9 @@ class _Wall(ArchComponent.Component):
|
||||
if off:
|
||||
dvec2 = DraftVecUtils.scaleTo(dvec,off)
|
||||
wire = DraftGeomUtils.offsetWire(wire,dvec2)
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec)
|
||||
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec,False, False, obj.WidthsOfWall)
|
||||
|
||||
w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
elif obj.Align == "Right":
|
||||
@@ -901,7 +921,9 @@ class _Wall(ArchComponent.Component):
|
||||
if off:
|
||||
dvec2 = DraftVecUtils.scaleTo(dvec,off)
|
||||
wire = DraftGeomUtils.offsetWire(wire,dvec2)
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec)
|
||||
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec,False, False, obj.WidthsOfWall)
|
||||
|
||||
w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
elif obj.Align == "Center":
|
||||
@@ -914,10 +936,13 @@ class _Wall(ArchComponent.Component):
|
||||
d1 = Vector(dvec).multiply(off)
|
||||
w2 = DraftGeomUtils.offsetWire(wire,d1)
|
||||
else:
|
||||
dvec.multiply(width/2)
|
||||
w1 = DraftGeomUtils.offsetWire(wire,dvec)
|
||||
dvec.multiply(width/2) ## TODO width Value should be of no use (width/2), width Direction remains 'in use'
|
||||
|
||||
widthsOfWallHalfen = [i/2 for i in obj.WidthsOfWall]
|
||||
w1 = DraftGeomUtils.offsetWire(wire,dvec,False, False, widthsOfWallHalfen)
|
||||
dvec = dvec.negative()
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec)
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec,False, False, widthsOfWallHalfen)
|
||||
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
if sh:
|
||||
sh.fix(0.1,0,1) # fixes self-intersecting wires
|
||||
|
||||
@@ -1171,14 +1171,24 @@ def calculatePlacement(shape):
|
||||
pla.Rotation = r
|
||||
return pla
|
||||
|
||||
def offsetWire(wire,dvec,bind=False,occ=False):
|
||||
def offsetWire(wire,dvec,bind=False,occ=False,widthList=None):
|
||||
'''
|
||||
offsetWire(wire,vector,[bind]): offsets the given wire along the
|
||||
given vector. The vector will be applied at the first vertex of
|
||||
the wire. If bind is True (and the shape is open), the original
|
||||
wire and the offsetted one are bound by 2 edges, forming a face.
|
||||
|
||||
If widthList is provided (values only, not lengths - i.e. no unit),
|
||||
each value will be used to offset each corresponding edge in the wire
|
||||
|
||||
(The 1st value override 'dvec' for 1st segement of wire;
|
||||
if a value is zero, value of 'widthList[0]' will follow;
|
||||
if widthList[0]' == 0, but dvec still provided, dvec will be followed)
|
||||
'''
|
||||
|
||||
## TODO In future, 'vector' direction to offset could be 'calculated' in this function - if 'direction' in dvec is not / need not be provided 'outside' the function
|
||||
## 'dvec' to be obsolete in future ?
|
||||
|
||||
edges = wire.Edges # Seems has repeatedly sortEdges, remark out here - edges = Part.__sortEdges__(wire.Edges)
|
||||
norm = getNormal(wire)
|
||||
closed = isReallyClosed(wire)
|
||||
@@ -1206,14 +1216,39 @@ def offsetWire(wire,dvec,bind=False,occ=False):
|
||||
|
||||
for i in range(len(edges)):
|
||||
curredge = edges[i]
|
||||
delta = dvec
|
||||
|
||||
if widthList:
|
||||
try:
|
||||
if widthList[i] > 0:
|
||||
delta = DraftVecUtils.scaleTo(dvec, widthList[i])
|
||||
elif widthList[0] > 0:
|
||||
delta = DraftVecUtils.scaleTo(dvec, widthList[0]) # to follow widthList[0]
|
||||
|
||||
# i.e. if widthList[0] == 0, though widthList is not False
|
||||
# but if dev is provided still, fallback to dvec
|
||||
elif dvec:
|
||||
delta = dvec
|
||||
|
||||
else:
|
||||
return None
|
||||
except:
|
||||
if widthList[0] > 0:
|
||||
delta = DraftVecUtils.scaleTo(dvec, widthList[0]) # to follow widthList[0]
|
||||
delta = dvec
|
||||
else:
|
||||
delta = dvec
|
||||
|
||||
if i != 0:
|
||||
if isinstance(curredge.Curve,Part.Circle):
|
||||
v = curredge.tangentAt(curredge.FirstParameter)
|
||||
else:
|
||||
v = vec(curredge)
|
||||
|
||||
## TODO - 2019.6.16 - 'calculate' 'offset' direction (in vector) edge by edge instead of rotating previous vector based on dvec in future
|
||||
|
||||
angle = DraftVecUtils.angle(firstVec,v,norm) # use vec deduced depending on geometry instead of - angle = DraftVecUtils.angle(vec(edges[0]),v,norm)
|
||||
delta = DraftVecUtils.rotate(delta,angle,norm)
|
||||
|
||||
#print("edge ",i,": ",curredge.Curve," ",curredge.Orientation," parameters:",curredge.ParameterRange," vector:",delta)
|
||||
nedge = offset(curredge,delta,trim=True)
|
||||
if not nedge:
|
||||
@@ -1259,16 +1294,23 @@ def connect(edges,closed=False):
|
||||
if prev:
|
||||
#print("debug: DraftGeomUtils.connect prev : ",prev.Vertexes[0].Point,prev.Vertexes[-1].Point)
|
||||
|
||||
# If prev v2 had been calculated, do not calculate again, just use it as current v1 - avoid chance of slight difference in result
|
||||
if v2:
|
||||
v1 = v2
|
||||
# If the edge pairs has intersection
|
||||
# ... and if there is prev v2 (prev v2 was caculated intersection), do not calculate again, just use it as current v1 - avoid chance of slight difference in result
|
||||
# Otherwise, if edge pairs has no intersection (parallel edges, line - arc do no intersect, etc.), so just just current edge endpoints as v1
|
||||
# ... and connect these 2 non-intersecting edges
|
||||
|
||||
else:
|
||||
i = findIntersection(curr,prev,True,True)
|
||||
if i:
|
||||
# seem have chance that 2 parallel edges offset same width, result in 2 colinear edges - Wall / DraftGeomUtils seem make them 1 edge and thus 1 vertical plane
|
||||
i = findIntersection(curr,prev,True,True)
|
||||
if i:
|
||||
if v2:
|
||||
v1 = v2
|
||||
else:
|
||||
v1 = i[DraftVecUtils.closest(curr.Vertexes[0].Point,i)]
|
||||
else:
|
||||
else:
|
||||
v1 = curr.Vertexes[0].Point
|
||||
|
||||
nedges.append(Part.LineSegment(v2,v1).toShape())
|
||||
|
||||
else:
|
||||
v1 = curr.Vertexes[0].Point
|
||||
if next:
|
||||
|
||||
Reference in New Issue
Block a user