From 420eed18283784f636ae61384fdf4b43f5d1819e Mon Sep 17 00:00:00 2001 From: Richard Brice <37087370+RickBrice@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:15:38 -0700 Subject: [PATCH] Adds new simplified alignment example that makes us of the alignment helper functions --- src/examples/CMakeLists.txt | 5 + src/examples/IfcAlignment.cpp | 4 + src/examples/IfcSimplifiedAlignment.cpp | 160 ++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 src/examples/IfcSimplifiedAlignment.cpp diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index 7abc1d42ea..9e71d86f31 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -36,3 +36,8 @@ endif() ADD_EXECUTABLE(IfcAlignment IfcAlignment.cpp) TARGET_LINK_LIBRARIES(IfcAlignment ${IFCOPENSHELL_LIBRARIES}) set_target_properties(IfcAlignment PROPERTIES FOLDER Examples) + + +ADD_EXECUTABLE(IfcSimplifiedAlignment IfcSimplifiedAlignment.cpp) +TARGET_LINK_LIBRARIES(IfcSimplifiedAlignment ${IFCOPENSHELL_LIBRARIES}) +set_target_properties(IfcSimplifiedAlignment PROPERTIES FOLDER Examples) diff --git a/src/examples/IfcAlignment.cpp b/src/examples/IfcAlignment.cpp index 89a6ee45a7..f9ece6d5cb 100644 --- a/src/examples/IfcAlignment.cpp +++ b/src/examples/IfcAlignment.cpp @@ -23,6 +23,9 @@ // https://www.fhwa.dot.gov/bridge/pubs/hif22034.pdf // // Sections and page number for this document are cited in the code comments. +// +// This examples differs from IfcSimplifiedAlignment because it builds the +// alignment explicitly // Disable warnings coming from IfcOpenShell #pragma warning(disable : 4018 4267 4250 4984 4985) @@ -409,6 +412,7 @@ int main() { // start by defining a gradient curve composed of the vertical curve segments and associated with the horizontal composite curve auto gradient_curve = new Schema::IfcGradientCurve(vertical_curve_segments, false, composite_curve, nullptr); + file.addEntity(gradient_curve); // the gradient curve is a representation item typename aggregate_of::ptr profile_representation_items(new aggregate_of()); diff --git a/src/examples/IfcSimplifiedAlignment.cpp b/src/examples/IfcSimplifiedAlignment.cpp new file mode 100644 index 0000000000..b811a88675 --- /dev/null +++ b/src/examples/IfcSimplifiedAlignment.cpp @@ -0,0 +1,160 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +// This example illustrates the basic of building an alignment model. +// The alignment is based on "Bridge Geometry Manual", April 2022 +// US Department of Transportation, Federal Highway Administration (FHWA) +// https://www.fhwa.dot.gov/bridge/pubs/hif22034.pdf +// +// Sections and page number for this document are cited in the code comments. +// +// This examples differs from IfcAlignment because it uses utility methods +// to simplify alignment construction + +// Disable warnings coming from IfcOpenShell +#pragma warning(disable : 4018 4267 4250 4984 4985) + +#include "../ifcparse/Ifc4x3_add2.h" +#include "../ifcparse/IfcAlignmentHelper.h" + +#include + +#define Schema Ifc4x3_add2 + +// performs basic project setup including created the IfcProject object +// and initializing the project units to FEET +Schema::IfcProject* setup_project(IfcHierarchyHelper& file) { + std::vector file_description; + file_description.push_back("ViewDefinition[Alignment-basedReferenceView]"); + file.header().file_description().description(file_description); + + auto project = file.addProject(); + project->setName(std::string("FHWA Bridge Geometry Manual Example Alignment")); + + // set up project units for feet + // the call to file.addProject() sets up length units as millimeter. + auto units_in_context = project->UnitsInContext(); + auto units = units_in_context->Units(); + auto begin = units->begin(); + auto iter = begin; + auto end = units->end(); + for (; iter != end; iter++) { + auto unit = *iter; + if (unit->as() && unit->as()->UnitType() == Schema::IfcUnitEnum::IfcUnit_LENGTHUNIT) { + auto dimensions = new Schema::IfcDimensionalExponents(1, 0, 0, 0, 0, 0, 0); + file.addEntity(dimensions); + + auto conversion_factor = new Schema::IfcMeasureWithUnit(new Schema::IfcLengthMeasure(304.80), unit->as()); + file.addEntity(conversion_factor); + + auto conversion_based_unit = new Schema::IfcConversionBasedUnit(dimensions, Schema::IfcUnitEnum::IfcUnit_LENGTHUNIT, "FEET", conversion_factor); + file.addEntity(conversion_based_unit); + + units->remove(unit); // remove the millimeter unit + units->push(conversion_based_unit); // add the feet unit + units_in_context->setUnits(units); // update the UnitsInContext + + break; // Done!, the length unit was found, so break out of the loop + } + } + + return project; +} + +int main() { + IfcHierarchyHelper file; + + auto project = setup_project(file); + + // + // Define horizontal alignment + // + + // PI Data + // B.1.1 pg 211 + std::vector> points{ + { 500.0, 2500.0}, // beginning + {3340.0, 660.0}, // Point of intersection (PI), Curve #1 + {4340.0, 5000.0}, // Point of intersection (PI), Curve #2 + {7600.0, 4560.0}, // Point of intersection (PI), Curve #3 + {8480.0, 2010.0} // ending + }; + + // Curve Data + // B.1.3 pg 212 + std::vector radii{ 1000,1250,950 }; + + // + // Define vertical profile segments + // + + // Vertical Profile Data + // Figure B.2 pg 213 + double xStart = 10000.0; // subtract xStart so the points are distance along, not station + std::vector> vpoints { + {10000.0-xStart,100.0}, // Vertical point of beginning (VPOB) + {12000.0-xStart,135.0}, // Point of vertical intersection (VPI), Curve #1 + {15000.0-xStart,105.0}, // Point of vertical intersection (VPI), Curve #2 + {17400.0-xStart,153.0}, // Point of vertical intersection (VPI), Curve #3 + {19800.0-xStart,105.0}, // Point of vertical intersection (VPI), Curve #4 + {22800.0-xStart, 90.0} // Vertical poitn of ending (VPOE) + }; + + // Vertical Curve Lengths + // Figure B.2 pg 213 + std::vector vclengths{1600.0, 1200.0, 2000.0, 800.0}; + + // Use utility function to create alignment + auto alignment = addAlignment(file, "Example Alignment", points, radii, vpoints, vclengths); + + // Define the alignment's relationship with the project + + // IFC 4.1.4.1.1 "Every IfcAlignment must be related to IfcProject using the IfcRelAggregates relationship" + // https://standards.buildingsmart.org/IFC/RELEASE/IFC4_3/HTML/concepts/Object_Composition/Aggregation/Alignment_Aggregation_To_Project/content.html + // IfcProject <-> IfcRelAggregates <-> IfcAlignment + typename aggregate_of::ptr list_of_alignments_in_project(new aggregate_of()); + list_of_alignments_in_project->push(alignment); + auto aggregate_alignments_with_project = new Schema::IfcRelAggregates(IfcParse::IfcGlobalId(), nullptr, std::string("Alignments in project"), boost::none, project, list_of_alignments_in_project); + file.addEntity(aggregate_alignments_with_project); + + // Define the spatial structure of the alignment with respect to the site + + // IFC 4.1.5.1 alignment is referenced in spatial structure of an IfcSpatialElement. In this case IfcSite is the highest level IfcSpatialElement + // https://standards.buildingsmart.org/IFC/RELEASE/IFC4_3/HTML/concepts/Object_Connectivity/Alignment_Spatial_Reference/content.html + // IfcSite <-> IfcRelReferencedInSpatialStructure <-> IfcAlignment + // This means IfcAlignment is not part of the IfcSite (it is not an aggregate component) but instead IfcAlignment is used within + // the IfcSite by reference. This implies an IfcAlignment can traverse many IfcSite instances within an IfcProject + typename Schema::IfcSpatialReferenceSelect::list::ptr list_alignments_referenced_in_site(new Schema::IfcSpatialReferenceSelect::list); + list_alignments_referenced_in_site->push(alignment); + + // Complete the model by creating sites for the 3 bridges + for (int i = 1; i <= 3; i++) { + std::ostringstream os; + os << "Site of Bridge " << i; + auto site = file.addSite(project, nullptr); + site->setName(os.str()); + + auto rel_referenced_in_spatial_structure = new Schema::IfcRelReferencedInSpatialStructure(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, list_alignments_referenced_in_site, site); + file.addEntity(rel_referenced_in_spatial_structure); + } + + // That's it - save the model to a file + std::ofstream ofs("FHWA_Bridge_Geometry_Alignment_Example_Simplified.ifc"); + ofs << file; +}