mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
Filled openings now handle offset wall axes
This commit is contained in:
@@ -64,9 +64,10 @@ class AddFilledOpening(bpy.types.Operator, tool.Ifc.Operator):
|
||||
if not raycast[0]:
|
||||
return {"FINISHED"}
|
||||
|
||||
axis = [voided_obj.matrix_world @ Vector((0, 0, 0)), voided_obj.matrix_world @ Vector((1, 0, 0))]
|
||||
|
||||
# In this prototype, we assume openings are only added to axis-based elements
|
||||
layers = tool.Model.get_material_layer_parameters(element)
|
||||
axis = tool.Model.get_wall_axis(voided_obj, layers=layers)["base"]
|
||||
|
||||
new_matrix = voided_obj.matrix_world.copy()
|
||||
new_matrix.col[3] = tool.Cad.point_on_edge(target, axis).to_4d()
|
||||
if not filling.is_a("IfcDoor"):
|
||||
|
||||
@@ -404,7 +404,7 @@ class DumbWallGenerator:
|
||||
|
||||
def generate(self, link_to_scene=True):
|
||||
self.file = IfcStore.get_file()
|
||||
self.layers = get_material_layer_parameters(self.relating_type)
|
||||
self.layers = tool.Model.get_material_layer_parameters(self.relating_type)
|
||||
if not self.layers["thickness"]:
|
||||
return
|
||||
|
||||
@@ -698,7 +698,7 @@ class DumbWallJoiner:
|
||||
ifcopenshell.api.run("geometry.disconnect_path", tool.Ifc.get(), element=element1, connection_type="ATSTART")
|
||||
ifcopenshell.api.run("geometry.disconnect_path", tool.Ifc.get(), element=element1, connection_type="ATEND")
|
||||
|
||||
axis1 = self.get_wall_axis(wall1)
|
||||
axis1 = tool.Model.get_wall_axis(wall1)
|
||||
axis = copy.deepcopy(axis1["reference"])
|
||||
body = copy.deepcopy(axis1["reference"])
|
||||
self.recreate_wall(element1, wall1, axis, body)
|
||||
@@ -707,7 +707,7 @@ class DumbWallJoiner:
|
||||
element1 = tool.Ifc.get_entity(wall1)
|
||||
if not element1:
|
||||
return
|
||||
axis1 = self.get_wall_axis(wall1)
|
||||
axis1 = tool.Model.get_wall_axis(wall1)
|
||||
axis2 = copy.deepcopy(axis1)
|
||||
intersect, connection = mathutils.geometry.intersect_point_line(target.to_2d(), *axis1["reference"])
|
||||
if connection < 0 or connection > 1 or tool.Cad.is_x(connection, (0, 1)):
|
||||
@@ -738,7 +738,7 @@ class DumbWallJoiner:
|
||||
if rel.RelatedConnectionType in ["ATSTART", "ATEND"]:
|
||||
rel.RelatedConnectionType = "ATSTART" if rel.RelatedConnectionType == "ATEND" else "ATEND"
|
||||
|
||||
axis1 = self.get_wall_axis(wall1)
|
||||
axis1 = tool.Model.get_wall_axis(wall1)
|
||||
axis1["reference"][0], axis1["reference"][1] = axis1["reference"][1], axis1["reference"][0]
|
||||
|
||||
flip_matrix = Matrix.Rotation(pi, 4, "Z")
|
||||
@@ -751,8 +751,8 @@ class DumbWallJoiner:
|
||||
def merge(self, wall1, wall2):
|
||||
element1 = tool.Ifc.get_entity(wall1)
|
||||
element2 = tool.Ifc.get_entity(wall2)
|
||||
axis1 = self.get_wall_axis(wall1)
|
||||
axis2 = self.get_wall_axis(wall2)
|
||||
axis1 = tool.Model.get_wall_axis(wall1)
|
||||
axis2 = tool.Model.get_wall_axis(wall2)
|
||||
|
||||
angle = tool.Cad.angle_edges(axis1["reference"], axis2["reference"], signed=False, degrees=True)
|
||||
if not tool.Cad.is_x(angle, 0, tolerance=0.001):
|
||||
@@ -816,8 +816,8 @@ class DumbWallJoiner:
|
||||
def join_L(self, wall1, wall2):
|
||||
element1 = tool.Ifc.get_entity(wall1)
|
||||
element2 = tool.Ifc.get_entity(wall2)
|
||||
axis1 = self.get_wall_axis(wall1)
|
||||
axis2 = self.get_wall_axis(wall2)
|
||||
axis1 = tool.Model.get_wall_axis(wall1)
|
||||
axis2 = tool.Model.get_wall_axis(wall2)
|
||||
intersect = tool.Cad.intersect_edges(axis1["reference"], axis2["reference"])
|
||||
if intersect:
|
||||
intersect, _ = intersect
|
||||
@@ -844,7 +844,7 @@ class DumbWallJoiner:
|
||||
if not element1:
|
||||
return
|
||||
|
||||
axis1 = self.get_wall_axis(wall1)
|
||||
axis1 = tool.Model.get_wall_axis(wall1)
|
||||
intersect, connection = mathutils.geometry.intersect_point_line(target.to_2d(), *axis1["reference"])
|
||||
connection = "ATEND" if connection > 0.5 else "ATSTART"
|
||||
|
||||
@@ -864,7 +864,7 @@ class DumbWallJoiner:
|
||||
|
||||
ifcopenshell.api.run("geometry.disconnect_path", tool.Ifc.get(), element=element1, connection_type="ATEND")
|
||||
|
||||
axis1 = self.get_wall_axis(wall1)
|
||||
axis1 = tool.Model.get_wall_axis(wall1)
|
||||
axis = copy.deepcopy(axis1["reference"])
|
||||
body = copy.deepcopy(axis1["reference"])
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
@@ -877,8 +877,8 @@ class DumbWallJoiner:
|
||||
def join_T(self, wall1, wall2):
|
||||
element1 = tool.Ifc.get_entity(wall1)
|
||||
element2 = tool.Ifc.get_entity(wall2)
|
||||
axis1 = self.get_wall_axis(wall1)
|
||||
axis2 = self.get_wall_axis(wall2)
|
||||
axis1 = tool.Model.get_wall_axis(wall1)
|
||||
axis2 = tool.Model.get_wall_axis(wall2)
|
||||
intersect = tool.Cad.intersect_edges(axis1["reference"], axis2["reference"])
|
||||
if intersect:
|
||||
intersect, _ = intersect
|
||||
@@ -901,8 +901,8 @@ class DumbWallJoiner:
|
||||
def join_V(self, wall1, wall2):
|
||||
element1 = tool.Ifc.get_entity(wall1)
|
||||
element2 = tool.Ifc.get_entity(wall2)
|
||||
axis1 = self.get_wall_axis(wall1)
|
||||
axis2 = self.get_wall_axis(wall2)
|
||||
axis1 = tool.Model.get_wall_axis(wall1)
|
||||
axis2 = tool.Model.get_wall_axis(wall2)
|
||||
intersect = tool.Cad.intersect_edges(axis1["reference"], axis2["reference"])
|
||||
if intersect:
|
||||
intersect, _ = intersect
|
||||
@@ -926,12 +926,12 @@ class DumbWallJoiner:
|
||||
|
||||
def recreate_wall(self, element, obj, axis=None, body=None):
|
||||
if axis is None or body is None:
|
||||
axis = body = self.get_wall_axis(obj)["reference"]
|
||||
axis = body = tool.Model.get_wall_axis(obj)["reference"]
|
||||
self.axis = copy.deepcopy(axis)
|
||||
self.body = copy.deepcopy(body)
|
||||
height = self.get_height(tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id))
|
||||
self.clippings = []
|
||||
layers = get_material_layer_parameters(element)
|
||||
layers = tool.Model.get_material_layer_parameters(element)
|
||||
|
||||
for rel in element.ConnectedTo:
|
||||
connection = rel.RelatingConnectionType
|
||||
@@ -1041,28 +1041,6 @@ class DumbWallJoiner:
|
||||
)
|
||||
)
|
||||
|
||||
def get_wall_axis(self, obj, layers=None):
|
||||
x_values = [v[0] for v in obj.bound_box]
|
||||
min_x = min(x_values)
|
||||
max_x = max(x_values)
|
||||
axes = {}
|
||||
if layers:
|
||||
axes = {
|
||||
"base": [
|
||||
(obj.matrix_world @ Vector((min_x, layers["offset"], 0.0))).to_2d(),
|
||||
(obj.matrix_world @ Vector((max_x, layers["offset"], 0.0))).to_2d(),
|
||||
],
|
||||
"side": [
|
||||
(obj.matrix_world @ Vector((min_x, layers["offset"] + layers["thickness"], 0.0))).to_2d(),
|
||||
(obj.matrix_world @ Vector((max_x, layers["offset"] + layers["thickness"], 0.0))).to_2d(),
|
||||
],
|
||||
}
|
||||
axes["reference"] = [
|
||||
(obj.matrix_world @ Vector((min_x, 0.0, 0.0))).to_2d(),
|
||||
(obj.matrix_world @ Vector((max_x, 0.0, 0.0))).to_2d(),
|
||||
]
|
||||
return axes
|
||||
|
||||
def get_height(self, representation):
|
||||
height = 3.0
|
||||
item = representation.Items[0]
|
||||
@@ -1079,10 +1057,10 @@ class DumbWallJoiner:
|
||||
def join(self, wall1, wall2, connection1, connection2, is_relating=True, description="BUTT"):
|
||||
element1 = tool.Ifc.get_entity(wall1)
|
||||
element2 = tool.Ifc.get_entity(wall2)
|
||||
layers1 = get_material_layer_parameters(element1)
|
||||
layers2 = get_material_layer_parameters(element2)
|
||||
axis1 = self.get_wall_axis(wall1, layers1)
|
||||
axis2 = self.get_wall_axis(wall2, layers2)
|
||||
layers1 = tool.Model.get_material_layer_parameters(element1)
|
||||
layers2 = tool.Model.get_material_layer_parameters(element2)
|
||||
axis1 = tool.Model.get_wall_axis(wall1, layers1)
|
||||
axis2 = tool.Model.get_wall_axis(wall2, layers2)
|
||||
|
||||
angle = tool.Cad.angle_edges(axis1["reference"], axis2["reference"], signed=True, degrees=True)
|
||||
if tool.Cad.is_x(abs(angle), (0, 180), tolerance=0.001):
|
||||
@@ -1271,17 +1249,3 @@ class DumbWallJoiner:
|
||||
}
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def get_material_layer_parameters(element):
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
offset = 0.0
|
||||
thickness = 0.0
|
||||
material = ifcopenshell.util.element.get_material(element)
|
||||
if material:
|
||||
if material.is_a("IfcMaterialLayerSetUsage"):
|
||||
offset = material.OffsetFromReferenceLine * unit_scale
|
||||
material = material.ForLayerSet
|
||||
if material.is_a("IfcMaterialLayerSet"):
|
||||
thickness = sum([l.LayerThickness for l in material.MaterialLayers]) * unit_scale
|
||||
return {"thickness": thickness, "offset": offset}
|
||||
|
||||
@@ -22,7 +22,7 @@ import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.representation
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
from mathutils import Matrix
|
||||
from mathutils import Matrix, Vector
|
||||
from blenderbim.bim import import_ifc
|
||||
|
||||
|
||||
@@ -86,6 +86,20 @@ class Model(blenderbim.core.tool.Model):
|
||||
props.openings.remove(i)
|
||||
has_deleted_opening = True
|
||||
|
||||
@classmethod
|
||||
def get_material_layer_parameters(cls, element):
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
offset = 0.0
|
||||
thickness = 0.0
|
||||
material = ifcopenshell.util.element.get_material(element)
|
||||
if material:
|
||||
if material.is_a("IfcMaterialLayerSetUsage"):
|
||||
offset = material.OffsetFromReferenceLine * unit_scale
|
||||
material = material.ForLayerSet
|
||||
if material.is_a("IfcMaterialLayerSet"):
|
||||
thickness = sum([l.LayerThickness for l in material.MaterialLayers]) * unit_scale
|
||||
return {"thickness": thickness, "offset": offset}
|
||||
|
||||
@classmethod
|
||||
def get_manual_booleans(cls, element):
|
||||
body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
@@ -101,3 +115,26 @@ class Model(blenderbim.core.tool.Model):
|
||||
elif item.is_a("IfcBooleanClippingResult"):
|
||||
items.append(item.FirstOperand)
|
||||
return booleans
|
||||
|
||||
@classmethod
|
||||
def get_wall_axis(cls, obj, layers=None):
|
||||
x_values = [v[0] for v in obj.bound_box]
|
||||
min_x = min(x_values)
|
||||
max_x = max(x_values)
|
||||
axes = {}
|
||||
if layers:
|
||||
axes = {
|
||||
"base": [
|
||||
(obj.matrix_world @ Vector((min_x, layers["offset"], 0.0))).to_2d(),
|
||||
(obj.matrix_world @ Vector((max_x, layers["offset"], 0.0))).to_2d(),
|
||||
],
|
||||
"side": [
|
||||
(obj.matrix_world @ Vector((min_x, layers["offset"] + layers["thickness"], 0.0))).to_2d(),
|
||||
(obj.matrix_world @ Vector((max_x, layers["offset"] + layers["thickness"], 0.0))).to_2d(),
|
||||
],
|
||||
}
|
||||
axes["reference"] = [
|
||||
(obj.matrix_world @ Vector((min_x, 0.0, 0.0))).to_2d(),
|
||||
(obj.matrix_world @ Vector((max_x, 0.0, 0.0))).to_2d(),
|
||||
]
|
||||
return axes
|
||||
|
||||
Reference in New Issue
Block a user