some DumbWallJoiner.join() refactor

This commit is contained in:
Andrej730
2023-09-07 18:36:19 +05:00
parent 0ea38384cc
commit 09620e060f
2 changed files with 55 additions and 35 deletions
@@ -1119,8 +1119,13 @@ class DumbWallJoiner:
other = tool.Ifc.get_object(rel.RelatedElement)
if connection not in ["ATPATH", "NOTDEFINED"]:
self.join(
obj, other, connection, rel.RelatedConnectionType, is_relating=True, description=rel.Description
)
obj,
other,
connection,
rel.RelatedConnectionType,
is_relating=True,
description=rel.Description
)
for rel in element.ConnectedFrom:
if rel.is_a("IfcRelConnectsPathElements"):
connection = rel.RelatedConnectionType
@@ -1299,7 +1304,7 @@ class DumbWallJoiner:
# The user has moved the wall into an invalid position that cannot connect at the desired end
return False
self.axis[1 if connection1 == "ATEND" else 0] = intersect
self.axis = proposed_axis
# Work out body
@@ -1309,55 +1314,65 @@ class DumbWallJoiner:
tp1 = wall1.matrix_world @ Vector(wall1.bound_box[1])
# Axis lines on bottom, for reference, base, and side axes
bra1 = (Vector((*axis1["reference"][0], bp1[2])), Vector((*axis1["reference"][1], bp1[2])))
bba1 = (Vector((*axis1["base"][0], bp1[2])), Vector((*axis1["base"][1], bp1[2])))
bsa1 = (Vector((*axis1["side"][0], bp1[2])), Vector((*axis1["side"][1], bp1[2])))
bba2 = (Vector((*axis2["base"][0], bp2[2])), Vector((*axis2["base"][1], bp2[2])))
bsa2 = (Vector((*axis2["side"][0], bp2[2])), Vector((*axis2["side"][1], bp2[2])))
def to_3d_axis(axis, z):
return (Vector((*axis[0], z)), Vector((*axis[1], z)))
bra1 = to_3d_axis(axis1["reference"], bp1.z)
bba1 = to_3d_axis(axis1["base"], bp1.z)
bsa1 = to_3d_axis(axis1["side"], bp1.z)
bba2 = to_3d_axis(axis2["base"], bp2.z)
bsa2 = to_3d_axis(axis2["side"], bp2.z)
# Intersecting the walls sides defined by planes gives 4 lines of intersection
# Line point, and line direction
lp1, ld1 = mathutils.geometry.intersect_plane_plane(bba1[0], normal1, bba2[0], normal2)
lp2, ld2 = mathutils.geometry.intersect_plane_plane(bba1[0], normal1, bsa2[0], normal2)
lp3, ld3 = mathutils.geometry.intersect_plane_plane(bsa1[0], normal1, bba2[0], normal2)
lp4, ld4 = mathutils.geometry.intersect_plane_plane(bsa1[0], normal1, bsa2[0], normal2)
lpb1, ldb1 = mathutils.geometry.intersect_plane_plane(bba1[0], normal1, bba2[0], normal2)
lpb2, ldb2 = mathutils.geometry.intersect_plane_plane(bba1[0], normal1, bsa2[0], normal2)
lps1, lds1 = mathutils.geometry.intersect_plane_plane(bsa1[0], normal1, bba2[0], normal2)
lps2, lds2 = mathutils.geometry.intersect_plane_plane(bsa1[0], normal1, bsa2[0], normal2)
# Intersecting the 4 lines gives the 8 possible verts of intersection
# 4 on bottom, and 4 on top. 4 on our base line, 4 on our side line.
bb1 = mathutils.geometry.intersect_line_plane(lp1, lp1 + ld1, bp1, Vector((0, 0, 1)))
bb2 = mathutils.geometry.intersect_line_plane(lp2, lp2 + ld2, bp1, Vector((0, 0, 1)))
bs1 = mathutils.geometry.intersect_line_plane(lp3, lp3 + ld3, bp1, Vector((0, 0, 1)))
bs2 = mathutils.geometry.intersect_line_plane(lp4, lp4 + ld4, bp1, Vector((0, 0, 1)))
tb1 = mathutils.geometry.intersect_line_plane(lp1, lp1 + ld1, tp1, Vector((0, 0, 1)))
tb2 = mathutils.geometry.intersect_line_plane(lp2, lp2 + ld2, tp1, Vector((0, 0, 1)))
ts1 = mathutils.geometry.intersect_line_plane(lp3, lp3 + ld3, tp1, Vector((0, 0, 1)))
ts2 = mathutils.geometry.intersect_line_plane(lp4, lp4 + ld4, tp1, Vector((0, 0, 1)))
# Diagram: https://i.imgur.com/jwWx2Ox.png
# NOTE: bb/bs always equal lpb/lps?
bb1 = mathutils.geometry.intersect_line_plane(lpb1, lpb1 + ldb1, bp1, Vector((0, 0, 1)))
bb2 = mathutils.geometry.intersect_line_plane(lpb2, lpb2 + ldb2, bp1, Vector((0, 0, 1)))
bs1 = mathutils.geometry.intersect_line_plane(lps1, lps1 + lds1, bp1, Vector((0, 0, 1)))
bs2 = mathutils.geometry.intersect_line_plane(lps2, lps2 + lds2, bp1, Vector((0, 0, 1)))
# similar to bb/bs but also have local z offset
tb1 = mathutils.geometry.intersect_line_plane(lpb1, lpb1 + ldb1, tp1, Vector((0, 0, 1)))
tb2 = mathutils.geometry.intersect_line_plane(lpb2, lpb2 + ldb2, tp1, Vector((0, 0, 1)))
ts1 = mathutils.geometry.intersect_line_plane(lps1, lps1 + lds1, tp1, Vector((0, 0, 1)))
ts2 = mathutils.geometry.intersect_line_plane(lps2, lps2 + lds2, tp1, Vector((0, 0, 1)))
# Let's distinguish the 8 points by whether they are nearer or further away from the other end
# These 8 points will be used to find the final body position and clippings.
i = 0 if connection1 == "ATEND" else 1
j = 1 if connection1 == "ATEND" else 0
bbn = tool.Cad.closest_vector(axis1["base"][i].to_3d(), (bb1, bb2))
bbf = bb2 if bbn == bb1 else bb1
bsn = tool.Cad.closest_vector(axis1["side"][i].to_3d(), (bs1, bs2))
bsf = bs2 if bsn == bs1 else bs1
tbn = tool.Cad.closest_vector(axis1["base"][i].to_3d(), (tb1, tb2))
tbf = tb2 if tbn == tb1 else tb1
tsn = tool.Cad.closest_vector(axis1["side"][i].to_3d(), (ts1, ts2))
tsf = ts2 if tsn == ts1 else ts1
connected_at_end = connection1 == "ATEND"
i = 0 if connected_at_end else 1
def get_closest_and_furthest_vectors(point_2d, vectors):
closest = tool.Cad.closest_vector(point_2d.to_3d(), vectors)
farthest = vectors[1] if closest == vectors[0] else vectors[0]
return closest, farthest
bbn, bbf = get_closest_and_furthest_vectors(axis1["base"][i], (bb1, bb2))
bsn, bsf = get_closest_and_furthest_vectors(axis1["side"][i], (bs1, bs2))
tbn, tbf = get_closest_and_furthest_vectors(axis1["base"][i], (tb1, tb2))
tsn, tsf = get_closest_and_furthest_vectors(axis1["side"][i], (ts1, ts2))
j = 1 if connected_at_end else 0
if description == "MITRE":
# Mitre joints are an unofficial convention
bsf_ = tool.Cad.point_on_edge(bsf, bba1)
tbf_ = tool.Cad.point_on_edge(tbf, bba1)
tsf_ = tool.Cad.point_on_edge(tsf, bba1)
new_body = tool.Cad.furthest_vector(bba1[i], (bbf, bsf_)).copy()
new_body = tool.Cad.furthest_vector(bba1[i], (new_body, tbf_)).copy()
new_body = tool.Cad.furthest_vector(bba1[i], (bbf, bsf_))
new_body = tool.Cad.furthest_vector(bba1[i], (new_body, tbf_))
new_body = tool.Cad.furthest_vector(bba1[i], (new_body, tsf_)).copy()
self.body[j] = tool.Cad.point_on_edge(new_body, bra1).to_2d()
if connection1 == connection2:
if (connection1 == "ATEND" and angle > 0) or (connection1 != "ATEND" and angle < 0):
if (connected_at_end and angle > 0) or (not connected_at_end and angle < 0):
pt = bbf.to_2d().to_3d()
x_axis = bsn - bbf
y_axis = tbf - bbf
@@ -1366,7 +1381,7 @@ class DumbWallJoiner:
x_axis = bsf - bbn
y_axis = tbn - bbn
else:
if (connection1 == "ATEND" and angle < 0) or (connection1 != "ATEND" and angle > 0):
if (connected_at_end and angle < 0) or (not connected_at_end and angle > 0):
pt = bbf.to_2d().to_3d()
x_axis = bsn - bbf
y_axis = tbf - bbf
@@ -300,7 +300,12 @@ class BimToolUI:
add_layout_hotkey_operator(cls.layout, "Extend", "S_E", "")
add_layout_hotkey_operator(cls.layout, "Butt", "S_T", "")
add_layout_hotkey_operator(cls.layout, "Mitre", "S_Y", "")
add_layout_hotkey_operator(
cls.layout,
"Mitre",
"S_Y",
"Join two intersecting walls using a mitre joint.\nOther selected wall is connected to the active",
)
add_layout_hotkey_operator(cls.layout, "Merge", "S_M", bpy.ops.bim.merge_wall.__doc__)
add_layout_hotkey_operator(cls.layout, "Flip", "S_F", bpy.ops.bim.flip_wall.__doc__)