Merge branch 'v0.8.0' into ifcmax/initial-refresh

This commit is contained in:
Josef Wienerroither
2026-03-15 10:02:53 +01:00
32 changed files with 201 additions and 1267 deletions
+2 -2
View File
@@ -36,7 +36,7 @@ jobs:
with:
repository: IfcOpenShell/build-outputs
path: ${{ matrix.deps_dir }}
ref: windows-${{ matrix.arch }}
ref: ${{ matrix.build_branch }}
lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }}
@@ -106,4 +106,4 @@ jobs:
foreach ($zip in Get-ChildItem -Path "$env:USERPROFILE\output" -Filter *.zip) {
aws s3 cp "$($zip.FullName)" s3://ifcopenshell-builds/ --debug
Start-Sleep -Seconds 5
}
}
+1 -1
View File
@@ -91,7 +91,7 @@ jobs:
lfs: true
- name: Download
uses: actions/download-artifact@v8.0.0
uses: actions/download-artifact@v8.0.1
with:
# Artifact name
name: ifcos-artifacts
+6
View File
@@ -115,3 +115,9 @@ dev_environment.bat
src/ifcopenshell-python/ifcopenshell/express/*.exp
src/ifcopenshell-python/ifcopenshell/express/*.exp.cache.dat
# temp files from AI coding tools
*.claude
*.py.tmp*
*.json.tmp*
+2 -2
View File
@@ -3,9 +3,9 @@ name = "IfcOpenShell"
version = "0.0.0"
dependencies = [
"black==26.3.1",
"ruff==0.15.5",
"ruff==0.15.6",
"poethepoet",
"gersemi==0.26.0",
"gersemi==0.26.1",
]
[tool.black]
-1
View File
@@ -83,7 +83,6 @@ class BIM_PT_bsdd(Panel):
row = self.layout.row()
row.operator("bim.load_bsdd_dictionaries")
class BIM_UL_bsdd_dictionaries(UIList):
def draw_item(
self,
@@ -1787,7 +1787,7 @@ class CutDecorator:
# Handle both old float64 and new float32 checksums for version compatibility
rot_checksum_bytes: bytes = eval(DecoratorData.camera_rotation_checksum)
rot_check = tool.Blender.np_frombuffer_legacy(rot_checksum_bytes, 9)
rot_check = tool.Blender.np_frombuffer_legacy(rot_checksum_bytes, 9).reshape(3, 3)
rot_real = tool.Blender.np_array_legacy(obj.matrix_world.to_3x3())
rot_dot = np.dot(rot_check, rot_real.T)
angle_rad = np.arccos(np.clip((np.trace(rot_dot) - 1) / 2, -1, 1))
@@ -3305,9 +3305,8 @@ class AddTextLiteral(bpy.types.Operator):
attr.data_type = "string"
attr.string_value = literal_attr_values[attr_name]
box_alignment_mask = [False] * 9
box_alignment_mask[6] = True # bottom_left box_alignment
literal_props.box_alignment = box_alignment_mask
literal_props.align_vertical = "bottom"
literal_props.align_horizontal = "left"
return {"FINISHED"}
@@ -4178,10 +4177,7 @@ class SelectSimilarTextLiteralValue(bpy.types.Operator):
should_select = True
break
elif self.attribute_type == "box_alignment":
box_alignment_attr = next(
(attr for attr in literal.attributes if attr.name == "BoxAlignment"), None
)
if box_alignment_attr and box_alignment_attr.string_value == self.literal_value:
if literal.get_box_alignment() == self.literal_value:
should_select = True
break
+35 -42
View File
@@ -673,20 +673,6 @@ class BIMCameraProperties(PropertyGroup):
return ortho_scale, aspect_ratio
DEFAULT_BOX_ALIGNMENT = [False] * 6 + [True] + [False] * 2
BOX_ALIGNMENT_POSITIONS = [
"top-left",
"top-middle",
"top-right",
"middle-left",
"center",
"middle-right",
"bottom-left",
"bottom-middle",
"bottom-right",
]
class ElementValueRow(PropertyGroup):
"""Represents a single element value row with category, key, and formatted value"""
@@ -789,40 +775,38 @@ def get_category_items_with_counts(self, context):
class LiteralProps(PropertyGroup):
def set_box_alignment(self, new_value):
markers = new_value.count(True)
if not markers:
return
if markers > 1:
prev_value = self.get("box_alignment", DEFAULT_BOX_ALIGNMENT)
# looking for the first value changed to positive
first_changed_value = next((i for i in range(9) if new_value[i] and new_value[i] != prev_value[i]), None)
# if nothing have changed we just keep the previous value
if first_changed_value is None:
return
new_value = [False] * 9
new_value[first_changed_value] = True
self["box_alignment"] = new_value
position_string = BOX_ALIGNMENT_POSITIONS[next(i for i in range(9) if new_value[i])]
self.attributes["BoxAlignment"].set_value(position_string)
def get_box_alignment(self):
return self.get("box_alignment", DEFAULT_BOX_ALIGNMENT)
attributes: CollectionProperty(name="Attributes", type=Attribute)
box_alignment: BoolVectorProperty(
name="Box alignment", size=9, set=set_box_alignment, get=get_box_alignment, default=DEFAULT_BOX_ALIGNMENT
)
ifc_definition_id: IntProperty(name="IFC definition ID", default=0)
align_horizontal: EnumProperty(
items=[
("left", "Left", "", "ALIGN_LEFT", 0),
("middle", "Middle", "", "ALIGN_CENTER", 1),
("right", "Right", "", "ALIGN_RIGHT", 2),
],
default="left",
name="Horizontal Alignment",
)
align_vertical: EnumProperty(
items=[
("top", "Top", "", "ALIGN_TOP", 0),
("middle", "Middle", "", "ALIGN_MIDDLE", 1),
("bottom", "Bottom", "", "ALIGN_BOTTOM", 2),
],
default="middle",
name="Vertical Alignment",
)
def get_box_alignment(self) -> str:
alignment = self.align_vertical + "-" + self.align_horizontal
if alignment == "middle-middle":
alignment = "center"
return alignment
def get_literal_edited_data(self) -> dict[str, str]:
text_data = {
"CurrentValue": self.attributes["Literal"].string_value,
"Literal": self.attributes["Literal"].string_value,
"BoxAlignment": self.attributes["BoxAlignment"].string_value,
"BoxAlignment": self.get_box_alignment(),
}
return text_data
@@ -860,12 +844,19 @@ class LiteralProps(PropertyGroup):
if TYPE_CHECKING:
attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
value: str
box_alignment: tuple[bool, bool, bool, bool, bool, bool, bool, bool, bool]
ifc_definition_id: int
align_horizontal: str
align_vertical: str
element_value_rows: bpy.types.bpy_prop_collection_idprop[ElementValueRow]
category_for_adding: str
def update_text_alignment(self, context):
for literal_props in self.literals:
literal_props.align_horizontal = self.align_horizontal
literal_props.align_vertical = self.align_vertical
class BIMTextProperties(PropertyGroup):
is_editing: BoolProperty(name="Is Editing", default=False)
literals: CollectionProperty(name="Literals", type=LiteralProps)
@@ -899,6 +890,7 @@ class BIMTextProperties(PropertyGroup):
],
default="left",
name="Horizontal Alignment",
update=update_text_alignment,
)
align_vertical: EnumProperty(
items=[
@@ -908,6 +900,7 @@ class BIMTextProperties(PropertyGroup):
],
default="middle",
name="Vertical Alignment",
update=update_text_alignment,
)
if TYPE_CHECKING:
+4 -27
View File
@@ -781,33 +781,10 @@ class BIM_PT_text(Panel):
if other_attributes:
bonsai.bim.helper.draw_attributes(other_attributes, box)
row = box.row(align=True)
cols = [row.column(align=True) for j in range(3)]
for j in range(9):
cols[j % 3].prop(
literal_props,
"box_alignment",
text="",
index=j,
icon="RADIOBUT_ON" if literal_props.box_alignment[j] else "RADIOBUT_OFF",
)
col = row.column(align=True)
alignment_label_row = col.row(align=True)
alignment_label_row.label(text=" Text box alignment:")
box_alignment_value = (
literal_props.attributes[
next(
(idx for idx, attr in enumerate(literal_props.attributes) if attr.name == "BoxAlignment"),
-1,
)
].string_value
if any(attr.name == "BoxAlignment" for attr in literal_props.attributes)
else "N/A"
)
col.label(text=f" {box_alignment_value}")
row = box.row()
row.label(text="Alignment")
row.prop(literal_props, "align_horizontal", text="", expand=True)
row.prop(literal_props, "align_vertical", text="", expand=True)
def draw(self, context):
obj = context.active_object
@@ -102,7 +102,6 @@ class MaterialsData:
if (style_name := s.Name) is not None
]
results = natsorted(results, key=lambda i: i[1])
results.insert(0, ("-", "No Surface Style", ""))
return results
@classmethod
@@ -210,14 +210,15 @@ class AssignMaterialToSelected(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.assign_material_to_selected"
bl_label = "Assign Material To Selected"
bl_description = (
"Assign currently selected material in Materials UI to the selected objects.\n\n"
"ALT+CLICK to assign material as a usage."
"Assign currently selected material in Materials UI to the selected objects.\n"
"Occurrences automatically get usages for layer/profile sets.\n\n"
"ALT+CLICK to assign without a usage."
)
bl_options = {"REGISTER", "UNDO"}
material: bpy.props.IntProperty(name="Material IFC ID")
assign_as_usage: bpy.props.BoolProperty(
name="Assign Material As A Usage",
default=False,
should_auto_assign_usage: bpy.props.BoolProperty(
name="Auto Assign Usage",
default=True,
options={"SKIP_SAVE"},
)
@@ -230,25 +231,19 @@ class AssignMaterialToSelected(bpy.types.Operator, tool.Ifc.Operator):
def invoke(self, context, event):
if event.type == "LEFTMOUSE" and event.alt:
material_class = tool.Ifc.get().by_id(self.material).is_a()
if material_class not in ("IfcMaterialProfileSet", "IfcMaterialLayerSet"):
self.report({"ERROR"}, f"{material_class} cannot be assigned as a usage.")
return {"CANCELLED"}
self.assign_as_usage = True
self.should_auto_assign_usage = False
return self.execute(context)
def _execute(self, context):
material = tool.Ifc.get().by_id(self.material)
objects = tool.Blender.get_selected_objects()
material_type = material.is_a()
if self.assign_as_usage:
material_type += "Usage"
core.assign_material(
tool.Ifc,
tool.Material,
material_type=material_type,
material_type=material.is_a(),
objects=objects,
material=material,
should_auto_assign_usage=self.should_auto_assign_usage,
)
+11 -6
View File
@@ -118,12 +118,17 @@ class BIM_PT_materials(Panel):
row.operator("bim.edit_material", text="Save Material", icon="CHECKMARK").material = ifc_definition_id
row.operator("bim.disable_editing_material", text="", icon="CANCEL")
elif self.props.editing_material_type == "STYLE":
row = self.layout.row(align=True)
row.prop(self.props, "contexts", text="")
prop_with_search(row, self.props, "styles", text="")
row = self.layout.row(align=True)
row.operator("bim.edit_material_style", text="Assign Style", icon="CHECKMARK")
row.operator("bim.disable_editing_material", text="", icon="CANCEL")
if MaterialsData.data["styles"]:
row = self.layout.row(align=True)
row.prop(self.props, "contexts", text="")
prop_with_search(row, self.props, "styles", text="")
row = self.layout.row(align=True)
row.operator("bim.edit_material_style", text="Assign Style", icon="CHECKMARK")
row.operator("bim.disable_editing_material", text="", icon="CANCEL")
else:
row = self.layout.row(align=True)
row.label(text="No Styles Found")
row.operator("bim.disable_editing_material", text="", icon="CANCEL")
class BIM_PT_object_material(Panel):
+1 -1
View File
@@ -262,7 +262,7 @@ class BIM_PT_object_psets(Panel):
row = self.layout.row(align=True)
prop_with_search(row, props, "pset_name", text="")
if props.pset_name != "BBIM_BSDD" and not props.pset_name.startswith(tool.Bsdd.identifier_url):
if props.pset_name != "BBIM_BSDD" and not props.pset_name.startswith(tool.Bsdd.identifier_url()):
op = row.operator("bim.add_pset", icon="ADD", text="")
op.obj = obj.name
op.obj_type = "Object"
+9 -2
View File
@@ -113,6 +113,7 @@ def assign_material(
material_type: Union[str, None],
objects: list[bpy.types.Object],
material: Optional[ifcopenshell.entity_instance] = None,
should_auto_assign_usage: bool = True,
) -> None:
"""Assign material to the provided objects.
@@ -121,12 +122,18 @@ def assign_material(
"""
material_type = material_type or material_tool.get_object_ui_material_type()
material = material or material_tool.get_object_ui_active_material()
can_be_usage = should_auto_assign_usage and material_type in ("IfcMaterialLayerSet", "IfcMaterialProfileSet")
for obj in objects:
element = ifc.get_entity(obj)
if not element:
continue
ifc.run("material.assign_material", products=[element], type=material_type, material=material)
if can_be_usage and not material_tool.is_type_product(element):
element_material_type = material_type + "Usage"
else:
element_material_type = material_type
ifc.run("material.assign_material", products=[element], type=element_material_type, material=material)
assigned_material = material_tool.get_material(element)
assert assigned_material # Type checker.
@@ -136,7 +143,7 @@ def assign_material(
material_tool.add_material_to_set(material_set=material, material=default_material)
elif material_tool.is_a_material_set(assigned_material):
material_tool.add_material_to_set(material_set=assigned_material, material=material)
material_tool.ensure_material_assigned(elements=[element], material_type=material_type, material=material)
material_tool.ensure_material_assigned(elements=[element], material_type=element_material_type, material=material)
def unassign_material(ifc: type[tool.Ifc], material_tool: type[tool.Material], objects: list[bpy.types.Object]) -> None:
+1
View File
@@ -580,6 +580,7 @@ class Material:
def import_material_definitions(cls, material_type: str): pass
def is_a_flow_segment(cls, element): pass
def is_a_material_set(cls, material): pass
def is_type_product(cls, element): pass
def is_editing_materials(cls): pass
def is_material_used_in_sets(cls, material): pass
def load_material_attributes(cls, material): pass
+16 -4
View File
@@ -36,11 +36,23 @@ if TYPE_CHECKING:
class Bsdd(bonsai.core.tool.Bsdd):
identifier_url = "https://identifier.buildingsmart.org"
default_identifier_url = "https://identifier.buildingsmart.org"
default_api_url = "https://api.bsdd.buildingsmart.org/api/"
client = bsdd.Client()
bsdd_classes: dict[str, dict] = {}
bsdd_properties: dict[str, dict] = {}
@classmethod
def identifier_url(cls) -> str:
"""Derives the identifier base URL from the current client baseurl.
Falls back to the standard bSDD identifier URL when using the default API."""
if cls.client.baseurl == cls.default_api_url:
return cls.default_identifier_url
from urllib.parse import urlparse
parsed = urlparse(cls.client.baseurl)
return f"{parsed.scheme}://{parsed.netloc}"
@classmethod
def get_bsdd_props(cls) -> BIMBSDDProperties:
assert (scene := bpy.context.scene)
@@ -269,7 +281,7 @@ class Bsdd(bonsai.core.tool.Bsdd):
for obj in tool.Blender.get_selected_objects(include_active=True):
if element := tool.Ifc.get_entity(obj):
for reference in ifcopenshell.util.classification.get_references(element):
if (uri := reference.Location) and uri.startswith(cls.identifier_url):
if (uri := reference.Location) and uri.startswith(cls.identifier_url()):
classes.add((reference[1] or reference[2] or "Unnamed", uri))
dictionary_uris = (
@@ -383,7 +395,7 @@ class Bsdd(bonsai.core.tool.Bsdd):
def get_applicable_psets(cls, element: ifcopenshell.entity_instance):
uris = set()
for reference in ifcopenshell.util.classification.get_references(element):
if (uri := reference.Location) and uri.startswith(cls.identifier_url):
if (uri := reference.Location) and uri.startswith(cls.identifier_url()):
uris.add(uri)
psets = set()
for uri in uris:
@@ -399,7 +411,7 @@ class Bsdd(bonsai.core.tool.Bsdd):
def is_applicable(cls, pset_uri: str, element: ifcopenshell.entity_instance) -> bool:
uris = set()
for reference in ifcopenshell.util.classification.get_references(element):
if (uri := reference.Location) and uri.startswith(cls.identifier_url):
if (uri := reference.Location) and uri.startswith(cls.identifier_url()):
uris.add(uri)
class_uri, pset_name = pset_uri.rsplit("#", 1)
return class_uri in uris
+15 -7
View File
@@ -603,6 +603,10 @@ class Drawing(bonsai.core.tool.Drawing):
props = tool.Drawing.get_text_props(obj)
for literal_props in props.literals:
literal_data = bonsai.bim.helper.export_attributes(literal_props.attributes)
alignment = literal_props.align_vertical + "-" + literal_props.align_horizontal
if alignment == "middle-middle":
alignment = "center"
literal_data["BoxAlignment"] = alignment
literals.append(literal_data)
return literals
@@ -1176,22 +1180,26 @@ class Drawing(bonsai.core.tool.Drawing):
@classmethod
def import_text_attributes(cls, obj: bpy.types.Object) -> None:
from bonsai.bim.module.drawing.prop import BOX_ALIGNMENT_POSITIONS
props = cls.get_text_props(obj)
props.literals.clear()
ifc_literals = cls.get_text_literal(obj, return_list=True)
assert isinstance(ifc_literals, list)
if ifc_literals:
first_alignment = getattr(ifc_literals[0], "BoxAlignment", None) or "bottom-left"
if first_alignment == "center":
first_alignment = "middle-middle"
props.align_vertical, props.align_horizontal = first_alignment.split("-")
for ifc_literal in ifc_literals:
literal_props = props.literals.add()
bonsai.bim.helper.import_attributes(ifc_literal, literal_props.attributes)
box_alignment_mask = [False] * 9
position_string = literal_props.attributes["BoxAlignment"].string_value
box_alignment_mask[BOX_ALIGNMENT_POSITIONS.index(position_string)] = True
literal_props.box_alignment = box_alignment_mask # pyright: ignore[reportAttributeAccessIssue]
alignment = getattr(ifc_literal, "BoxAlignment", None) or "bottom-left"
if alignment == "center":
alignment = "middle-middle"
literal_props.align_vertical, literal_props.align_horizontal = alignment.split("-")
literal_props.ifc_definition_id = ifc_literal.id()
from bonsai.bim.module.drawing.data import DecoratorData
+4
View File
@@ -226,6 +226,10 @@ class Material(bonsai.core.tool.Material):
"IfcMaterialProfileSet",
]
@classmethod
def is_type_product(cls, element: ifcopenshell.entity_instance) -> bool:
return element.is_a("IfcTypeProduct")
@classmethod
def add_material_to_set(
cls, material_set: ifcopenshell.entity_instance, material: ifcopenshell.entity_instance
+5 -2
View File
@@ -533,9 +533,12 @@ class Polyline(bonsai.core.tool.Polyline):
polyline_data = polyline_data[0]
polyline_points = polyline_data.polyline_points
if polyline_points:
# Avoids creating two points at the same location
for point in polyline_points[1:]: # The first can be repeated to form a wall loop
# Avoids creating two points at the same location.
# The only exception is repeating the first point to close a loop (requires >= 3 existing points).
for i, point in enumerate(polyline_points):
if (x, y, z) == (point.x, point.y, point.z):
if i == 0 and len(polyline_points) >= 3:
continue
return "Cannot create two points at the same location"
# Avoids creating overlapping edges
if len(polyline_points) > 1:
+4 -1
View File
@@ -666,10 +666,13 @@ class TestImportTextAttributes(NewFile):
literal_props = props.literals[0]
assert literal_props.ifc_definition_id == item.id()
assert literal_props.box_alignment[:] == tuple([False] * 6 + [True] + [False] * 2)
assert literal_props.attributes["Literal"].string_value == "Literal"
assert literal_props.attributes["Path"].enum_value == "RIGHT"
assert literal_props.attributes["BoxAlignment"].string_value == "bottom-left"
assert literal_props.align_vertical == "bottom"
assert literal_props.align_horizontal == "left"
assert props.align_vertical == "bottom"
assert props.align_horizontal == "left"
class TestReplaceTextLiteralVariables(NewFile):
+2 -23
View File
@@ -620,17 +620,7 @@ const IfcGeom::Element* IfcGeom::Iterator::get_object(int id) {
}
} catch (const std::exception& e) {
Logger::Error(e);
}
#ifdef IFOPSH_WITH_OPENCASCADE
catch (const Standard_Failure& e) {
if (e.GetMessageString() && strlen(e.GetMessageString())) {
Logger::Error(e.GetMessageString());
} else {
Logger::Error("Unknown error returning product");
}
}
#endif
catch (...) {
} catch (...) {
Logger::Error("Unknown error returning product");
}
@@ -645,18 +635,7 @@ const IfcUtil::IfcBaseClass* IfcGeom::Iterator::create() {
} catch (const std::exception& e) {
Logger::Error(e);
had_error_processing_elements_ = true;
}
#ifdef IFOPSH_WITH_OPENCASCADE
catch (const Standard_Failure& e) {
if (e.GetMessageString() && strlen(e.GetMessageString())) {
Logger::Error(e.GetMessageString());
} else {
Logger::Error("Unknown error creating geometry");
}
had_error_processing_elements_ = true;
}
#endif
catch (...) {
} catch (...) {
Logger::Error("Unknown error creating geometry");
had_error_processing_elements_ = true;
}
-4
View File
@@ -68,10 +68,6 @@
#include "../ifcgeom/abstract_mapping.h"
#include "../ifcgeom/GeometrySerializer.h"
#ifdef IFOPSH_WITH_OPENCASCADE
#include <Standard_Failure.hxx>
#endif
#include <boost/algorithm/string.hpp>
#include <map>
File diff suppressed because it is too large Load Diff
@@ -56,6 +56,21 @@
#include "../../../ifcgeom/taxonomy.h"
#include "../../../ifcgeom/ConversionSettings.h"
namespace {
template <typename Fn>
bool handle_occt_exception(Fn&& fn) {
try {
return std::forward<Fn>(fn)();
} catch (const Standard_Failure& e) {
if (e.GetMessageString() && strlen(e.GetMessageString())) {
throw std::runtime_error(e.GetMessageString());
} else {
throw std::runtime_error("Unknown error creating geometry");
}
}
}
}
namespace IfcGeom {
class IFC_GEOMLIBRARY_API OpenCascadeKernel : public ifcopenshell::geometry::kernels::AbstractKernel {
@@ -84,6 +84,7 @@ namespace {
}
bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, ConversionResults& results) {
return handle_occt_exception([&]() -> bool {
bool valid_result = false;
bool first = true;
const double tol = settings_.get<settings::Precision>().get();
@@ -196,4 +197,5 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con
));
return true;
});
}
@@ -72,6 +72,8 @@ bool OpenCascadeKernel::convert(const taxonomy::extrusion::ptr extrusion, TopoDS
}
bool OpenCascadeKernel::convert_impl(const taxonomy::extrusion::ptr extrusion, IfcGeom::ConversionResults& results) {
return handle_occt_exception([&]() -> bool {
TopoDS_Shape shape;
if (!convert(extrusion, shape)) {
return false;
@@ -84,4 +86,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::extrusion::ptr extrusion, I
extrusion->surface_style
));
return true;
});
}
+4
View File
@@ -599,6 +599,8 @@ bool OpenCascadeKernel::convert(const taxonomy::face::ptr face, TopoDS_Shape& re
}
bool OpenCascadeKernel::convert_impl(const taxonomy::face::ptr face, IfcGeom::ConversionResults& results) {
return handle_occt_exception([&]() -> bool {
TopoDS_Shape shape;
if (!convert(face, shape)) {
return false;
@@ -609,4 +611,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::face::ptr face, IfcGeom::Co
face->surface_style
));
return true;
});
}
+4
View File
@@ -427,6 +427,8 @@ bool OpenCascadeKernel::convert(const taxonomy::loft::ptr loft, TopoDS_Shape& re
}
bool OpenCascadeKernel::convert_impl(const taxonomy::loft::ptr loft, IfcGeom::ConversionResults& results) {
return handle_occt_exception([&]() -> bool {
TopoDS_Shape shape;
if (!convert(loft, shape)) {
return false;
@@ -438,4 +440,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::loft::ptr loft, IfcGeom::Co
loft->surface_style
));
return true;
});
}
+8
View File
@@ -378,6 +378,8 @@ bool OpenCascadeKernel::convert(const taxonomy::loop::ptr loop, TopoDS_Wire& wir
}
bool OpenCascadeKernel::convert_impl(const taxonomy::loop::ptr loop, IfcGeom::ConversionResults& results) {
return handle_occt_exception([&]() -> bool {
TopoDS_Wire shape;
if (!convert(loop, shape)) {
return false;
@@ -389,9 +391,13 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::loop::ptr loop, IfcGeom::Co
loop->surface_style
));
return true;
});
}
bool OpenCascadeKernel::convert_impl(const taxonomy::edge::ptr edge, IfcGeom::ConversionResults& results) {
return handle_occt_exception([&]() -> bool {
TopoDS_Wire shape = boost::get<TopoDS_Wire>(convert_curve(edge));
results.emplace_back(ConversionResult(
@@ -400,4 +406,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::edge::ptr edge, IfcGeom::Co
edge->surface_style
));
return true;
});
}
@@ -107,6 +107,8 @@ bool OpenCascadeKernel::convert(const taxonomy::shell::ptr l, TopoDS_Shape& shap
}
bool OpenCascadeKernel::convert_impl(const taxonomy::shell::ptr shell, IfcGeom::ConversionResults& results) {
return handle_occt_exception([&]() -> bool {
TopoDS_Shape shape;
if (!convert(shell, shape)) {
return false;
@@ -118,4 +120,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::shell::ptr shell, IfcGeom::
shell->surface_style
));
return true;
});
}
@@ -102,6 +102,8 @@ bool OpenCascadeKernel::convert(const taxonomy::solid::ptr solid, TopoDS_Shape&
}
bool OpenCascadeKernel::convert_impl(const taxonomy::solid::ptr solid, IfcGeom::ConversionResults& results) {
return handle_occt_exception([&]() -> bool {
TopoDS_Shape shape;
if (!convert(solid, shape)) {
return false;
@@ -113,4 +115,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::solid::ptr solid, IfcGeom::
solid->surface_style
));
return true;
});
}
@@ -308,6 +308,8 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo
}
bool OpenCascadeKernel::convert_impl(const taxonomy::sweep_along_curve::ptr scs, IfcGeom::ConversionResults& results) {
return handle_occt_exception([&]() -> bool {
TopoDS_Shape shape;
// For tiny radii occt will fail building the sweep, in which case we enlarge the inputs to occt, and add a scale matrix to the output
bool enlarged = false;
@@ -352,4 +354,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::sweep_along_curve::ptr scs,
scs->surface_style
));
return true;
});
}