mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 15:08:51 +00:00
Fix limitations in AddSlabFromWalls operator.
- The operator is now unaffected by the order in which walls are joined. - It has been updated to support split walls.
This commit is contained in:
@@ -103,7 +103,7 @@ class DumbSlabGenerator:
|
|||||||
return self.create_slab()
|
return self.create_slab()
|
||||||
|
|
||||||
def derive_from_walls(self):
|
def derive_from_walls(self):
|
||||||
walls, is_closed_loop = tool.Model.get_connected_walls(bpy.context.selected_objects)
|
walls = tool.Model.get_connected_walls(bpy.context.selected_objects)
|
||||||
polyline_points = []
|
polyline_points = []
|
||||||
poly = tool.Model.get_polygons_from_wall_axis(walls)
|
poly = tool.Model.get_polygons_from_wall_axis(walls)
|
||||||
polyline_points = [tuple([v for v in c]) for c in poly.exterior.coords]
|
polyline_points = [tuple([v for v in c]) for c in poly.exterior.coords]
|
||||||
@@ -768,12 +768,9 @@ class AddSlabFromWall(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
if not self.relating_type:
|
if not self.relating_type:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
walls, is_closed_loop = tool.Model.get_connected_walls(bpy.context.selected_objects)
|
walls = tool.Model.get_connected_walls(bpy.context.selected_objects)
|
||||||
if not is_closed_loop:
|
if not walls:
|
||||||
self.report(
|
self.report({"WARNING"}, "Please select a closed loop of walls, or deselect the walls to add a slab using the polyline tool.")
|
||||||
{"WARNING"},
|
|
||||||
"Please select a closed loop of walls, or deselect the walls to add a slab using the polyline tool.",
|
|
||||||
)
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
DumbSlabGenerator(self.relating_type).generate("WALLS")
|
DumbSlabGenerator(self.relating_type).generate("WALLS")
|
||||||
|
|||||||
@@ -674,44 +674,39 @@ class Model(bonsai.core.tool.Model):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_connected_walls(
|
def get_connected_walls(
|
||||||
cls, walls: list[bpy.types.Object], opposite_direction: bool = False
|
cls, walls: list[bpy.types.Object]) -> list[bpy.types.Object]:
|
||||||
) -> list[bpy.types.Object]:
|
|
||||||
"""
|
"""
|
||||||
Loop through walls by retrieving the next connected wall using the ConnectedTo attribute.
|
Loop through walls by retrieving the next connected wall using the connection path.
|
||||||
If the function encounters the first wall again, it will return the list of connected walls and indicate that a closed loop has been formed.
|
If the function encounters the first wall again, it will return the list of connected walls.
|
||||||
If it reaches the end of the connections, the function will call itself in the opposite direction using the ConnectedFrom method
|
|
||||||
to obtain a list of connected walls in an open loop.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
is_closed_loop = False
|
first_wall = tool.Ifc.get_entity(walls[0])
|
||||||
wall1 = tool.Ifc.get_entity(walls[0])
|
previous_wall = None
|
||||||
wall = wall1
|
current_wall = first_wall
|
||||||
if not opposite_direction:
|
ordered_walls = [first_wall]
|
||||||
connection = "ConnectedTo"
|
|
||||||
relation = "RelatedElement"
|
|
||||||
else:
|
|
||||||
connection = "ConnectedFrom"
|
|
||||||
relation = "RelatingElement"
|
|
||||||
|
|
||||||
ordered_walls = []
|
|
||||||
ordered_walls.append(wall1)
|
|
||||||
for i in range(len(walls)):
|
for i in range(len(walls)):
|
||||||
if not getattr(wall, connection) or (
|
paths = []
|
||||||
next_wall := tool.Ifc.get_object(getattr(getattr(wall, connection)[0], relation)) not in walls
|
paths.extend([path for path in current_wall.ConnectedTo])
|
||||||
):
|
paths.extend([path for path in current_wall.ConnectedFrom])
|
||||||
if opposite_direction:
|
|
||||||
return ordered_walls, is_closed_loop
|
|
||||||
ordered_walls, is_closed_loop = cls.get_connected_walls(walls, True)
|
|
||||||
break
|
|
||||||
next_wall = getattr(getattr(wall, connection)[0], relation)
|
|
||||||
if next_wall == wall1:
|
|
||||||
is_closed_loop = True
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
ordered_walls.append(next_wall)
|
|
||||||
wall = next_wall
|
|
||||||
|
|
||||||
return [tool.Ifc.get_object(wall) for wall in ordered_walls], is_closed_loop
|
if len(paths) <= 1:
|
||||||
|
return []
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
next_wall = path.RelatedElement if path.RelatedElement != current_wall else path.RelatingElement
|
||||||
|
if next_wall == previous_wall:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if next_wall != current_wall and next_wall != first_wall and next_wall not in ordered_walls:
|
||||||
|
ordered_walls.append(next_wall)
|
||||||
|
previous_wall = current_wall
|
||||||
|
current_wall = next_wall
|
||||||
|
break
|
||||||
|
|
||||||
|
if next_wall == first_wall:
|
||||||
|
return [tool.Ifc.get_object(wall) for wall in ordered_walls]
|
||||||
|
return []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_polygons_from_wall_axis(cls, walls: list[bpy.types.Object]) -> list[shapely.Polygon]:
|
def get_polygons_from_wall_axis(cls, walls: list[bpy.types.Object]) -> list[shapely.Polygon]:
|
||||||
@@ -727,8 +722,18 @@ class Model(bonsai.core.tool.Model):
|
|||||||
layers2 = tool.Model.get_material_layer_parameters(tool.Ifc.get_entity(w2))
|
layers2 = tool.Model.get_material_layer_parameters(tool.Ifc.get_entity(w2))
|
||||||
axis1 = tool.Model.get_wall_axis(w1, layers1)
|
axis1 = tool.Model.get_wall_axis(w1, layers1)
|
||||||
axis2 = tool.Model.get_wall_axis(w2, layers2)
|
axis2 = tool.Model.get_wall_axis(w2, layers2)
|
||||||
intersection1 = tool.Cad.intersect_edges(axis1["reference"], axis2["reference"])
|
intersection1 = tool.Cad.intersect_edges_v2(axis1["reference"], axis2["reference"])
|
||||||
intersection2 = tool.Cad.intersect_edges(axis1["side"], axis2["side"])
|
intersection2 = tool.Cad.intersect_edges_v2(axis1["side"], axis2["side"])
|
||||||
|
if intersection1[0] is None or intersection2[0] is None:
|
||||||
|
for v1 in axis1["reference"]:
|
||||||
|
for v2 in axis2["reference"]:
|
||||||
|
if tool.Cad.are_vectors_equal(v1, v2, 1e-5):
|
||||||
|
intersection1 = [v1]
|
||||||
|
for v1 in axis1["side"]:
|
||||||
|
for v2 in axis2["side"]:
|
||||||
|
if tool.Cad.are_vectors_equal(v1, v2, 1e-5):
|
||||||
|
intersection2 = [v1]
|
||||||
|
|
||||||
points1.append(intersection1[0])
|
points1.append(intersection1[0])
|
||||||
points2.append(intersection2[0])
|
points2.append(intersection2[0])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user