Fix #3256. Support file profiles made out of multiple representation items.

This commit is contained in:
Dion Moult
2023-07-05 14:38:48 +10:00
parent a1caef5b4f
commit 6beca6382f
@@ -19,9 +19,12 @@
import bpy import bpy
import gpu import gpu
import bmesh import bmesh
import shapely
import logging import logging
import numpy as np import numpy as np
import ifcopenshell import ifcopenshell
import ifcopenshell.util.shape
import ifcopenshell.util.element
import ifcopenshell.util.shape_builder import ifcopenshell.util.shape_builder
import ifcopenshell.util.representation import ifcopenshell.util.representation
import blenderbim.tool as tool import blenderbim.tool as tool
@@ -215,9 +218,8 @@ class FilledOpeningGenerator:
def generate_opening_from_filling(self, filling, filling_obj, voided_obj): def generate_opening_from_filling(self, filling, filling_obj, voided_obj):
thickness = voided_obj.dimensions[1] + 0.1 + 0.1 thickness = voided_obj.dimensions[1] + 0.1 + 0.1
ifc_file = tool.Ifc.get() unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file) shape_builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
shape_builder = ifcopenshell.util.shape_builder.ShapeBuilder(ifc_file)
profile = None profile = None
filling_type = ifcopenshell.util.element.get_type(filling) filling_type = ifcopenshell.util.element.get_type(filling)
@@ -226,26 +228,44 @@ class FilledOpeningGenerator:
filling_type, "Model", "Profile", "ELEVATION_VIEW" filling_type, "Model", "Profile", "ELEVATION_VIEW"
) )
filling_obj = tool.Ifc.get_object(filling_type) filling_obj = tool.Ifc.get_object(filling_type)
context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW") context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
if profile: if profile:
curve_3d = ifcopenshell.util.representation.resolve_representation(profile).Items[0] profile = ifcopenshell.util.representation.resolve_representation(profile)
def get_curve_2d_from_3d(curve_3d): def get_curve_2d_from_3d(profile):
if tool.Ifc.get_schema() == "IFC2X3": if len(profile.Items) == 1:
coords = [Vector(p).xz for p in shape_builder.get_polyline_coords(curve_3d)] curve_3d = profile.Items[0]
ifc_curve = shape_builder.polyline(coords, closed=True) if tool.Ifc.get_schema() == "IFC2X3":
else: coords = [Vector(p).xz for p in shape_builder.get_polyline_coords(curve_3d)]
return shape_builder.polyline(coords, closed=True)
# using different algorithm to keep arc segments possible in the future # using different algorithm to keep arc segments possible in the future
ifc_segments = [shape_builder.deep_copy(s) for s in curve_3d.Segments] ifc_segments = [shape_builder.deep_copy(s) for s in curve_3d.Segments]
ifc_points = ifc_file.createIfcCartesianPointList2D( ifc_points = tool.Ifc.get().createIfcCartesianPointList2D(
[Vector(p).xz for p in curve_3d.Points.CoordList] [Vector(p).xz for p in curve_3d.Points.CoordList]
) )
ifc_curve = ifc_file.createIfcIndexedPolyCurve(Points=ifc_points, Segments=ifc_segments) return tool.Ifc.get().createIfcIndexedPolyCurve(Points=ifc_points, Segments=ifc_segments)
return ifc_curve
settings = ifcopenshell.geom.settings()
settings.set(settings.INCLUDE_CURVES, True)
geometry = ifcopenshell.geom.create_shape(settings, profile)
verts = ifcopenshell.util.shape.get_vertices(geometry)
# [0, 2] represents X and Z ordinates
verts = [(np.around(v[[0, 2]], decimals=3) / unit_scale).tolist() for v in verts]
edges = ifcopenshell.util.shape.get_edges(geometry)
boundary_lines = [shapely.LineString([verts[v] for v in e]) for e in edges]
unioned_boundaries = shapely.union_all(shapely.GeometryCollection(boundary_lines))
closed_polygons = shapely.polygonize(boundary_lines)
polygon = max(closed_polygons.geoms, key=lambda polygon: polygon.area)
if tool.Ifc.get_schema() == "IFC2X3":
return shape_builder.polyline(list(polygon.exterior.coords))
points = tool.Ifc.get().createIfcCartesianPointList2D(list(polygon.exterior.coords))
return tool.Ifc.get().createIfcIndexedPolyCurve(points)
extrusion = shape_builder.extrude( extrusion = shape_builder.extrude(
get_curve_2d_from_3d(curve_3d), get_curve_2d_from_3d(profile),
magnitude=thickness / unit_scale, magnitude=thickness / unit_scale,
position=Vector([0.0, -0.1 / unit_scale, 0.0]), position=Vector([0.0, -0.1 / unit_scale, 0.0]),
position_x_axis=Vector((1, 0, 0)), position_x_axis=Vector((1, 0, 0)),