Discard old examples - modernize others

This commit is contained in:
Thomas Krijnen
2026-07-31 03:58:50 +02:00
parent 3fc83847dd
commit 008ac8a354
7 changed files with 283 additions and 231 deletions
+3 -21
View File
@@ -221,29 +221,11 @@ jobs:
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake --build . cmake --build .
./arbitrary_open_profile_def && test -f arbitrary_open_profile_def.ifc
./composite_profile_def && test -f composite_profile_def.ifc
./csg_primitive && test -f csg_primitive.ifc
./ellipse_pies && test -f ellipse_pies.ifc
./faces && test -f faces.ifc
./ifc_curve_rebar && test -f ifc_curve_rebar.ifc
./profiles
test -f IfcUShapeProfileDef.ifc
test -f IfcTShapeProfileDef.ifc
test -f IfcZShapeProfileDef.ifc
test -f IfcEllipseProfileDef.ifc
test -f IfcIShapeProfileDef.ifc
test -f IfcLShapeProfileDef.ifc
test -f IfcCShapeProfileDef.ifc
test -f IfcCircleProfileDef.ifc
test -f IfcRectangleProfileDef.ifc
test -f IfcTrapeziumProfileDef.ifc
./IfcParseExamples "../IfcParseExamples_test.ifc"
./IfcOpenHouse && test -f IfcOpenHouse.ifc ./IfcOpenHouse && test -f IfcOpenHouse.ifc
./IfcParseExamples IfcOpenHouse.ifc
./IfcAdvancedHouse && test -f IfcAdvancedHouse.ifc ./IfcAdvancedHouse && test -f IfcAdvancedHouse.ifc
./IfcAlignment && test -f IfcAlignment.ifc ./IfcAlignment && test -f FHWA_Bridge_Geometry_Alignment_Example.ifc
./IfcSimplifiedAlignment && test -f IfcSimplifiedAlignment.ifc ./IfcSimplifiedAlignment && test -f FHWA_Bridge_Geometry_Alignment_Example_Simplified.ifc
./triangulated_faceset && test -f triangulated_faceset.ifc
- name: Test ifcopenshell-python - name: Test ifcopenshell-python
run: | run: |
+3
View File
@@ -53,6 +53,9 @@ endmacro()
function(ifcopenshell_plugin_target TARGET) function(ifcopenshell_plugin_target TARGET)
set_target_properties(${TARGET} PROPERTIES PREFIX "") set_target_properties(${TARGET} PROPERTIES PREFIX "")
if((NOT WIN32) AND BUILD_SHARED_LIBS AND NOT WASM_BUILD AND NOT CREATE_BUNDLE AND NOT CMAKE_INSTALL_RPATH AND COMMAND SET_INSTALL_SELF_RPATH)
SET_INSTALL_SELF_RPATH(${TARGET})
endif()
endfunction() endfunction()
function(ifcopenshell_wasm_plugin_link_options TARGET REGISTRATION_SYMBOL) function(ifcopenshell_wasm_plugin_link_options TARGET REGISTRATION_SYMBOL)
+5 -2
View File
@@ -87,9 +87,12 @@ macro(build_schema_example exe_name schema)
endif() endif()
endmacro() endmacro()
if("2x3" IN_LIST SCHEMA_VERSIONS) if(SCHEMA_VERSIONS)
list(GET SCHEMA_VERSIONS -1 schema)
build_schema_example(IfcParseExamples ${schema})
if(WITH_OPENCASCADE) if(WITH_OPENCASCADE)
build_schema_example(IfcAdvancedHouse 2x3 geometry_serializer) build_schema_example(IfcOpenHouse ${schema} geometry_serializer)
build_schema_example(IfcAdvancedHouse ${schema} geometry_serializer)
endif() endif()
endif() endif()
+225 -187
View File
@@ -45,6 +45,7 @@
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema) #include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
#include "ifcparse/hierarchy_helper.h" #include "ifcparse/hierarchy_helper.h"
#include "plugin/plugin.h"
#include "../ifcgeom/Serialization/Serialization.h" #include "../ifcgeom/Serialization/Serialization.h"
@@ -69,23 +70,21 @@ void createGroundShape(TopoDS_Shape& shape);
int main() { int main() {
#ifdef IFCOPENSHELL_EXAMPLE_PLUGIN_PATH
ifcopenshell::plugin::set_search_paths({IFCOPENSHELL_EXAMPLE_PLUGIN_PATH});
#endif
// The hierarchy_helper is a subclass of the regular file that provides several // The hierarchy_helper is a subclass of the regular file that provides several
// convenience functions for working with geometry in IFC files. // convenience functions for working with geometry in IFC files.
hierarchy_helper<IfcSchema> file; hierarchy_helper<IfcSchema> file;
file.header().file_name().setname("IfcOpenHouse.ifc"); file.header().file_name().setname("IfcOpenHouse.ifc");
// Start by adding a wall to the file, initially leaving most attributes blank. // Start by adding a wall to the file, initially leaving most attributes blank.
IfcSchema::IfcWallStandardCase* south_wall = new IfcSchema::IfcWallStandardCase( auto south_wall = file.create<IfcSchema::IfcWallStandardCase>();
guid(), // GlobalId south_wall.setGlobalId(guid());
0, // OwnerHistory south_wall.setName("South wall");
"South wall"s, // Name
null, // Description
null, // ObjectType
0, // ObjectPlacement
0, // Representation
null // Tag
#ifdef SCHEMA_IfcWall_HAS_PredefinedType #ifdef SCHEMA_IfcWall_HAS_PredefinedType
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD south_wall.setPredefinedType(IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD);
#endif #endif
file.addBuildingProduct(south_wall); file.addBuildingProduct(south_wall);
@@ -113,8 +112,8 @@ int main() {
south_wall.setRepresentation(south_wall_shape); south_wall.setRepresentation(south_wall_shape);
south_wall.setObjectPlacement(file.addLocalPlacement(storey_placement)); south_wall.setObjectPlacement(file.addLocalPlacement(storey_placement));
// A pale white colour is assigned to the wall. // A pale white colour is assigned to the wall.
surface_style_t* wall_colour = setSurfaceColour(file, south_wall_shape, 0.75, 0.73, 0.68); auto wall_colour = setSurfaceColour(file, south_wall_shape, 0.75, 0.73, 0.68);
// Now create a footing for the wall to rest on. // Now create a footing for the wall to rest on.
auto footing = file.create<IfcSchema::IfcFooting>(); auto footing = file.create<IfcSchema::IfcFooting>();
@@ -125,24 +124,26 @@ int main() {
file.addBuildingProduct(footing); file.addBuildingProduct(footing);
// The footing will span the entire floor plan of our building. The IfcRepresentationContext is // The footing will span the entire floor plan of our building. The IfcRepresentationContext is
// something that has been created automatically as well, but representations could have been // something that has been created automatically as well, but representations could have been
// assigned to a specific context, for example to add a two dimensional plan representation as well. // assigned to a specific context, for example to add a two dimensional plan representation as well.
footing->setRepresentation(file.addBox(10100, 5460, 2000)); footing.setRepresentation(file.addBox(10100, 5460, 2000));
footing->setObjectPlacement(file.addLocalPlacement(storey_placement, 0, 2500, -2000)); footing.setObjectPlacement(file.addLocalPlacement(storey_placement, 0, 2500, -2000));
// The footing will have a dark gray colour // The footing will have a dark gray colour
surface_style_t* footing_colour = setSurfaceColour(file,footing->Representation(), 0.26, 0.22, 0.18); auto footing_colour = setSurfaceColour(file, footing.Representation(), 0.26, 0.22, 0.18);
// IFC has two ways to apply boolean operations to geometry. IfcBooleanResults are commonly used // IFC has two ways to apply boolean operations to geometry. IfcBooleanResults are commonly used
// to clip geometry to a surface, for example to a slanted roof. For openings that are filled // to clip geometry to a surface, for example to a slanted roof. For openings that are filled
// with another element, for example a door or a window, an IfcOpeningElement is used instead. // with another element, for example a door or a window, an IfcOpeningElement is used instead.
// An opening element is created with rectangular geometry: // An opening element is created with rectangular geometry:
IfcSchema::IfcOpeningElement* west_opening = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), auto west_opening = file.create<IfcSchema::IfcOpeningElement>();
null, null, null, file.addLocalPlacement(south_wall->ObjectPlacement(), -2500, 0, 400), west_opening.setGlobalId(guid());
file.addBox(6000, 3630, 1600), null west_opening.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
west_opening.setObjectPlacement(file.addLocalPlacement(south_wall.ObjectPlacement(), -2500, 0, 400));
west_opening.setRepresentation(file.addBox(6000, 3630, 1600));
#ifdef SCHEMA_IfcOpeningElement_HAS_PredefinedType #ifdef SCHEMA_IfcOpeningElement_HAS_PredefinedType
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING west_opening.setPredefinedType(IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING);
#endif #endif
// Relate the opening element to the wall. // Relate the opening element to the wall.
@@ -152,12 +153,14 @@ int main() {
void_element.setRelatingBuildingElement(south_wall); void_element.setRelatingBuildingElement(south_wall);
void_element.setRelatedOpeningElement(west_opening); void_element.setRelatedOpeningElement(west_opening);
// Now create an additional opening // Now create an additional opening
IfcSchema::IfcOpeningElement* south_opening = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), auto south_opening = file.create<IfcSchema::IfcOpeningElement>();
null, null, null, file.addLocalPlacement(storey_placement, 3000, 0, 400), south_opening.setGlobalId(guid());
file.addBox(1860, 3000, 1600), null south_opening.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
south_opening.setObjectPlacement(file.addLocalPlacement(storey_placement, 3000, 0, 400));
south_opening.setRepresentation(file.addBox(1860, 3000, 1600));
#ifdef SCHEMA_IfcOpeningElement_HAS_PredefinedType #ifdef SCHEMA_IfcOpeningElement_HAS_PredefinedType
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING south_opening.setPredefinedType(IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING);
#endif #endif
// Relate the opening element to the wall. // Relate the opening element to the wall.
@@ -167,46 +170,17 @@ int main() {
void_element2.setRelatingBuildingElement(south_wall); void_element2.setRelatingBuildingElement(south_wall);
void_element2.setRelatedOpeningElement(south_opening); void_element2.setRelatedOpeningElement(south_opening);
// CV-2x3-144: Roofs are aggregates and shall have at least one contained element and no own geometry // Create a roof element that will consist of two slabs:
IfcSchema::IfcSlab* south_roof_part = new IfcSchema::IfcSlab(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), "South roof"s, auto roof = file.create<IfcSchema::IfcRoof>();
null, null, 0, 0, null, IfcSchema::IfcSlabTypeEnum::IfcSlabType_ROOF); roof.setGlobalId(guid());
roof.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
// The geometry is instantiated by using IfcMappedItems. This way geometry definitions can roof.setName("Roof");
// be reused while maintaining the cardinality constraint that the ShapeOfProduct relation roof.setObjectPlacement(file.addLocalPlacement(storey_placement));
// imposes on the IfcProductDefinitionShape. Note that this constrained is lifted in IFC4. #ifdef SCHEMA_IfcRoof_HAS_PredefinedType
south_roof_part->setRepresentation(file.addMappedItem(roof_rep)); roof.setPredefinedType(IfcSchema::IfcRoofTypeEnum::IfcRoofType_GABLE_ROOF);
south_roof_part->setObjectPlacement(file.addLocalPlacement(roof->ObjectPlacement(), 0, -400, 2700)); #else
roof.setShapeType(IfcSchema::IfcRoofTypeEnum::IfcRoofType_GABLE_ROOF);
// The same roof geometry is re-used on the north side of the roof, by inverting the X-axis of #endif
// the local placement the roof is rotated 180 degrees around the Z-axis
IfcSchema::IfcSlab* north_roof_part = new IfcSchema::IfcSlab(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), "North roof"s,
null, null, 0, 0, null, IfcSchema::IfcSlabTypeEnum::IfcSlabType_ROOF);
north_roof_part->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
north_roof_part->setRepresentation(file.addMappedItem(roof_rep));
north_roof_part->setObjectPlacement(file.addLocalPlacement(roof->ObjectPlacement(), 0, 5400, 2700, 0, 0, 1, -1, 0, 0));
IfcSchema::IfcObjectDefinition::list::ptr roof_parts(new IfcSchema::IfcObjectDefinition::list);
roof_parts->push(south_roof_part);
roof_parts->push(north_roof_part);
IfcSchema::IfcRelDecomposes* roof_decomposition = new IfcSchema::IfcRelAggregates(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, roof, roof_parts);
file.addEntity(roof_decomposition);
file.addBuildingProduct(south_roof_part);
file.addBuildingProduct(north_roof_part);
file.addBuildingProduct(roof);
setSurfaceColour(file, roof_rep, 0.24, 0.08, 0.04);
// Copy the south wall to the north
IfcSchema::IfcWallStandardCase* north_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), "North wall"s,
null, null, file.addLocalPlacement(storey_placement, 0, 5000, 0), file.addAxisBox(10000, 360, 3000), null
#ifdef SCHEMA_IfcWall_HAS_PredefinedType
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD
#endif
);
file.addBuildingProduct(north_wall);
setSurfaceColour(file,north_wall->Representation(), wall_colour);
// The roof geometry is slanted 45 degrees by specifying a direction for the box extrusion // The roof geometry is slanted 45 degrees by specifying a direction for the box extrusion
auto roof_rep = file.addEmptyRepresentation(); auto roof_rep = file.addEmptyRepresentation();
@@ -225,37 +199,102 @@ int main() {
south_roof_part.setRepresentation(file.addMappedItem(roof_rep)); south_roof_part.setRepresentation(file.addMappedItem(roof_rep));
south_roof_part.setObjectPlacement(file.addLocalPlacement(roof.ObjectPlacement(), 0, -400, 2700)); south_roof_part.setObjectPlacement(file.addLocalPlacement(roof.ObjectPlacement(), 0, -400, 2700));
// Now create a wall on the east of the building, again starting with just a box shape // The same roof geometry is re-used on the north side of the roof, by inverting the X-axis of
IfcSchema::IfcWallStandardCase* east_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), // the local placement the roof is rotated 180 degrees around the Z-axis
"East wall"s, null, null, file.addLocalPlacement(storey_placement, 4820, 2500, 0, 0, 0, 1, 0, 1, 0), clipped_wall_body_reps[0], null auto north_roof_part = file.create<IfcSchema::IfcSlab>();
#ifdef SCHEMA_IfcWall_HAS_PredefinedType north_roof_part.setGlobalId(guid());
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD north_roof_part.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
#endif north_roof_part.setName("North roof");
); north_roof_part.setPredefinedType(IfcSchema::IfcSlabTypeEnum::IfcSlabType_ROOF);
file.addBuildingProduct(east_wall); north_roof_part.setRepresentation(file.addMappedItem(roof_rep));
north_roof_part.setObjectPlacement(file.addLocalPlacement(roof.ObjectPlacement(), 0, 5400, 2700, 0, 0, 1, -1, 0, 0));
// The east wall is copied to the west location of the house auto roof_decomposition = file.create<IfcSchema::IfcRelAggregates>();
IfcSchema::IfcWallStandardCase* west_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), roof_decomposition.setGlobalId(guid());
"West wall"s, null, null, file.addLocalPlacement(storey_placement, -4820, 2500, 0, 0, 0, 1, 0, -1, 0), clipped_wall_body_reps[1], null roof_decomposition.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
roof_decomposition.setRelatingObject(roof);
roof_decomposition.setRelatedObjects({south_roof_part, north_roof_part});
file.addBuildingProduct(south_roof_part);
file.addBuildingProduct(north_roof_part);
file.addBuildingProduct(roof);
setSurfaceColour(file, roof_rep, 0.24, 0.08, 0.04);
// Copy the south wall to the north
auto north_wall = file.create<IfcSchema::IfcWallStandardCase>();
north_wall.setGlobalId(guid());
north_wall.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
north_wall.setName("North wall");
north_wall.setObjectPlacement(file.addLocalPlacement(storey_placement, 0, 5000, 0));
north_wall.setRepresentation(file.addAxisBox(10000, 360, 3000));
#ifdef SCHEMA_IfcWall_HAS_PredefinedType #ifdef SCHEMA_IfcWall_HAS_PredefinedType
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD north_wall.setPredefinedType(IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD);
#endif #endif
);
file.addBuildingProduct(west_wall); file.addBuildingProduct(north_wall);
setSurfaceColour(file, north_wall.Representation(), wall_colour);
// Two identical representations are created for the two remaining walls. Mapped items
// are not used, because it is not allowed by the standard for wall body representations.
// MappedItems are not allowed for Axis representations as per CV-2x3-161
IfcSchema::IfcProductDefinitionShape clipped_wall_body_reps[2];
for (int i = 0; i < 2; ++i) {
auto body = file.addEmptyRepresentation();
file.addBox(body, 5000, 360, 6000);
file.clipRepresentation(body, file.addPlacement3d(-2500, 0, 3000, -1, 0, 1), false);
file.clipRepresentation(body, file.addPlacement3d(2500, 0, 3000, 1, 0, 1), false);
setSurfaceColour(file, body, wall_colour);
auto axis = file.addEmptyRepresentation("Axis", "Curve2D");
file.addAxis(axis, 5000);
clipped_wall_body_reps[i] = file.create<IfcSchema::IfcProductDefinitionShape>();
clipped_wall_body_reps[i].setRepresentations({body, axis});
}
// Now create a wall on the east of the building, again starting with just a box shape
auto east_wall = file.create<IfcSchema::IfcWallStandardCase>();
east_wall.setGlobalId(guid());
east_wall.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
east_wall.setName("East wall");
east_wall.setObjectPlacement(file.addLocalPlacement(storey_placement, 4820, 2500, 0, 0, 0, 1, 0, 1, 0));
east_wall.setRepresentation(clipped_wall_body_reps[0]);
#ifdef SCHEMA_IfcWall_HAS_PredefinedType
east_wall.setPredefinedType(IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD);
#endif
file.addBuildingProduct(east_wall); file.addBuildingProduct(east_wall);
// Not all viewers support opening elements with mapped representations, hence an exact copy of the // The east wall is copied to the west location of the house
// same subtraction box is instantiated for the otherwise identical opening element. auto west_wall = file.create<IfcSchema::IfcWallStandardCase>();
IfcSchema::IfcOpeningElement* west_opening_copy = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), west_wall.setGlobalId(guid());
null, null, null, file.addLocalPlacement(west_wall->ObjectPlacement(), 2500, -2500+4820, 400, 0, 0, 1, 0, 1, 0), west_wall.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
file.addBox(6000, 3630, 1600), null west_wall.setName("West wall");
west_wall.setObjectPlacement(file.addLocalPlacement(storey_placement, -4820, 2500, 0, 0, 0, 1, 0, -1, 0));
west_wall.setRepresentation(clipped_wall_body_reps[1]);
#ifdef SCHEMA_IfcWall_HAS_PredefinedType
west_wall.setPredefinedType(IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD);
#endif
file.addBuildingProduct(west_wall);
// Not all viewers support opening elements with mapped representations, hence an exact copy of the
// same subtraction box is instantiated for the otherwise identical opening element.
auto west_opening_copy = file.create<IfcSchema::IfcOpeningElement>();
west_opening_copy.setGlobalId(guid());
west_opening_copy.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
west_opening_copy.setObjectPlacement(file.addLocalPlacement(west_wall.ObjectPlacement(), 2500, -2500 + 4820, 400, 0, 0, 1, 0, 1, 0));
west_opening_copy.setRepresentation(file.addBox(6000, 3630, 1600));
#ifdef SCHEMA_IfcOpeningElement_HAS_PredefinedType #ifdef SCHEMA_IfcOpeningElement_HAS_PredefinedType
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING west_opening_copy.setPredefinedType(IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING);
#endif #endif
);
file.addEntity(west_opening_copy); auto west_void = file.create<IfcSchema::IfcRelVoidsElement>();
file.addEntity(new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, west_wall, west_opening_copy)); west_void.setGlobalId(guid());
west_void.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
west_void.setRelatingBuildingElement(west_wall);
west_void.setRelatedOpeningElement(west_opening_copy);
// Up until now we have only used simple extrusions for the creation of the geometry. For the // Up until now we have only used simple extrusions for the creation of the geometry. For the
// ground mesh of the IfcSite we will use a Nurbs surface created in Open Cascade. The surface // ground mesh of the IfcSite we will use a Nurbs surface created in Open Cascade. The surface
@@ -269,17 +308,11 @@ int main() {
BRepGProp::SurfaceProperties(shape, prop); BRepGProp::SurfaceProperties(shape, prop);
const double site_area = prop.Mass() / 1000 / 1000; const double site_area = prop.Mass() / 1000 / 1000;
IfcSchema::IfcProperty::list::ptr properties(new IfcSchema::IfcProperty::list); auto total_area = file.create<IfcSchema::IfcPropertySingleValue>();
properties->push(new IfcSchema::IfcPropertySingleValue("TotalArea", null, new IfcSchema::IfcAreaMeasure(site_area), 0)); total_area.setName("TotalArea");
IfcSchema::IfcPropertySet* pset = new IfcSchema::IfcPropertySet(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), "Pset_SiteCommon"s, null, properties); auto area = file.create<IfcSchema::IfcAreaMeasure>();
#ifdef SCHEMA_HAS_IfcDefinitionSelect area.set_attribute_value(0, site_area);
IfcSchema::IfcObjectDefinition::list::ptr related_objs(new IfcSchema::IfcObjectDefinition::list); total_area.setNominalValue(area);
#else
IfcSchema::IfcObject::list::ptr related_objs(new IfcSchema::IfcObject::list);
#endif
related_objs->push(file.getSingle<IfcSchema::IfcSite>());
IfcSchema::IfcRelDefinesByProperties* site_prop = new IfcSchema::IfcRelDefinesByProperties(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, related_objs, pset);
file.addEntity(site_prop);
auto pset = file.create<IfcSchema::IfcPropertySet>(); auto pset = file.create<IfcSchema::IfcPropertySet>();
pset.setGlobalId(guid()); pset.setGlobalId(guid());
@@ -307,52 +340,12 @@ int main() {
// Some BIM authoring applications, such as Autodesk Revit, ignore the geometrical representation // Some BIM authoring applications, such as Autodesk Revit, ignore the geometrical representation
// by and large and construct native walls using the layer thickness and reference line offset // by and large and construct native walls using the layer thickness and reference line offset
// provided here. // provided here.
#ifdef SCHEMA_IfcMaterial_HAS_Description auto material = file.create<IfcSchema::IfcMaterial>();
IfcSchema::IfcMaterial* material = new IfcSchema::IfcMaterial("Brick", null, null); material.setName("Brick");
#else
IfcSchema::IfcMaterial* material = new IfcSchema::IfcMaterial("Brick");
#endif
IfcSchema::IfcMaterialLayer* layer = new IfcSchema::IfcMaterialLayer(
material,
360,
null
#ifdef SCHEMA_IfcMaterialLayer_HAS_Name
, null
, null
, null
, null
#endif
);
IfcSchema::IfcMaterialLayer::list::ptr layers (new aggregate_of<IfcSchema::IfcMaterialLayer>());
layers->push(layer);
IfcSchema::IfcMaterialLayerSet* layer_set = new IfcSchema::IfcMaterialLayerSet(
layers,
"Wall"s
#ifdef SCHEMA_IfcMaterialLayerSet_HAS_Description
, null
#endif
);
IfcSchema::IfcMaterialLayerSetUsage* layer_usage = new IfcSchema::IfcMaterialLayerSetUsage(
layer_set,
IfcSchema::IfcLayerSetDirectionEnum::IfcLayerSetDirection_AXIS2,
IfcSchema::IfcDirectionSenseEnum::IfcDirectionSense_POSITIVE,
-180
#ifdef SCHEMA_IfcMaterialLayerSetUsage_HAS_ReferenceExtent
, null
#endif
);
IfcSchema::IfcRelAssociatesMaterial* associates_material = new IfcSchema::IfcRelAssociatesMaterial( auto layer = file.create<IfcSchema::IfcMaterialLayer>();
guid(), layer.setMaterial(material);
file.getSingle<IfcSchema::IfcOwnerHistory>(), layer.setLayerThickness(360);
null,
null,
#ifdef SCHEMA_HAS_IfcDefinitionSelect
file.instances_by_type<IfcSchema::IfcWallStandardCase>()->as<IfcSchema::IfcDefinitionSelect>(),
#else
file.instances_by_type<IfcSchema::IfcWallStandardCase>()->as<IfcSchema::IfcRoot>(),
#endif
layer_usage);
auto layer_set = file.create<IfcSchema::IfcMaterialLayerSet>(); auto layer_set = file.create<IfcSchema::IfcMaterialLayerSet>();
layer_set.setMaterialLayers({layer}); layer_set.setMaterialLayers({layer});
@@ -379,34 +372,53 @@ int main() {
stair_points.push_back(XY(500, 200)); stair_points.push_back(XY(500, 200));
stair_points.push_back(XY(500, 400)); stair_points.push_back(XY(500, 400));
stair_points.push_back(XY( 0, 400)); stair_points.push_back(XY( 0, 400));
IfcSchema::IfcStairFlight* stair = new IfcSchema::IfcStairFlight(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), auto stair = file.create<IfcSchema::IfcStairFlight>();
null, null, null, file.addLocalPlacement(storey_placement, 5050, 1000, 0, 0, 1, 0, 1, 0, 0), stair.setGlobalId(guid());
file.addExtrudedPolyline(stair_points, 1200), null, 2, 2, 0.2, 0.25 stair.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
stair.setObjectPlacement(file.addLocalPlacement(storey_placement, 5050, 1000, 0, 0, 1, 0, 1, 0, 0));
stair.setRepresentation(file.addExtrudedPolyline(stair_points, 1200));
#ifdef SCHEMA_IfcStairFlight_HAS_NumberOfRisers
stair.setNumberOfRisers(2);
#else
stair.setNumberOfRiser(2);
#endif
stair.setNumberOfTreads(2);
stair.setRiserHeight(0.2);
stair.setTreadLength(0.25);
#ifdef SCHEMA_IfcStairFlight_HAS_PredefinedType #ifdef SCHEMA_IfcStairFlight_HAS_PredefinedType
, IfcSchema::IfcStairFlightTypeEnum::IfcStairFlightType_STRAIGHT stair.setPredefinedType(IfcSchema::IfcStairFlightTypeEnum::IfcStairFlightType_STRAIGHT);
#endif #endif
file.addBuildingProduct(stair); file.addBuildingProduct(stair);
setSurfaceColour(file, stair.Representation(), footing_colour); setSurfaceColour(file, stair.Representation(), footing_colour);
IfcSchema::IfcOpeningElement* door_opening = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), auto door_opening = file.create<IfcSchema::IfcOpeningElement>();
null, null, null, file.addLocalPlacement(storey_placement, 5000-180, 2500-900, 0), file.addBox(1000, 1000, 2200), null door_opening.setGlobalId(guid());
door_opening.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
door_opening.setObjectPlacement(file.addLocalPlacement(storey_placement, 5000 - 180, 2500 - 900, 0));
door_opening.setRepresentation(file.addBox(1000, 1000, 2200));
#ifdef SCHEMA_IfcOpeningElement_HAS_PredefinedType #ifdef SCHEMA_IfcOpeningElement_HAS_PredefinedType
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING door_opening.setPredefinedType(IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING);
#endif #endif
);
file.addEntity(door_opening); auto door_void = file.create<IfcSchema::IfcRelVoidsElement>();
file.addEntity(new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, east_wall, door_opening)); door_void.setGlobalId(guid());
door_void.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
door_void.setRelatingBuildingElement(east_wall);
door_void.setRelatedOpeningElement(door_opening);
// A single shape representation can contain multiple representiation items. This way a product // A single shape representation can contain multiple representiation items. This way a product
// can be a composition of multiple solids. The following door will be composed of four boxes // can be a composition of multiple solids. The following door will be composed of four boxes
// which constitute the door and its frame. // which constitute the door and its frame.
IfcSchema::IfcDoor* door = new IfcSchema::IfcDoor(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, null, auto door = file.create<IfcSchema::IfcDoor>();
file.addLocalPlacement(storey_placement, 4800, 1600, 0, 0, 0, 1, 0, 1, 0), 0, null, 2200, 1000 door.setGlobalId(guid());
door.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
door.setObjectPlacement(file.addLocalPlacement(storey_placement, 4800, 1600, 0, 0, 0, 1, 0, 1, 0));
door.setOverallWidth(1000);
door.setOverallHeight(2200);
#ifdef SCHEMA_IfcDoor_HAS_PredefinedType #ifdef SCHEMA_IfcDoor_HAS_PredefinedType
, IfcSchema::IfcDoorTypeEnum::IfcDoorType_DOOR door.setPredefinedType(IfcSchema::IfcDoorTypeEnum::IfcDoorType_DOOR);
, IfcSchema::IfcDoorTypeOperationEnum::IfcDoorTypeOperation_SINGLE_SWING_LEFT door.setOperationType(IfcSchema::IfcDoorTypeOperationEnum::IfcDoorTypeOperation_SINGLE_SWING_LEFT);
, null
#endif #endif
door.setRepresentation(file.addBox(80, 80, 2120, IfcSchema::IfcAxis2Placement2D{}, file.addPlacement3d(460, 0, 0))); door.setRepresentation(file.addBox(80, 80, 2120, IfcSchema::IfcAxis2Placement2D{}, file.addPlacement3d(460, 0, 0)));
@@ -424,13 +436,31 @@ int main() {
file.addBox(door_body, 860, 30, 2120); file.addBox(door_body, 860, 30, 2120);
file.addBuildingProduct(door); file.addBuildingProduct(door);
setSurfaceColour(file, door.Representation(), 0.9, 0.9, 0.9);
auto fills = file.create<IfcSchema::IfcRelFillsElement>();
fills.setGlobalId(guid());
fills.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
fills.setRelatingOpeningElement(door_opening);
fills.setRelatedBuildingElement(door);
#ifdef SCHEMA_HAS_IfcDoorType #ifdef SCHEMA_HAS_IfcDoorType
IfcSchema::IfcDoorType* door_type = new IfcSchema::IfcDoorType(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), "Door type"s, null, null, null, null, null, null, auto door_type = file.create<IfcSchema::IfcDoorType>();
IfcSchema::IfcDoorTypeEnum::IfcDoorType_DOOR, IfcSchema::IfcDoorTypeOperationEnum::IfcDoorTypeOperation_SINGLE_SWING_LEFT, false, null); door_type.setGlobalId(guid());
door_type.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
door_type.setName("Door type");
door_type.setPredefinedType(IfcSchema::IfcDoorTypeEnum::IfcDoorType_DOOR);
door_type.setOperationType(IfcSchema::IfcDoorTypeOperationEnum::IfcDoorTypeOperation_SINGLE_SWING_LEFT);
door_type.setParameterTakesPrecedence(false);
file.addRelatedObject<IfcSchema::IfcRelDefinesByType>(door_type, door); file.addRelatedObject<IfcSchema::IfcRelDefinesByType>(door_type, door);
#elif defined(SCHEMA_HAS_IfcDoorStyle) #elif defined(SCHEMA_HAS_IfcDoorStyle)
IfcSchema::IfcDoorStyle* door_style = new IfcSchema::IfcDoorStyle(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), "Door type"s, null, null, null, null, null, auto door_style = file.create<IfcSchema::IfcDoorStyle>();
IfcSchema::IfcDoorStyleOperationEnum::IfcDoorStyleOperation_SINGLE_SWING_LEFT, IfcSchema::IfcDoorStyleConstructionEnum::IfcDoorStyleConstruction_WOOD, false, false); door_style.setGlobalId(guid());
door_style.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
door_style.setName("Door type");
door_style.setOperationType(IfcSchema::IfcDoorStyleOperationEnum::IfcDoorStyleOperation_SINGLE_SWING_LEFT);
door_style.setConstructionType(IfcSchema::IfcDoorStyleConstructionEnum::IfcDoorStyleConstruction_WOOD);
door_style.setParameterTakesPrecedence(false);
door_style.setSizeable(false);
file.addRelatedObject<IfcSchema::IfcRelDefinesByType>(door_style, door); file.addRelatedObject<IfcSchema::IfcRelDefinesByType>(door_style, door);
#endif #endif
@@ -458,8 +488,8 @@ int main() {
frame_representations.push_back(vertical_bar); // Add another reference to the vertical bar created above frame_representations.push_back(vertical_bar); // Add another reference to the vertical bar created above
// The beams all have the same surface style assigned // The beams all have the same surface style assigned
surface_style_t* frame_style = 0; surface_style_t frame_style;
for (IfcSchema::IfcShapeRepresentation::list::it i = frame_representations->begin(); i != frame_representations->end(); i += 2) { for (auto i = frame_representations.begin(); i != frame_representations.end(); i += 2) {
if (frame_style) { if (frame_style) {
setSurfaceColour(file, *i, frame_style); setSurfaceColour(file, *i, frame_style);
} else { } else {
@@ -477,16 +507,18 @@ int main() {
window_placements.push_back(file.addLocalPlacement(storey_placement, 3000-930, -45, 400)); window_placements.push_back(file.addLocalPlacement(storey_placement, 3000-930, -45, 400));
window_placements.push_back(file.addLocalPlacement(storey_placement, -4855+45, 885-930, 400, 0, 0, 1, 0, 1, 0)); window_placements.push_back(file.addLocalPlacement(storey_placement, -4855+45, 885-930, 400, 0, 0, 1, 0, 1, 0));
for (IfcSchema::IfcLocalPlacement::list::it it = window_placements->begin(); it != window_placements->end(); ++it) { for (auto& place : window_placements) {
// Create the window at the current location // Create the window at the current location
IfcSchema::IfcLocalPlacement* place = *it; auto window = file.create<IfcSchema::IfcWindow>();
IfcSchema::IfcWindow* window = new IfcSchema::IfcWindow(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), window.setGlobalId(guid());
null, null, null, place, 0, null, 1600, 1860 window.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
window.setObjectPlacement(place);
window.setOverallWidth(1860);
window.setOverallHeight(1600);
#ifdef SCHEMA_IfcWindow_HAS_PredefinedType #ifdef SCHEMA_IfcWindow_HAS_PredefinedType
, IfcSchema::IfcWindowTypeEnum::IfcWindowType_WINDOW window.setPredefinedType(IfcSchema::IfcWindowTypeEnum::IfcWindowType_WINDOW);
, IfcSchema::IfcWindowTypePartitioningEnum::IfcWindowTypePartitioning_SINGLE_PANEL window.setPartitioningType(IfcSchema::IfcWindowTypePartitioningEnum::IfcWindowTypePartitioning_SINGLE_PANEL);
, null
#endif #endif
file.addBuildingProduct(window); file.addBuildingProduct(window);
@@ -508,20 +540,26 @@ int main() {
frame_placement != frame_placements.end() && frame_representation != frame_representations.end(); frame_placement != frame_placements.end() && frame_representation != frame_representations.end();
++frame_placement, ++frame_representation) ++frame_placement, ++frame_representation)
{ {
IfcSchema::IfcMember* frame_part = new IfcSchema::IfcMember(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), auto frame_part = file.create<IfcSchema::IfcMember>();
null, null, null, *frame_placement, file.addMappedItem(*frame_representation), null frame_part.setGlobalId(guid());
frame_part.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
frame_part.setObjectPlacement(*frame_placement);
frame_part.setRepresentation(file.addMappedItem(*frame_representation));
#ifdef SCHEMA_IfcMember_HAS_PredefinedType #ifdef SCHEMA_IfcMember_HAS_PredefinedType
, IfcSchema::IfcMemberTypeEnum::IfcMemberType_MULLION frame_part.setPredefinedType(IfcSchema::IfcMemberTypeEnum::IfcMemberType_MULLION);
#endif #endif
window_parts.push_back(frame_part); window_parts.push_back(frame_part);
file.relatePlacements(window, frame_part); file.relatePlacements(window, frame_part);
} }
// Add the glass plate to the list of parts // Add the glass plate to the list of parts
IfcSchema::IfcPlate* glass_part = new IfcSchema::IfcPlate(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, auto glass_part = file.create<IfcSchema::IfcPlate>();
null, null, file.addLocalPlacement(storey_placement, 930, 45, 90), file.addBox(1680, 10, 1420), null glass_part.setGlobalId(guid());
glass_part.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
glass_part.setObjectPlacement(file.addLocalPlacement(storey_placement, 930, 45, 90));
glass_part.setRepresentation(file.addBox(1680, 10, 1420));
#ifdef SCHEMA_IfcPlate_HAS_PredefinedType #ifdef SCHEMA_IfcPlate_HAS_PredefinedType
, IfcSchema::IfcPlateTypeEnum::IfcPlateType_SHEET glass_part.setPredefinedType(IfcSchema::IfcPlateTypeEnum::IfcPlateType_SHEET);
#endif #endif
window_parts.push_back(glass_part); window_parts.push_back(glass_part);
+38 -19
View File
@@ -25,6 +25,7 @@
#include "ifcparse/file.h" #include "ifcparse/file.h"
#include "ifcparse/logger.h" #include "ifcparse/logger.h"
#include "plugin/plugin.h"
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema) #include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema) #include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
@@ -47,13 +48,29 @@ struct is_ifc4_or_higher<T, std::void_t<decltype(T::IfcMaterialDefinition)>> : s
typedef std::map<std::string, std::map<std::string, std::string>> element_properties; typedef std::map<std::string, std::map<std::string, std::string>> element_properties;
std::string string_value(const std::string& value) {
return value;
}
std::string string_value(const std::optional<std::string>& value) {
return value.value_or("");
}
bool has_string(const std::string& value) {
return !value.empty();
}
bool has_string(const std::optional<std::string>& value) {
return value.has_value();
}
#ifdef SCHEMA_HAS_IfcBuildingElement #ifdef SCHEMA_HAS_IfcBuildingElement
typedef IfcSchema::IfcBuildingElement element_t; typedef IfcSchema::IfcBuildingElement element_t;
#else #else
typedef IfcSchema::IfcBuiltElement element_t; typedef IfcSchema::IfcBuiltElement element_t;
#endif #endif
std::string format_string(const AttributeValue& argument) { std::string format_string(const attribute_value& argument) {
// Argument is a runtime tagged variant for the various data types in a IFC model, // Argument is a runtime tagged variant for the various data types in a IFC model,
// in this particular case we only care about flattening it to a string. // in this particular case we only care about flattening it to a string.
// @todo mostly duplicated from XmlSerializer.cpp // @todo mostly duplicated from XmlSerializer.cpp
@@ -62,21 +79,21 @@ std::string format_string(const AttributeValue& argument) {
} }
auto argument_type = argument.type(); auto argument_type = argument.type();
switch (argument_type) { switch (argument_type) {
case IfcUtil::Argument_BOOL: { case ifcopenshell::Argument_BOOL: {
const bool b = argument; const bool b = argument;
return b ? "true" : "false"; return b ? "true" : "false";
} }
case IfcUtil::Argument_DOUBLE: { case ifcopenshell::Argument_DOUBLE: {
const double d = argument; const double d = argument;
std::stringstream stream; std::stringstream stream;
stream << std::setprecision(std::numeric_limits< double >::max_digits10) << d; stream << std::setprecision(std::numeric_limits< double >::max_digits10) << d;
return stream.str(); return stream.str();
break; } break; }
case IfcUtil::Argument_STRING: case ifcopenshell::Argument_STRING:
case IfcUtil::Argument_ENUMERATION: { case ifcopenshell::Argument_ENUMERATION: {
return static_cast<std::string>(argument); return static_cast<std::string>(argument);
break; } break; }
case IfcUtil::Argument_INT: { case ifcopenshell::Argument_INT: {
const int v = argument; const int v = argument;
std::stringstream stream; std::stringstream stream;
stream << v; stream << v;
@@ -90,40 +107,38 @@ template <typename Schema, typename T>
void process_pset(element_properties& props, const T& inst) { void process_pset(element_properties& props, const T& inst) {
// Process an individual Property or Quantity set. // Process an individual Property or Quantity set.
if (auto pset = inst.template as<typename Schema::IfcPropertySet>()) { if (auto pset = inst.template as<typename Schema::IfcPropertySet>()) {
if (!pset.Name()) { auto pset_name = pset.Name();
if (!has_string(pset_name)) {
return; return;
} }
auto ps = pset.HasProperties(); auto ps = pset.HasProperties();
for (const auto& p : ps) { for (const auto& p : ps) {
if (auto singleval = p.template as<typename Schema::IfcPropertySingleValue>()) { if (auto singleval = p.template as<typename Schema::IfcPropertySingleValue>()) {
std::string propname, propvalue; std::string propname, propvalue;
if constexpr (is_ifc4_or_higher<Schema>::value) { auto property_name = singleval.Name();
if (!singleval.Name()) { if (!has_string(property_name)) {
continue; continue;
}
propname = *singleval.Name();
}
if constexpr (!is_ifc4_or_higher<Schema>::value) {
propname = *singleval.Name();
} }
propname = string_value(property_name);
auto nominal_value = singleval.NominalValue(); auto nominal_value = singleval.NominalValue();
if (!nominal_value) { if (!nominal_value) {
propvalue = "-"; propvalue = "-";
} else { } else {
props[*pset.Name()][propname] = format_string(nominal_value.get_attribute_value(0)); props[string_value(pset_name)][propname] = format_string(nominal_value.get_attribute_value(0));
} }
} }
} }
} }
if (auto qset = inst.template as<typename Schema::IfcElementQuantity>()) { if (auto qset = inst.template as<typename Schema::IfcElementQuantity>()) {
if (!qset.Name()) { auto qset_name = qset.Name();
if (!has_string(qset_name)) {
return; return;
} }
auto qs = qset.Quantities(); auto qs = qset.Quantities();
for (const auto& q : qs) { for (const auto& q : qs) {
if (q.template as<typename Schema::IfcPhysicalSimpleQuantity>() && q.get_attribute_value(3).type() == IfcUtil::Argument_DOUBLE) { if (q.template as<typename Schema::IfcPhysicalSimpleQuantity>() && q.get_attribute_value(3).type() == ifcopenshell::Argument_DOUBLE) {
double v = q.get_attribute_value(3); double v = q.get_attribute_value(3);
props[*qset.Name()][q.Name()] = std::to_string(v); props[string_value(qset_name)][string_value(q.Name())] = std::to_string(v);
} }
} }
} }
@@ -193,6 +208,10 @@ int main(int argc, char** argv) {
return 1; return 1;
} }
#ifdef IFCOPENSHELL_EXAMPLE_PLUGIN_PATH
ifcopenshell::plugin::set_search_paths({IFCOPENSHELL_EXAMPLE_PLUGIN_PATH});
#endif
// Redirect the output (both progress and log) to stdout // Redirect the output (both progress and log) to stdout
::logger::root().set_output(&std::cout, &std::cout); ::logger::root().set_output(&std::cout, &std::cout);
+1 -1
View File
@@ -268,7 +268,7 @@ Ifc4x3_add2::IfcAlignment addHorizontalAlignment(hierarchy_helper<Ifc4x3_add2>&
return alignment; return alignment;
} }
std::tuple<typename std::vector<Ifc4x3_add2::IfcObjectDefinition>&, typename std::vector<Ifc4x3_add2::IfcSegment>&, Ifc4x3_add2::IfcGradientCurve> _createVerticalAlignment(hierarchy_helper<Ifc4x3_add2>& file, Ifc4x3_add2::IfcCompositeCurve composite_curve,const std::vector<std::pair<double, double>>& vpoints, const std::vector<double>& vclengths, bool include_geometry) { std::tuple<std::vector<Ifc4x3_add2::IfcObjectDefinition>, std::vector<Ifc4x3_add2::IfcSegment>, Ifc4x3_add2::IfcGradientCurve> _createVerticalAlignment(hierarchy_helper<Ifc4x3_add2>& file, Ifc4x3_add2::IfcCompositeCurve composite_curve,const std::vector<std::pair<double, double>>& vpoints, const std::vector<double>& vclengths, bool include_geometry) {
std::vector<Ifc4x3_add2::IfcObjectDefinition> vertical_segments; // business logic std::vector<Ifc4x3_add2::IfcObjectDefinition> vertical_segments; // business logic
std::vector<Ifc4x3_add2::IfcSegment> vertical_curve_segments; // geometry std::vector<Ifc4x3_add2::IfcSegment> vertical_curve_segments; // geometry
+8 -1
View File
@@ -26,6 +26,7 @@
#endif #endif
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <boost/dll/runtime_symbol_info.hpp>
#include <boost/dll/shared_library.hpp> #include <boost/dll/shared_library.hpp>
#include <algorithm> #include <algorithm>
@@ -449,7 +450,13 @@ std::filesystem::path ifcopenshell::plugin::module_directory(const void* symbol)
throw std::runtime_error("Unable to resolve module path"); throw std::runtime_error("Unable to resolve module path");
} }
const auto directory = std::filesystem::path(info.dli_fname).parent_path(); auto directory = std::filesystem::path(info.dli_fname).parent_path();
if (directory.empty()) {
// dladdr() returns the invocation string for symbols in the main
// executable. When it was found through PATH this can be just the
// executable name, so resolve the actual program location instead.
directory = boost::dll::program_location().parent_path();
}
plugin_debug("module_directory resolved " + path_string(directory)); plugin_debug("module_directory resolved " + path_string(directory));
return directory; return directory;
#endif #endif