Compare commits

...

122 Commits

Author SHA1 Message Date
Thomas Krijnen 214c228962 Change signature of attribute setters to take and return boost::optionals
Remove set- prefix for setters
2015-03-20 21:11:46 +00:00
Thomas Krijnen a28b5517e8 Fix compilation with gcc. Thanks Ivano. 2015-03-13 10:40:31 +00:00
Thomas Krijnen df1805921b Create writable argument copies when duplicating entity instances 2015-03-12 17:54:52 +00:00
Thomas Krijnen 5ea13970c8 Instantiate xml_writer_settings based on boost version. Thanks Liam. 2015-03-06 15:49:46 +00:00
Thomas Krijnen aad6c77d00 Skip IfcSweptDiskSolid.InnerRadii under IfcGeometricRepresentationContext.Precision. Thanks Stefan. 2015-03-03 19:18:51 +00:00
Thomas Krijnen 9bbbc6e7d9 Extend Python's dir() function on entity instances with attribute and inverse attribute names of entities 2015-02-27 13:41:33 +00:00
Thomas Krijnen d41dbc386e DISABLE_TRIANGULATION for serializers that operate on Open Cascade's BRep format 2015-02-23 22:01:21 +00:00
Thomas Krijnen 9cd0a76f84 Update bl_info structure in blender addon 2015-02-23 19:13:47 +00:00
Thomas Krijnen dada40735b #include <xlocale.h> header on OS X 2015-02-20 22:02:22 +00:00
Thomas Krijnen 2ce89c8b22 Properly read the CONVERT_BACK_UNITS setting for serialized elements 2015-02-20 18:06:52 +00:00
Thomas Krijnen 0552c336df Correct omitted initialization list item from IfcGeom::IteratorSettings 2015-02-20 17:16:01 +00:00
Thomas Krijnen 349e7ddaa7 USE_WORLD_COORDS by default when USE_PYTHON_OPENCASCADE is set. 2015-02-20 16:03:20 +00:00
Thomas Krijnen f20ae8e25e create a setting to produce pythonOCC shapes for ifcopenshell.geom.iterator and -create_shape() 2015-02-19 21:45:17 +00:00
Thomas Krijnen 8f853ac5af Initialize the attributes of IfcLateBoundEntity to NULL upon construction.
Make sure IfcWritableEntity does not return null pointers, since getArgumentCount() is unreliable for instances being created from keyword arguments in Python.
2015-02-19 20:20:47 +00:00
Thomas Krijnen 6822e84849 Initialize IfcGeomIterator so that no entities are skipped by default 2015-02-19 20:17:53 +00:00
Thomas Krijnen 73266ea216 transfer ownership from Python to C++ when adding an instance to a file 2015-02-19 18:11:09 +00:00
Thomas Krijnen b0ccf69870 Don't add inverse references to the entity being added itself. 2015-02-19 14:42:19 +00:00
Thomas Krijnen 573655e5ef Add the possibility to bundle binary modules for different architectures with the python-ifcopenshell module 2015-02-19 13:37:37 +00:00
Thomas Krijnen 2a7135f347 Correct visibility of IfcBaseType methods. Thanks Ian. 2015-02-19 10:53:41 +00:00
Thomas Krijnen a57a305e9d Correctly cast writable enumeration attributes to string, as reported in: https://sourceforge.net/p/ifcopenshell/discussion/1782717/thread/53b70ea0 2015-02-17 22:14:09 +00:00
Thomas Krijnen e6ff1126ad Catch errors in entity traversal while adding a new entity. In particular for late bound instances having unset attributes. 2015-02-17 22:02:06 +00:00
Thomas Krijnen 6c8a60db6e Fixes related to r312: gcc refuses to erase a const_iterator 2015-02-17 21:24:18 +00:00
Thomas Krijnen b5c9de8d64 Changes related to r312 2015-02-17 20:36:23 +00:00
Thomas Krijnen 5fe4cfab63 More fixes related to locales 2015-02-17 20:23:21 +00:00
Thomas Krijnen b3e5264aa9 WARNING: more function renames 2015-02-17 20:07:09 +00:00
Thomas Krijnen e3d5b6220d Rename AddEntity to addEntity 2015-02-17 19:55:27 +00:00
Thomas Krijnen 846e881cf4 Update build files 2015-02-17 19:52:18 +00:00
Thomas Krijnen ee87466521 1) Implement a breadth-first traversal of forward references 2) implement entity instance deletion from a file 3) recursively copy entity instances to another file 2015-02-17 19:48:41 +00:00
Thomas Krijnen def1328a91 Some more checks and fixes in the IfcBooleanResult code. Most notably set the result to FirstOperand in case healing the result fails. 2015-02-06 17:14:05 +00:00
Thomas Krijnen a7c0c08725 Remove macro redefinition warning 2015-02-06 15:56:07 +00:00
Thomas Krijnen 63e9b706c1 Add missing #includes for OCC 6.8.0 specific #if 2015-02-06 14:20:33 +00:00
Thomas Krijnen 16d400e192 Stricter template syntax in latest commit 2015-02-06 13:37:50 +00:00
Thomas Krijnen 3801e52bff Add an XML serializer (NB: Not ifcXML / 10303-28) that describes property set data, decomposition relations and SPF header fields 2015-02-06 13:07:50 +00:00
Thomas Krijnen c597404dfe Increase the severity of the 'different schema' message 2015-02-06 12:59:36 +00:00
Thomas Krijnen 47b9ed4482 Add a cast in templated list conversion 2015-02-06 12:58:59 +00:00
Thomas Krijnen d23dee551c #ifdef away the two trailing precision arguments for gp_Trsf::SetValues() when OCC >= 6.8.0 2015-02-06 12:49:53 +00:00
Thomas Krijnen 79817341e0 Ignore entity types earlier in IfcConvert so that representations are not processed in vain 2015-02-05 11:55:25 +00:00
Thomas Krijnen 0124034803 Fix typo in locale code 2015-02-04 15:31:01 +00:00
Thomas Krijnen 2da6f5428d Make real number parsing and serializing locale-independent, as suggested by Ian Clevy. 2015-02-03 13:53:36 +00:00
Thomas Krijnen 5f677baf63 Fixes #30. Thanks to Ian Clevy. 2015-02-03 09:40:17 +00:00
Thomas Krijnen b5f055e54b Fix repr() of ifcopenshell.geom.settings 2015-01-29 11:34:11 +00:00
Thomas Krijnen 4c79f713ed Make sure C++ exceptions do not crash the Python interpreter 2015-01-26 18:11:48 +00:00
Thomas Krijnen b789839e4a Fix errors in serialization 2015-01-25 10:50:12 +00:00
Thomas Krijnen 23d5827229 Zero exit code when printing help and version information in IfcConvert 2015-01-23 16:10:49 +00:00
Thomas Krijnen f0425b16d1 Have a peek at a representation's context in the geometry wrapper as well to determine suitability for processing 2015-01-22 10:39:48 +00:00
Thomas Krijnen e1edda588e Properly test for the optional IfcGeometricRepresentationContext.ContextType being null in IfcGeomIterator.h 2015-01-22 10:38:35 +00:00
Thomas Krijnen 6c7c88d7a5 Python wrapper: enable iteration over all entities, get attribute optionality information 2015-01-21 17:01:22 +00:00
Thomas Krijnen 3503c8c933 Fix typo in wrapper generator 2015-01-20 14:39:52 +00:00
Thomas Krijnen e37b062757 python 2/3 compatibility: from functools import reduce 2015-01-20 13:52:08 +00:00
Thomas Krijnen 97b6f444d1 Use BRepMesh_IncrementalMesh rather than BRepMesh::Mesh. Thanks lorinma. 2015-01-19 16:02:34 +00:00
Thomas Krijnen 418dabaff2 Fix typo 2015-01-18 15:32:50 +00:00
Thomas Krijnen 7b17c2dccd Make header values writable 2015-01-16 16:26:40 +00:00
Thomas Krijnen f6f541ee3b Use BRepMesh_IncrementalMesh rather than BRepMesh::Mesh. Thanks lorinma. 2015-01-16 14:32:50 +00:00
Thomas Krijnen 09168d8910 Don't rely on operator bool() but on bool operator!() for truthiness of boost::optionals. Fixes compilation with boost 1.56+. 2015-01-16 13:24:40 +00:00
Thomas Krijnen e57f20f5f2 Small compilation fix 2015-01-14 09:39:52 +00:00
Thomas Krijnen 511e83c2c6 Shuffle around wrapper statements to fix setting arguments 2015-01-10 23:01:52 +00:00
Thomas Krijnen 8581fed39b Track inverse attributes more correctly
Rename Size() to size() on EntityList and friends
2015-01-10 22:13:52 +00:00
Thomas Krijnen 1d319f7ac4 Compilation fixes and python 2 compatibility. Thanks Yorik. 2015-01-07 10:22:55 +00:00
Thomas Krijnen 9780c047e9 Improvements for precision handling 2015-01-06 14:09:28 +00:00
Thomas Krijnen 1c757c351b Fix compilation of IfcOpenHouse, move IfcGeom::tesselate back directly in IfcGeom namespace 2015-01-06 10:19:24 +00:00
Thomas Krijnen f3c26c372d Parse the spf header and check schema_identifiers against compiled schema 2015-01-05 17:46:23 +00:00
Thomas Krijnen 4d5d749255 Merge developments from the python_wrapper branch into master 2015-01-05 14:11:42 +00:00
Thomas Krijnen 8872affe54 Update CMake build script 2014-12-19 12:37:31 +00:00
Thomas Krijnen 3236218aba Compilation fixes related to previous commit 2014-12-19 12:36:06 +00:00
Thomas Krijnen 2a403e240d *** See: https://sourceforge.net/p/ifcopenshell/discussion/1782718/thread/6bd0f843/ ***
Massive refactor of the IfcGeomObjects module, which is now the IfcGeom::Iterator class.
2014-12-19 12:14:36 +00:00
Thomas Krijnen 3f285ea639 Prevent another exception being thrown upon adding entity instances to a file, as reported by ch0kee 2014-11-27 09:22:58 +00:00
Thomas Krijnen 4c976c8b70 Track the surface style of an IfcBooleanResult 2014-11-26 14:32:54 +00:00
Thomas Krijnen d88d4d5951 Add support for IfcAsymmetricIShapeProfileDef 2014-11-26 14:01:31 +00:00
Thomas Krijnen eb815120dc Take unit information into account when applying precision. Thanks Stefan 2014-11-26 13:08:47 +00:00
Thomas Krijnen 7f8d84a1af Fix omitted return statement in previous commit 2014-11-17 15:32:00 +00:00
Thomas Krijnen 24044fb92a Catch all errors when parsing boost program_options in IfcConvert 2014-11-04 12:45:20 +00:00
Thomas Krijnen cd366bf8c2 Reconstruct the form of the transformation to improve the output of the OpenCascade-based serializers 2014-11-04 12:36:59 +00:00
Thomas Krijnen 96ce5f6b25 Don't compare smart pointers to zero, but convert to bool 2014-11-04 12:02:28 +00:00
Thomas Krijnen 120de2f601 Remove erroneous qualifier 2014-11-02 18:50:12 +00:00
Thomas Krijnen 872dd4e831 Rewrite IfcFile::AddEntity() not to rely on exceptions, as suggested by ch0kee. 2014-11-02 18:36:51 +00:00
Thomas Krijnen 6e44683b5d Add another IfcFacetedBrep test case 2014-07-28 20:12:52 +00:00
Thomas Krijnen e77216d41c More robust processing of IfcPolyline and IfcPolyLoop 2014-07-28 20:03:53 +00:00
Thomas Krijnen cf2e82e8f5 Create a compsolid shape for an extrusion of a IfcCompositeProfileDef and process the opening subtraction individually 2014-07-24 11:22:31 +00:00
Thomas Krijnen 9a1c7af953 Fixes for IfcRectangleHollowProfileDef and filleted profile generation. 2014-07-24 11:14:54 +00:00
Thomas Krijnen 5648b8d8bc Correct an invalid default value for IfcCartesianTransformationOperator3D.Axis3. Thanks Stefan. 2014-07-19 10:30:13 +00:00
Thomas Krijnen 1837b79ac3 Add faceted_brep_csg test case 2014-07-06 14:38:48 +00:00
Thomas Krijnen e6aa449ef8 Accept IfcBooleanResult operands that convert to set of shapes in IfcOpenShell rather than a single shape (i.e IfcShellBasedSurfaceModel, IfcFaceBasedSurfaceModel, IfcFacetedBrep, IfcGeometricSet) 2014-07-06 14:21:56 +00:00
Thomas Krijnen aa1ff90241 Remove a duplicated cartesian point from the closed polyline created by the addBox() function as seen in IfcOpenHouse. Thanks Bernd. 2014-06-28 12:39:40 +00:00
Thomas Krijnen 1c39eba3f7 Fix typo 2014-06-27 12:24:49 +00:00
Thomas Krijnen 92c5bb637b - Check the validity of solids created from sewed shells and potentially revert to a shell or compound of faces
- Flag shape representations, for which no item succeeds, as failed
2014-06-27 12:00:41 +00:00
Thomas Krijnen d45056f9c5 Increase precision for writing floats 2014-06-11 10:24:11 +00:00
Thomas Krijnen 83b6ce9083 Apply the same precision value when merging a compound of faces into a solid just-in-time for subtraction 2014-06-09 12:56:47 +00:00
Thomas Krijnen 81292f1adc Detect cases where Newell's Method returns a zero-length vector and make no attempt to normalize it in order to prevent an exception. In this case the face will be flagged as invalid down the road, because its perimeter doesn't span any area. 2014-06-07 17:49:21 +00:00
Thomas Krijnen 49e4ff31ca Fix header of IfcReinforcingBar.ifc 2014-05-14 09:01:33 +00:00
Thomas Krijnen 7066337449 Update IfcParseExamples 2014-05-12 13:56:41 +00:00
Thomas Krijnen 948d7675f0 - Take better care of inverse cardinalities and respect more CoordinationView agreements in IfcOpenHouse
- Track inverse relationships in an IfcWrite context as well
- Fix for lists of SELECT types
2014-05-05 16:17:28 +00:00
Thomas Krijnen 1b54ba039d - Add support for IFC4 nurbs surfaces (IfcBSplineSurfaceWithKnots and IfcAdvancedFace)
- Remove unnecessary typedefs
2014-05-04 14:42:55 +00:00
Thomas Krijnen e87b8988cd Add Test Files from http://www.buildingsmart-tech.org/ifc/IFC4/final/html/annex/annex-e/ifc/ 2014-04-30 14:14:05 +00:00
Thomas Krijnen bd83259d2b More fixes for parsing files with comments 2014-04-19 09:35:08 +00:00
Thomas Krijnen 604d6b032d Add test file with IfcSweptDiskSolids. Thanks Bernd. 2014-04-17 17:50:19 +00:00
Thomas Krijnen b30fbf73ae Add support for IfcSweptDiskSolid 2014-04-16 16:51:03 +00:00
Thomas Krijnen ed1db3dc68 Process IfcStyledItems directly applied to an IfcFacetedBrep 2014-04-09 10:57:45 +00:00
Thomas Krijnen 68740367a5 Account for unit magnitude in matrix translation part when CONVERT_BACK_UNITS is enabled 2014-04-08 07:28:07 +00:00
Thomas Krijnen 365b5f5d48 Fix product's 4x4 matrix on the IfcGeomServer 2014-04-07 17:59:20 +00:00
Thomas Krijnen b406d1c100 When writing collada files, postfix geometry instance nodes to make them distinct from their geometry library references 2014-04-07 14:01:16 +00:00
Thomas Krijnen 95a1332228 IfcGeomServer, small fixes: refrain from using auto type and restore std::cout rdbuf on exit so implicit flush doesn't segfault 2014-04-06 12:50:51 +00:00
Thomas Krijnen a0d74bdf83 Revamp the 'IfcGeomServer' idea to have an executable rather than a library to interface with. This way IFC processing runs in a separate process from the client application, so that crashes or out of memory issues do not bring down the client application. 2014-04-06 11:16:20 +00:00
Thomas Krijnen 24279776ab Increased verbosity in unsupported entity instances 2014-04-02 15:28:04 +00:00
Thomas Krijnen aebb9469a9 Fixes for parsing files with comments 2014-04-02 15:04:09 +00:00
Thomas Krijnen 0ecaf28e3e Measure conversion time of IfcConvert more faithfully 2014-03-31 14:03:06 +00:00
Thomas Krijnen 3e7c0cfd55 IfcSurfaceCurveSweptAreaSolid improvements 2014-03-31 14:00:02 +00:00
Thomas Krijnen aae576aae2 Take into account face location when serializing shape as tesselated faceset. 2014-03-22 21:13:02 +00:00
Thomas Krijnen 1aab95459b IfcConvert: Handle invalid command line options gracefully and notify user 2014-03-22 13:12:22 +00:00
Thomas Krijnen 80b39c0d22 No longer accept and silently convert invalid REAL tokens to zero 2014-03-22 13:02:21 +00:00
Thomas Krijnen bc801d00ba Handle missing or invalid unit and precision information more gracefully during IfcGeomObject initialization 2014-03-22 12:56:08 +00:00
Thomas Krijnen 54ecdb8295 For .obj conversion terminate lines with "\n" rather than std::endl causing a significant speed increase due to longer intermittently flushing the stream 2014-03-22 11:12:50 +00:00
Thomas Krijnen 71ea636206 Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
Add CSG example.
2014-03-22 10:31:51 +00:00
Thomas Krijnen 2f16bb42ed Add missing header to installation files. Thanks Fred. 2014-03-22 09:22:27 +00:00
Thomas Krijnen 268109875f Update build scripts to include TKOffset 2014-03-19 09:47:24 +00:00
Thomas Krijnen dab6e1d220 Add example file to generate file with IfcCompositeProfileDef and IfcDerivedProfileDef 2014-03-16 13:35:14 +00:00
Thomas Krijnen 220b36b09c Support for IfcCompositeProfileDef and IfcDerivedProfileDef 2014-03-16 13:34:01 +00:00
Thomas Krijnen 4c17d153f4 Add support for IfcGeometricSet IfcRevolvedAreaSolid IfcSurfaceOfLinearExtrusion IfcSurfaceOfRevolution IfcCenterLineProfileDef IfcArbitraryOpenProfileDef 2014-03-15 11:51:23 +00:00
Thomas Krijnen 7597f25db0 Implementations for more parameterized profile definitions 2014-03-08 17:21:39 +00:00
Thomas Krijnen ec2ed06272 Add support for ellipses with SemiAxis2 > SemiAxis1 2014-03-03 19:07:39 +00:00
Thomas Krijnen 05c98de100 Add parameterized profile test files and script to generate them 2014-02-23 11:25:35 +00:00
Thomas Krijnen 17f873b486 First stab at a new express parser to have some more luck with Ifc4 2014-02-17 22:13:55 +00:00
Thomas Krijnen 87259c0cab Bump version numbers 2014-01-12 11:03:50 +00:00
141 changed files with 131278 additions and 22697 deletions
+40 -15
View File
@@ -123,16 +123,20 @@ ENDIF(MSVC)
INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} ${OCC_INCLUDE_DIR} ${OPENCOLLADA_INCLUDE_DIRS} /usr/inc /usr/local/inc /usr/local/include/oce ${ICU_INCLUDE_DIR} ${Boost_INCLUDE_DIRS})
ADD_LIBRARY(IfcParse STATIC
ADD_LIBRARY(IfcParse STATIC
../src/ifcparse/Ifc2x3-latebound.cpp
../src/ifcparse/Ifc2x3.cpp
../src/ifcparse/IfcUtil.cpp
../src/ifcparse/IfcParse.cpp
../src/ifcparse/Ifc4-latebound.cpp
../src/ifcparse/Ifc4.cpp
../src/ifcparse/IfcCharacterDecoder.cpp
../src/ifcparse/IfcWrite.cpp
../src/ifcparse/IfcGuidHelper.cpp
../src/ifcparse/IfcHierarchyHelper.cpp
../src/ifcparse/IfcHierarchyHelper.cpp
../src/ifcparse/IfcLateBoundEntity.cpp
../src/ifcparse/IfcParse.cpp
../src/ifcparse/IfcSIPrefix.cpp
../src/ifcparse/IfcSpfHeader.cpp
../src/ifcparse/IfcUtil.cpp
../src/ifcparse/IfcWrite.cpp
)
ADD_LIBRARY(IfcGeom STATIC
@@ -140,8 +144,9 @@ ADD_LIBRARY(IfcGeom STATIC
../src/ifcgeom/IfcGeomFaces.cpp
../src/ifcgeom/IfcGeomFunctions.cpp
../src/ifcgeom/IfcGeomHelpers.cpp
../src/ifcgeom/IfcGeomObjects.cpp
../src/ifcgeom/IfcGeomMaterial.cpp
../src/ifcgeom/IfcGeomRenderStyles.cpp
../src/ifcgeom/IfcGeomRepresentation.cpp
../src/ifcgeom/IfcGeomShapes.cpp
../src/ifcgeom/IfcGeomWires.cpp
../src/ifcgeom/IfcRegister.cpp
@@ -155,14 +160,21 @@ TARGET_LINK_LIBRARIES(IfcGeom IfcParse)
LINK_DIRECTORIES (${LINK_DIRECTORIES} ${IfcOpenShell_BINARY_DIR} ${OCC_LIBRARY_DIR} ${OPENCOLLADA_LIBRARY_DIR} /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64 ${ICU_LIBRARY_DIR} ${Boost_LIBRARY_DIRS})
ADD_EXECUTABLE(IfcConvert
ADD_EXECUTABLE(IfcConvert
../src/ifcconvert/ColladaSerializer.cpp
../src/ifcconvert/IfcConvert.cpp
../src/ifcconvert/OpenCascadeBasedSerializer.cpp
../src/ifcconvert/WavefrontObjSerializer.cpp
../src/ifcconvert/WavefrontObjSerializer.cpp
../src/ifcconvert/XmlSerializer.cpp
)
TARGET_LINK_LIBRARIES (IfcConvert IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES ${Boost_LIBRARIES} ${OPENCOLLADA_LIBRARIES})
TARGET_LINK_LIBRARIES (IfcConvert IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset ${Boost_LIBRARIES} ${OPENCOLLADA_LIBRARIES})
ADD_EXECUTABLE(IfcGeomServer
../src/ifcgeomserver/IfcGeomServer.cpp
)
TARGET_LINK_LIBRARIES (IfcGeomServer IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset)
# Build python wrapper using separate CMakeLists.txt
ADD_SUBDIRECTORY(../src/ifcwrap ifcwrap)
@@ -175,7 +187,12 @@ ADD_SUBDIRECTORY(../src/examples examples)
# CMake installation targets
SET(include_files_geom
../src/ifcgeom/IfcGeom.h
../src/ifcgeom/IfcGeomObjects.h
../src/ifcgeom/IfcGeomElement.h
../src/ifcgeom/IfcGeomIterator.h
../src/ifcgeom/IfcGeomIteratorSettings.h
../src/ifcgeom/IfcGeomMaterial.h
../src/ifcgeom/IfcGeomRenderStyles.h
../src/ifcgeom/IfcGeomRepresentation.h
../src/ifcgeom/IfcRegister.h
../src/ifcgeom/IfcRegisterConvertCurve.h
../src/ifcgeom/IfcRegisterConvertFace.h
@@ -191,18 +208,26 @@ SET(include_files_geom
../src/ifcgeom/IfcRepresentationShapeItem.h
)
SET(include_files_parse
../src/ifcparse/Ifc2x3-latebound.h
../src/ifcparse/Ifc2x3.h
../src/ifcparse/Ifc2x3enum.h
../src/ifcparse/Ifc4-latebound.h
../src/ifcparse/Ifc4.h
../src/ifcparse/Ifc4enum.h
../src/ifcparse/IfcCharacterDecoder.h
../src/ifcparse/IfcEntityDescriptor.h
../src/ifcparse/IfcException.h
../src/ifcparse/IfcFile.h
../src/ifcparse/IfcHierarchyHelper.h
../src/ifcparse/IfcLateBoundEntity.h
../src/ifcparse/IfcParse.h
../src/ifcparse/IfcSIPrefix.h
../src/ifcparse/IfcSpfHeader.h
../src/ifcparse/IfcSpfStream.h
../src/ifcparse/IfcUtil.h
../src/ifcparse/SharedPointer.h
../src/ifcparse/IfcWrite.h
../src/ifcparse/IfcWritableEntity.h
../src/ifcparse/IfcWrite.h
../src/ifcparse/SharedPointer.h
)
INSTALL(FILES ${include_files_geom} DESTINATION include/ifcgeom)
INSTALL(FILES ${include_files_parse} DESTINATION include/ifcparse)
+1 -1
View File
@@ -2,4 +2,4 @@ ADD_EXECUTABLE(IfcParseExamples IfcParseExamples.cpp)
TARGET_LINK_LIBRARIES (IfcParseExamples IfcParse)
ADD_EXECUTABLE(IfcOpenHouse IfcOpenHouse.cpp)
TARGET_LINK_LIBRARIES (IfcOpenHouse IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet)
TARGET_LINK_LIBRARIES (IfcOpenHouse IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKOffset)
+283 -140
View File
@@ -31,7 +31,12 @@
#include <Standard_Version.hxx>
#ifdef USE_IFC4
#include "../ifcparse/Ifc4.h"
#else
#include "../ifcparse/Ifc2x3.h"
#endif
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcHierarchyHelper.h"
#include "../ifcgeom/IfcGeom.h"
@@ -50,18 +55,21 @@ int main(int argc, char** argv) {
// The IfcHierarchyHelper is a subclass of the regular IfcFile that provides several
// convenience functions for working with geometry in IFC files.
IfcHierarchyHelper file;
file.filename("IfcOpenHouse.ifc");
file.header().file_name().name("IfcOpenHouse.ifc");
// Start by adding a wall to the file, initially leaving most attributes blank.
Ifc2x3::IfcWallStandardCase* south_wall = new Ifc2x3::IfcWallStandardCase(
IfcSchema::IfcWallStandardCase* south_wall = new IfcSchema::IfcWallStandardCase(
guid(), // GlobalId
0, // OwnerHistory
0, // OwnerHistory
S("South wall"), // Name
null, // Description
null, // ObjectType
0, // ObjectPlacement
0, // Representation
null, // ObjectPlacement
null, // Representation
null // Tag
#ifdef USE_IFC4
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD
#endif
);
file.addBuildingProduct(south_wall);
@@ -70,124 +78,190 @@ int main(int argc, char** argv) {
// Lateron changing the name of the IfcProject can be done by obtaining a reference to the
// project, which has been created automatically.
file.getSingle<Ifc2x3::IfcProject>()->setName("IfcOpenHouse");
file.getSingle<IfcSchema::IfcProject>()->Name(S("IfcOpenHouse"));
// An IfcOwnerHistory has been initialized as well, which should be assigned to the wall.
south_wall->setOwnerHistory(file.getSingle<Ifc2x3::IfcOwnerHistory>());
south_wall->OwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
// The wall will be shaped as a box, with the dimensions specified in millimeters.
Ifc2x3::IfcProductDefinitionShape* south_wall_shape = file.addBox(10000, 360, 3000);
// The wall will be shaped as a box, with the dimensions specified in millimeters. The resulting
// product definition will consist of both a body representation as well as an axis representation
// that runs over the centerline of the box in the X-axis.
IfcSchema::IfcProductDefinitionShape* south_wall_shape = file.addAxisBox(10000, 360, 3000);
// Obtain a reference to the placement of the IfcBuildingStorey in order to create a hierarchy
// of placements for the products
IfcSchema::IfcObjectPlacement* storey_placement = *file.getSingle<IfcSchema::IfcBuildingStorey>()->ObjectPlacement();
// The shape has to be assigned to the representation of the wall and is placed at the origin
// of the coordinate system.
south_wall->setRepresentation(south_wall_shape);
south_wall->setObjectPlacement(file.addLocalPlacement());
south_wall->Representation(south_wall_shape);
south_wall->ObjectPlacement(file.addLocalPlacement(storey_placement));
// A pale white colour is assigned to the wall.
Ifc2x3::IfcPresentationStyleAssignment* wall_colour = file.setSurfaceColour(
south_wall->Representation(), 0.75, 0.73, 0.68);
IfcSchema::IfcPresentationStyleAssignment* wall_colour = file.setSurfaceColour(
south_wall_shape, 0.75, 0.73, 0.68);
// Now create a footing for the wall to rest on.
Ifc2x3::IfcFooting* footing = new Ifc2x3::IfcFooting(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
S("Footing"), null, null, 0, 0, null, Ifc2x3::IfcFootingTypeEnum::IfcFootingType_STRIP_FOOTING);
IfcSchema::IfcFooting* footing = new IfcSchema::IfcFooting(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
S("Footing"), null, null, null, null, null, IfcSchema::IfcFootingTypeEnum::IfcFootingType_STRIP_FOOTING);
file.addBuildingProduct(footing);
// 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
// assigned to a specific context, for example to add a two dimensional plan representation as well.
footing->setRepresentation(file.addBox(10100, 5460, 2000, 0, 0, 0, file.getSingle<Ifc2x3::IfcRepresentationContext>()));
footing->setObjectPlacement(file.addLocalPlacement(0, 2500, -2000));
footing->Representation(file.addBox(10100, 5460, 2000));
footing->ObjectPlacement(file.addLocalPlacement(storey_placement, 0, 2500, -2000));
// The footing will have a dark gray colour
Ifc2x3::IfcPresentationStyleAssignment* footing_colour = file.setSurfaceColour(footing->Representation(), 0.26, 0.22, 0.18);
IfcSchema::IfcPresentationStyleAssignment* footing_colour = file.setSurfaceColour(*footing->Representation(), 0.26, 0.22, 0.18);
// 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
// with another element, for example a door or a window, an IfcOpeningElement is used instead.
// An opening element is created with rectangular geometry
Ifc2x3::IfcOpeningElement* west_opening = new Ifc2x3::IfcOpeningElement(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
null, null, null, file.addLocalPlacement(-2500, 0, 400),
file.addBox(6000, 3630, 1600, 0, 0, 0, file.getSingle<Ifc2x3::IfcRepresentationContext>()), null);
file.AddEntity(west_opening);
// An opening element is created with rectangular geometry:
IfcSchema::IfcOpeningElement* west_opening = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, null, file.addLocalPlacement(*south_wall->ObjectPlacement(), -2500, 0, 400),
file.addBox(6000, 3630, 1600), null
#ifdef USE_IFC4
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING
#endif
);
file.addEntity(west_opening);
// Relate the opening element to the wall.
Ifc2x3::IfcRelVoidsElement* void_element = new Ifc2x3::IfcRelVoidsElement(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
IfcSchema::IfcRelVoidsElement* void_element = new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, south_wall, west_opening);
file.AddEntity(void_element);
file.addEntity(void_element);
// Now create an additional opening
Ifc2x3::IfcOpeningElement* south_opening = new Ifc2x3::IfcOpeningElement(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
null, null, null, file.addLocalPlacement(3000, 0, 400),
file.addBox(1860, 3000, 1600, 0, 0, 0, file.getSingle<Ifc2x3::IfcRepresentationContext>()), null);
file.AddEntity(south_opening);
file.AddEntity(new Ifc2x3::IfcRelVoidsElement(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(), null, null, south_wall, south_opening));
IfcSchema::IfcOpeningElement* south_opening = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, null, file.addLocalPlacement(storey_placement, 3000, 0, 400),
file.addBox(1860, 3000, 1600), null
#ifdef USE_IFC4
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING
#endif
);
file.addEntity(south_opening);
file.addEntity(new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, south_wall, south_opening));
// Create a roof element
Ifc2x3::IfcRoof* south_roof = new Ifc2x3::IfcRoof(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(), S("South roof"), null, null,
0, 0, null, Ifc2x3::IfcRoofTypeEnum::IfcRoofType_GABLE_ROOF);
// The roof geometry is slanted 45 degrees by specifying a direction for the box extrusion
south_roof->setRepresentation(file.addBox(10200, 360, sqrt(2.0*2900*2900), 0, file.addPlacement3d(0, 0, 0, 0, 1, 0),
file.addTriplet<Ifc2x3::IfcDirection>(0, -sqrt(0.5), sqrt(0.5)), file.getSingle<Ifc2x3::IfcRepresentationContext>()));
south_roof->setObjectPlacement(file.addLocalPlacement(0, -400, 2700));
file.addBuildingProduct(south_roof);
// Create a roof element that will consist of two slabs:
IfcSchema::IfcRoof* roof = new IfcSchema::IfcRoof(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), S("Roof"), null, null,
file.addLocalPlacement(storey_placement), null, null, IfcSchema::IfcRoofTypeEnum::IfcRoofType_GABLE_ROOF);
// The roof geometry is slanted 45 degrees by specifying a direction for the box extrusion
IfcSchema::IfcShapeRepresentation* roof_rep = file.addEmptyRepresentation();
file.addBox(roof_rep, 10200, 360, sqrt(2.0*2900*2900), 0, file.addPlacement3d(0, 0, 0, 0, 1, 0),
file.addTriplet<IfcSchema::IfcDirection>(0, -sqrt(0.5), sqrt(0.5)));
// CV-2x3-144: Roofs are aggregates and shall have at least one contained element and no own geometry
IfcSchema::IfcSlab* south_roof_part = new IfcSchema::IfcSlab(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), S("South roof"),
null, null, null, null, null, IfcSchema::IfcSlabTypeEnum::IfcSlabType_ROOF);
// The geometry is instantiated by using IfcMappedItems. This way geometry definitions can
// be reused while maintaining the cardinality constraint that the ShapeOfProduct relation
// imposes on the IfcProductDefinitionShape. Note that this constrained is lifted in IFC4.
south_roof_part->Representation(file.addMappedItem(roof_rep));
south_roof_part->ObjectPlacement(file.addLocalPlacement(*roof->ObjectPlacement(), 0, -400, 2700));
// The same roof geometry is re-used on the north side of the roof, by inverting the X-axis of
// the local placement the roof is rotated 180 degrees around the Z-axis
Ifc2x3::IfcRoof* north_roof = new Ifc2x3::IfcRoof(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(), S("North roof"),
null, null, 0, 0, null, Ifc2x3::IfcRoofTypeEnum::IfcRoofType_GABLE_ROOF);
north_roof->setOwnerHistory(file.getSingle<Ifc2x3::IfcOwnerHistory>());
north_roof->setRepresentation(south_roof->Representation());
north_roof->setObjectPlacement(file.addLocalPlacement(0, 5400, 2700, 0, 0, 1, -1, 0, 0));
file.addBuildingProduct(north_roof);
IfcSchema::IfcSlab* north_roof_part = new IfcSchema::IfcSlab(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), S("North roof"),
null, null, null, null, null, IfcSchema::IfcSlabTypeEnum::IfcSlabType_ROOF);
north_roof_part->OwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
north_roof_part->Representation(file.addMappedItem(roof_rep));
north_roof_part->ObjectPlacement(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);
// By specifying a surface style for the south part of the roof, it gets assigned to the other
// roof part as well, because they share the same representation.
file.setSurfaceColour(south_roof->Representation(), 0.24, 0.08, 0.04);
file.addBuildingProduct(south_roof_part);
file.addBuildingProduct(north_roof_part);
file.addBuildingProduct(roof);
file.setSurfaceColour(roof_rep, 0.24, 0.08, 0.04);
// Copy the south wall to the north
file.addBuildingProduct(new Ifc2x3::IfcWallStandardCase(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(), S("North wall"),
null, null, file.addLocalPlacement(0, 5000, 0), south_wall->Representation(), null));
// Now create a wall on the east of the building, again starting with just a box shape
Ifc2x3::IfcWallStandardCase* east_wall = new Ifc2x3::IfcWallStandardCase(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
S("East wall"), null, null, file.addLocalPlacement(4820, 2500, 0, 0, 0, 1, 0, 1, 0), file.addBox(5000, 360, 6000), null);
file.addBuildingProduct(east_wall);
IfcSchema::IfcWallStandardCase* north_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), S("North wall"),
null, null, file.addLocalPlacement(storey_placement, 0, 5000, 0), file.addAxisBox(10000, 360, 3000), null
#ifdef USE_IFC4
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD
#endif
);
file.addBuildingProduct(north_wall);
file.setSurfaceColour(*north_wall->Representation(), wall_colour);
IfcSchema::IfcShapeRepresentation* clipped_wall_body_rep = file.addEmptyRepresentation();
file.addBox(clipped_wall_body_rep, 5000, 360, 6000);
// The east wall geometry is clipped using two IfcHalfSpaceSolids, created from an
// 'axis 3d placement' that specifies the plane against which the geometry is clipped.
file.clipRepresentation(east_wall->Representation(), file.addPlacement3d(-2500, 0, 3000, -1, 0, 1), false);
file.clipRepresentation(east_wall->Representation(), file.addPlacement3d(2500, 0, 3000, 1, 0, 1), false);
file.clipRepresentation(clipped_wall_body_rep, file.addPlacement3d(-2500, 0, 3000, -1, 0, 1), false);
file.clipRepresentation(clipped_wall_body_rep, file.addPlacement3d(2500, 0, 3000, 1, 0, 1), false);
file.setSurfaceColour(east_wall->Representation(), wall_colour);
// Now create a wall on the east of the building, again starting with just a box shape
IfcSchema::IfcWallStandardCase* east_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
S("East wall"), null, null, file.addLocalPlacement(storey_placement, 4820, 2500, 0, 0, 0, 1, 0, 1, 0), file.addMappedItem(clipped_wall_body_rep), null
#ifdef USE_IFC4
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD
#endif
);
file.addBuildingProduct(east_wall);
file.setSurfaceColour(clipped_wall_body_rep, wall_colour);
// The east wall is copied to the west location of the house
Ifc2x3::IfcWallStandardCase* west_wall = new Ifc2x3::IfcWallStandardCase(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
S("West wall"), null, null, file.addLocalPlacement(-4820, 2500, 0, 0, 0, 1, 0, -1, 0), east_wall->Representation(), null);
IfcSchema::IfcWallStandardCase* west_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
S("West wall"), null, null, file.addLocalPlacement(storey_placement, -4820, 2500, 0, 0, 0, 1, 0, -1, 0), file.addMappedItem(clipped_wall_body_rep), null
#ifdef USE_IFC4
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD
#endif
);
file.addBuildingProduct(west_wall);
for (int i = 0; i < 2; ++i) {
// CV-2x3-161: MappedItems are not allowed for Axis representations
IfcSchema::IfcWallStandardCase* wall = i == 0 ? east_wall : west_wall;
IfcSchema::IfcShapeRepresentation* wall_axis_rep = file.addEmptyRepresentation("Axis", "Curve2D");
file.addAxis(wall_axis_rep, 5000);
IfcSchema::IfcRepresentation::list::ptr reps = wall->Representation().get()->Representations();
reps->push(wall_axis_rep);
wall->Representation().get()->Representations(reps);
}
// The west wall is assigned an opening element we created for the south wall, opening elements are
// not shared accross building elements, even if they share the same representation. Hence, the east
// wall will not feature this opening.
// NB: an Opening Element can only be used to create a single void within a single Element, as per:
// http://www.buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcproductextension/lexical/ifcfeatureelementsubtraction.htm
Ifc2x3::IfcOpeningElement* west_opening_copy = new Ifc2x3::IfcOpeningElement(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
null, null, null, west_opening->ObjectPlacement(), west_opening->Representation(), null);
file.AddEntity(west_opening_copy);
file.AddEntity(new Ifc2x3::IfcRelVoidsElement(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(), null, null, west_wall, west_opening_copy));
// 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.
IfcSchema::IfcOpeningElement* west_opening_copy = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, null, file.addLocalPlacement(*west_wall->ObjectPlacement(), 2500, -2500+4820, 400, 0, 0, 1, 0, 1, 0),
file.addBox(6000, 3630, 1600), null
#ifdef USE_IFC4
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING
#endif
);
file.addEntity(west_opening_copy);
file.addEntity(new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, west_wall, west_opening_copy));
// 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
// will be tesselated using the deflection specified.
TopoDS_Shape shape;
createGroundShape(shape);
IfcEntities geometrical_entities(new IfcEntityList());
Ifc2x3::IfcProductDefinitionShape* ground_representation = IfcGeom::tesselate(shape, 100., geometrical_entities);
file.getSingle<Ifc2x3::IfcSite>()->setRepresentation(ground_representation);
file.AddEntities(geometrical_entities);
Ifc2x3::IfcShapeRepresentation::list ground_reps = geometrical_entities->as<Ifc2x3::IfcShapeRepresentation>();
for (Ifc2x3::IfcShapeRepresentation::it it = ground_reps->begin(); it != ground_reps->end(); ++it) {
(*it)->setContextOfItems(file.getSingle<Ifc2x3::IfcRepresentationContext>());
IfcEntityList::ptr geometrical_entities(new IfcEntityList);
IfcSchema::IfcProductDefinitionShape* ground_representation = IfcGeom::tesselate(shape, 100., geometrical_entities);
file.getSingle<IfcSchema::IfcSite>()->Representation(ground_representation);
file.addEntities(geometrical_entities);
IfcSchema::IfcShapeRepresentation::list::ptr ground_reps = geometrical_entities->as<IfcSchema::IfcShapeRepresentation>();
for (IfcSchema::IfcShapeRepresentation::list::it it = ground_reps->begin(); it != ground_reps->end(); ++it) {
(*it)->ContextOfItems(file.getRepresentationContext("Model"));
}
file.setSurfaceColour(ground_representation, 0.15, 0.25, 0.05);
@@ -198,24 +272,58 @@ int main(int argc, char** argv) {
// 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
// provided here.
Ifc2x3::IfcMaterial* material = new Ifc2x3::IfcMaterial("Brick");
Ifc2x3::IfcMaterialLayer* layer = new Ifc2x3::IfcMaterialLayer(material, 360, null);
Ifc2x3::IfcMaterialLayer::list layers (new IfcTemplatedEntityList<Ifc2x3::IfcMaterialLayer>());
#ifdef USE_IFC4
IfcSchema::IfcMaterial* material = new IfcSchema::IfcMaterial("Brick", null, null);
#else
IfcSchema::IfcMaterial* material = new IfcSchema::IfcMaterial("Brick");
#endif
IfcSchema::IfcMaterialLayer* layer = new IfcSchema::IfcMaterialLayer(
material,
360,
null
#ifdef USE_IFC4
, null
, null
, null
, null
#endif
);
IfcSchema::IfcMaterialLayer::list::ptr layers (new IfcTemplatedEntityList<IfcSchema::IfcMaterialLayer>());
layers->push(layer);
Ifc2x3::IfcMaterialLayerSet* layer_set = new Ifc2x3::IfcMaterialLayerSet(layers, S("Wall"));
Ifc2x3::IfcMaterialLayerSetUsage* layer_usage = new Ifc2x3::IfcMaterialLayerSetUsage(layer_set,
Ifc2x3::IfcLayerSetDirectionEnum::IfcLayerSetDirection_AXIS2,
Ifc2x3::IfcDirectionSenseEnum::IfcDirectionSense_POSITIVE, -180);
IfcSchema::IfcMaterialLayerSet* layer_set = new IfcSchema::IfcMaterialLayerSet(
layers,
S("Wall")
#ifdef USE_IFC4
, null
#endif
);
IfcSchema::IfcMaterialLayerSetUsage* layer_usage = new IfcSchema::IfcMaterialLayerSetUsage(
layer_set,
IfcSchema::IfcLayerSetDirectionEnum::IfcLayerSetDirection_AXIS2,
IfcSchema::IfcDirectionSenseEnum::IfcDirectionSense_POSITIVE,
-180
#ifdef USE_IFC4
, null
#endif
);
Ifc2x3::IfcRelAssociatesMaterial* associates_material = new Ifc2x3::IfcRelAssociatesMaterial(guid(),
file.getSingle<Ifc2x3::IfcOwnerHistory>(), null, null,
file.EntitiesByType<Ifc2x3::IfcWallStandardCase>()->as<Ifc2x3::IfcRoot>(), layer_usage);
IfcSchema::IfcRelAssociatesMaterial* associates_material = new IfcSchema::IfcRelAssociatesMaterial(
guid(),
file.getSingle<IfcSchema::IfcOwnerHistory>(),
null,
null,
#ifdef USE_IFC4
file.entitiesByType<IfcSchema::IfcWallStandardCase>()->generalize(),
#else
file.entitiesByType<IfcSchema::IfcWallStandardCase>()->as<IfcSchema::IfcRoot>(),
#endif
layer_usage);
file.AddEntity(material);
file.AddEntity(layer);
file.AddEntity(layer_set);
file.AddEntity(layer_usage);
file.AddEntity(associates_material);
file.addEntity(material);
file.addEntity(layer);
file.addEntity(layer_set);
file.addEntity(layer_usage);
file.addEntity(associates_material);
// In addition, another common way to represent geometry in IFC files is to use extrusions of
// planar areas bounded by a polygon.
@@ -226,38 +334,52 @@ int main(int argc, char** argv) {
stair_points.push_back(XY(500, 200));
stair_points.push_back(XY(500, 400));
stair_points.push_back(XY( 0, 400));
Ifc2x3::IfcStairFlight* stair = new Ifc2x3::IfcStairFlight(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
null, null, null, file.addLocalPlacement(5050, 1000, 0, 0, 1, 0, 1, 0, 0),
file.addExtrudedPolyline(stair_points, 1200), null, 2, 2, 0.2, 0.25);
IfcSchema::IfcStairFlight* stair = new IfcSchema::IfcStairFlight(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, null, file.addLocalPlacement(storey_placement, 5050, 1000, 0, 0, 1, 0, 1, 0, 0),
file.addExtrudedPolyline(stair_points, 1200), null, 2, 2, 0.2, 0.25
#ifdef USE_IFC4
, IfcSchema::IfcStairFlightTypeEnum::IfcStairFlightType_STRAIGHT
#endif
);
file.addBuildingProduct(stair);
file.setSurfaceColour(stair->Representation(), footing_colour);
file.setSurfaceColour(*stair->Representation(), footing_colour);
Ifc2x3::IfcOpeningElement* door_opening = new Ifc2x3::IfcOpeningElement(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
null, null, null, file.addLocalPlacement(5000-180, 2500-900, 0), file.addBox(1000, 1000, 2200), null);
file.AddEntity(door_opening);
file.AddEntity(new Ifc2x3::IfcRelVoidsElement(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(), null, null, east_wall, door_opening));
IfcSchema::IfcOpeningElement* door_opening = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, null, file.addLocalPlacement(storey_placement, 5000-180, 2500-900, 0), file.addBox(1000, 1000, 2200), null
#ifdef USE_IFC4
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING
#endif
);
file.addEntity(door_opening);
file.addEntity(new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, east_wall, door_opening));
// 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
// which constitute the door and its frame.
Ifc2x3::IfcDoor* door = new Ifc2x3::IfcDoor(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(), null, null, null,
file.addLocalPlacement(4800, 1600, 0, 0, 0, 1, 0, 1, 0), 0, null, 2200, 1000);
door->setRepresentation(file.addBox(80, 80, 2120, 0, file.addPlacement3d(460, 0, 0)));
Ifc2x3::IfcRepresentation::list door_representations = door->Representation()->Representations();
Ifc2x3::IfcShapeRepresentation* door_body = 0;
for (Ifc2x3::IfcRepresentation::it i = door_representations->begin(); i != door_representations->end(); ++i) {
Ifc2x3::IfcRepresentation* rep = *i;
if (rep->is(Ifc2x3::Type::IfcShapeRepresentation) && rep->RepresentationIdentifier() == "Body") {
door_body = (Ifc2x3::IfcShapeRepresentation*) rep;
IfcSchema::IfcDoor* door = new IfcSchema::IfcDoor(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, null,
file.addLocalPlacement(storey_placement, 4800, 1600, 0, 0, 0, 1, 0, 1, 0), null, null, 2200, 1000
#ifdef USE_IFC4
, IfcSchema::IfcDoorTypeEnum::IfcDoorType_DOOR
, IfcSchema::IfcDoorTypeOperationEnum::IfcDoorTypeOperation_SINGLE_SWING_LEFT
, null
#endif
);
door->Representation(file.addBox(80, 80, 2120, 0, file.addPlacement3d(460, 0, 0)));
IfcSchema::IfcRepresentation::list::ptr door_representations = door->Representation().get()->Representations();
IfcSchema::IfcShapeRepresentation* door_body = 0;
for (IfcSchema::IfcRepresentation::list::it i = door_representations->begin(); i != door_representations->end(); ++i) {
IfcSchema::IfcRepresentation* rep = *i;
if (rep->is(IfcSchema::Type::IfcShapeRepresentation) && *rep->RepresentationIdentifier() == "Body") {
door_body = (IfcSchema::IfcShapeRepresentation*) rep;
}
}
file.addBox(door_body, 80, 80, 2120, 0, file.addPlacement3d(-460, 0, 0));
file.addBox(door_body, 1000, 80, 80, 0, file.addPlacement3d( 0, 0, 2120));
file.addBox(door_body, 860, 30, 2120);
file.addBuildingProduct(door);
file.setSurfaceColour(door->Representation(), 0.9, 0.9, 0.9);
file.AddEntity(new Ifc2x3::IfcRelFillsElement(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(), null, null, door_opening, door));
file.setSurfaceColour(*door->Representation(), 0.9, 0.9, 0.9);
file.addEntity(new IfcSchema::IfcRelFillsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, door_opening, door));
// Surface styles are assigned to representation items, hence there is no real limitation to
// assign different colours within the same representation. However, some viewers have
@@ -270,77 +392,98 @@ int main(int argc, char** argv) {
// Therefore the OverallWidth and OverallHeight of the window attributes will need to
// match the bounding box of the representation. Furthermore, the window placement needs
// to align with the lowerleft corner of the constituent parts.
Ifc2x3::IfcProductDefinitionShape::list frame_representations (new IfcTemplatedEntityList<Ifc2x3::IfcProductDefinitionShape>());
frame_representations->push(file.addBox(1860, 90, 90));
frame_representations->push(*frame_representations->begin()); // Add a reference to the shape created above
frame_representations->push(file.addBox(90, 90, 1420));
frame_representations->push(*(frame_representations->end()-1)); // Add a reference to the shape created above
IfcSchema::IfcShapeRepresentation::list::ptr frame_representations(new IfcSchema::IfcShapeRepresentation::list);
IfcSchema::IfcShapeRepresentation* horizontal_bar = file.addEmptyRepresentation();
IfcSchema::IfcShapeRepresentation* vertical_bar = file.addEmptyRepresentation();
file.addBox(horizontal_bar, 1860, 90, 90);
file.addBox(vertical_bar, 90, 90, 1420);
frame_representations->push(horizontal_bar);
frame_representations->push(horizontal_bar); // Add another reference to the horizontal bar created above
frame_representations->push(vertical_bar);
frame_representations->push(vertical_bar); // Add another reference to the vertical bar created above
// The beams all have the same surface style assigned
Ifc2x3::IfcPresentationStyleAssignment* frame_style = 0;
for (Ifc2x3::IfcProductDefinitionShape::it i = frame_representations->begin(); i != frame_representations->end(); ++i) {
IfcSchema::IfcPresentationStyleAssignment* frame_style = 0;
for (IfcSchema::IfcShapeRepresentation::list::it i = frame_representations->begin(); i != frame_representations->end(); i += 2) {
if (frame_style) {
file.setSurfaceColour(*i, frame_style);
} else {
frame_style = file.setSurfaceColour(*i, 0.5, 0.4, 0.3);
}
// Because of the duplication the iterator is incremented twice
}
// This window will be placed at five locations within the building. A list of placements is
// created and is iterated over to create all window instances.
Ifc2x3::IfcLocalPlacement::list window_placements (new IfcTemplatedEntityList<Ifc2x3::IfcLocalPlacement>());
window_placements->push(file.addLocalPlacement(2*-1770-430-930, -45, 400));
window_placements->push(file.addLocalPlacement( -1770-430-930, -45, 400));
window_placements->push(file.addLocalPlacement( -430-930, -45, 400));
window_placements->push(file.addLocalPlacement( 3000-930, -45, 400));
window_placements->push(file.addLocalPlacement( -4855+45, 885-930, 400, 0, 0, 1, 0, 1, 0));
IfcSchema::IfcLocalPlacement::list::ptr window_placements (new IfcSchema::IfcLocalPlacement::list);
window_placements->push(file.addLocalPlacement(storey_placement, 2*-1770-430-930, -45, 400));
window_placements->push(file.addLocalPlacement(storey_placement, -1770-430-930, -45, 400));
window_placements->push(file.addLocalPlacement(storey_placement, -430-930, -45, 400));
window_placements->push(file.addLocalPlacement(storey_placement, 3000-930, -45, 400));
window_placements->push(file.addLocalPlacement(storey_placement, -4855+45, 885-930, 400, 0, 0, 1, 0, 1, 0));
for (Ifc2x3::IfcLocalPlacement::it it = window_placements->begin(); it != window_placements->end(); ++it) {
for (IfcSchema::IfcLocalPlacement::list::it it = window_placements->begin(); it != window_placements->end(); ++it) {
// Create the window at the current location
Ifc2x3::IfcLocalPlacement* place = *it;
Ifc2x3::IfcWindow* window = new Ifc2x3::IfcWindow(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
null, null, null, place, 0, null, 1600, 1860);
IfcSchema::IfcLocalPlacement* place = *it;
IfcSchema::IfcWindow* window = new IfcSchema::IfcWindow(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, null, place, null, null, 1600, 1860
#ifdef USE_IFC4
, IfcSchema::IfcWindowTypeEnum::IfcWindowType_WINDOW
, IfcSchema::IfcWindowTypePartitioningEnum::IfcWindowTypePartitioning_SINGLE_PANEL
, null
#endif
);
file.addBuildingProduct(window);
// Initalize a list of parts for the window to be composed of
Ifc2x3::IfcObjectDefinition::list window_parts(new IfcTemplatedEntityList<Ifc2x3::IfcObjectDefinition>());
IfcSchema::IfcObjectDefinition::list::ptr window_parts(new IfcTemplatedEntityList<IfcSchema::IfcObjectDefinition>());
// The placements for the beams are not shared accross the different windows because every
// beam is placed relative to its parent window entity.
Ifc2x3::IfcLocalPlacement::list frame_placements (new IfcTemplatedEntityList<Ifc2x3::IfcLocalPlacement>());
frame_placements->push(file.addLocalPlacement( 930,45));
frame_placements->push(file.addLocalPlacement( 930, 45, 1510));
frame_placements->push(file.addLocalPlacement(-885+930, 45, 90));
frame_placements->push(file.addLocalPlacement( 885+930, 45, 90));
IfcSchema::IfcLocalPlacement::list::ptr frame_placements (new IfcTemplatedEntityList<IfcSchema::IfcLocalPlacement>());
frame_placements->push(file.addLocalPlacement(storey_placement, 930,45));
frame_placements->push(file.addLocalPlacement(storey_placement, 930, 45, 1510));
frame_placements->push(file.addLocalPlacement(storey_placement, -885+930, 45, 90));
frame_placements->push(file.addLocalPlacement(storey_placement, 885+930, 45, 90));
// Now iterate over the placements and representations of the beam and add them to list of parts
Ifc2x3::IfcLocalPlacement::it frame_placement;
Ifc2x3::IfcProductDefinitionShape::it frame_representation;
IfcSchema::IfcLocalPlacement::list::it frame_placement;
IfcSchema::IfcShapeRepresentation::list::it frame_representation;
for (frame_placement = frame_placements->begin(), frame_representation = frame_representations->begin();
frame_placement != frame_placements->end() && frame_representation != frame_representations->end();
++frame_placement, ++frame_representation)
{
Ifc2x3::IfcMember* frame_part = new Ifc2x3::IfcMember(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
null, null, null, *frame_placement, *frame_representation, null);
file.AddEntity(frame_part);
IfcSchema::IfcMember* frame_part = new IfcSchema::IfcMember(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, null, *frame_placement, file.addMappedItem(*frame_representation), null
#ifdef USE_IFC4
, IfcSchema::IfcMemberTypeEnum::IfcMemberType_MULLION
#endif
);
file.addEntity(frame_part);
window_parts->push(frame_part);
file.relatePlacements(window, frame_part);
}
// Add the glass plate to the list of parts
Ifc2x3::IfcPlate* glass_part = new Ifc2x3::IfcPlate(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(), null,
null, null, file.addLocalPlacement(930, 45, 90), file.addBox(1680, 10, 1420), null);
file.AddEntity(glass_part);
IfcSchema::IfcPlate* glass_part = new IfcSchema::IfcPlate(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null,
null, null, file.addLocalPlacement(storey_placement, 930, 45, 90), file.addBox(1680, 10, 1420), null
#ifdef USE_IFC4
, IfcSchema::IfcPlateTypeEnum::IfcPlateType_SHEET
#endif
);
file.addEntity(glass_part);
window_parts->push(glass_part);
file.relatePlacements(window, glass_part);
file.setSurfaceColour(glass_part->Representation(), 0.6, 0.7, 0.75, 0.1);
file.setSurfaceColour(*glass_part->Representation(), 0.6, 0.7, 0.75, 0.1);
// Now create a decomposition relation between the window and the parts. Most viewers and authoring
// tools will consider the window a single entity that can be selected as a whole.
Ifc2x3::IfcRelDecomposes* decomposition = new Ifc2x3::IfcRelAggregates(guid(), file.getSingle<Ifc2x3::IfcOwnerHistory>(),
IfcSchema::IfcRelDecomposes* decomposition = new IfcSchema::IfcRelAggregates(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
null, null, window, window_parts);
file.AddEntity(decomposition);
file.addEntity(decomposition);
}
// Finally create a file stream for our output and write the IFC file to it.
@@ -385,6 +528,6 @@ void createGroundShape(TopoDS_Shape& shape) {
#if OCC_VERSION_HEX < 0x60502
shape = BRepBuilderAPI_MakeFace(surf);
#else
shape = BRepBuilderAPI_MakeFace(surf, 1);
shape = BRepBuilderAPI_MakeFace(surf, Precision::Confusion());
#endif
}
+10 -10
View File
@@ -17,9 +17,9 @@
* *
********************************************************************************/
#include "../ifcparse/IfcParse.h"
#include "../ifcparse/IfcFile.h"
using namespace Ifc2x3;
using namespace IfcSchema;
int main(int argc, char** argv) {
@@ -40,7 +40,7 @@ int main(int argc, char** argv) {
// Lets get a list of IfcBuildingElements, this is the parent
// type of things like walls, windows and doors.
// EntitiesByType is a templated function and returns a
// entitiesByType is a templated function and returns a
// templated class that behaves like a std::vector.
// Note that the return types are all typedef'ed as members of
// the generated classes, ::list for the templated vector class,
@@ -54,20 +54,20 @@ int main(int argc, char** argv) {
// we need to cast them to IfcWindows. Since these properties
// are optional we need to make sure the properties are
// defined for the window in question before accessing them.
IfcBuildingElement::list elements = file.EntitiesByType<IfcBuildingElement>();
IfcBuildingElement::list::ptr elements = file.entitiesByType<IfcBuildingElement>();
std::cout << "Found " << elements->Size() << " elements in " << argv[1] << ":" << std::endl;
std::cout << "Found " << elements->size() << " elements in " << argv[1] << ":" << std::endl;
for ( IfcBuildingElement::it it = elements->begin(); it != elements->end(); ++ it ) {
for ( IfcBuildingElement::list::it it = elements->begin(); it != elements->end(); ++ it ) {
const IfcBuildingElement::ptr element = *it;
const IfcBuildingElement* element = *it;
std::cout << element->entity->toString() << std::endl;
if ( element->is(IfcWindow::Class()) ) {
const IfcWindow::ptr window = reinterpret_pointer_cast<IfcBuildingElement,IfcWindow>(element);
const IfcWindow* window = (IfcWindow*)element;
if ( window->hasOverallWidth() && window->hasOverallHeight() ) {
const double area = window->OverallWidth()*window->OverallHeight();
if ( window->OverallWidth() && window->OverallHeight() ) {
const double area = window->OverallWidth().get() * window->OverallHeight().get();
std::cout << "The area of this window is " << area << std::endl;
}
}
+140
View File
@@ -0,0 +1,140 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Example that generates various representations from *
* IfcArbitraryOpenProfileDefs and its subclass IfcCenterLineProfileDef *
* *
********************************************************************************/
#include <string>
#include <iostream>
#include <fstream>
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcHierarchyHelper.h"
typedef std::string S;
typedef IfcWrite::IfcGuidHelper guid;
boost::none_t const null = (static_cast<boost::none_t>(0));
static int i = 0;
void create_product_from_item(IfcHierarchyHelper& file, IfcSchema::IfcRepresentationItem* item, const std::string& s) {
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
guid(), 0, S("product"), null, null, 0, 0, null, null);
file.addBuildingProduct(product);
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
product->setObjectPlacement(file.addLocalPlacement(120 * i++));
IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
items->push(item);
if (s == "GeometricSet") {
IfcSchema::IfcGeometricSet* set = new IfcSchema::IfcGeometricSet(items->generalize());
file.addEntity(set);
items = IfcSchema::IfcRepresentationItem::list(new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
items->push(set);
}
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), s, items);
reps->push(rep);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
file.addEntity(rep);
file.addEntity(shape);
product->setRepresentation(shape);
}
void create_surfaces_from_profile(IfcHierarchyHelper& file, IfcSchema::IfcProfileDef* profile) {
IfcSchema::IfcSurfaceOfLinearExtrusion* extrusion = new IfcSchema::IfcSurfaceOfLinearExtrusion(profile, file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 100.);
file.addEntity(extrusion);
IfcSchema::IfcAxis1Placement* ax1 = new IfcSchema::IfcAxis1Placement(file.addTriplet<IfcSchema::IfcCartesianPoint>(0,100,0), file.addTriplet<IfcSchema::IfcDirection>(1,0,0));
IfcSchema::IfcSurfaceOfRevolution* revolution = new IfcSchema::IfcSurfaceOfRevolution(profile, file.addPlacement3d(), ax1);
file.addEntity(ax1);
file.addEntity(revolution);
create_product_from_item(file, extrusion, "GeometricSet");
create_product_from_item(file, revolution, "GeometricSet");
}
void create_solids_from_profile(IfcHierarchyHelper& file, IfcSchema::IfcProfileDef* profile) {
IfcSchema::IfcExtrudedAreaSolid* extrusion = new IfcSchema::IfcExtrudedAreaSolid(profile, file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 100.);
file.addEntity(extrusion);
IfcSchema::IfcAxis1Placement* ax1 = new IfcSchema::IfcAxis1Placement(file.addTriplet<IfcSchema::IfcCartesianPoint>(0,100,0), file.addTriplet<IfcSchema::IfcDirection>(1,0,0));
IfcSchema::IfcRevolvedAreaSolid* revolution1 = new IfcSchema::IfcRevolvedAreaSolid(profile, file.addPlacement3d(), ax1, 360.);
IfcSchema::IfcRevolvedAreaSolid* revolution2 = new IfcSchema::IfcRevolvedAreaSolid(profile, file.addPlacement3d(), ax1, 90.);
file.addEntity(ax1);
file.addEntity(revolution1);
file.addEntity(revolution2);
create_product_from_item(file, extrusion, "SweptSolid");
create_product_from_item(file, revolution1, "SweptSolid");
create_product_from_item(file, revolution2, "SweptSolid");
}
void create_products_from_curve(IfcHierarchyHelper& file, IfcSchema::IfcBoundedCurve* curve) {
IfcSchema::IfcArbitraryOpenProfileDef* open = new IfcSchema::IfcArbitraryOpenProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_CURVE, null, curve);
IfcSchema::IfcCenterLineProfileDef* center_line = new IfcSchema::IfcCenterLineProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, null, curve, 10.);
file.addEntity(open);
file.addEntity(center_line);
create_surfaces_from_profile(file, open);
create_solids_from_profile(file, center_line);
}
int main(int argc, char** argv) {
const char filename[] = "IfcArbitraryOpenProfileDef.ifc";
IfcHierarchyHelper file;
file.filename(filename);
double coords1[] = {-50.0, 0.0};
double coords2[] = { 50.0, 0.0};
IfcSchema::IfcCartesianPoint::list points (new IfcTemplatedEntityList<IfcSchema::IfcCartesianPoint>());
points->push(new IfcSchema::IfcCartesianPoint(std::vector<double>(coords1, coords1+2)));
points->push(new IfcSchema::IfcCartesianPoint(std::vector<double>(coords2, coords2+2)));
file.addEntities(points->generalize());
IfcSchema::IfcPolyline* poly = new IfcSchema::IfcPolyline(points);
file.addEntity(poly);
create_products_from_curve(file, poly);
IfcSchema::IfcEllipse* ellipse = new IfcSchema::IfcEllipse(file.addPlacement2d(), 50., 25.);
file.addEntity(ellipse);
IfcEntityList::ptr trim1(new IfcEntityList);
IfcEntityList::ptr trim2(new IfcEntityList);
trim1->push(new IfcWrite::IfcSelectHelper( 0., Ifc2x3::Type::IfcParameterValue));
trim2->push(new IfcWrite::IfcSelectHelper(180., Ifc2x3::Type::IfcParameterValue));
IfcSchema::IfcTrimmedCurve* trim = new IfcSchema::IfcTrimmedCurve(ellipse, trim1, trim2, true, IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
file.addEntity(trim);
create_products_from_curve(file, trim);
file.getSingle<Ifc2x3::IfcProject>()->setName("IfcArbitraryOpenProfileDef");
std::ofstream f(filename);
f << file;
}
+119
View File
@@ -0,0 +1,119 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Example that generates extrusions of parameterized profiles. *
* *
********************************************************************************/
#include <string>
#include <iostream>
#include <fstream>
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcHierarchyHelper.h"
typedef std::string S;
typedef IfcWrite::IfcGuidHelper guid;
boost::none_t const null = (static_cast<boost::none_t>(0));
int main(int argc, char** argv) {
const char filename[] = "IfcCompositeProfileDef.ifc";
IfcHierarchyHelper file;
file.filename(filename);
double coords1[] = {100.0, 0.0};
double coords2[] = {200.0, 0.0};
double coords3[] = {300.0, 0.0};
IfcSchema::IfcProfileDef::list profiles (new IfcTemplatedEntityList<IfcSchema::IfcProfileDef>());
IfcSchema::IfcCartesianTransformationOperator2D* transform1 = new IfcSchema::IfcCartesianTransformationOperator2D(file.addDoublet<IfcSchema::IfcDirection>(1, 0), file.addDoublet<IfcSchema::IfcDirection>(0, -1), file.addDoublet<IfcSchema::IfcCartesianPoint>(40, 0), null);
IfcSchema::IfcCartesianTransformationOperator2D* transform2 = new IfcSchema::IfcCartesianTransformationOperator2D(file.addDoublet<IfcSchema::IfcDirection>(0, -1), file.addDoublet<IfcSchema::IfcDirection>(1, 0), file.addDoublet<IfcSchema::IfcCartesianPoint>(40, 0), 0.3);
IfcSchema::IfcProfileDef* p1 = new Ifc2x3::IfcIShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, file.addPlacement2d(), 25.0, 50.0, 5.0, 5.0, 2.0);
IfcSchema::IfcProfileDef* p2 = new Ifc2x3::IfcLShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, file.addPlacement2d(), 50.0, 25.0, 5.0, 1.0, 2.0, 2.0, null, null);
IfcSchema::IfcProfileDef* p3 = new Ifc2x3::IfcTShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, file.addPlacement2d(), 50.0, 40.0, 10.0, 10.0, 3.0, 2.0, 1.0, 2.0, 2.0, null);
IfcSchema::IfcProfileDef* p4 = new Ifc2x3::IfcCShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, file.addPlacement2d(80.), 50.0, 25.0, 5.0, 10.0, 2.0, null);
file.addEntity(p2);
file.addEntity(p3);
file.addEntity(transform1);
file.addEntity(transform2);
IfcSchema::IfcDerivedProfileDef* p5 = new IfcSchema::IfcDerivedProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, null, p2, transform1, null);
IfcSchema::IfcDerivedProfileDef* p6 = new IfcSchema::IfcDerivedProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, null, p3, transform2, null);
profiles->push(p1);
profiles->push(p5);
profiles->push(p6);
profiles->push(p4);
file.addEntities(profiles->generalize());
IfcSchema::IfcCompositeProfileDef* composite = new IfcSchema::IfcCompositeProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, S("IFC"), profiles, null);
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
guid(), 0, S("profile"), null, null, 0, 0, null, null);
file.addBuildingProduct(product);
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
product->setObjectPlacement(file.addLocalPlacement());
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(composite,
file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 20.0);
file.addEntity(composite);
file.addEntity(solid);
IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
items->push(solid);
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("SweptSolid"), items);
reps->push(rep);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
file.addEntity(rep);
file.addEntity(shape);
product->setRepresentation(shape);
file.getSingle<IfcSchema::IfcProject>()->setName("IfcCompositeProfileDef");
std::ofstream f(filename);
f << file;
}
+193
View File
@@ -0,0 +1,193 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Example that generates a Constructive Solid Geometry example *
* *
********************************************************************************/
#include <string>
#include <iostream>
#include <fstream>
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcHierarchyHelper.h"
typedef std::string S;
typedef IfcWrite::IfcGuidHelper guid;
boost::none_t const null = (static_cast<boost::none_t>(0));
class Node {
private:
typedef enum {
OP_ADD, OP_SUBTRACT, OP_INTERSECT, OP_TERMINAL
} Op;
typedef enum {
PRIM_BOX, PRIM_CONE, PRIM_CYLINDER, PRIM_PYRAMID, PRIM_SPHERE
} Prim;
double x,y,z, zx,zy,zz, xx,xy,xz, a,b,c;
const Node *left, *right;
Op op;
Prim prim;
Node& operate(Op op, const Node& p) {
left = new Node(*this);
right = new Node(p);
this->op = op;
return *this;
}
Node(Prim p, double la, double lb=0., double lc=0.)
: prim(p), op(OP_TERMINAL),
x(0.), y(0.), z(0.),
zx(0.), zy(0.), zz(1.),
xx(1.), xy(0.), xz(0.),
a(la), b(lb), c(lc) {}
public:
static Node Sphere(double r) {
return Node(PRIM_SPHERE, r);
}
static Node Box(double dx, double dy, double dz) {
return Node(PRIM_BOX, dx, dy, dz);
}
static Node Pyramid(double dx, double dy, double dz) {
return Node(PRIM_PYRAMID, dx, dy, dz);
}
static Node Cylinder(double r, double h) {
return Node(PRIM_CYLINDER, r, h);
}
static Node Cone(double r, double h) {
return Node(PRIM_CONE, r, h);
}
Node& move(
double px = 0., double py = 0., double pz = 0.,
double zx = 0., double zy = 0., double zz = 1.,
double xx = 1., double xy = 0., double xz = 0.)
{
this->x = px; this->y = py; this->z = pz;
this->zx = zx; this->zy = zy; this->zz = zz;
this->xx = xx; this->xy = xy; this->xz = xz;
return *this;
}
Node& add(const Node& p) {
return operate(OP_ADD, p);
}
Node& subtract(const Node& p) {
return operate(OP_SUBTRACT, p);
}
Node& intersect(const Node& p) {
return operate(OP_INTERSECT, p);
}
IfcSchema::IfcRepresentationItem* serialize(IfcHierarchyHelper& file) const {
IfcSchema::IfcRepresentationItem* my;
if (op == OP_TERMINAL) {
IfcSchema::IfcAxis2Placement3D* place = file.addPlacement3d(x,y,z,zx,zy,zz,xx,xy,xz);
if (prim == PRIM_SPHERE) {
my = new IfcSchema::IfcSphere(place, a);
} else if (prim == PRIM_BOX) {
my = new IfcSchema::IfcBlock(place, a, b, c);
} else if (prim == PRIM_PYRAMID) {
my = new IfcSchema::IfcRectangularPyramid(place, a, b, c);
} else if (prim == PRIM_CYLINDER) {
my = new IfcSchema::IfcRightCircularCylinder(place, b, a);
} else if (prim == PRIM_CONE) {
my = new IfcSchema::IfcRightCircularCone(place, b, a);
}
} else {
IfcSchema::IfcBooleanOperator::IfcBooleanOperator o;
if (op == OP_ADD) {
o = IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION;
} else if (op == OP_SUBTRACT) {
o = IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE;
} else if (op == OP_INTERSECT) {
o = IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION;
}
my = new IfcSchema::IfcBooleanResult(o, left->serialize(file), right->serialize(file));
}
file.addEntity(my);
return my;
}
};
int main(int argc, char** argv) {
const char filename[] = "IfcCsgPrimitive.ifc";
IfcHierarchyHelper file;
file.filename(filename);
IfcSchema::IfcRepresentationItem* csg1 = Node::Box(8000.,6000.,3000.).subtract(
Node::Box(7600.,5600.,2800.).move(200.,200.,200.)
).add(
Node::Pyramid(8000.,6000.,3000.).move(0,0,3000.).add(
Node::Cylinder(1000.,4000.).move(4000.,1000.,4000., 0.,1.,0.)
).subtract(
Node::Pyramid(7600.,5600.,2800.).move(200.,200.,3000.)
).subtract(
Node::Cylinder(900.,4000.).move(4000.,1000.,4000., 0.,1.,0.).intersect(
Node::Box(2000.,4000.,1000.).move(3000.,1000.,4000.)
)
)
).serialize(file);
const double x = 1000.; const double y = -4000.;
IfcSchema::IfcRepresentationItem* csg2 = Node::Sphere(5000.).move(x,y,-4500.).intersect(
Node::Box(6000., 6000., 6000.).move(x-3000., y-3000., 0.)
).add(
Node::Cone(500., 3000.).move(x,y).add(
Node::Cone(1500., 1000.).move(x,y, 900.).add(
Node::Cone(1100., 1000.).move(x,y, 1800.).add(
Node::Cone(750., 600.).move(x,y, 2700.)
)))).serialize(file);
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
guid(), 0, S("IfcCsgPrimitive"), null, null, 0, 0, null, null);
file.addBuildingProduct(product);
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
product->setObjectPlacement(file.addLocalPlacement());
IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
items->push(csg1);
items->push(csg2);
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("CSG"), items);
reps->push(rep);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
file.addEntity(rep);
file.addEntity(shape);
product->setRepresentation(shape);
file.getSingle<IfcSchema::IfcProject>()->setName("IfcCompositeProfileDef");
std::ofstream f(filename);
f << file;
}
+148
View File
@@ -0,0 +1,148 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Example that generates profiles of trimmed ellipses. *
* *
********************************************************************************/
#include <string>
#include <iostream>
#include <fstream>
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcHierarchyHelper.h"
typedef std::string S;
typedef IfcWrite::IfcGuidHelper guid;
boost::none_t const null = (static_cast<boost::none_t>(0));
typedef struct {
double r1;
double r2;
double t1;
double t2;
} EllipsePie;
static int i = 0;
void create_testcase_for(IfcHierarchyHelper& file, const EllipsePie& pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference pref) {
const double deg = 1. / 180. * 3.141592653;
double flt1[] = {0. , 0. };
double flt2[] = {pie.r1 * cos(pie.t1*deg), pie.r2 * sin(pie.t1*deg)};
double flt3[] = {pie.r1 * cos(pie.t2*deg), pie.r2 * sin(pie.t2*deg)};
std::vector<double> coords1(flt1, flt1 + 2);
std::vector<double> coords2(flt2, flt2 + 2);
std::vector<double> coords3(flt3, flt3 + 2);
Ifc2x3::IfcCartesianPoint* p1 = new Ifc2x3::IfcCartesianPoint(coords1);
Ifc2x3::IfcCartesianPoint* p2 = new Ifc2x3::IfcCartesianPoint(coords2);
Ifc2x3::IfcCartesianPoint* p3 = new Ifc2x3::IfcCartesianPoint(coords3);
Ifc2x3::IfcCartesianPoint::list points(new IfcTemplatedEntityList<Ifc2x3::IfcCartesianPoint>());
points->push(p3);
points->push(p1);
points->push(p2);
file.addEntities(points->generalize());
Ifc2x3::IfcEllipse* ellipse = new Ifc2x3::IfcEllipse(file.addPlacement2d(), pie.r1, pie.r2);
file.addEntity(ellipse);
IfcEntityList::ptr trim1(new IfcEntityList);
IfcEntityList::ptr trim2(new IfcEntityList);
if (pref == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER) {
trim1->push(new IfcWrite::IfcSelectHelper(pie.t1, Ifc2x3::Type::IfcParameterValue));
trim2->push(new IfcWrite::IfcSelectHelper(pie.t2, Ifc2x3::Type::IfcParameterValue));
} else {
trim1->push(p2);
trim2->push(p3);
}
Ifc2x3::IfcTrimmedCurve* trim = new Ifc2x3::IfcTrimmedCurve(ellipse, trim1, trim2, true, pref);
file.addEntity(trim);
Ifc2x3::IfcCompositeCurveSegment::list segments(new IfcTemplatedEntityList<Ifc2x3::IfcCompositeCurveSegment>());
Ifc2x3::IfcCompositeCurveSegment* s2 = new Ifc2x3::IfcCompositeCurveSegment(Ifc2x3::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, trim);
Ifc2x3::IfcPolyline* poly = new Ifc2x3::IfcPolyline(points);
file.addEntity(poly);
Ifc2x3::IfcCompositeCurveSegment* s1 = new Ifc2x3::IfcCompositeCurveSegment(Ifc2x3::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly);
segments->push(s1);
segments->push(s2);
file.addEntities(segments->generalize());
Ifc2x3::IfcCompositeCurve* ccurve = new Ifc2x3::IfcCompositeCurve(segments, false);
Ifc2x3::IfcArbitraryClosedProfileDef* profile = new Ifc2x3::IfcArbitraryClosedProfileDef(Ifc2x3::IfcProfileTypeEnum::IfcProfileType_AREA, null, ccurve);
file.addEntity(ccurve);
file.addEntity(profile);
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
guid(), 0, S("profile"), null, null, 0, 0, null, null);
file.addBuildingProduct(product);
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
product->setObjectPlacement(file.addLocalPlacement(200 * i++));
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(profile,
file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 20.0);
file.addEntity(solid);
IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
items->push(solid);
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("SweptSolid"), items);
reps->push(rep);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
file.addEntity(rep);
file.addEntity(shape);
product->setRepresentation(shape);
}
int main(int argc, char** argv) {
const std::string filename = "ellipse_pies.ifc";
IfcHierarchyHelper file;
{ EllipsePie pie = {80., 50., 0., 150.};
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
{ EllipsePie pie = {80, 50., 30., 300.};
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
{ EllipsePie pie = {80, 50., 300., 30.};
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
{ EllipsePie pie = {50., 80., 0., 150.};
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
{ EllipsePie pie = {50, 80., 30., 300.};
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
{ EllipsePie pie = {50, 80., 300., 30.};
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
std::ofstream f(filename.c_str());
f << file;
}
+206
View File
@@ -0,0 +1,206 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Example that generates extrusions of parameterized profiles. *
* *
********************************************************************************/
#include <string>
#include <iostream>
#include <fstream>
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcHierarchyHelper.h"
typedef std::string S;
typedef IfcWrite::IfcGuidHelper guid;
boost::none_t const null = (static_cast<boost::none_t>(0));
void create_testcase_for(IfcSchema::IfcProfileDef::list::ptr profiles) {
IfcSchema::IfcProfileDef* profile = *profiles->begin();
const std::string profile_type = IfcSchema::Type::ToString(profile->type());
const std::string filename = profile_type + ".ifc";
IfcHierarchyHelper file;
file.filename(filename);
int i = 0;
for (IfcSchema::IfcProfileDef::list::it it = profiles->begin(); it != profiles->end(); ++it, ++i) {
IfcSchema::IfcProfileDef* profile = *it;
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
guid(), 0, S("profile"), null, null, 0, 0, null, null);
file.addBuildingProduct(product);
file.getSingle<IfcSchema::IfcProject>()->setName(profile_type);
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
product->setObjectPlacement(file.addLocalPlacement(0, 100. * i));
if (profile->is(IfcSchema::Type::IfcParameterizedProfileDef)) {
((IfcSchema::IfcParameterizedProfileDef*) profile)->setPosition(file.addPlacement2d());
}
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(profile,
file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 20.0);
file.addEntity(profile);
file.addEntity(solid);
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);
items->push(solid);
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("SweptSolid"), items);
reps->push(rep);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
file.addEntity(rep);
file.addEntity(shape);
product->setRepresentation(shape);
}
std::ofstream f(filename.c_str());
f << file;
}
int main(int argc, char** argv) {
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcUShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, null, null, null, null));
profiles->push(new Ifc2x3::IfcUShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, 2.0, 2.0, null, null));
profiles->push(new Ifc2x3::IfcUShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, null, null, 4.0, null));
profiles->push(new Ifc2x3::IfcUShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, 1.0, 3.0, 6.0, null));
create_testcase_for(profiles); }
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcTShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, null, null, null, null, null, null));
profiles->push(new Ifc2x3::IfcTShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, 2.0, 2.0, 2.0, null, null, null));
profiles->push(new Ifc2x3::IfcTShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, null, null, null, 2.0, 2.0, null));
profiles->push(new Ifc2x3::IfcTShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, 3.0, 2.0, 1.0, 2.0, 2.0, null));
create_testcase_for(profiles); }
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcZShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, null, null));
profiles->push(new Ifc2x3::IfcZShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 5.0, 2.0, 2.0));
create_testcase_for(profiles); }
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcEllipseProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 25.0, 15.0));
profiles->push(new Ifc2x3::IfcEllipseProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 15.0, 25.0));
create_testcase_for(profiles); }
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcIShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 25.0, 50.0, 5.0, 5.0, null));
profiles->push(new Ifc2x3::IfcIShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 25.0, 50.0, 5.0, 5.0, 2.0));
profiles->push(new Ifc2x3::IfcAsymmetricIShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 25.0, 50.0, 5.0, 5.0, 2.0, 20.0, 10.0, 5.0, null));
create_testcase_for(profiles); }
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcLShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, null, null, null, null, null));
profiles->push(new Ifc2x3::IfcLShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 2.0, 2.0, null, null, null));
profiles->push(new Ifc2x3::IfcLShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, null, null, 2.0, null, null));
profiles->push(new Ifc2x3::IfcLShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 1.0, 2.0, 2.0, null, null));
create_testcase_for(profiles); }
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcCShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 10.0, null, null));
profiles->push(new Ifc2x3::IfcCShapeProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 10.0, 2.0, null));
create_testcase_for(profiles); }
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcCircleProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 25.0));
profiles->push(new Ifc2x3::IfcCircleHollowProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 25.0, 5.0));
create_testcase_for(profiles); }
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcRectangleProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0));
profiles->push(new Ifc2x3::IfcRoundedRectangleProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0));
profiles->push(new Ifc2x3::IfcRectangleHollowProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, null, null));
profiles->push(new Ifc2x3::IfcRectangleHollowProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 25.0, 5.0, 2.0, 4.0));
create_testcase_for(profiles); }
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
profiles->push(new Ifc2x3::IfcTrapeziumProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 30.0, 25.0, 0.0));
profiles->push(new Ifc2x3::IfcTrapeziumProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 60.0, 25.0, -20.0));
profiles->push(new Ifc2x3::IfcTrapeziumProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
null, 0, 50.0, 10.0, 25.0, 30.0));
create_testcase_for(profiles); }
}
+47 -30
View File
@@ -30,19 +30,16 @@ bl_info = {
"description": "Import files in the "\
"Industry Foundation Classes (.ifc) file format",
"author": "Thomas Krijnen, IfcOpenShell",
"blender": (2, 6, 5),
"api": 52851,
"blender": (2, 73, 0),
"location": "File > Import",
"warning": "",
"wiki_url": "http://sourceforge.net/apps/"\
"mediawiki/ifcopenshell/index.php",
"tracker_url": "http://sourceforge.net/tracker/?group_id=543113",
"tracker_url": "https://sourceforge.net/p/ifcopenshell/"\
"_list/tickets?source=navbar",
"category": "Import-Export"}
if "bpy" in locals():
import imp
if "IfcImport" in locals():
imp.reload(IfcImport)
if "ifcopenshell" in locals():
imp.reload(ifcopenshell)
import bpy
import mathutils
@@ -62,27 +59,31 @@ bpy.types.Object.ifc_type = StringProperty(name="IFC Entity Type",
description="The STEP Datatype keyword")
def import_ifc(filename, use_names, process_relations):
from . import IfcImport
def import_ifc(filename, use_names, process_relations, blender_booleans):
from . import ifcopenshell
from .ifcopenshell import geom as ifcopenshell_geom
print("Reading %s..."%bpy.path.basename(filename))
valid_file = IfcImport.Init(filename)
settings = ifcopenshell_geom.settings()
settings.set(settings.DISABLE_OPENING_SUBTRACTIONS, blender_booleans)
iterator = ifcopenshell_geom.iterator(settings, filename)
valid_file = iterator.findContext()
if not valid_file:
IfcImport.CleanUp()
return False
print("Done reading file")
id_to_object = {}
id_to_parent = {}
id_to_matrix = {}
openings = []
old_progress = -1
print("Creating geometry...")
while True:
ob = IfcImport.Get()
ob = iterator.get()
f = ob.mesh.faces
v = ob.mesh.verts
mats = ob.mesh.materials
matids = ob.mesh.material_ids
m = ob.matrix
f = ob.geometry.faces
v = ob.geometry.verts
mats = ob.geometry.materials
matids = ob.geometry.material_ids
m = ob.transformation.matrix.data
t = ob.type[0:21]
nm = ob.name if len(ob.name) and use_names else ob.guid
@@ -91,7 +92,7 @@ def import_ifc(filename, use_names, process_relations):
faces = [[f[i], f[i + 1], f[i + 2]] \
for i in range(0, len(f), 3)]
me = bpy.data.meshes.new('mesh%d' % ob.mesh.id)
me = bpy.data.meshes.new('mesh%d' % ob.geometry.id)
me.from_pydata(verts, [], faces)
def add_material(mname, props):
@@ -138,8 +139,10 @@ def import_ifc(filename, use_names, process_relations):
bob.ifc_id, bob.ifc_guid, bob.ifc_name, bob.ifc_type = \
ob.id, ob.guid, ob.name, ob.type
bob.hide = ob.type == 'IfcSpace' or ob.type == 'IfcOpeningElement'
bob.hide_render = bob.hide
if ob.type == 'IfcSpace' or ob.type == 'IfcOpeningElement':
if not (ob.type == 'IfcOpeningElement' and blender_booleans):
bob.hide = bob.hide_render = True
bob.draw_type = 'WIRE'
if ob.id not in id_to_object: id_to_object[ob.id] = []
id_to_object[ob.id].append(bob)
@@ -147,16 +150,19 @@ def import_ifc(filename, use_names, process_relations):
if ob.parent_id > 0:
id_to_parent[ob.id] = ob.parent_id
if blender_booleans and ob.type == 'IfcOpeningElement':
openings.append(ob.id)
faces = me.polygons if hasattr(me, 'polygons') else me.faces
if len(faces) == len(matids):
for face, matid in zip(faces, matids):
face.material_index = matid + (1 if needs_default else 0)
progress = IfcImport.Progress() // 2
progress = iterator.progress() // 2
if progress > old_progress:
print("\r[" + "#" * progress + " " * (50 - progress) + "]", end="")
old_progress = progress
if not IfcImport.Next():
if not iterator.next():
break
print("\rDone creating geometry" + " " * 30)
@@ -172,11 +178,11 @@ def import_ifc(filename, use_names, process_relations):
if parent_id in id_to_object:
bob = id_to_object[parent_id][0]
else:
parent_ob = IfcImport.GetObject(parent_id)
parent_ob = iterator.getObject(parent_id)
if parent_ob.id == -1:
bob = None
else:
m = parent_ob.matrix
m = parent_ob.transformation.matrix.data
nm = parent_ob.name if len(parent_ob.name) and use_names \
else parent_ob.guid
bob = bpy.data.objects.new(nm, None)
@@ -218,12 +224,19 @@ def import_ifc(filename, use_names, process_relations):
if process_relations:
print("Done processing relations")
for opening_id in openings:
parent_id = id_to_parent[opening_id]
if parent_id in id_to_object:
parent_ob = id_to_object[parent_id][0]
for opening_ob in id_to_object[opening_id]:
mod = parent_ob.modifiers.new("opening", "BOOLEAN")
mod.operation = "DIFFERENCE"
mod.object = opening_ob
txt = bpy.data.texts.new("%s.log"%bpy.path.basename(filename))
txt.from_string(IfcImport.GetLog())
txt.from_string(iterator.getLog())
IfcImport.CleanUp()
return True
@@ -242,9 +255,13 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
" relations to parenting" \
" (warning: may be slow on large files)",
default=False)
blender_booleans = BoolProperty(name="Use Blender booleans",
description="Use Blender boolean modifiers for opening" \
" elements",
default=False)
def execute(self, context):
if not import_ifc(self.filepath, self.use_names, self.process_relations):
if not import_ifc(self.filepath, self.use_names, self.process_relations, self.blender_booleans):
self.report({'ERROR'},
'Unable to parse .ifc file or no geometrical entities found'
)
+23 -30
View File
@@ -35,7 +35,7 @@ std::string collada_id(const std::string& s) {
return id;
}
void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector<float>& floats, const char* coords /* = "XYZ" */) {
void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector<double>& floats, const char* coords /* = "XYZ" */) {
COLLADASW::FloatSource source(mSW);
source.setId(mesh_id + suffix);
source.setArrayId(mesh_id + suffix + COLLADASW::LibraryGeometries::ARRAY_ID_SUFFIX);
@@ -45,13 +45,18 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const
source.getParameterNameList().push_back(std::string(1, coords[i]));
}
source.prepareToAppendValues();
for (std::vector<float>::const_iterator it = floats.begin(); it != floats.end(); ++it) {
for (std::vector<double>::const_iterator it = floats.begin(); it != floats.end(); ++it) {
source.appendValues(*it);
}
source.finish();
}
void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::string mesh_id, const std::string& default_material_name, const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int> material_ids, const std::vector<IfcGeomObjects::Material>& materials) {
void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::string mesh_id, const std::string& default_material_name, const std::vector<double>& positions, const std::vector<double>& normals, const std::vector<int>& indices, const std::vector<int> material_ids, const std::vector<IfcGeom::Material>& materials) {
// The goal of the IfcGeom::Iterator is to filter out empty geometries, but
// since this function would crash trying to deference the material_ids in
// that case, a hard return statement is added just in case.
if (indices.empty()) return;
openMesh(mesh_id);
// The normals vector can be empty for example when the WELD_VERTICES setting is used.
@@ -70,17 +75,13 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::str
std::vector<int>::const_iterator index_range_start = indices.begin();
std::vector<int>::const_iterator material_it = material_ids.begin();
int previous_material_id = -2;
int previous_material_id = -1;
for (std::vector<int>::const_iterator it = indices.begin(); ; it += 3) {
const int current_material_id = material_it == material_ids.end()
? -3
: *(material_it++);
const int current_material_id = *(material_it++);
const int num_triangles = std::distance(index_range_start, it) / 3;
if ((previous_material_id != current_material_id && num_triangles > 0) || (it == indices.end())) {
COLLADASW::Triangles triangles(mSW);
triangles.setMaterial(collada_id(previous_material_id < 0
? default_material_name
: materials[previous_material_id].name()));
triangles.setMaterial(materials[previous_material_id].name());
triangles.setCount(num_triangles);
int offset = 0;
triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX,"#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++ ) );
@@ -113,7 +114,7 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::close() {
closeLibrary();
}
void ColladaSerializer::ColladaExporter::ColladaScene::add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector<std::string>& material_ids, const std::vector<float>& matrix) {
void ColladaSerializer::ColladaExporter::ColladaScene::add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector<std::string>& material_ids, const std::vector<double>& matrix) {
if (!scene_opened) {
openVisualScene(scene_id);
scene_opened = true;
@@ -155,7 +156,7 @@ void ColladaSerializer::ColladaExporter::ColladaScene::write() {
}
}
void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeomObjects::Material& material) {
void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeom::Material& material) {
openEffect(collada_id(material.name()) + "-fx");
COLLADASW::EffectProfile effect(mSW);
effect.setShaderType(COLLADASW::EffectProfile::LAMBERT);
@@ -186,20 +187,20 @@ void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::close
closeLibrary();
}
void ColladaSerializer::ColladaExporter::ColladaMaterials::add(const IfcGeomObjects::Material& material) {
void ColladaSerializer::ColladaExporter::ColladaMaterials::add(const IfcGeom::Material& material) {
if (!contains(material)) {
effects.write(material);
materials.push_back(material);
}
}
bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const IfcGeomObjects::Material& material) {
bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const IfcGeom::Material& material) {
return std::find(materials.begin(), materials.end(), material) != materials.end();
}
void ColladaSerializer::ColladaExporter::ColladaMaterials::write() {
effects.close();
for (std::vector<IfcGeomObjects::Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) {
for (std::vector<IfcGeom::Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) {
const std::string& material_name = collada_id((*it).name());
openMaterial(material_name);
addInstanceEffect("#" + material_name + "-fx");
@@ -218,18 +219,10 @@ void ColladaSerializer::ColladaExporter::startDocument(const std::string& unit_n
asset.add();
}
void ColladaSerializer::ColladaExporter::writeTesselated(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector<float>& matrix, const std::vector<float>& vertices, const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int>& material_ids, const std::vector<IfcGeomObjects::Material>& _materials) {
const IfcGeomObjects::Material default_for_type = IfcGeomObjects::Material(IfcGeom::get_default_style(type));
void ColladaSerializer::ColladaExporter::write(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector<double>& matrix, const std::vector<double>& vertices, const std::vector<double>& normals, const std::vector<int>& indices, const std::vector<int>& material_ids, const std::vector<IfcGeom::Material>& _materials) {
std::vector<std::string> material_references;
const bool needs_default = std::find(material_ids.begin(), material_ids.end(), -1) != material_ids.end();
if (needs_default) {
if (!materials.contains(default_for_type)) {
materials.add(default_for_type);
}
material_references.push_back(collada_id(default_for_type.name()));
}
for (std::vector<IfcGeomObjects::Material>::const_iterator it = _materials.begin(); it != _materials.end(); ++it) {
const IfcGeomObjects::Material& material = *it;
for (std::vector<IfcGeom::Material>::const_iterator it = _materials.begin(); it != _materials.end(); ++it) {
const IfcGeom::Material& material = *it;
if (!materials.contains(material)) {
materials.add(material);
}
@@ -259,7 +252,7 @@ void ColladaSerializer::ColladaExporter::endDocument() {
geometries.close();
for (std::vector<DeferredObject>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it) {
const std::string object_name = it->Name();
scene.add(object_name, object_name, object_name, it->material_references, it->matrix);
scene.add(object_name + "-instance", object_name, object_name, it->material_references, it->matrix);
}
scene.write();
stream.endDocument();
@@ -273,9 +266,9 @@ void ColladaSerializer::writeHeader() {
exporter.startDocument(unit_name, unit_magnitude);
}
void ColladaSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {
const IfcGeomObjects::IfcRepresentationTriangulation& mesh = o->mesh();
exporter.writeTesselated(o->guid(), o->name(), o->type(), o->id(), o->matrix(), mesh.verts(), mesh.normals(), mesh.faces(), mesh.material_ids(), mesh.materials());
void ColladaSerializer::write(const IfcGeom::TriangulationElement<double>* o) {
const IfcGeom::Representation::Triangulation<double>& mesh = o->geometry();
exporter.write(o->guid(), o->name(), o->type(), o->id(), o->transformation().matrix().data(), mesh.verts(), mesh.normals(), mesh.faces(), mesh.material_ids(), mesh.materials());
}
void ColladaSerializer::finalize() {
+19 -18
View File
@@ -35,7 +35,7 @@
#include <COLLADASWBaseInputElement.h>
#include <COLLADASWAsset.h>
#include "../ifcgeom/IfcGeomObjects.h"
#include "../ifcgeom/IfcGeomIterator.h"
#include "../ifcconvert/GeometrySerializer.h"
@@ -51,8 +51,8 @@ private:
explicit ColladaGeometries(COLLADASW::StreamWriter& stream)
: COLLADASW::LibraryGeometries(&stream)
{}
void addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector<float>& floats, const char* coords = "XYZ");
void write(const std::string mesh_id, const std::string& default_material_name, const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int> material_ids, const std::vector<IfcGeomObjects::Material>& materials);
void addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector<double>& floats, const char* coords = "XYZ");
void write(const std::string mesh_id, const std::string& default_material_name, const std::vector<double>& positions, const std::vector<double>& normals, const std::vector<int>& indices, const std::vector<int> material_ids, const std::vector<IfcGeom::Material>& materials);
void close();
};
class ColladaScene : public COLLADASW::LibraryVisualScenes
@@ -66,7 +66,7 @@ private:
, scene_id(scene_id)
, scene_opened(false)
{}
void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector<std::string>& material_ids, const std::vector<float>& matrix);
void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector<std::string>& material_ids, const std::vector<double>& matrix);
void write();
};
class ColladaMaterials : public COLLADASW::LibraryMaterials
@@ -78,34 +78,34 @@ private:
explicit ColladaEffects(COLLADASW::StreamWriter& stream)
: COLLADASW::LibraryEffects(&stream)
{}
void write(const IfcGeomObjects::Material& material);
void write(const IfcGeom::Material& material);
void close();
};
std::vector<IfcGeomObjects::Material> materials;
std::vector<IfcGeom::Material> materials;
ColladaEffects effects;
public:
explicit ColladaMaterials(COLLADASW::StreamWriter& stream)
: COLLADASW::LibraryMaterials(&stream)
, effects(stream)
{}
void add(const IfcGeomObjects::Material& material);
bool contains(const IfcGeomObjects::Material& material);
void add(const IfcGeom::Material& material);
bool contains(const IfcGeom::Material& material);
void write();
};
class DeferredObject {
public:
std::string guid, name, type;
int obj_id;
std::vector<float> matrix;
std::vector<float> vertices;
std::vector<float> normals;
std::vector<double> matrix;
std::vector<double> vertices;
std::vector<double> normals;
std::vector<int> indices;
std::vector<int> material_ids;
std::vector<IfcGeomObjects::Material> materials;
std::vector<IfcGeom::Material> materials;
std::vector<std::string> material_references;
DeferredObject(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector<float>& matrix, const std::vector<float>& vertices,
const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int>& material_ids,
const std::vector<IfcGeomObjects::Material>& materials, const std::vector<std::string>& material_references)
DeferredObject(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector<double>& matrix, const std::vector<double>& vertices,
const std::vector<double>& normals, const std::vector<int>& indices, const std::vector<int>& material_ids,
const std::vector<IfcGeom::Material>& materials, const std::vector<std::string>& material_references)
: guid(guid)
, name(name)
, type(type)
@@ -136,7 +136,7 @@ private:
std::vector<DeferredObject> deferreds;
virtual ~ColladaExporter() {}
void startDocument(const std::string& unit_name, float unit_magnitude);
void writeTesselated(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector<float>& matrix, const std::vector<float>& vertices, const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int>& material_ids, const std::vector<IfcGeomObjects::Material>& materials);
void write(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector<double>& matrix, const std::vector<double>& vertices, const std::vector<double>& normals, const std::vector<int>& indices, const std::vector<int>& material_ids, const std::vector<IfcGeom::Material>& materials);
void endDocument();
};
ColladaExporter exporter;
@@ -149,14 +149,15 @@ public:
{}
bool ready();
void writeHeader();
void writeTesselated(const IfcGeomObjects::IfcGeomObject* o);
void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {}
void write(const IfcGeom::TriangulationElement<double>* o);
void write(const IfcGeom::BRepElement<double>* o) {}
void finalize();
bool isTesselated() const { return true; }
void setUnitNameAndMagnitude(const std::string& name, float magnitude) {
unit_name = name;
unit_magnitude = magnitude;
}
void setFile(IfcParse::IfcFile*) {}
};
#endif
+7 -8
View File
@@ -20,17 +20,16 @@
#ifndef GEOMETRYSERIALIZER_H
#define GEOMETRYSERIALIZER_H
#include "../ifcgeom/IfcGeomObjects.h"
#include "../ifcconvert/Serializer.h"
#include "../ifcgeom/IfcGeomIterator.h"
class GeometrySerializer {
class GeometrySerializer : public Serializer {
public:
virtual bool ready() = 0;
virtual void writeHeader() = 0;
virtual void finalize() = 0;
virtual bool isTesselated() const = 0;
virtual ~GeometrySerializer() {}
virtual void writeTesselated(const IfcGeomObjects::IfcGeomObject* o) = 0;
virtual void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) = 0;
virtual bool isTesselated() const = 0;
virtual void write(const IfcGeom::TriangulationElement<double>* o) = 0;
virtual void write(const IfcGeom::BRepElement<double>* o) = 0;
virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) = 0;
};
+139 -82
View File
@@ -33,12 +33,13 @@
#include <boost/program_options.hpp>
#include "../ifcgeom/IfcGeomObjects.h"
#include "../ifcgeom/IfcGeomIterator.h"
#include "../ifcconvert/ColladaSerializer.h"
#include "../ifcconvert/IgesSerializer.h"
#include "../ifcconvert/StepSerializer.h"
#include "../ifcconvert/WavefrontObjSerializer.h"
#include "../ifcconvert/XmlSerializer.h"
void printVersion() {
std::cerr << "IfcOpenShell IfcConvert " << IFCOPENSHELL_VERSION << std::endl;
@@ -55,6 +56,7 @@ void printUsage(const boost::program_options::options_description& generic_optio
#endif
std::cerr << " .stp STEP Standard for the Exchange of Product Data" << std::endl
<< " .igs IGES Initial Graphics Exchange Specification" << std::endl
<< " .xml XML Property definitions and decomposition tree" << std::endl
<< std::endl
<< "Command line options" << std::endl << generic_options << std::endl
<< "Advanced options" << std::endl << geom_options << std::endl;
@@ -84,35 +86,48 @@ int main(int argc, char** argv) {
("input-file", boost::program_options::value<std::string>(), "input IFC file")
("output-file", boost::program_options::value<std::string>(), "output geometry file");
std::vector<std::string> ignore_types_vector;
std::vector<std::string> entity_vector;
boost::program_options::options_description geom_options;
geom_options.add_options()
("weld-vertices", "Specifies whether vertices are welded, meaning that the coordinates "
"vector will only contain unique xyz-triplets. This results in a "
"manifold mesh which is useful for modelling applications, but might "
"result in unwanted shading artifacts in rendering applications.")
("use-world-coords", "Specifies whether to apply the local placements of building elements "
"directly to the coordinates of the representation mesh rather than "
"to represent the local placement in the 4x3 matrix, which will in that "
"case be the identity matrix.")
("convert-back-units", "Specifies whether to convert back geometrical output back to the "
"unit of measure in which it is defined in the IFC file. Default is "
"to use meters.")
("sew-shells", "Specifies whether to sew the faces of IfcConnectedFaceSets together. This is a "
"potentially time consuming operation, but guarantees a consistent orientation "
"of surface normals, even if the faces are not properly oriented in the IFC file.")
("merge-boolean-operands", "Specifies whether to merge all IfcOpeningElement operands into a single "
"operand before applying the subtraction operation. This may "
"introduce a performance improvement at the risk of failing, in "
"which case the subtraction is applied one-by-one.")
("force-ccw-face-orientation", "Recompute topological face normals using Newell's Method to "
"guarantee that face vertices are defined in a Counter Clock "
"Wise order, even if the faces are not part of a closed shell.")
("disable-opening-subtractions", "Specifies whether to disable the boolean subtraction of "
"IfcOpeningElement Representations from their RelatingElements.")
("ignore-types", boost::program_options::value< std::vector<std::string> >(&ignore_types_vector)->multitoken(),
"A list of IFC datatype keywords that should not be included in the geometrical output. "
"Defaults to IfcOpeningElement and IfcSpace");
("weld-vertices",
"Specifies whether vertices are welded, meaning that the coordinates "
"vector will only contain unique xyz-triplets. This results in a "
"manifold mesh which is useful for modelling applications, but might "
"result in unwanted shading artefacts in rendering applications.")
("use-world-coords",
"Specifies whether to apply the local placements of building elements "
"directly to the coordinates of the representation mesh rather than "
"to represent the local placement in the 4x3 matrix, which will in that "
"case be the identity matrix.")
("convert-back-units",
"Specifies whether to convert back geometrical output back to the "
"unit of measure in which it is defined in the IFC file. Default is "
"to use meters.")
("sew-shells",
"Specifies whether to sew the faces of IfcConnectedFaceSets together. "
"This is a potentially time consuming operation, but guarantees a "
"consistent orientation of surface normals, even if the faces are not "
"properly oriented in the IFC file.")
("merge-boolean-operands",
"Specifies whether to merge all IfcOpeningElement operands into a single "
"operand before applying the subtraction operation. This may "
"introduce a performance improvement at the risk of failing, in "
"which case the subtraction is applied one-by-one.")
("force-ccw-face-orientation",
"Recompute topological face normals using Newell's Method to "
"guarantee that face vertices are defined in a Counter Clock "
"Wise order, even if the faces are not part of a closed shell.")
("disable-opening-subtractions",
"Specifies whether to disable the boolean subtraction of "
"IfcOpeningElement Representations from their RelatingElements.")
("include",
"Specifies that the entities listed after --entities are to be included")
("exclude",
"Specifies that the entities listed after --entities are to be excluded")
("entities", boost::program_options::value< std::vector<std::string> >(&entity_vector)->multitoken(),
"A list of entities that should be included in or excluded from the "
"geometrical output, depending on whether --ignore or --include is "
"specified. Defaults to IfcOpeningElement and IfcSpace to be excluded.");
boost::program_options::options_description cmdline_options;
cmdline_options.add(generic_options).add(fileio_options).add(geom_options);
@@ -122,14 +137,25 @@ int main(int argc, char** argv) {
positional_options.add("output-file", 1);
boost::program_options::variables_map vmap;
boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
options(cmdline_options).positional(positional_options).run(), vmap);
try {
boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
options(cmdline_options).positional(positional_options).run(), vmap);
} catch (const boost::program_options::unknown_option& e) {
std::cerr << "[Error] Unknown option '" << e.get_option_name() << "'" << std::endl << std::endl;
// Usage information will be emitted below
} catch (...) {
// Catch other errors such as invalid command line syntax
}
boost::program_options::notify(vmap);
if (vmap.count("version")) {
printVersion();
return 1;
return 0;
} else if (vmap.count("help") || !vmap.count("input-file")) {
printUsage(generic_options, geom_options);
return vmap.count("help") ? 0 : 1;
} else if (vmap.count("include") && vmap.count("exclude")) {
std::cerr << "[Error] --include and --ignore can not be specified together" << std::endl;
printUsage(generic_options, geom_options);
return 1;
}
@@ -142,20 +168,22 @@ int main(int argc, char** argv) {
const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0;
const bool force_ccw_face_orientation = vmap.count("force-ccw-face-orientation") != 0;
const bool disable_opening_subtractions = vmap.count("disable-opening-subtractions") != 0;
const bool include_entities = vmap.count("include") != 0;
// Gets the set ifc types to be ignored from the command line.
std::set<std::string> ignore_types;
for (std::vector<std::string>::const_iterator it = ignore_types_vector.begin(); it != ignore_types_vector.end(); ++it) {
std::set<std::string> entities;
for (std::vector<std::string>::const_iterator it = entity_vector.begin(); it != entity_vector.end(); ++it) {
std::string lowercase_type = *it;
for (std::string::iterator c = lowercase_type.begin(); c != lowercase_type.end(); ++c) {
*c = tolower(*c);
}
ignore_types.insert(lowercase_type);
entities.insert(lowercase_type);
}
// If none are specified these are the defaults to skip from output
if (ignore_types_vector.empty()) {
ignore_types.insert("ifcopeningelement");
ignore_types.insert("ifcspace");
// If no entities are specified these are the defaults to skip from output
if (entity_vector.empty()) {
entities.insert("ifcopeningelement");
entities.insert("ifcspace");
}
const std::string input_filename = vmap["input-file"].as<std::string>();
@@ -170,27 +198,48 @@ int main(int argc, char** argv) {
return 1;
}
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS, use_world_coords);
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES, weld_vertices);
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS, sew_shells);
IfcGeomObjects::Settings(IfcGeomObjects::CONVERT_BACK_UNITS, convert_back_units);
IfcGeomObjects::Settings(IfcGeomObjects::FASTER_BOOLEANS, merge_boolean_operands);
IfcGeomObjects::Settings(IfcGeomObjects::FORCE_CCW_FACE_ORIENTATION, force_ccw_face_orientation);
IfcGeomObjects::Settings(IfcGeomObjects::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions);
std::string output_extension = output_filename.substr(output_filename.size()-4);
for (std::string::iterator c = output_extension.begin(); c != output_extension.end(); ++c) {
*c = tolower(*c);
}
Logger::SetOutput(&std::cout, &log_stream);
Logger::Verbosity(verbose ? Logger::LOG_NOTICE : Logger::LOG_ERROR);
if (output_extension == ".xml") {
int exit_code = 1;
try {
XmlSerializer s(output_filename);
IfcParse::IfcFile f;
if (!f.Init(input_filename)) {
Logger::Message(Logger::LOG_ERROR, "Unable to parse .ifc file");
} else {
s.setFile(&f);
s.finalize();
exit_code = 0;
}
} catch (...) {}
write_log();
return exit_code;
}
IfcGeom::IteratorSettings settings;
settings.set(IfcGeom::IteratorSettings::APPLY_DEFAULT_MATERIALS, true);
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, use_world_coords);
settings.set(IfcGeom::IteratorSettings::WELD_VERTICES, weld_vertices);
settings.set(IfcGeom::IteratorSettings::SEW_SHELLS, sew_shells);
settings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, convert_back_units);
settings.set(IfcGeom::IteratorSettings::FASTER_BOOLEANS, merge_boolean_operands);
settings.set(IfcGeom::IteratorSettings::FORCE_CCW_FACE_ORIENTATION, force_ccw_face_orientation);
settings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions);
GeometrySerializer* serializer;
if (output_extension == ".obj") {
const std::string mtl_filename = output_filename.substr(0,output_filename.size()-3) + "mtl";
if (!use_world_coords) {
Logger::Message(Logger::LOG_NOTICE, "Using world coords when writing WaveFront OBJ files");
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS, true);
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true);
}
serializer = new WaveFrontOBJSerializer(output_filename, mtl_filename);
#ifdef WITH_OPENCOLLADA
@@ -211,7 +260,25 @@ int main(int argc, char** argv) {
return 1;
}
Logger::Verbosity(verbose ? Logger::LOG_NOTICE : Logger::LOG_ERROR);
if (!serializer->isTesselated()) {
if (weld_vertices) {
Logger::Message(Logger::LOG_NOTICE, "Weld vertices setting ignored when writing STEP or IGES files");
}
settings.disable_triangulation() = true;
}
IfcGeom::Iterator<double> context_iterator(settings, input_filename);
try {
if (include_entities) {
context_iterator.includeEntities(entities);
} else {
context_iterator.excludeEntities(entities);
}
} catch (const IfcParse::IfcException& e) {
std::cout << "[Error] " << e.what() << std::endl;
return 1;
}
if (!serializer->ready()) {
Logger::Message(Logger::LOG_ERROR, "Unable to open output file for writing");
@@ -219,22 +286,17 @@ int main(int argc, char** argv) {
return 1;
}
if (!serializer->isTesselated()) {
IfcGeomObjects::Settings(IfcGeomObjects::DISABLE_TRIANGULATION, true);
if (weld_vertices) {
Logger::Message(Logger::LOG_NOTICE, "Weld vertices setting ignored when writing STEP or IGES files");
}
}
// Parse the file supplied in argv[1]. Returns true on succes.
if ( ! IfcGeomObjects::Init(input_filename, &std::cout, &log_stream) ) {
time_t start,end;
time(&start);
if (!context_iterator.findContext()) {
Logger::Message(Logger::LOG_ERROR, "Unable to parse .ifc file or no geometrical entities found");
write_log();
return 1;
}
if (convert_back_units) {
serializer->setUnitNameAndMagnitude(IfcGeomObjects::GetUnitName(), IfcGeomObjects::GetUnitMagnitude());
serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<const float>(context_iterator.getUnitMagnitude()));
} else {
serializer->setUnitNameAndMagnitude("METER", 1.0f);
}
@@ -243,40 +305,33 @@ int main(int argc, char** argv) {
std::set<std::string> materials;
time_t start,end;
time(&start);
int old_progress = -1;
Logger::Status("Creating geometry...");
// The functions IfcGeomObjects::Get() and IfcGeomObjects::Next() wrap an iterator of all geometrical entities in the Ifc file.
// IfcGeomObjects::Get() returns an IfcGeomObjects::IfcGeomObject (see IfcGeomObjects.h for definition)
// IfcGeomObjects::Next() is used to poll whether more geometrical entities are available
// The functions IfcGeom::Iterator::get() and IfcGeom::Iterator::next()
// wrap an iterator of all geometrical products in the Ifc file.
// IfcGeom::Iterator::get() returns an IfcGeom::TriangulationElement or
// -BRepElement pointer, based on current settings. (see IfcGeomIterator.h
// for definition) IfcGeom::Iterator::next() is used to poll whether more
// geometrical entities are available. None of these functions throw
// exceptions, neither for parsing errors or geometrical errors. Upon
// calling next() the entity to be returned has already been processed, a
// true return value guarantees that a successfully processed product is
// available.
do {
const IfcGeomObjects::IfcObject* geom_object;
const IfcGeom::Element<double>* geom_object = context_iterator.get();
if (serializer->isTesselated()) {
geom_object = IfcGeomObjects::Get();
serializer->write(static_cast<const IfcGeom::TriangulationElement<double>*>(geom_object));
} else {
geom_object = IfcGeomObjects::GetShapeModel();
serializer->write(static_cast<const IfcGeom::BRepElement<double>*>(geom_object));
}
std::string lowercase_type = geom_object->type();
for (std::string::iterator c = lowercase_type.begin(); c != lowercase_type.end(); ++c) {
*c = tolower(*c);
}
if (ignore_types.find(lowercase_type) != ignore_types.end()) continue;
if (serializer->isTesselated()) {
serializer->writeTesselated(static_cast<const IfcGeomObjects::IfcGeomObject*>(geom_object));
} else {
serializer->writeShapeModel(static_cast<const IfcGeomObjects::IfcGeomShapeModelObject*>(geom_object));
}
const int progress = IfcGeomObjects::Progress() / 2;
if ( old_progress!= progress ) Logger::ProgressBar(progress);
const int progress = context_iterator.progress() / 2;
if (old_progress!= progress) Logger::ProgressBar(progress);
old_progress = progress;
} while ( IfcGeomObjects::Next() );
} while (context_iterator.next());
serializer->finalize();
delete serializer;
@@ -288,6 +343,8 @@ int main(int argc, char** argv) {
time(&end);
int dif = (int) difftime (end,start);
printf ("\nConversion took %d seconds\n", dif );
return 0;
}
void write_log() {
+1 -1
View File
@@ -24,7 +24,7 @@
#include <IGESControl_Writer.hxx>
#include <Interface_Static.hxx>
#include "../ifcgeom/IfcGeomObjects.h"
#include "../ifcgeom/IfcGeomIterator.h"
#include "../ifcconvert/OpenCascadeBasedSerializer.h"
+24 -15
View File
@@ -24,6 +24,8 @@
#include <BRepBuilderAPI_GTransform.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <Standard_Version.hxx>
#include "OpenCascadeBasedSerializer.h"
bool OpenCascadeBasedSerializer::ready() {
@@ -34,18 +36,25 @@ bool OpenCascadeBasedSerializer::ready() {
return succeeded;
}
void OpenCascadeBasedSerializer::writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->mesh().begin(); it != o->mesh().end(); ++ it) {
void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement<double>* o) {
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) {
gp_GTrsf gtrsf = it->Placement();
const std::vector<double>& matrix = o->transformation().matrix().data();
// TODO:
gp_GTrsf o_trsf;
int k = 0;
for( int i = 1; i < 5; ++ i )
for ( int j = 1; j < 4; ++ j )
o_trsf.SetValue(j, i, o->matrix()[k++]);
// Convert the matrix back into a transformation object. The tolerance values
// are taken into consideration to reconstruct the form of the transformation.
gp_Trsf o_trsf;
o_trsf.SetValues(
matrix[0], matrix[3], matrix[6], matrix[ 9],
matrix[1], matrix[4], matrix[7], matrix[10],
matrix[2], matrix[5], matrix[8], matrix[11]
#if OCC_VERSION_HEX < 0x60800
, Precision::Angular(), Precision::Confusion()
#endif
);
gtrsf.PreMultiply(o_trsf);
const TopoDS_Shape& s = it->Shape();
bool trsf_valid = false;
@@ -64,18 +73,18 @@ void OpenCascadeBasedSerializer::writeShapeModel(const IfcGeomObjects::IfcGeomSh
}
#define RATHER_SMALL (1e-3)
#define ALMOST_THE_SAME(a,b) (fabs(a-b) < RATHER_SMALL)
#define APPROXIMATELY_THE_SAME(a,b) (fabs(a-b) < RATHER_SMALL)
const char* OpenCascadeBasedSerializer::getSymbolForUnitMagnitude(float mag) {
if (ALMOST_THE_SAME(mag, 0.001f)) {
if (APPROXIMATELY_THE_SAME(mag, 0.001f)) {
return "MM";
} else if (ALMOST_THE_SAME(mag, 0.01f)) {
} else if (APPROXIMATELY_THE_SAME(mag, 0.01f)) {
return "CM";
} else if (ALMOST_THE_SAME(mag, 1.0f)) {
} else if (APPROXIMATELY_THE_SAME(mag, 1.0f)) {
return "M";
} else if (ALMOST_THE_SAME(mag, 0.3048f)) {
} else if (APPROXIMATELY_THE_SAME(mag, 0.3048f)) {
return "FT";
} else if (ALMOST_THE_SAME(mag, 0.0254f)) {
} else if (APPROXIMATELY_THE_SAME(mag, 0.0254f)) {
return "INCH";
} else {
return 0;
+4 -3
View File
@@ -20,7 +20,7 @@
#ifndef OPENCASCADEBASEDSERIALIZER_H
#define OPENCASCADEBASEDSERIALIZER_H
#include "../ifcgeom/IfcGeomObjects.h"
#include "../ifcgeom/IfcGeomIterator.h"
#include "../ifcconvert/GeometrySerializer.h"
@@ -38,9 +38,10 @@ public:
void writeMaterial(const IfcGeom::SurfaceStyle& style) {}
bool ready();
virtual void writeShape(const TopoDS_Shape& shape) = 0;
void writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {}
void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o);
void write(const IfcGeom::TriangulationElement<double>* o) {}
void write(const IfcGeom::BRepElement<double>* o);
bool isTesselated() const { return false; }
void setFile(IfcParse::IfcFile*) {}
};
#endif
+35
View File
@@ -0,0 +1,35 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef SERIALIZER_H
#define SERIALIZER_H
#include "../ifcparse/IfcFile.h"
class Serializer {
public:
virtual ~Serializer() {}
virtual bool ready() = 0;
virtual void writeHeader() = 0;
virtual void finalize() = 0;
virtual void setFile(IfcParse::IfcFile*) = 0;
};
#endif
+1 -1
View File
@@ -24,7 +24,7 @@
#include <STEPControl_Writer.hxx>
#include <Interface_Static.hxx>
#include "../ifcgeom/IfcGeomObjects.h"
#include "../ifcgeom/IfcGeomIterator.h"
#include "../ifcconvert/OpenCascadeBasedSerializer.h"
+22 -27
View File
@@ -28,7 +28,7 @@ bool WaveFrontOBJSerializer::ready() {
}
void WaveFrontOBJSerializer::writeHeader() {
obj_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << std::endl;
obj_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << "\n";
#ifdef WIN32
const char dir_separator = '\\';
#else
@@ -39,55 +39,55 @@ void WaveFrontOBJSerializer::writeHeader() {
if (slash != std::string::npos) {
mtl_basename = mtl_basename.substr(slash+1);
}
obj_stream << "mtllib " << mtl_basename << std::endl;
mtl_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << std::endl;
obj_stream << "mtllib " << mtl_basename << "\n";
mtl_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << "\n";
}
void WaveFrontOBJSerializer::writeMaterial(const IfcGeomObjects::Material& style) {
mtl_stream << "newmtl " << style.name() << std::endl;
void WaveFrontOBJSerializer::writeMaterial(const IfcGeom::Material& style) {
mtl_stream << "newmtl " << style.name() << "\n";
if (style.hasDiffuse()) {
const double* diffuse = style.diffuse();
mtl_stream << "Kd " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << std::endl;
mtl_stream << "Kd " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << "\n";
}
if (style.hasSpecular()) {
const double* specular = style.specular();
mtl_stream << "Ks " << specular[0] << " " << specular[1] << " " << specular[2] << std::endl;
mtl_stream << "Ks " << specular[0] << " " << specular[1] << " " << specular[2] << "\n";
}
if (style.hasSpecularity()) {
mtl_stream << "Ns " << style.specularity() << std::endl;
mtl_stream << "Ns " << style.specularity() << "\n";
}
if (style.hasTransparency()) {
const double transparency = 1.0 - style.transparency();
if (transparency < 1) {
mtl_stream << "Tr " << transparency << std::endl;
mtl_stream << "d " << transparency << std::endl;
mtl_stream << "D " << transparency << std::endl;
mtl_stream << "Tr " << transparency << "\n";
mtl_stream << "d " << transparency << "\n";
mtl_stream << "D " << transparency << "\n";
}
}
}
void WaveFrontOBJSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {
void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement<double>* o) {
std::string tmp = o->name().empty() ? o->guid() : o->name();
std::replace( tmp.begin(), tmp.end(), ' ', '_');
const std::string name = tmp;
obj_stream << "g " << name << std::endl;
obj_stream << "s 1" << std::endl;
obj_stream << "g " << name << "\n";
obj_stream << "s 1" << "\n";
const IfcGeomObjects::IfcRepresentationTriangulation& mesh = o->mesh();
const IfcGeom::Representation::Triangulation<double>& mesh = o->geometry();
const int vcount = mesh.verts().size() / 3;
for ( std::vector<float>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) {
for ( std::vector<double>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) {
const double x = *(it++);
const double y = *(it++);
const double z = *(it++);
obj_stream << "v " << x << " " << y << " " << z << std::endl;
obj_stream << "v " << x << " " << y << " " << z << "\n";
}
for ( std::vector<float>::const_iterator it = mesh.normals().begin(); it != mesh.normals().end(); ) {
for ( std::vector<double>::const_iterator it = mesh.normals().begin(); it != mesh.normals().end(); ) {
const double x = *(it++);
const double y = *(it++);
const double z = *(it++);
obj_stream << "vn " << x << " " << y << " " << z << std::endl;
obj_stream << "vn " << x << " " << y << " " << z << "\n";
}
int previous_material_id = -2;
@@ -97,14 +97,9 @@ void WaveFrontOBJSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject
const int material_id = *(material_it++);
if (material_id != previous_material_id) {
IfcGeomObjects::Material material(0);
if (material_id >= 0) {
material = mesh.materials()[material_id];
} else {
material = IfcGeomObjects::Material(IfcGeom::get_default_style(o->type()));
}
const IfcGeom::Material& material = mesh.materials()[material_id];
const std::string material_name = material.name();
obj_stream << "usemtl " << material_name << std::endl;
obj_stream << "usemtl " << material_name << "\n";
if (materials.find(material_name) == materials.end()) {
writeMaterial(material);
materials.insert(material_name);
@@ -115,7 +110,7 @@ void WaveFrontOBJSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject
const int v1 = *(it++)+vcount_total;
const int v2 = *(it++)+vcount_total;
const int v3 = *(it++)+vcount_total;
obj_stream << "f " << v1 << "//" << v1 << " " << v2 << "//" << v2 << " " << v3 << "//" << v3 << std::endl;
obj_stream << "f " << v1 << "//" << v1 << " " << v2 << "//" << v2 << " " << v3 << "//" << v3 << "\n";
}
vcount_total += vcount;
}
+4 -3
View File
@@ -44,12 +44,13 @@ public:
virtual ~WaveFrontOBJSerializer() {}
bool ready();
void writeHeader();
void writeMaterial(const IfcGeomObjects::Material& style);
void writeTesselated(const IfcGeomObjects::IfcGeomObject* o);
void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {}
void writeMaterial(const IfcGeom::Material& style);
void write(const IfcGeom::TriangulationElement<double>* o);
void write(const IfcGeom::BRepElement<double>* o) {}
void finalize() {}
bool isTesselated() const { return true; }
void setUnitNameAndMagnitude(const std::string& name, float magnitude) {}
void setFile(IfcParse::IfcFile*) {}
};
#endif
+262
View File
@@ -0,0 +1,262 @@
#include <map>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
#include <boost/version.hpp>
#include "XmlSerializer.h"
using boost::property_tree::ptree;
using namespace IfcSchema;
static std::map<std::string, std::string> argument_name_map;
// Format an IFC attribute and maybe returns as string. Only literal scalar
// values are converted. Things like entity instances and lists are omitted.
boost::optional<std::string> format_attribute(const Argument* argument, IfcUtil::ArgumentType argument_type) {
boost::optional<std::string> value;
switch(argument_type) {
case IfcUtil::Argument_BOOL: {
const bool b = *argument;
value = b ? "true" : "false";
break; }
case IfcUtil::Argument_DOUBLE: {
const double d = *argument;
std::stringstream stream;
stream << d;
value = stream.str();
break; }
case IfcUtil::Argument_STRING:
case IfcUtil::Argument_ENUMERATION: {
value = static_cast<std::string>(*argument);
break; }
case IfcUtil::Argument_INT: {
const int v = *argument;
std::stringstream stream;
stream << v;
value = stream.str();
break; }
case IfcUtil::Argument_ENTITY: {
IfcUtil::IfcBaseClass* e = *argument;
if (Type::IsSimple(e->type())) {
IfcUtil::IfcBaseType* f = (IfcUtil::IfcBaseType*) e;
value = format_attribute(f->getArgument(0), f->getArgumentType(0));
} else if (e->is(IfcSchema::Type::IfcSIUnit) || e->is(IfcSchema::Type::IfcConversionBasedUnit)) {
// Some string concatenation to have a unit name as a XML attribute.
std::string unit_name;
if (e->is(IfcSchema::Type::IfcSIUnit)) {
IfcSchema::IfcSIUnit* unit = (IfcSchema::IfcSIUnit*) e;
unit_name = IfcSchema::IfcSIUnitName::ToString(unit->Name());
if (unit->Prefix()) {
unit_name = IfcSchema::IfcSIPrefix::ToString(*unit->Prefix()) + unit_name;
}
} else {
IfcSchema::IfcConversionBasedUnit* unit = (IfcSchema::IfcConversionBasedUnit*) e;
unit_name = unit->Name();
}
for (std::string::iterator c = unit_name.begin(); c != unit_name.end(); ++c) *c = tolower(*c);
value = unit_name;
}
break; }
}
return value;
}
// Formats an entity instances as a ptree node, and insert into the DOM. Recurses
// over the entity attributes and writes them as xml attributes of the node.
ptree& format_entity_instance(IfcUtil::IfcBaseEntity* instance, ptree& tree, bool as_link = false) {
ptree child;
const unsigned n = instance->getArgumentCount();
for (unsigned i = 0; i < n; ++i) {
const Argument* argument = instance->getArgument(i);
if (argument->isNull()) continue;
std::string argument_name = instance->getArgumentName(i);
std::map<std::string, std::string>::const_iterator argument_name_it;
argument_name_it = argument_name_map.find(argument_name);
if (argument_name_it != argument_name_map.end()) {
argument_name = argument_name_it->second;
}
const IfcUtil::ArgumentType argument_type = instance->getArgumentType(i);
boost::optional<std::string> value;
try {
value = format_attribute(argument, argument_type);
} catch (...) {}
if (value) {
if (as_link) {
if (argument_name == "id") {
child.put("<xmlattr>.xlink:href", std::string("#") + *value);
}
} else {
std::stringstream stream;
stream << "<xmlattr>." << argument_name;
child.put(stream.str(), *value);
}
}
}
return tree.add_child(Type::ToString(instance->type()), child);
}
// A function to be called recursively. Template specialization is used
// to descend into decomposition, containment and property relationships.
template <typename A>
void descend(A* instance, ptree& tree) {
format_entity_instance(instance, tree);
}
// Returns related entity instances using IFC's objectified relationship
// model. The second and third argument require a member function pointer.
template <typename T, typename U, typename V, typename F, typename G>
typename V::list::ptr get_related(T* t, F f, G g) {
typename U::list::ptr li = (*t.*f)()->template as<U>();
typename V::list::ptr acc(new typename V::list);
for (typename U::list::it it = li->begin(); it != li->end(); ++it) {
U* u = *it;
acc->push((*u.*g)());
}
return acc;
}
// Member functions for IFC attributes have identical names for getters and setters. Hence a full member function signature is needed to identify them.
typedef IfcTemplatedEntityList<IfcProduct>::ptr (IfcRelContainedInSpatialStructure::*get_related_elements) (void) const;
typedef IfcTemplatedEntityList<IfcObjectDefinition>::ptr (IfcRelDecomposes::*get_related_objects) (void) const;
typedef IfcPropertySetDefinition* (IfcRelDefinesByProperties::*get_related_properties) (void) const;
// Descends into the tree by recursing into IfcRelContainedInSpatialStructure,
// IfcRelDecomposes and IfcRelDefinesByProperties relations.
template <>
void descend(IfcProduct* product, ptree& tree) {
ptree& child = format_entity_instance(product, tree);
if (product->is(Type::IfcSpatialStructureElement)) {
IfcSpatialStructureElement* structure = (IfcSpatialStructureElement*) product;
IfcProduct::list::ptr elements = get_related
<IfcSpatialStructureElement, IfcRelContainedInSpatialStructure, IfcProduct>
(structure, &IfcSpatialStructureElement::ContainsElements, static_cast<get_related_elements>(&IfcRelContainedInSpatialStructure::RelatedElements));
for (IfcProduct::list::it it = elements->begin(); it != elements->end(); ++it) {
descend(*it, child);
}
}
IfcObjectDefinition::list::ptr structures = get_related
<IfcProduct, IfcRelDecomposes, IfcObjectDefinition>
(product, &IfcProduct::IsDecomposedBy, static_cast<get_related_objects>(&IfcRelDecomposes::RelatedObjects));
for (IfcObjectDefinition::list::it it = structures->begin(); it != structures->end(); ++it) {
IfcObjectDefinition* ob = *it;
if (ob->is(Type::IfcSpatialStructureElement)) {
descend((IfcProduct*)ob, child);
} else {
descend(ob, child);
}
}
IfcPropertySetDefinition::list::ptr property_sets = get_related
<IfcProduct, IfcRelDefinesByProperties, IfcPropertySetDefinition>
(product, &IfcProduct::IsDefinedBy, static_cast<get_related_properties>(&IfcRelDefinesByProperties::RelatingPropertyDefinition));
for (IfcPropertySetDefinition::list::it it = property_sets->begin(); it != property_sets->end(); ++it) {
IfcPropertySetDefinition* pset = *it;
if (pset->is(Type::IfcPropertySet)) {
format_entity_instance(pset, child, true);
}
}
}
// Descends into the tree by recursing into IfcRelDecomposes relations.
template <>
void descend(IfcProject* project, ptree& tree) {
ptree& child = format_entity_instance(project, tree);
IfcObjectDefinition::list::ptr structures = get_related
<IfcProject, IfcRelDecomposes, IfcObjectDefinition>
(project, &IfcProject::IsDecomposedBy, static_cast<get_related_objects>(&IfcRelDecomposes::RelatedObjects));
for (IfcObjectDefinition::list::it it = structures->begin(); it != structures->end(); ++it) {
IfcObjectDefinition* ob = *it;
if (ob->is(Type::IfcSpatialStructureElement)) {
descend((IfcProduct*)ob, child);
} else {
descend(ob, child);
}
}
}
// Format IfcProperty instances and insert into the DOM. IfcComplexProperties are flattened out.
void format_properties(IfcProperty::list::ptr properties, ptree& node) {
for (IfcProperty::list::it it = properties->begin(); it != properties->end(); ++it) {
IfcProperty* p = *it;
if (p->is(Type::IfcComplexProperty)) {
IfcComplexProperty* complex = (IfcComplexProperty*) p;
format_properties(complex->HasProperties(), node);
} else {
format_entity_instance(p, node);
}
}
}
void XmlSerializer::finalize() {
argument_name_map.insert(std::make_pair("GlobalId", "id"));
IfcProject::list::ptr projects = file->entitiesByType<IfcProject>();
if (projects->size() != 1) {
Logger::Message(Logger::LOG_ERROR, "Expected a single IfcProject");
return;
}
IfcProject* project = *projects->begin();
ptree root, header, decomposition, properties;
// Write the SPF header as XML nodes.
BOOST_FOREACH(const std::string& s, file->header().file_description().description()) {
header.add_child("file_description.description", ptree(s));
}
BOOST_FOREACH(const std::string& s, file->header().file_name().author()) {
header.add_child("file_name.author", ptree(s));
}
BOOST_FOREACH(const std::string& s, file->header().file_name().organization()) {
header.add_child("file_name.organization", ptree(s));
}
BOOST_FOREACH(const std::string& s, file->header().file_schema().schema_identifiers()) {
header.add_child("file_schema.schema_identifiers", ptree(s));
}
header.put("file_description.implementation_level", file->header().file_description().implementation_level());
header.put("file_name.name", file->header().file_name().name());
header.put("file_name.time_stamp", file->header().file_name().time_stamp());
header.put("file_name.preprocessor_version", file->header().file_name().preprocessor_version());
header.put("file_name.originating_system", file->header().file_name().originating_system());
header.put("file_name.authorization", file->header().file_name().authorization());
// Descend into the decomposition structure of the IFC file.
descend(project, decomposition);
// Write all property sets and values as XML nodes.
IfcPropertySet::list::ptr psets = file->entitiesByType<IfcPropertySet>();
for (IfcPropertySet::list::it it = psets->begin(); it != psets->end(); ++it) {
IfcPropertySet* pset = *it;
ptree& node = format_entity_instance(pset, properties);
format_properties(pset->HasProperties(), node);
}
root.add_child("ifc.header", header);
root.add_child("ifc.properties", properties);
root.add_child("ifc.decomposition", decomposition);
root.put("ifc.<xmlattr>.xmlns:xlink", "http://www.w3.org/1999/xlink");
#if BOOST_VERSION >= 105600
boost::property_tree::xml_writer_settings<ptree::key_type> settings = boost::property_tree::xml_writer_make_settings<ptree::key_type>('\t', 1);
#else
boost::property_tree::xml_writer_settings<char> settings('\t', 1);
#endif
boost::property_tree::write_xml(xml_filename, root, std::locale(), settings);
}
+41
View File
@@ -0,0 +1,41 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef XMLSERIALIZER_H
#define XMLSERIALIZER_H
#include "../ifcconvert/Serializer.h"
class XmlSerializer : public Serializer {
private:
IfcParse::IfcFile* file;
std::string xml_filename;
public:
XmlSerializer(const std::string& xml_filename)
: Serializer()
, xml_filename(xml_filename)
{}
bool ready() { return true; }
void writeHeader() {}
void finalize();
void setFile(IfcParse::IfcFile* f) { file = f; }
};
#endif
-659
View File
@@ -1,659 +0,0 @@
header = """
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
""".strip()
###############################################################################
# #
# This file can be used to generate C++ code from Express schema files. The #
# generated code works alongside the IfcOpenShell IfcParse library. This #
# script has only been tested on IFC2X3_TC1.exp and will most probably not #
# work on any other schemas. #
# #
# Note this script uses funcparserlib, which is available at: #
# http://code.google.com/p/funcparserlib/ #
# The script only works with revision 30f7ee896bc9 because it uses the some() #
# parser and is incompatible with other changes as well. #
# #
###############################################################################
import os, sys
import IfcDocumentation
filename = sys.argv[1]
#
# A class to split the Express schema files into seperate tokens
#
class Tokenizer(object):
comment = ['(*','*)']
termchars = ',;()=[]:'
def __init__(self, fn):
if hasattr(fn,'read'): object.__setattr__(self,'f',fn)
else: object.__setattr__(self,'f',open(fn,'rb'))
def __getattr__(self, name):
return getattr(self.f, name)
def __setattr__(self, name, value):
setattr(self.f, name, value)
def __iter__(self): return self
def next(self):
def get():
buffer = ''
in_comment = False
in_string = False
offset = self.tell()
while True:
c = self.read(2)
if len(c) < 2: raise StopIteration
if c in Tokenizer.comment:
in_comment = c == Tokenizer.comment[0]
continue
if in_string and c == "''":
buffer += "'"
continue
self.seek(-1,1)
if not in_string and c[0].isspace():
if ( len(buffer) ): return buffer
else:
offset = self.tell()
continue
if not in_comment:
if len(buffer) and (c[0] in Tokenizer.termchars or buffer[-1] in Tokenizer.termchars):
self.seek(-1,1)
return buffer
buffer += c[0]
return get()
#
# Some global variables to keep track of variable names
#
express_to_cpp = {
'BOOLEAN':'bool',
'LOGICAL':'bool',
'INTEGER':'int',
'REAL':'double',
'NUMBER':'double',
'STRING':'std::string'
}
schema_version = ''
enumerations = set()
selections = set()
entity_names = set()
simple_types = {}
selectable_simple_types = set()
argument_count = {}
parent_relations = {}
argument_names_and_types = {}
entity_map = {}
#
# Since inherited arguments of Express entities are placed in sequence before the
# non-inherited ones, we need to keep track of how many inherited arguments exist
#
def argument_start(c):
if c not in parent_relations: return 0
i = 0
while True:
c = parent_relations[c]
i += argument_count[c] if c in argument_count else 0
if not (c in parent_relations): break
return i
def parent_arguments(c):
if c not in parent_relations: return []
l = []
while True:
c = parent_relations[c]
i += argument_count[c] if c in argument_count else 0
if not (c in parent_relations): break
return []
#
# Every constructor also initializes their parent class members, hence they
# need be stored as well.
#
def parent_arguments(c):
if c not in parent_relations: return []
l = []
while True:
c = parent_relations[c]
i += argument_count[c] if c in argument_count else 0
if not (c in parent_relations): break
return []
#
# Several classes to generate code from Express types and entities
#
class ArrayType:
def __init__(self,l):
self.type = express_to_cpp.get(l[3],l[3])
self.upper = l[2]
self.lower = l[1]
def is_select_list(self): return self.type in selections
def __str__(self):
if self.type in entity_names:
return "SHARED_PTR< IfcTemplatedEntityList< %s > >"%self.type
elif self.type in selections:
return "SHARED_PTR< IfcTemplatedEntityList< IfcAbstractSelect > >"
else:
return "std::vector< %(type)s > /*[%(lower)s:%(upper)s]*/"%self.__dict__
def is_shared_ptr(self): return self.type in entity_names or self.type in selections
def type_enum(self):
if self.type in simple_types:
t = simple_types[self.type].type_enum()
else:
t = self.type
if t in entity_names or t == "Argument_ENTITY":
return "Argument_ENTITY_LIST"
elif t in selections:
return "Argument_ENTITY_LIST"
elif t == "int":
return "Argument_VECTOR_INT"
elif t == "double" or t == "Argument_DOUBLE":
return "Argument_VECTOR_DOUBLE"
elif t == "std::string" or t == "Argument_STRING":
return "Argument_VECTOR_STRING"
elif isinstance(t, BinaryType):
return "Argument_UNKNOWN"
else:
assert False, t
class ScalarType:
def __init__(self,l): self.type = express_to_cpp.get(l,l)
def __str__(self): return self.type
def is_select_list(self): return False
def type_enum(self):
if self.type in simple_types:
return simple_types[self.type].type_enum()
elif self.type in entity_names:
return "Argument_ENTITY"
else:
return { "bool":"Argument_BOOL","int":"Argument_INT","double":"Argument_DOUBLE","std::string":"Argument_STRING"}[self.type]
class EnumType:
def __init__(self,l):
self.v = [(x,'%s_%s'%('%(fancy_name)s',x)) for x in l]
self.maxlen = max([len(v) for v in self.v])
def __str__(self):
if generator_mode == 'HEADER':
return "enum {%s}"%", ".join([v2 for v1,v2 in self.v])
elif generator_mode == 'SOURCE_TO':
return '{ "%s" }'%'","'.join([v1 for v1,v2 in self.v])
elif generator_mode == 'SOURCE_FROM':
return "".join([' if(s=="%s"%s) return ::%s::%s::%s;\n'%(v1.upper()," "*(self.maxlen-len(v1)),schema_version,"%(name)s",v2) for v1,v2 in self.v])
def is_select_list(self): return False
def __len__(self): return len(self.v)
def type_enum(self):
return "Argument_ENUMERATION"
class SelectType:
def __init__(self,l):
for x in l:
if x in simple_types: selectable_simple_types.add(x)
def __str__(self): return "IfcSchemaEntity"
def is_select_list(self): return False
def type_enum(self): return "Argument_ENTITY"
class BinaryType:
def __init__(self,l): self.l = int(l)
def __str__(self): return "char[%s]"%self.l
def is_select_list(self): return False
def type_enum(self): raise NotImplementedError()
class InverseType:
def __init__(self,l):
self.name, self.type, self.reference = l
def type_enum(self): return "Argument_ENTITY"
def is_select_list(self): return False
class Typedef:
def __init__(self,l):
self.name,self.type=l[1:3]
self.fancy_name = self.name[:-4] if self.name.endswith("Enum") else self.name
if isinstance(self.type,EnumType):
enumerations.add(self.name)
self.len = len(self.type)
elif isinstance(self.type,SelectType): selections.add(self.name)
simple_types[self.name] = self
comment = IfcDocumentation.description(self.name)
self.comment = comment+"\n" if comment else ''
def __str__(self):
global generator_mode
if generator_mode == 'HEADER' and isinstance(self.type,EnumType):
return ("namespace %(name)s {\n%(comment)stypedef %(type)s %(name)s;\nconst char* ToString(%(name)s v);\n%(name)s FromString(const std::string& s);\n}"%self.__dict__)%self.__dict__
elif generator_mode == 'HEADER':
return "%stypedef %s %s;"%(self.comment,self.type,self.name)
elif generator_mode == 'SOURCE' and isinstance(self.type,EnumType):
generator_mode = 'SOURCE_TO'
s = "const char* %(name)s::ToString(%(name)s v) {\n if ( v < 0 || v >= %(len)d ) throw IfcException(\"Unable to find find keyword in schema\");\n const char* names[] = %(type)s;\n return names[v];\n}\n"%self.__dict__
generator_mode = 'SOURCE_FROM'
s += ("%(name)s::%(name)s %(name)s::FromString(const std::string& s) {\n%(type)s throw IfcException(\"Unable to find find keyword in schema\");\n}"%self.__dict__)%self.__dict__
generator_mode = 'SOURCE'
return s
def type_enum(self):
return self.type.type_enum()
class Argument(object):
def __init__(self,l):
self.name, self.optional, self.type = l
def is_enum(self): return str(self.type) in enumerations
def type_str(self):
if self.type.is_select_list():
# This is extremely hackish indeed
return "optional< IfcEntities >" if self.optional else "IfcEntities"
elif str(self.type) in entity_names:
return "%(type)s*"%self.__dict__
else:
t = "%(type)s::%(type)s"%self.__dict__ if self.is_enum() else self.type
return "optional< %s >"%t if self.optional else t
class ArgumentList:
def __init__(self,l):
self.l = [Argument(a) for a in l]
self.argstart = 0
def __len__(self): return len(self.l)
def __str__(self):
s = ""
argv = self.argstart
for a in self.l:
class_name = indent = comment = optional_comment = ""
is_array = isinstance(a.type,ArrayType) and a.type.is_shared_ptr()
return_type = str(a.type)
if generator_mode == 'SOURCE':
class_name = "%(class_name)s::"
if isinstance(a.type,BinaryType) or (isinstance(a.type,ArrayType) and isinstance(a.type.type,BinaryType)):
function_body = " { throw; /* Not implemented argument*/ }"
elif isinstance(a.type,ArrayType) and str(a.type.type) in entity_names:
function_body = " { RETURN_AS_LIST(%s,%d) }"%(a.type.type,argv)
elif isinstance(a.type,ArrayType) and str(a.type.type) in selections:
function_body = " { RETURN_AS_LIST(IfcAbstractSelect,%d) }"%(argv)
elif return_type in entity_names:
function_body = " { return reinterpret_pointer_cast<IfcBaseClass,%s>(*entity->getArgument(%d)); }"%(return_type,argv)
elif return_type in enumerations:
function_body = " { return %s::FromString(*entity->getArgument(%d)); }"%(return_type,argv)
else:
function_body = " { return *entity->getArgument(%d); }"%argv
function_body2 = " { return !entity->getArgument(%d)->isNull(); }"%argv
if isinstance(a.type,BinaryType) or (isinstance(a.type,ArrayType) and isinstance(a.type.type,BinaryType)):
function_body3 = " { if ( ! entity->isWritable() ) { throw; } }"
elif return_type in enumerations:
function_body3 = " { if ( ! entity->isWritable() ) { entity = new IfcWritableEntity(entity); } ((IfcWritableEntity*)entity)->setArgument(%d,v%s,%s::ToString(v)); }"%(argv,"->generalize()" if is_array else "",return_type)
else:
function_body3 = " { if ( ! entity->isWritable() ) { entity = new IfcWritableEntity(entity); } ((IfcWritableEntity*)entity)->setArgument(%d,v%s); }"%(argv,"->generalize()" if is_array else "")
else:
indent = " "
function_body = function_body2 = function_body3 = ";"
comment = IfcDocumentation.description((self.class_name,a.name))
comment = comment+"\n" if comment else ''
comment = comment.replace("///","%s///"%indent)
optional_comment = "%s/// Whether the optional attribute %s is defined for this %s\n"%(indent,a.name,self.class_name)
if a.optional: s += "\n%s%sbool %shas%s()%s"%(optional_comment,indent,class_name,a.name,function_body2)
if ( str(a.type) in enumerations ):
return_type = "%(type)s::%(type)s"%a.__dict__
elif ( str(a.type) in entity_names ):
return_type = "%(type)s*"%a.__dict__
s += "\n%s%s%s %s%s()%s"%(comment,indent,return_type,class_name,a.name,function_body)
s += "\n%svoid %sset%s(%s v)%s"%(indent,class_name,a.name,return_type,function_body3)
argv += 1
if generator_mode == 'HEADER':
s += "\n virtual unsigned int getArgumentCount() const { return %(n_arguments)d; }" % dict(class_name=self.class_name, n_arguments=len(self.l) + argument_start(self.class_name))
s += "\n virtual ArgumentType getArgumentType(unsigned int i) const {"
if len(self.l):
s += " switch (i) {"
for i, a in enumerate(self.l):
s += "case %d: " % (i + argument_start(self.class_name))
s += "return %s; " % a.type.type_enum()
s += "}"
if self.parent_class is not None:
s += " return %s::getArgumentType(i); }" % self.parent_class
else:
s += " throw IfcException(\"argument out of range\"); }"
s += "\n virtual const char* getArgumentName(unsigned int i) const {"
if len(self.l):
s += " switch (i) {"
for i, a in enumerate(self.l):
s += "case %d: " % (i + argument_start(self.class_name))
s += "return \"%s\"; " % a.name
s += "}"
if self.parent_class is not None:
s += " return %s::getArgumentName(i); }" % self.parent_class
else:
s += " throw IfcException(\"argument out of range\"); }"
s += "\n virtual ArgumentPtr getArgument(unsigned int i) const { return entity->getArgument(i); }"
return s
class InverseList:
def __init__(self,l):
self.l = l
def __str__(self):
if self.l is None: return ""
s = ""
for i in self.l:
if generator_mode == 'HEADER':
s += "\n SHARED_PTR< IfcTemplatedEntityList< %s > > %s(); // INVERSE %s::%s"%(i.type.type,i.name,i.type.type,i.reference)
elif generator_mode == 'SOURCE':
s += "\n%s::list %s::%s() { RETURN_INVERSE(%s) }"%(i.type.type,"%(class_name)s",i.name,i.type.type)
return s
class Classdef:
def __init__(self,l):
self.class_name, self.parent_class, self.arguments, derive, self.inverse = l
self.arguments.class_name = self.class_name
self.arguments.parent_class = self.parent_class
entity_names.add(self.class_name)
parent_relations[self.class_name] = self.parent_class
argument_count[self.class_name] = len(self.arguments)
entity_map[self.class_name] = self
# For derived attributes only a reference is kepts to overridden attributes in parent classes
self.derive = [x[0].split('.')[-1] for x in derive[1] if x[0].startswith("SELF\\")] if derive else []
def list_constructor_args(self):
s = entity_map[self.parent_class].list_constructor_args() if self.parent_class else []
i = len(s) + 1
s += [(a.type_str(),b+i,a.name) for a,b in zip(self.arguments.l,range(len(self.arguments)))]
return s
def get_constructor_args(self):
return ["%s v%d_%s"%x for x in self.list_constructor_args() if x[2] not in self.get_derived()]
def get_constructor_implementation(self):
s = entity_map[self.parent_class].get_constructor_implementation() if self.parent_class else []
i = len(s) + 1
b = 0
for a in self.arguments.l:
is_enumeration = str(a.type) in enumerations
# boost::optional is not used for pointer types, because they are set to NULL using 0
use_boost_optional = a.optional and str(a.type) not in entity_names
# boost::optional types need to be dereferenced before passing to the writable entity
dereference = "*" if use_boost_optional else ""
generalize = "->generalize()" if (isinstance(a.type,ArrayType) and a.type.is_shared_ptr() and not a.type.is_select_list()) else ""
if isinstance(a.type,BinaryType) or (isinstance(a.type,ArrayType) and isinstance(a.type.type,BinaryType)):
continue
if is_enumeration:
impl = "e->setArgument(%d,%sv%d_%s,%s::ToString(%sv%d_%s))"%(b+i-1,dereference,b+i,a.name,str(a.type),dereference,b+i,a.name)
else:
impl = "e->setArgument(%d,(%sv%d_%s)%s)"%(b+i-1,dereference,b+i,a.name,generalize)
if use_boost_optional:
s.append(["if (v%d_%s) { %s; } else { e->setArgument(%d); } "%(b+i,a.name,impl,b+i-1),a.name,i-1])
else: s.append([impl,a.name,i-1])
b += 1
return s
def get_derived(self):
s = entity_map[self.parent_class].get_derived() if self.parent_class else []
return s + self.derive
def __str__(self):
self.constructor_args_list = self.get_constructor_args()
self.constructor_args = ", ".join(self.constructor_args_list)
if generator_mode == 'HEADER':
comment = IfcDocumentation.description(self.class_name)
comment = comment+"\n" if comment else ''
return "%sclass %s : public %s {\npublic:%s%s%s\n};" % (comment,self.class_name,
"IfcBaseEntity" if self.parent_class is None else self.parent_class,
self.arguments,
self.inverse,
("\n bool is(Type::Enum v) const;"+
"\n Type::Enum type() const;"+
"\n static Type::Enum Class();"+
"\n %(class_name)s (IfcAbstractEntityPtr e = IfcAbstractEntityPtr());"+
("\n %(class_name)s (%(constructor_args)s);" if len(self.constructor_args_list) else "")+
"\n typedef %(class_name)s* ptr;"+
"\n typedef SHARED_PTR< IfcTemplatedEntityList< %(class_name)s > > list;"+
"\n typedef IfcTemplatedEntityList< %(class_name)s >::it it;")%self.__dict__
)
elif generator_mode == 'SOURCE':
self.arguments.argstart = argument_start(self.class_name)
self.constructor_implementation = "; ".join([x[0] if x[1] not in self.get_derived() else "e->setArgumentDerived(%d)"%x[2] for x in self.get_constructor_implementation()])
return (("\n// Function implementations for %(class_name)s"+str(self.arguments)+str(self.inverse)+
("\nbool %(class_name)s::is(Type::Enum v) const { return v == Type::%(class_name)s; }" if self.parent_class is None else
"\nbool %(class_name)s::is(Type::Enum v) const { return v == Type::%(class_name)s || %(parent_class)s::is(v); }")+
"\nType::Enum %(class_name)s::type() const { return Type::%(class_name)s; }"+
"\nType::Enum %(class_name)s::Class() { return Type::%(class_name)s; }"+
"\n%(class_name)s::%(class_name)s(IfcAbstractEntityPtr e) { if (!is(Type::%(class_name)s)) throw IfcException(\"Unable to find find keyword in schema\"); entity = e; }"+
("\n%(class_name)s::%(class_name)s(%(constructor_args)s) { IfcWritableEntity* e = new IfcWritableEntity(Class()); %(constructor_implementation)s; entity = e; EntityBuffer::Add(this); }" if len(self.constructor_args_list) else "")
)%self.__dict__)%self.__dict__
from funcparserlib.parser import a, skip, many, maybe, some
#
# Lambda functions to map combinator output to classes
#
array_type = lambda t: ArrayType(t)
scalar_type = lambda t: ScalarType(t)
enum_type = lambda t: EnumType(t)
select_type = lambda t: SelectType(t)
binary_type = lambda t: BinaryType(t)
inverse_type = lambda t: InverseType(t)
format_type = lambda t: Typedef(t)
argument_list = lambda t: ArgumentList(t)
inverse_list = lambda t: InverseList(t)
format_options = lambda t: [t[0]]+t[1]
#
# The actual grammar definition
#
s = some(lambda t: not t in ['UNIQUE','WHERE','END_ENTITY','END_TYPE','INVERSE','DERIVE'])
x = lambda s:skip(a(s))
list_or_array = a('ARRAY') | a('LIST') | a('SET')
binary = x('BINARY')+x('(') + s + x(')') >> binary_type
array = list_or_array + x('[') + s + x(':') + s + x(']') + x('OF') + skip(maybe(a('UNIQUE'))) + (binary|s) >> array_type
options = x('(') + s + many(x(',')+s) + x(')') >> format_options
enum = x('ENUMERATION') + x('OF') + options >> enum_type
select = x('SELECT') + options >> select_type
single = s + skip(maybe(x('(')+s+x(')')) + maybe(a('FIXED'))) >> scalar_type
type_type = array | enum | select | single
type_start = a('TYPE') + s + x('=') + type_type + x(';')
type_end = a('END_TYPE') + x(';')
to_end = many(some(lambda t: t != ';'))
clause = s + x(':') + to_end + x(';')
where = a('WHERE') + many(clause)
type = type_start + maybe(where) + type_end >> format_type
subtype = x('SUBTYPE') + x('OF') + x('(') + s + x(')')
supertype = maybe(x('ABSTRACT')) + x('SUPERTYPE') + x('OF') + x('(') + x('ONEOF') + options + x(')')
entity_start = x('ENTITY') + s + skip(maybe(supertype)) + maybe(subtype) + x(';')
entity_end = x('END_ENTITY') + x(';')
key_value = s + x(':') + maybe(a('OPTIONAL')) + (array|binary|single) + x(';')
arguments = many(key_value) >> argument_list
unique_value = s + x(':') + s + many(a(',')+s) + a(';')
unique = skip(a('UNIQUE') + many(unique_value))
inverse_def = s + x(':') + (array|single) + x('FOR') + s + x(';') >> inverse_type
inverse = maybe(x('INVERSE') + many( inverse_def )) >> inverse_list
derive = a('DERIVE') + many(clause)
entity = entity_start + arguments + skip(maybe(unique)) + maybe(derive) + inverse + skip(maybe(where)) + entity_end >> Classdef
schema = skip(a('SCHEMA')) + s + x(';')
express = schema + many(type) + many(entity)
schema_version,types,entities = express.parse(list(Tokenizer(filename)))
schema_version = schema_version.capitalize()
#
# Writing of the three generated files starts here
#
h_file = open("%s.h"%schema_version,'w')
enumh_file = open("%senum.h"%schema_version,'w')
cpp_file = open("%s.cpp"%schema_version,'w')
header += """
/********************************************************************************
* *
* This file has been generated from %s. Do not make modifications *
* but instead modify the python script that has been used to generate this. *
* *
********************************************************************************/
"""%filename
generator_mode = 'HEADER'
print >>h_file, header
print >>enumh_file, header
print >>cpp_file, header
print >>h_file, """#ifndef %(schema_upper)s_H
#define %(schema_upper)s_H
#include <string>
#include <vector>
#include <map>
#include <boost/optional.hpp>
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcException.h"
#include "../ifcparse/%(schema)senum.h"
using namespace IfcUtil;
using IfcParse::IfcException;
using boost::optional;
#define RETURN_INVERSE(T) \\
IfcEntities e = entity->getInverse(T::Class()); \\
SHARED_PTR< IfcTemplatedEntityList<T> > l ( new IfcTemplatedEntityList<T>() ); \\
for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) { \\
l->push(reinterpret_pointer_cast<IfcBaseClass,T>(*it)); \\
} \\
return l;
#define RETURN_AS_SINGLE(T,a) \\
return reinterpret_pointer_cast<IfcBaseClass,T>(*entity->getArgument(a));
#define RETURN_AS_LIST(T,a) \\
IfcEntities e = *entity->getArgument(a); \\
SHARED_PTR< IfcTemplatedEntityList<T> > l ( new IfcTemplatedEntityList<T>() ); \\
for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) { \\
l->push(reinterpret_pointer_cast<IfcBaseClass,T>(*it)); \\
} \\
return l;
namespace %(schema)s {
"""%{'schema_upper':schema_version.upper(),'schema':schema_version}
simple_enumerations = sorted(selectable_simple_types)
entity_enumerations = sorted(entity_names)
all_enumerations = simple_enumerations + entity_enumerations
print >>enumh_file, """#ifndef IFC2X3ENUM_H
#define IFC2X3ENUM_H
namespace Ifc2x3 {
namespace Type {
typedef enum {
%(enum)s
} Enum;
Enum Parent(Enum v);
Enum FromString(const std::string& s);
std::string ToString(Enum v);
bool IsSimple(Enum v);
}
}
#endif
"""%{'schema_upper':schema_version.upper(),'schema':schema_version,'enum':", ".join(all_enumerations + ["ALL"])}
defined_types = set(express_to_cpp.values())
deferred_types = []
for t in [T for T in types if not (isinstance(T.type,EnumType) or isinstance(T.type,SelectType))]:
if isinstance(t.type,ScalarType) and str(t.type) not in defined_types:
deferred_types.append(t)
else:
print >>h_file, t
for t in [T for T in types if isinstance(T.type,SelectType)]:
print >>h_file, t
for t in deferred_types:
print >>h_file, t
for t in [T for T in types if isinstance(T.type,EnumType)]:
print >>h_file, t
print >>h_file, "// Forward definitions"
print >>h_file, "class %s;\n"%"; class ".join([e.class_name for e in entities])
defined_classes = set()
while True:
classes = [c for c in entities if c.class_name not in defined_classes]
if not len(classes): break
for c in classes:
if c.parent_class is None or c.parent_class in defined_classes:
defined_classes.add(c.class_name)
print >>h_file, c
print >>h_file, "void InitStringMap();"
print >>h_file, "IfcSchemaEntity SchemaEntity(IfcAbstractEntityPtr e = 0);"
print >>h_file, "}\n\n#endif"
generator_mode = 'SOURCE'
print >>cpp_file, """#include "%(schema)s.h"
#include "IfcException.h"
#include "IfcWrite.h"
#include "IfcWritableEntity.h"
using namespace %(schema)s;
using namespace IfcParse;
using namespace IfcWrite;
IfcSchemaEntity %(schema)s::SchemaEntity(IfcAbstractEntityPtr e) {
switch(e->type()){"""%{'schema':schema_version}
for e in simple_enumerations:
print >>cpp_file, " case Type::%s: return new IfcEntitySelect(e); break;"%e
for e in entity_enumerations:
print >>cpp_file, " case Type::%s: return new %s(e); break;"%(e,e)
print >>cpp_file, " default: throw IfcException(\"Unable to find find keyword in schema\"); break; "
print >>cpp_file, " }\n}"
print >>cpp_file
print >>cpp_file, "std::string Type::ToString(Enum v) {"
print >>cpp_file, " if (v < 0 || v >= %d) throw IfcException(\"Unable to find find keyword in schema\");"%len(all_enumerations)
print >>cpp_file, ' const char* names[] = { "%s" };'%'","'.join(all_enumerations)
print >>cpp_file, ' return names[v];'
print >>cpp_file, "}"
print >>cpp_file
#print >>cpp_file, "Type::Enum Type::FromStringOld(const std::string& s){"
#elseif = "if"
#maxlen = max([len(e) for e in all_enumerations])
#for e in all_enumerations:
# print >>cpp_file, ' %s(s=="%s"%s) { return %s; }'%(elseif,e.upper()," "*(maxlen-len(e)),e)
#print >>cpp_file, " throw;"
#print >>cpp_file, "}"
print >>cpp_file, "std::map<std::string,Type::Enum> string_map;"
print >>cpp_file, "void Ifc2x3::InitStringMap() {"
maxlen = max([len(e) for e in all_enumerations])
for e in all_enumerations:
print >>cpp_file, ' string_map["%s"%s] = Type::%s;'%(e.upper()," "*(maxlen-len(e)),e)
print >>cpp_file, """}
Type::Enum Type::FromString(const std::string& s) {
std::map<std::string,Type::Enum>::const_iterator it = string_map.find(s);
if ( it == string_map.end() ) throw IfcException("Unable to find find keyword in schema");
else return it->second;
}"""
print >>cpp_file, "Type::Enum Type::Parent(Enum v){"
print >>cpp_file, " if (v < 0 || v >= %d) return (Enum)-1;"%len(all_enumerations)
for e in entity_enumerations:
if e not in parent_relations or parent_relations[e] is None: continue
print >>cpp_file, ' if(v==%s%s) { return %s; }'%(e," "*(maxlen-len(e)),parent_relations[e])
print >>cpp_file, " return (Enum)-1;"
print >>cpp_file, "}"
print >>cpp_file, "bool Type::IsSimple(Enum v){"
print >>cpp_file, " return v == Type::%s;"%" || v == Type::".join(simple_enumerations)
print >>cpp_file, "}"
for t in [T for T in types if isinstance(T.type,EnumType)]:
print >>cpp_file, t
for e in entities: print >>cpp_file, e,
+9
View File
@@ -0,0 +1,9 @@
This folder contains Python code to generate C++ type information based on an
Express schema. In particular is has only been tested using recent version of
the IFC schema and will most likely fail on any other Express schema.
The code can be invoked in the following way and results in two header files
and a single implementation file named according to the schema name in the
Express file. A python 3 interpreter with the pyparsing library is required.
$ python bootstrap.py express.bnf > express_parser.py && python express_parser.py IFC2X3_TC1.exp
+186
View File
@@ -0,0 +1,186 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import sys
import string
from pyparsing import *
class Expression:
def __init__(self, contents):
self.contents = contents[0]
def __repr__(self):
if self.op is None: return repr(self.contents)
c = [isinstance(c,str) and c or str(c) for c in self.contents]
if "%s" in self.op: return self.op % (" ".join(c))
else: return "(%s)" % (" %s "%self.op).join(c)
def __iter__(self):
return self.contents.__iter__()
class Union(Expression):
op = "|"
class Concat(Expression):
op = "+"
class Optional(Expression):
op = "Optional(%s)"
class Repeated(Expression):
op = "ZeroOrMore(%s)"
class Term(Expression):
op = None
class Keyword:
def __init__(self, contents):
self.contents = contents[0]
def __repr__(self):
return self.contents
class Terminal:
def __init__(self, contents):
self.contents = contents[0]
def __repr__(self):
s = self.contents
is_keyword = len(s) >= 4 and s[0::len(s)-1] == '""' and \
all(c in alphanums+"_" for c in s[1:-1])
ty = "CaselessKeyword" if is_keyword else "CaselessLiteral"
return "%s(%s)" % (ty, s)
LPAREN = Suppress("(")
RPAREN = Suppress(")")
LBRACK = Suppress("[")
RBRACK = Suppress("]")
LBRACE = Suppress("{")
RBRACE = Suppress("}")
EQUALS = Suppress("=")
VBAR = Suppress("|")
PERIOD = Suppress(".")
HASH = Suppress("#")
identifier = Word(alphanums+"_")
keyword = Word(alphanums+"_").setParseAction(Keyword)
expression = Forward()
optional = Group(LBRACK + expression + RBRACK).setParseAction(Optional)
repeated = Group(LBRACE + expression + RBRACE).setParseAction(Repeated)
terminal = quotedString.setParseAction(Terminal)
term = (keyword | terminal | optional | repeated | (LPAREN + expression + RPAREN)).setParseAction(Term)
concat = Group(term + OneOrMore(term)).setParseAction(Concat)
factor = concat | term
union = Group(factor + OneOrMore(VBAR + factor)).setParseAction(Union)
rule = identifier + EQUALS + expression + PERIOD
expression << (union | factor)
grammar = OneOrMore(Group(rule))
grammar.ignore(HASH + restOfLine)
express = grammar.parseFile(sys.argv[1])
def find_keywords(expr, li = None):
if li is None: li = []
if isinstance(expr, Term):
expr = expr.contents
if isinstance(expr, Keyword):
li.append(repr(expr))
return li
elif isinstance(expr, Expression):
for term in expr:
find_keywords(term, li)
return set(li)
actions = {
'type_decl' : "lambda t: TypeDeclaration(t)",
'entity_decl' : "lambda t: EntityDeclaration(t)",
'underlying_type' : "lambda t: UnderlyingType(t)",
'enumeration_type' : "lambda t: EnumerationType(t)",
'aggregation_types' : "lambda t: AggregationType(t)",
'general_aggregation_types' : "lambda t: AggregationType(t)",
'select_type' : "lambda t: SelectType(t)",
'binary_type' : "lambda t: BinaryType(t)",
'subtype_declaration' : "lambda t: SubtypeExpression(t)",
'derive_clause' : "lambda t: AttributeList('derive', t)",
'derived_attr' : "lambda t: DerivedAttribute(t)",
'inverse_clause' : "lambda t: AttributeList('inverse', t)",
'inverse_attr' : "lambda t: InverseAttribute(t)",
'bound_spec' : "lambda t: BoundSpecification(t)",
'explicit_attr' : "lambda t: ExplicitAttribute(t)",
}
to_emit = set(id for id, expr in express)
emitted = set()
to_combine = set(["simple_id"])
to_ignore = set(["where_clause", "supertype_constraint", "unique_clause"])
statements = []
while True:
emitted_in_loop = set()
for id, expr in express:
kws = find_keywords(expr)
found = [k in emitted for k in kws]
if id in to_emit and all(found):
emitted_in_loop.add(id)
emitted.add(id)
stmt = "(%s)" % expr
if id in to_combine:
stmt = "originalTextFor(Combine%s)" % stmt
if id in actions:
stmt = "%s.setParseAction(%s)" % (stmt, actions[id])
statements.append("%s = %s" % (id, stmt))
to_emit -= emitted_in_loop
if not emitted_in_loop: break
for id in to_emit:
action = ".setParseAction(%s)" % actions[id] if id in actions else ""
statements.append("%s = Forward()%s" % (id, action))
for id in to_emit:
expr = [e for k, e in express if k == id][0]
stmt = "(%s)" % expr
if id in to_combine:
stmt = "Suppress%s" % stmt
statements.append("%s << %s" % (id, stmt))
print ("""import sys
from pyparsing import *
from nodes import *
%s
import schema
import mapping
import header
import enum_header
import implementation
import latebound_header
import latebound_implementation
syntax.ignore(Regex(r"\((?:\*(?:[^*]*\*+)+?\))"))
ast = syntax.parseFile(sys.argv[1])
schema = schema.Schema(ast)
mapping = mapping.Mapping(schema)
header.Header(mapping).emit()
enum_header.EnumHeader(mapping).emit()
implementation.Implementation(mapping).emit()
latebound_header.LateBoundHeader(mapping).emit()
latebound_implementation.LateBoundImplementation(mapping).emit()
"""%('\n'.join(statements)))
@@ -36,7 +36,7 @@ name_to_oid = {}
oid_to_desc = {}
oid_to_name = {}
oid_to_pid = {}
regices = list(zip([re.compile(s,re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>',r'(\n[\t ]*){2,}',r'^[\t ]+','^']],['','\n\n',' ','/// ']))
regices = list(zip([re.compile(s,re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>',r'(\n[\t ]*){2,}',r'^[\t ]+']],['','\n\n',' ']))
definition_files = ['DocEntity.csv', 'DocEnumeration.csv', 'DocDefined.csv', 'DocSelect.csv']
for fn in definition_files:
@@ -49,23 +49,22 @@ for fn in definition_files:
with open('DocEntityAttributes.csv') as f:
for pid, x, oid in csv.reader(f, delimiter=';', quotechar='"'):
oid_to_pid[oid] = pid
with open('DocAttribute.csv') as f:
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
pid = oid_to_pid[oid]
pname = oid_to_name[pid]
name_to_oid[(pname, name)] = oid
oid_to_desc[oid] = desc
def description(item):
global name_to_oid, oid_to_desc, oid_to_name, oid_to_pid
oid = name_to_oid.get(item,0)
desc = oid_to_desc.get(oid,None)
desc = oid_to_desc.get(oid, None)
if desc:
for a,b in entitydefs.items(): desc = desc.replace("&%s;"%a,b)
desc = desc.replace("\r","")
for r,s in regices[:-1]: desc = r.sub(s,desc)
for r,s in regices: desc = r.sub(s,desc)
desc = desc.strip()
r,s = regices[-1]
desc = r.sub(s,desc)
return desc
return desc.split("\n")
else: return []
+38
View File
@@ -0,0 +1,38 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import templates
class EnumHeader:
def __init__(self, mapping):
enumerable_types = sorted(set([name for name, type in mapping.schema.types.items()] + [name for name, type in mapping.schema.entities.items()]))
self.str = templates.enum_header % {
'schema_name_upper' : mapping.schema.name.upper(),
'schema_name' : mapping.schema.name.capitalize(),
'types' : ', '.join(enumerable_types)
}
self.schema_name = mapping.schema.name.capitalize()
def __repr__(self):
return self.str
def emit(self):
f = open('%senum.h'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
+344
View File
@@ -0,0 +1,344 @@
# Taken from http://sourceforge.net/p/exp-engine/expresso/ci/master/tree/docs/iso-10303-11--2004.bnf
ABS = "abs" .
ABSTRACT = "abstract" .
ACOS = "acos" .
AGGREGATE = "aggregate" .
ALIAS = "alias" .
AND = "and" .
ANDOR = "andor" .
ARRAY = "array" .
AS = "as" .
ASIN = "asin" .
ATAN = "atan" .
BAG = "bag" .
BASED_ON = "based_on" .
BEGIN = "begin" .
BINARY = "binary" .
BLENGTH = "blength" .
BOOLEAN = "boolean" .
BY = "by" .
CASE = "case" .
CONSTANT = "constant" .
CONST_E = "const_e" .
COS = "cos" .
DERIVE = "derive" .
DIV = "div" .
ELSE = "else" .
END = "end" .
END_ALIAS = "end_alias" .
END_CASE = "end_case" .
END_CONSTANT = "end_constant" .
END_ENTITY = "end_entity" .
END_FUNCTION = "end_function" .
END_IF = "end_if" .
END_LOCAL = "end_local" .
END_PROCEDURE = "end_procedure" .
END_REPEAT = "end_repeat" .
END_RULE = "end_rule" .
END_SCHEMA = "end_schema" .
END_SUBTYPE_CONSTRAINT = "end_subtype_constraint" .
END_TYPE = "end_type" .
ENTITY = "entity" .
ENUMERATION = "enumeration" .
ESCAPE = "escape" .
EXISTS = "exists" .
EXTENSIBLE = "extensible" .
EXP = "exp" .
FALSE = "false" .
FIXED = "fixed" .
FOR = "for" .
FORMAT = "format" .
FROM = "from" .
FUNCTION = "function" .
GENERIC = "generic" .
GENERIC_ENTITY = "generic_entity" .
HIBOUND = "hibound" .
HIINDEX = "hiindex" .
IF = "if" .
IN = "in" .
INSERT = "insert" .
INTEGER = "integer" .
INVERSE = "inverse" .
LENGTH = "length" .
LIKE = "like" .
LIST = "list" .
LOBOUND = "lobound" .
LOCAL = "local" .
LOG = "log" .
LOG10 = "log10" .
LOG2 = "log2" .
LOGICAL = "logical" .
LOINDEX = "loindex" .
MOD = "mod" .
NOT = "not" .
NUMBER = "number" .
NVL = "nvl" .
ODD = "odd" .
OF = "of" .
ONEOF = "oneof" .
OPTIONAL = "optional" .
OR = "or" .
OTHERWISE = "otherwise" .
PI = "pi" .
PROCEDURE = "procedure" .
QUERY = "query" .
REAL = "real" .
REFERENCE = "reference" .
REMOVE = "remove" .
RENAMED = "renamed" .
REPEAT = "repeat" .
RETURN = "return" .
ROLESOF = "rolesof" .
RULE = "rule" .
SCHEMA = "schema" .
SELECT = "select" .
SELF = "self" .
SET = "set" .
SIN = "sin" .
SIZEOF = "sizeof" .
SKIP = "skip" .
SQRT = "sqrt" .
STRING = "string" .
SUBTYPE = "subtype" .
SUBTYPE_CONSTRAINT = "subtype_constraint" .
SUPERTYPE = "supertype" .
TAN = "tan" .
THEN = "then" .
TO = "to" .
TOTAL_OVER = "total_over" .
TRUE = "true" .
TYPE = "type" .
TYPEOF = "typeof" .
UNIQUE = "unique" .
UNKNOWN = "unknown" .
UNTIL = "until" .
USE = "use" .
USEDIN = "usedin" .
VALUE = "value" .
VALUE_IN = "value_in" .
VALUE_UNIQUE = "value_unique" .
VAR = "var" .
WHERE = "where" .
WHILE = "while" .
WITH = "with" .
XOR = "xor" .
bit = "0" | "1" .
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
digits = digit { digit } .
encoded_character = octet octet octet octet .
hex_digit = digit | "a" | "b" | "c" | "d" | "e" | "f" .
letter = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" .
lparen_then_not_lparen_star = "(" { "(" } not_lparen_star { not_lparen_star } .
not_lparen_star = not_paren_star | ")" .
not_paren_star = letter | digit | not_paren_star_special .
not_paren_star_quote_special = "!" | "#" | "$" | "%" | "&" | "+" | "," | "-" | "." | "/" | ":" | ";" | "<" | "=" | ">" | "?" | "@" | "[" | "\\" | "]" | "^" | "_" | "{" | "|" | "}" | "~" .
not_paren_star_special = not_paren_star_quote_special | "\"\"" .
not_quote = not_paren_star_quote_special | letter | digit | "(" | ")" | "*" .
not_rparen_star = not_paren_star | "(" .
octet = hex_digit hex_digit .
special = not_paren_star_quote_special | "(" | ")" | "*" | "\"\"" .
not_rparen_star_then_rparen = not_rparen_star { not_rparen_star } ")" { ")" } .
binary_literal = "%" bit { bit } .
encoded_string_literal = "\"" encoded_character { encoded_character } "\"" .
integer_literal = digits .
real_literal = ( digits "." [ digits ] [ "e" [ sign ] digits ] ) | integer_literal .
simple_id = letter { letter | digit | "_" } .
simple_string_literal = "'" { ( "'" "'" ) | not_quote } "'" .
embedded_remark = "(*" [ remark_tag ] { ( not_paren_star { not_paren_star } ) | lparen_then_not_lparen_star | ( "*" { "*" } ) | not_rparen_star_then_rparen | embedded_remark } "*)" .
remark = embedded_remark | tail_remark .
remark_tag = "\"" remark_ref { "." remark_ref } "\"" .
remark_ref = attribute_ref | constant_ref | entity_ref | enumeration_ref | function_ref | parameter_ref | procedure_ref | rule_label_ref | rule_ref | schema_ref | subtype_constraint_ref | type_label_ref | type_ref | variable_ref .
tail_remark = "--" [ remark_tag ] .
attribute_ref = attribute_id .
constant_ref = constant_id .
entity_ref = entity_id .
enumeration_ref = enumeration_id .
function_ref = function_id .
parameter_ref = parameter_id .
procedure_ref = procedure_id .
rule_label_ref = rule_label_id .
rule_ref = rule_id .
schema_ref = schema_id .
subtype_constraint_ref = subtype_constraint_id .
type_label_ref = type_label_id .
type_ref = type_id .
variable_ref = variable_id .
abstract_entity_declaration = ABSTRACT .
abstract_supertype = ABSTRACT SUPERTYPE ";" .
abstract_supertype_declaration = ABSTRACT SUPERTYPE [ subtype_constraint ] .
actual_parameter_list = "(" [ parameter ] { "," parameter } ")" .
add_like_op = "+" | "-" | OR | XOR .
aggregate_initializer = "[" [ element { "," element } ] "]" .
aggregate_source = simple_expression .
aggregate_type = AGGREGATE [ ":" type_label ] OF parameter_type .
aggregation_types = array_type | bag_type | list_type | set_type .
algorithm_head = { declaration } [ constant_decl ] [ local_decl ] .
alias_stmt = ALIAS variable_id FOR general_ref { qualifier } ";" stmt { stmt } END_ALIAS ";" .
array_type = ARRAY bound_spec OF [ OPTIONAL ] [ UNIQUE ] instantiable_type .
assignment_stmt = general_ref { qualifier } ":=" expression ";" .
attribute_decl = redeclared_attribute | attribute_id .
attribute_id = simple_id .
attribute_qualifier = "." attribute_ref .
bag_type = BAG [ bound_spec ] OF instantiable_type .
binary_type = BINARY [ width_spec ] .
boolean_type = BOOLEAN .
bound_1 = numeric_expression .
bound_2 = numeric_expression .
bound_spec = "[" bound_1 ":" bound_2 "]" .
built_in_constant = CONST_E | PI | SELF | "?" .
built_in_function = ABS | ACOS | ASIN | ATAN | BLENGTH | COS | EXISTS | EXP | FORMAT | HIBOUND | HIINDEX | LENGTH | LOBOUND | LOINDEX | LOG | LOG2 | LOG10 | NVL | ODD | ROLESOF | SIN | SIZEOF | SQRT | TAN | TYPEOF | USEDIN | VALUE | VALUE_IN | VALUE_UNIQUE .
built_in_procedure = INSERT | REMOVE .
case_action = case_label { "," case_label } ":" stmt .
case_label = expression .
case_stmt = CASE selector OF { case_action } [ OTHERWISE ":" stmt ] END_CASE ";" .
compound_stmt = BEGIN stmt { stmt } END ";" .
concrete_types = aggregation_types | simple_types | type_ref .
constant_body = constant_id ":" instantiable_type ":=" expression ";" .
constant_decl = CONSTANT constant_body { constant_body } END_CONSTANT ";" .
constant_factor = built_in_constant | constant_ref .
constant_id = simple_id .
constructed_types = enumeration_type | select_type .
declaration = entity_decl | function_decl | procedure_decl | subtype_constraint_decl | type_decl .
derived_attr = attribute_decl ":" parameter_type ":=" expression ";" .
derive_clause = DERIVE derived_attr { derived_attr } .
domain_rule = rule_label_id ":" expression .
element = expression [ ":" repetition ] .
entity_body = { explicit_attr } [ derive_clause ] [ inverse_clause ] [ unique_clause ] [ where_clause ] .
entity_constructor = entity_ref "(" [ expression { "," expression } ] ")" .
entity_decl = entity_head entity_body END_ENTITY ";" .
entity_head = ENTITY entity_id subsuper ";" .
entity_id = simple_id .
enumeration_extension = BASED_ON type_ref [ WITH enumeration_items ] .
enumeration_id = simple_id .
enumeration_items = "(" enumeration_id { "," enumeration_id } ")" .
enumeration_reference = [ type_ref "." ] enumeration_ref .
enumeration_type = [ EXTENSIBLE ] ENUMERATION [ ( OF enumeration_items ) | enumeration_extension ] .
escape_stmt = ESCAPE ";" .
explicit_attr = attribute_decl { "," attribute_decl } ":" [ OPTIONAL ] parameter_type ";" .
expression = simple_expression [ rel_op_extended simple_expression ] .
factor = simple_factor [ "**" simple_factor ] .
formal_parameter = parameter_id { "," parameter_id } ":" parameter_type .
function_call = ( built_in_function | function_ref ) actual_parameter_list .
function_decl = function_head algorithm_head stmt { stmt } END_FUNCTION ";" .
function_head = FUNCTION function_id [ "(" formal_parameter { ";" formal_parameter } ")" ] ":" parameter_type ";" .
function_id = simple_id .
generalized_types = aggregate_type | general_aggregation_types | generic_entity_type | generic_type .
general_aggregation_types = general_array_type | general_bag_type | general_list_type | general_set_type .
general_array_type = ARRAY [ bound_spec ] OF [ OPTIONAL ] [ UNIQUE ] parameter_type .
general_bag_type = BAG [ bound_spec ] OF parameter_type .
general_list_type = LIST [ bound_spec ] OF [ UNIQUE ] parameter_type .
general_ref = parameter_ref | variable_ref .
general_set_type = SET [ bound_spec ] OF parameter_type .
generic_entity_type = GENERIC_ENTITY [ ":" type_label ] .
generic_type = GENERIC [ ":" type_label ] .
group_qualifier = "\\" entity_ref .
if_stmt = IF logical_expression THEN stmt { stmt } [ ELSE stmt { stmt } ] END_IF ";" .
increment = numeric_expression .
increment_control = variable_id ":=" bound_1 TO bound_2 [ BY increment ] .
index = numeric_expression .
index_1 = index .
index_2 = index .
index_qualifier = "[" index_1 [ ":" index_2 ] "]" .
instantiable_type = concrete_types | entity_ref .
integer_type = INTEGER .
interface_specification = reference_clause | use_clause .
interval = "{" interval_low interval_op interval_item interval_op interval_high "}" .
interval_high = simple_expression .
interval_item = simple_expression .
interval_low = simple_expression .
interval_op = "<=" | "<" .
inverse_attr = attribute_decl ":" [ ( SET | BAG ) [ bound_spec ] OF ] entity_ref FOR [ entity_ref "." ] attribute_ref ";" .
inverse_clause = INVERSE inverse_attr { inverse_attr } .
list_type = LIST [ bound_spec ] OF [ UNIQUE ] instantiable_type .
literal = binary_literal | logical_literal | real_literal | string_literal .
local_decl = LOCAL local_variable { local_variable } END_LOCAL ";" .
local_variable = variable_id { "," variable_id } ":" parameter_type [ ":=" expression ] ";" .
logical_expression = expression .
logical_literal = FALSE | TRUE | UNKNOWN .
logical_type = LOGICAL .
multiplication_like_op = "*" | "/" | DIV | MOD | AND | "||" .
named_types = entity_ref | type_ref .
named_type_or_rename = named_types [ AS ( entity_id | type_id ) ] .
null_stmt = ";" .
number_type = NUMBER .
numeric_expression = simple_expression .
one_of = ONEOF "(" supertype_expression { "," supertype_expression } ")" .
parameter = expression .
parameter_id = simple_id .
parameter_type = generalized_types | simple_types | named_types .
population = entity_ref .
precision_spec = numeric_expression .
primary = literal | ( qualifiable_factor { qualifier } ) .
procedure_call_stmt = ( built_in_procedure | procedure_ref ) actual_parameter_list ";" .
procedure_decl = procedure_head algorithm_head { stmt } END_PROCEDURE ";" .
procedure_head = PROCEDURE procedure_id [ "(" [ VAR ] formal_parameter { ";" [ VAR ] formal_parameter } ")" ] ";" .
procedure_id = simple_id .
qualifiable_factor = function_call | attribute_ref | constant_factor | general_ref | population .
qualified_attribute = SELF group_qualifier attribute_qualifier .
qualifier = attribute_qualifier | group_qualifier | index_qualifier .
query_expression = QUERY "(" variable_id "<*" aggregate_source "|" logical_expression ")" .
real_type = REAL [ "(" precision_spec ")" ] .
redeclared_attribute = qualified_attribute [ RENAMED attribute_id ] .
referenced_attribute = attribute_ref | qualified_attribute .
reference_clause = REFERENCE FROM schema_ref [ "(" resource_or_rename { "," resource_or_rename } ")" ] ";" .
rel_op = "<=" | ">=" | "<>" | "=" | ":<>:" | ":=:" | "<" | ">" .
rel_op_extended = rel_op | IN | LIKE .
rename_id = constant_id | entity_id | function_id | procedure_id | type_id .
repeat_control = [ increment_control ] [ while_control ] [ until_control ] .
repeat_stmt = REPEAT repeat_control ";" stmt { stmt } END_REPEAT ";" .
repetition = numeric_expression .
resource_or_rename = resource_ref [ AS rename_id ] .
resource_ref = constant_ref | entity_ref | function_ref | procedure_ref | type_ref .
return_stmt = RETURN [ "(" expression ")" ] ";" .
rule_decl = rule_head algorithm_head { stmt } where_clause END_RULE ";" .
rule_head = RULE rule_id FOR "(" entity_ref { "," entity_ref } ")" ";" .
rule_id = simple_id .
rule_label_id = simple_id .
schema_body = { interface_specification } [ constant_decl ] { declaration | rule_decl } .
schema_decl = SCHEMA schema_id [ schema_version_id ] ";" schema_body END_SCHEMA ";" .
schema_id = simple_id .
schema_version_id = string_literal .
selector = expression .
select_extension = BASED_ON type_ref [ WITH select_list ] .
select_list = "(" named_types { "," named_types } ")" .
select_type = [ EXTENSIBLE [ GENERIC_ENTITY ] ] SELECT [ select_list | select_extension ] .
set_type = SET [ bound_spec ] OF instantiable_type .
sign = "+" | "-" .
simple_expression = term { add_like_op term } .
simple_factor = aggregate_initializer | interval | query_expression | ( [ unary_op ] ( "(" expression ")" | primary ) ) | entity_constructor | enumeration_reference .
simple_types = binary_type | boolean_type | integer_type | logical_type | number_type | real_type | string_type .
skip_stmt = SKIP ";" .
stmt = alias_stmt | assignment_stmt | case_stmt | compound_stmt | escape_stmt | if_stmt | null_stmt | procedure_call_stmt | repeat_stmt | return_stmt | skip_stmt .
string_literal = simple_string_literal | encoded_string_literal .
string_type = STRING [ width_spec ] .
subsuper = [ supertype_constraint ] [ subtype_declaration ] .
subtype_constraint = OF "(" supertype_expression ")" .
subtype_constraint_body = [ abstract_supertype ] [ total_over ] [ supertype_expression ";" ] .
subtype_constraint_decl = subtype_constraint_head subtype_constraint_body END_SUBTYPE_CONSTRAINT ";" .
subtype_constraint_head = SUBTYPE_CONSTRAINT subtype_constraint_id FOR entity_ref ";" .
subtype_constraint_id = simple_id .
subtype_declaration = SUBTYPE OF "(" entity_ref { "," entity_ref } ")" .
supertype_constraint = abstract_supertype_declaration | abstract_entity_declaration | supertype_rule .
supertype_expression = supertype_factor { ANDOR supertype_factor } .
supertype_factor = supertype_term { AND supertype_term } .
supertype_rule = SUPERTYPE subtype_constraint .
supertype_term = one_of | "(" supertype_expression ")" | entity_ref .
syntax = schema_decl { schema_decl } .
term = factor { multiplication_like_op factor } .
total_over = TOTAL_OVER "(" entity_ref { "," entity_ref } ")" ";" .
type_decl = TYPE type_id "=" underlying_type ";" [ where_clause ] END_TYPE ";" .
type_id = simple_id .
type_label = type_label_id | type_label_ref .
type_label_id = simple_id .
unary_op = "+" | "-" | NOT .
underlying_type = constructed_types | concrete_types .
unique_clause = UNIQUE unique_rule ";" { unique_rule ";" } .
unique_rule = rule_label_id ":" referenced_attribute { "," referenced_attribute } .
until_control = UNTIL logical_expression .
use_clause = USE FROM schema_ref [ "(" named_type_or_rename { "," named_type_or_rename } ")" ] ";" .
variable_id = simple_id .
where_clause = WHERE domain_rule ";" { domain_rule ";" } .
while_control = WHILE logical_expression .
width = numeric_expression .
width_spec = "(" width ")" [ FIXED ] .
+129
View File
@@ -0,0 +1,129 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import templates
import documentation
class Header:
def __init__(self, mapping):
declarations = []
write = lambda str, **kwargs: declarations.append(str%dict({
'documentation': templates.multi_line_comment(documentation.description(kwargs['name']))}, **kwargs))
forward_names = list(mapping.schema.entities.keys()) + list(mapping.schema.simpletypes.keys())
forward_definitions = "".join(["class %s; "%n for n in forward_names])
for name, type in mapping.schema.selects.items():
write(templates.select, name=name)
for name, type in mapping.schema.enumerations.items():
short_name = name[:-4] if name.endswith("Enum") else name
write(templates.enumeration, name=name, values=", ".join(["%s_%s"%(short_name, v) for v in type.values]))
emitted_simpletypes = set()
while len(emitted_simpletypes) < len(mapping.schema.simpletypes):
for name, type in mapping.schema.simpletypes.items():
if name in emitted_simpletypes: continue
type_str = mapping.make_type_string(mapping.flatten_type_string(type))
attr_type = mapping.make_argument_type(type)
superclass = mapping.simple_type_parent(name)
if superclass is None:
superclass = "IfcUtil::IfcBaseType"
elif superclass not in emitted_simpletypes:
continue
emitted_simpletypes.add(name)
write(templates.simpletype, name=name, type=type_str, attr_type=attr_type, superclass=superclass)
class_definitions = []
write = lambda str, **kwargs: class_definitions.append(str%dict({
'documentation': templates.multi_line_comment(documentation.description(kwargs['name']))}, **kwargs))
emitted_entities = set()
while len(emitted_entities) < len(mapping.schema.entities):
for name, type in mapping.schema.entities.items():
if name in emitted_entities: continue
if len(type.supertypes) == 0 or set(type.supertypes) < emitted_entities:
attr_lines = []
def write_method(attr):
attr_lines.extend(["/// %s"%d for d in documentation.description((name, attr.name))])
type_str = mapping.get_parameter_type(attr, allow_optional=True, allow_entities=True)
if mapping.make_argument_type(attr) != "IfcUtil::Argument_UNKNOWN":
attr_lines.append("%s %s() const;"%(type_str, attr.name))
attr_lines.append("void %s(%s v);"%(attr.name, type_str))
[write_method(attr) for attr in type.attributes]
inv_lines = []
def write_inverse(attr):
inv_lines.append(templates.inverse_attr%{'name':attr.name, 'entity':attr.entity, 'attribute':attr.attribute})
if type.inverse:
[write_inverse(attr) for attr in type.inverse.elements]
attributes = "\n".join(["%s%s"%(' '*4, a) for a in attr_lines])
if len(attributes): attributes += '\n'
inverse = "\n".join(["%s%s"%(' '*4, a) for a in inv_lines])
if len(inverse): inverse += '\n'
supertypes = type.supertypes if len(type.supertypes) else ['IfcUtil::IfcBaseEntity']
superclass = ": %s "%(", ".join(["public %s"%c for c in supertypes]))
argument_count = mapping.argument_count(type)
argument_start = argument_count - len(type.attributes)
argument_name_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return "%s"; '%(i+argument_start, attr.name) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
argument_name_function_body_tail = (" return %s::getArgumentName(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' throw IfcParse::IfcException("argument out of range"); '
argument_name_function_body = argument_name_function_body_switch_stmt + argument_name_function_body_tail
argument_type_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return %s; '%(i+argument_start, mapping.make_argument_type(attr)) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
argument_type_function_body_tail = (" return %s::getArgumentType(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' throw IfcParse::IfcException("argument out of range"); '
argument_type_function_body = argument_type_function_body_switch_stmt + argument_type_function_body_tail
argument_entity_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return %s; '%(i+argument_start, mapping.make_argument_entity(attr)) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
argument_entity_function_body_tail = (" return %s::getArgumentEntity(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' throw IfcParse::IfcException("argument out of range"); '
argument_entity_function_body = argument_entity_function_body_switch_stmt + argument_entity_function_body_tail
constructor_arguments = ", ".join("%(full_type)s v%(index)d_%(name)s"%a for a in mapping.get_assignable_arguments(type))
write(templates.entity, **locals())
emitted_entities.add(name)
self.str = templates.header % {
'schema_name_upper' : mapping.schema.name.upper(),
'schema_name' : mapping.schema.name.capitalize(),
'declarations' : ''.join(declarations),
'forward_definitions' : forward_definitions,
'class_definitions' : ''.join(class_definitions)
}
self.schema_name = mapping.schema.name.capitalize()
def __repr__(self):
return self.str
def emit(self):
f = open('%s.h'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
+234
View File
@@ -0,0 +1,234 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import templates
class Implementation:
def __init__(self, mapping):
enumeration_functions = []
entity_implementations = []
schema_entity_statements = []
schema_name = mapping.schema.name.capitalize()
stringify = lambda s: '"%s"'%s
cat = lambda vs: "".join(vs)
catc = lambda vs: ", ".join(vs)
catnl = lambda vs: "\n".join(vs)
cator = lambda vs: " || ".join(vs)
nl = lambda s: "%s\n"%s if len(s) else s
write = lambda str, **kwargs: enumeration_functions.append(str%kwargs)
for name, enum in mapping.schema.enumerations.items():
short_name = name[:-4] if name.endswith("Enum") else name
context = locals()
write(
templates.enumeration_function,
max_id = len(enum.values),
name = name,
values = catc(map(stringify, enum.values)),
from_string_statements = catnl(templates.enum_from_string_stmt%dict(context,**locals()) for value in enum.values)
)
write = lambda str, **kwargs: entity_implementations.append(str%kwargs)
for name, type in mapping.schema.entities.items():
parent_type_test = "" if not type.supertypes or len(type.supertypes) != 1 \
else templates.parent_type_test%(type.supertypes[0])
constructor_arguments = mapping.get_assignable_arguments(type, include_derived = True)
constructor_arguments_str = catc("%(full_type)s v%(index)d_%(name)s"%a for a in constructor_arguments if not a['is_derived'])
attributes = []
constructor_implementations = []
write_attr = lambda str, **kwargs: attributes.append(str%kwargs)
for arg in constructor_arguments:
if not arg['is_inherited'] and not arg['is_derived']:
def find_template(arg):
simple = mapping.schema.is_simpletype(arg['list_instance_type'])
select = arg['list_instance_type'] == "IfcUtil::IfcBaseClass"
express = arg['list_instance_type'] in mapping.express_to_cpp_typemapping
if arg['is_optional']:
if arg['is_enum']: return templates.get_attr_stmt_optional_enum
elif arg['is_nested']: return templates.get_attr_stmt_optional_nested_array
elif arg['is_array'] and not (select or simple or express): return templates.get_attr_stmt_optional_array
elif arg['non_optional_type'].endswith('*'): return templates.get_attr_stmt_optional_entity
else: return templates.get_attr_stmt_generic
else:
if arg['is_enum']: return templates.get_attr_stmt_enum
elif arg['is_nested']: return templates.get_attr_stmt_nested_array
elif arg['is_array'] and not (select or simple or express): return templates.get_attr_stmt_array
elif arg['non_optional_type'].endswith('*'): return templates.get_attr_stmt_entity
else: return templates.get_attr_stmt_generic
tmpl = find_template(arg)
write_attr(
templates.const_function,
class_name = name,
name = arg['name'],
arguments = '',
return_type = arg['full_type'],
body = tmpl % {'index': arg['index']-1,
'type' : arg['non_optional_type'].split('::')[0],
'list_instance_type' : arg['list_instance_type']}
)
def find_template(arg):
simple = mapping.schema.is_simpletype(arg['list_instance_type'])
select = arg['list_instance_type'] == "IfcUtil::IfcBaseClass"
express = arg['list_instance_type'] in mapping.express_to_cpp_typemapping
if arg['is_optional']:
if arg['is_enum']: return templates.set_attr_stmt_optional_enum
elif arg['is_array'] and not (select or simple or express): return templates.set_attr_stmt_optional_array
else: return templates.set_attr_stmt_optional_generic
else:
if arg['is_enum']: return templates.set_attr_stmt_enum
elif arg['is_array'] and not (select or simple or express): return templates.set_attr_stmt_array
else: return templates.set_attr_stmt_generic
tmpl = find_template(arg)
write_attr(
templates.function,
class_name = name,
name = arg['name'],
arguments = '%s v'%arg['full_type'],
return_type = 'void',
body = tmpl % {'index': arg['index']-1,
'type' : arg['non_optional_type'].split('::')[0]}
)
if arg['is_derived']:
constructor_implementations.append(templates.constructor_stmt_derived % {'index' : arg['index']-1})
else:
arg_name = "v%(index)d_%(name)s"%arg
deref_name = ("*%s"%arg_name) if arg['is_optional'] else arg_name
tmpl = templates.constructor_stmt_array if arg['is_templated_list'] \
else templates.constructor_stmt_enum if arg['is_enum'] \
else templates.constructor_stmt
impl = tmpl % {'name' : deref_name,
'index' : arg['index']-1,
'type' : arg['non_optional_type'].split('::')[0]}
if arg['is_optional']:
impl = templates.constructor_stmt_optional%{'name' : arg_name,
'index' : arg['index']-1,
'stmt' : impl}
constructor_implementations.append(impl)
def get_attribute_index(entity, attr_name):
related_entity = mapping.schema.entities[entity]
return [a['name'] for a in mapping.get_assignable_arguments(related_entity, include_derived=True)].index(attr_name)
inverse = [templates.const_function % {
'class_name' : name,
'name' : i.name,
'arguments' : '',
'return_type' : '%s::list::ptr' % i.entity,
'body' : templates.get_inverse % {'type': i.entity, 'index':get_attribute_index(i.entity, i.attribute)}
} for i in (type.inverse.elements if type.inverse else [])]
superclass = "%s((IfcAbstractEntity*)0)" % type.supertypes[0] if len(type.supertypes) == 1 else 'IfcUtil::IfcBaseEntity()'
write(
templates.entity_implementation,
name = name,
parent_type_test = parent_type_test,
constructor_arguments = constructor_arguments_str,
constructor_implementation = cat(constructor_implementations),
attributes = nl(catnl(attributes)),
inverse = nl(catnl(inverse)),
superclass = superclass
)
selectable_simple_types = sorted(set(sum([b.values for a,b in mapping.schema.selects.items()], [])) & set(mapping.schema.types.keys()))
schema_entity_statements += [templates.schema_entity_stmt%locals() for name, type in mapping.schema.simpletypes.items()]
schema_entity_statements += [templates.schema_entity_stmt%locals() for name, type in mapping.schema.entities.items()]
enumerable_types = sorted(set([name for name, type in mapping.schema.types.items()] + [name for name, type in mapping.schema.entities.items()]))
max_len = max(map(len, enumerable_types))
type_name_strings = catc(map(stringify, enumerable_types))
string_map_statements = [templates.string_map_statement % {
'uppercase_name' : name.upper(),
'name' : name,
'padding' : ' ' * (max_len - len(name))
} for name in enumerable_types]
parent_type_statements = [templates.parent_type_stmt % {
'name' : name,
'parent' : type.supertypes[0],
'padding' : ' ' * (max_len - len(name))
} for name, type in mapping.schema.entities.items() if type.supertypes and len(type.supertypes) == 1]
max_id = len(enumerable_types)
simple_type_statements = cator("v == Type::%s"%name for name in selectable_simple_types)
simple_type_impl = []
for class_name, type in mapping.schema.simpletypes.items():
type_str = mapping.make_type_string(mapping.flatten_type_string(type))
attr_type = mapping.make_argument_type(type)
superclass = mapping.simple_type_parent(class_name)
simpletype_impl_is = templates.simpletype_impl_is_with_supertype if superclass \
else templates.simpletype_impl_is_without_supertype
constructor = templates.constructor_single_initlist if superclass \
else templates.constructor
def compose(params):
class_name, attr_type, superclass, superclass_init, name, tmpl, return_type, args, body = params
arguments = ",".join(args)
body = body % locals()
return tmpl % locals()
simple_type_impl.append(templates.simpletype_impl_comment % {'name': class_name})
simple_type_impl.extend(map(compose, map(lambda x: (class_name, attr_type, superclass, "(IfcAbstractEntity*)0")+x, (
('getArgumentType', templates.const_function, 'IfcUtil::ArgumentType', ('unsigned int i',), templates.simpletype_impl_argument_type ),
('getArgument', templates.const_function, 'Argument*', ('unsigned int i',), templates.simpletype_impl_argument ),
('is', templates.const_function, 'bool', ('Type::Enum v',), simpletype_impl_is ),
('type', templates.const_function, 'Type::Enum', (), templates.simpletype_impl_type ),
('Class', templates.function, 'Type::Enum', (), templates.simpletype_impl_class ),
('', constructor, '', ('IfcAbstractEntity* e',), templates.simpletype_impl_explicit_constructor),
('', constructor, '', ("%s v" % type_str,), templates.simpletype_impl_constructor ),
('', templates.cast_function, type_str, (), templates.simpletype_impl_cast )
))))
simple_type_impl.append('')
self.str = templates.implementation % {
'schema_name_upper' : mapping.schema.name.upper(),
'schema_name' : mapping.schema.name.capitalize(),
'max_id' : max_id,
'enumeration_functions' : cat(enumeration_functions),
'schema_entity_statements' : catnl(schema_entity_statements),
'type_name_strings' : type_name_strings,
'string_map_statements' : catnl(string_map_statements),
'simple_type_statement' : simple_type_statements,
'parent_type_statements' : catnl(parent_type_statements),
'entity_implementations' : catnl(entity_implementations),
'simple_type_impl' : catnl(simple_type_impl)
}
self.schema_name = mapping.schema.name.capitalize()
def __repr__(self):
return self.str
def emit(self):
f = open('%s.cpp'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
+35
View File
@@ -0,0 +1,35 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import templates
class LateBoundHeader:
def __init__(self, mapping):
self.str = templates.lb_header % {
'schema_name_upper' : mapping.schema.name.upper(),
'schema_name' : mapping.schema.name.capitalize()
}
self.schema_name = mapping.schema.name.capitalize()
def __repr__(self):
return self.str
def emit(self):
f = open('%s-latebound.h'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
@@ -0,0 +1,119 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import templates
class LateBoundImplementation:
def __init__(self, mapping):
schema_name = mapping.schema.name.capitalize()
entity_descriptors = []
enumeration_descriptors = []
derived_field_statements = []
inverse_implementations = []
for name, type in mapping.schema.simpletypes.items():
entity_descriptors.append(templates.entity_descriptor % {
'type' : name,
'parent_statement' : '0',
'entity_descriptor_attributes' : templates.entity_descriptor_attribute_without_entity % {
'name' : 'wrappedValue',
'optional' : 'false',
'type' : mapping.make_argument_type(mapping.schema.types[name].type)
}
})
emitted_entities = set()
entities_to_emit = mapping.schema.entities.keys()
while len(emitted_entities) < len(mapping.schema.entities):
for name, type in mapping.schema.entities.items():
if name in emitted_entities: continue
if len(type.supertypes) == 0 or set(type.supertypes) < emitted_entities:
constructor_arguments = mapping.get_assignable_arguments(type, include_derived = True)
entity_descriptor_attributes = []
for arg in constructor_arguments:
if not arg['is_inherited']:
is_enumeration = arg['argument_type_enum'] == 'IfcUtil::Argument_ENUMERATION'
tmpl = templates.entity_descriptor_attribute_with_entity
entity_name = arg['argument_type'] if is_enumeration else arg['argument_entity'].split('::')[1]
entity_descriptor_attributes.append(tmpl % {
'name' : arg['name'],
'optional' : 'true' if arg['is_optional'] else 'false',
'type' : arg['argument_type_enum'],
'entity_name': entity_name
})
emitted_entities.add(name)
parent_statement = '0' if len(type.supertypes) != 1 else templates.entity_descriptor_parent % {
'type' : type.supertypes[0]
}
entity_descriptors.append(templates.entity_descriptor % {
'type' : name,
'parent_statement' : parent_statement,
'entity_descriptor_attributes' : '\n'.join(entity_descriptor_attributes)
})
for name, enum in mapping.schema.enumerations.items():
enumeration_descriptor_values = '\n'.join([templates.enumeration_descriptor_value % {
'name' : v
} for v in enum.values])
enumeration_descriptors.append(templates.enumeration_descriptor % {
'type' : name,
'enumeration_descriptor_values' : enumeration_descriptor_values
})
for name, type in mapping.schema.entities.items():
constructor_arguments = mapping.get_assignable_arguments(type, include_derived = True)
statements = ''.join(templates.derived_field_statement_attrs % (a['index']-1) for a in constructor_arguments if a['is_derived'])
if len(statements):
derived_field_statements.append(templates.derived_field_statement % {
'type' : name,
'statements' : statements
})
for name, type in mapping.schema.entities.items():
if type.inverse:
for attr in type.inverse.elements:
related_entity = mapping.schema.entities[attr.entity]
related_attrs = [a['name'] for a in mapping.get_assignable_arguments(related_entity, include_derived=True)]
inverse_implementations.append(templates.inverse_implementation % {
'type' : name,
'name' : attr.name,
'related_type' : attr.entity,
'index' : related_attrs.index(attr.attribute)
})
self.str = templates.lb_implementation % {
'schema_name_upper' : mapping.schema.name.upper(),
'schema_name' : mapping.schema.name.capitalize(),
'entity_descriptors' : '\n'.join(entity_descriptors),
'enumeration_descriptors' : '\n'.join(enumeration_descriptors),
'derived_field_statements' : '\n'.join(derived_field_statements),
'inverse_implementations' : '\n'.join(inverse_implementations)
}
self.schema_name = mapping.schema.name.capitalize()
def __repr__(self):
return self.str
def emit(self):
f = open('%s-latebound.cpp'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
+199
View File
@@ -0,0 +1,199 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import nodes
import templates
class Mapping:
express_to_cpp_typemapping = {
'boolean' : 'bool',
'logical' : 'bool',
'integer' : 'int',
'real' : 'double',
'number' : 'double',
'string' : 'std::string'
}
def __init__(self, schema):
self.schema = schema
def flatten_type_string(self, type):
return self.flatten_type_string(self.schema.types[type].type.type) if self.schema.is_simpletype(type) else type
def flatten_type(self, type):
res = self.flatten_type(self.schema.types[type].type.type) if self.schema.is_simpletype(type) else type
return res
def simple_type_parent(self, type):
parent = self.schema.types[type].type.type
if isinstance(parent, nodes.AggregationType): parent = None
return None if parent in self.express_to_cpp_typemapping else parent
def make_type_string(self, type):
if isinstance(type, str):
return self.express_to_cpp_typemapping.get(type, type)
else:
is_list = self.schema.is_entity(type.type)
is_nested_list = isinstance(type.type, nodes.AggregationType)
tmpl = templates.list_list_type if is_nested_list else templates.list_type if is_list else templates.array_type
return tmpl % {
'instance_type' : self.make_type_string(type.type),
'lower' : type.bounds.lower,
'upper' : type.bounds.upper,
}
def is_array(self, type):
if isinstance(type, nodes.AggregationType):
return True
elif isinstance(type, str) and self.schema.is_type(type):
return self.is_array(self.schema.types[type].type.type)
else:
return False
def make_argument_entity(self, attr):
type = attr.type if hasattr(attr, 'type') else attr
while isinstance(type, nodes.AggregationType): type = type.type
if type in self.express_to_cpp_typemapping or isinstance(type, nodes.BinaryType): return "Type::UNDEFINED"
else: return "Type::%s" % type
def make_argument_type(self, attr):
def _make_argument_type(type):
if type in self.express_to_cpp_typemapping:
return self.express_to_cpp_typemapping.get(type, type).split('::')[-1].upper()
elif self.schema.is_entity(type):
return "ENTITY"
elif self.schema.is_type(type):
return _make_argument_type(self.schema.types[type].type.type)
elif isinstance(type, nodes.BinaryType):
return "UNKNOWN"
elif isinstance(type, nodes.EnumerationType):
return "ENUMERATION"
elif isinstance(type, nodes.SelectType):
return "ENTITY"
elif isinstance(type, nodes.AggregationType):
ty = _make_argument_type(type.type)
if ty == "UNKNOWN": return "UNKNOWN"
return "%s_LIST"%ty if ty.startswith("ENTITY") else ("VECTOR_%s"%ty)
else: raise ValueError
supported = {'INT', 'BOOL', 'DOUBLE', 'STRING', 'VECTOR_INT', 'VECTOR_DOUBLE', 'VECTOR_STRING', 'ENTITY', 'ENTITY_LIST', 'ENTITY_LIST_LIST', 'ENUMERATION'}
ty = _make_argument_type(attr.type if hasattr(attr, 'type') else attr)
if ty not in supported: ty = 'UNKNOWN'
return "IfcUtil::Argument_%s" % ty
def get_type_dep(self, type):
if isinstance(type, str):
return self.express_to_cpp_typemapping.get(type, type)
else:
return self.get_type_dep(type.type)
def get_parameter_type(self, attr, allow_optional, allow_entities, allow_pointer = True):
attr_type = self.flatten_type(attr.type)
type_str = self.express_to_cpp_typemapping.get(str(attr_type), attr_type)
if self.schema.is_enumeration(attr_type):
type_str = '%s::%s'%(attr_type, attr_type)
elif isinstance(type_str, nodes.AggregationType):
is_nested_list = isinstance(attr_type.type, nodes.AggregationType)
ty = self.get_parameter_type(attr_type.type if is_nested_list else attr_type, False, allow_entities, False)
if True and self.schema.is_select(attr_type.type):
type_str = templates.untyped_list
elif self.schema.is_simpletype(ty) or ty in self.express_to_cpp_typemapping.values():
type_str = templates.array_type % {
'instance_type' : ty,
'lower' : attr_type.bounds.lower,
'upper' : attr_type.bounds.upper
}
else:
tmpl = templates.list_list_type if is_nested_list else templates.list_type
type_str = tmpl % {
'instance_type': ty
}
elif allow_pointer and (self.schema.is_entity(type_str) or self.schema.is_select(type_str)):
type_str += '*'
elif not allow_pointer and self.schema.is_select(type_str):
type_str = "IfcUtil::IfcBaseClass*"
if allow_optional and attr.optional:# and not is_ptr:
type_str = "boost::optional< %s >"%type_str
return type_str
def argument_count(self, t):
c = sum([self.argument_count(self.schema.entities[s]) for s in t.supertypes])
return c + len(t.attributes)
def arguments(self, t):
c = sum([self.arguments(self.schema.entities[s]) for s in t.supertypes], [])
return c + t.attributes
def derived_in_supertype(self, t):
c = sum([self.derived_in_supertype(self.schema.entities[s]) for s in t.supertypes], [])
return c + ([str(s) for s in t.derive.elements] if t.derive else [])
def list_instance_type(self, attr):
f = lambda v : 'IfcUtil::IfcBaseClass' if self.schema.is_select(v) else v
if self.is_array(attr.type):
if not isinstance(attr.type, str) and self.is_array(attr.type.type):
if isinstance(attr.type.type, str):
return f(attr.type.type)
else: return f(attr.type.type.type)
else:
if isinstance(attr.type, str):
return f(attr.type)
else: return f(attr.type.type)
return None
def is_templated_list(self, attr):
ty = self.list_instance_type(attr)
arr = self.is_array(attr.type)
simple = self.schema.is_simpletype(ty)
express = ty in self.express_to_cpp_typemapping
select = ty == 'IfcUtil::IfcBaseClass'
return arr and not simple and not express and not select
def get_assignable_arguments(self, t, include_derived = False):
count = self.argument_count(t)
num_inherited = count - len(t.attributes)
derived = set(self.derived_in_supertype(t))
attrs = enumerate(self.arguments(t))
def include(attr):
not_derived = include_derived or (attr.name not in derived)
supported = self.make_argument_type(attr) != "IfcUtil::Argument_UNKNOWN"
return not_derived and supported
return [{
'index' : i+1,
'name' : attr.name,
'full_type' : self.get_parameter_type(attr, allow_optional=True, allow_entities=True),
'specialized_type' : self.get_parameter_type(attr, allow_optional=True, allow_entities=False),
'non_optional_type' : self.get_parameter_type(attr, allow_optional=False, allow_entities=False),
'list_instance_type' : self.list_instance_type(attr),
'is_optional' : attr.optional,
'is_inherited' : i < num_inherited,
'is_enum' : attr.type in self.schema.enumerations,
'is_array' : self.is_array(attr.type),
'is_nested' : self.is_array(attr.type) and not isinstance(attr.type, str) and self.is_array(attr.type.type),
'is_derived' : attr.name in derived,
'is_templated_list' : self.is_templated_list(attr),
'argument_type_enum' : self.make_argument_type(attr),
'argument_entity' : self.make_argument_entity(attr),
'argument_type' : attr.type
} for i, attr in attrs if include(attr)]
+175
View File
@@ -0,0 +1,175 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import string
import collections
class Node:
def __init__(self, tokens):
self.tokens = tokens
self.init()
def tokens_of_type(self, cls):
return [t for t in self.tokens if isinstance(t, cls)]
def single_token_of_type(self, cls, k = None, v = None):
ts = [t for t in self.tokens if isinstance(t, cls) and (k is None or getattr(t, k) == v)]
return ts[0] if len(ts) == 1 else None
class TypeDeclaration(Node):
name = property(lambda self: self.tokens[1])
type = property(lambda self: self.tokens[3])
def init(self):
assert self.tokens[0] == 'type'
assert isinstance(self.type, UnderlyingType)
def __repr__(self):
return "%s = TypeDeclaration(%s)" % (self.name, self.type)
class EntityDeclaration(Node):
name = property(lambda self: self.tokens[1])
attributes = property(lambda self: self.tokens_of_type(ExplicitAttribute))
def init(self):
assert self.tokens[0] == 'entity'
s = self.single_token_of_type(SubtypeExpression)
self.inverse = self.single_token_of_type(AttributeList, 'type', 'inverse')
self.derive = self.single_token_of_type(AttributeList, 'type', 'derive')
self.supertypes = s.types if s else []
def __repr__(self):
builder = ""
builder += "Entity(%s)" % (self.name)
if len(self.supertypes):
builder += "\n Supertypes: %s"%(",".join(self.supertypes))
if len(self.attributes):
builder += "\n Attributes: %s"%("".join(["\n %s"%a for a in self.attributes]))
if self.derive:
builder += "\n Derive:"
builder += str(self.derive)
if self.inverse:
builder += "\n Inverse:"
builder += str(self.inverse)
builder += "\n"
return builder
class UnderlyingType(Node):
type = property(lambda self: self.tokens[0])
def init(self):
pass
def __repr__(self):
return repr(self.type)
class EnumerationType(Node):
type = property(lambda self: self.tokens[0])
values = property(lambda self: self.tokens[3::2])
def init(self):
assert self.type == 'enumeration'
def __repr__(self):
return ",".join(self.values)
class AggregationType(Node):
aggregate_type = property(lambda self: self.tokens[0])
bounds = property(lambda self: None if self.tokens[1] == 'of' else self.tokens[1])
type = property(lambda self: self.tokens[-1])
def init(self):
assert self.bounds is None or isinstance(self.bounds, BoundSpecification)
def __repr__(self):
return "%s%s of %s"%(self.aggregate_type, self.bounds, self.type)
class SelectType(Node):
type = property(lambda self: self.tokens[0])
values = property(lambda self: self.tokens[2::2])
def init(self):
assert self.type == 'select'
def __repr__(self):
return ",".join(self.values)
class SubSuperTypeExpression(Node):
type = property(lambda self: self.tokens[0])
types = property(lambda self: self.tokens[3::2])
def init(self):
assert self.type == self.class_type
class SubtypeExpression(SubSuperTypeExpression):
class_type = 'subtype'
class AttributeList(Node):
elements = property(lambda self: self.tokens[1:])
def __init__(self, ty, toks):
self.type = ty
Node.__init__(self, toks)
def init(self):
assert self.type == self.tokens[0]
def __repr__(self):
return "".join(["\n %s"%s for s in self.elements])
class InverseAttribute(Node):
name = property(lambda self: self.tokens[0])
type = property(lambda self: self.tokens[2])
bounds = property(lambda self: None if len(self.tokens) == 6 else self.tokens[3])
entity = property(lambda self: self.tokens[-4])
attribute = property(lambda self: self.tokens[-2])
def init(self):
assert self.bounds is None or isinstance(self.bounds, BoundSpecification)
def __repr__(self):
return "%s = %s.%s (%s%s)"%(self.name, self.entity, self.attribute, self.type, self.bounds or "")
class DerivedAttribute(Node):
def init(self):
name_index = list(self.tokens).index(':') - 1
self.name = self.tokens[name_index]
def __repr__(self):
return str(self.name)
class BinaryType(Node):
def init(self):
pass
def __repr__(self):
return "BINARY"
class BoundSpecification(Node):
lower = property(lambda self: self.tokens[1])
upper = property(lambda self: self.tokens[3])
def init(self):
# assert self.lower in string.digits or self.lower == '?'
# assert self.upper in string.digits or self.upper == '?'
pass
def __repr__(self):
return "[%s:%s]"%(self.lower, self.upper)
class ExplicitAttribute(Node):
name = property(lambda self: self.tokens[0])
type = property(lambda self: self.tokens[-2])
optional = property(lambda self: len(self.tokens) == 5 and self.tokens[-3] == 'optional')
def init(self):
# NB: This assumes a single name per attribute
# definition, which is not necessarily the case.
assert self.tokens[1] == ':'
def __repr__(self):
return "%s : %s%s" % (self.name, self.type, " ?" if self.optional else "")
+46
View File
@@ -0,0 +1,46 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import nodes
import collections
class Schema:
def is_enumeration(self, v):
return v in self.enumerations
def is_select(self, v):
return v in self.selects
def is_simpletype(self, v):
return v in self.simpletypes
def is_type(self, v):
return v in self.types
def is_entity(self, v):
return v in self.entities
def __init__(self, parsetree):
self.name = parsetree[1]
sort = lambda d: collections.OrderedDict(sorted(d.items()))
self.types = sort({t.name:t for t in parsetree if isinstance(t, nodes.TypeDeclaration)})
self.entities = sort({t.name:t for t in parsetree if isinstance(t, nodes.EntityDeclaration)})
of_type = lambda *types: sort({a: b.type.type for a,b in self.types.items() if any(isinstance(b.type.type, ty) for ty in types)})
self.enumerations = of_type(nodes.EnumerationType)
self.selects = of_type(nodes.SelectType)
self.simpletypes = of_type(str, nodes.AggregationType)
+448
View File
@@ -0,0 +1,448 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
header = """
#ifndef %(schema_name_upper)s_H
#define %(schema_name_upper)s_H
#include <string>
#include <vector>
#include <map>
#include <boost/optional.hpp>
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcException.h"
#include "../ifcparse/%(schema_name)senum.h"
#define IfcSchema %(schema_name)s
namespace %(schema_name)s {
const char* const Identifier = "%(schema_name_upper)s";
// Forward definitions
%(forward_definitions)s
%(declarations)s
%(class_definitions)s
void InitStringMap();
IfcUtil::IfcBaseClass* SchemaEntity(IfcAbstractEntity* e = 0);
}
#endif
"""
enum_header = """
#ifndef %(schema_name_upper)sENUM_H
#define %(schema_name_upper)sENUM_H
#define IfcSchema %(schema_name)s
namespace %(schema_name)s {
namespace Type {
typedef enum {
%(types)s, UNDEFINED
} Enum;
Enum Parent(Enum v);
Enum FromString(const std::string& s);
std::string ToString(Enum v);
bool IsSimple(Enum v);
}
}
#endif
"""
lb_header = """
#ifndef %(schema_name_upper)sRT_H
#define %(schema_name_upper)sRT_H
#define IfcSchema %(schema_name)s
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcEntityDescriptor.h"
#include "../ifcparse/IfcWritableEntity.h"
namespace %(schema_name)s {
namespace Type {
int GetAttributeCount(Enum t);
int GetAttributeIndex(Enum t, const std::string& a);
IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a);
Enum GetAttributeEntity(Enum t, unsigned char a);
const std::string& GetAttributeName(Enum t, unsigned char a);
bool GetAttributeOptional(Enum t, unsigned char a);
bool GetAttributeDerived(Enum t, unsigned char a);
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
std::set<std::string> GetInverseAttributeNames(Enum t);
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
}}
#endif
"""
implementation= """
#include "../ifcparse/%(schema_name)s.h"
#include "../ifcparse/IfcException.h"
#include "../ifcparse/IfcWrite.h"
#include "../ifcparse/IfcWritableEntity.h"
using namespace %(schema_name)s;
using namespace IfcParse;
using namespace IfcWrite;
IfcUtil::IfcBaseClass* %(schema_name)s::SchemaEntity(IfcAbstractEntity* e) {
switch(e->type()) {
%(schema_entity_statements)s
default: throw IfcException("Unable to find find keyword in schema"); break;
}
}
std::string Type::ToString(Enum v) {
if (v < 0 || v >= %(max_id)d) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { %(type_name_strings)s };
return names[v];
}
static std::map<std::string,Type::Enum> string_map;
void %(schema_name)s::InitStringMap() {
%(string_map_statements)s
}
Type::Enum Type::FromString(const std::string& s) {
if (string_map.empty()) InitStringMap();
std::map<std::string,Type::Enum>::const_iterator it = string_map.find(s);
if ( it == string_map.end() ) throw IfcException("Unable to find find keyword in schema");
else return it->second;
}
Type::Enum Type::Parent(Enum v){
if (v < 0 || v >= %(max_id)d) return (Enum)-1;
%(parent_type_statements)s
return (Enum)-1;
}
bool Type::IsSimple(Enum v) {
return %(simple_type_statement)s;
}
%(enumeration_functions)s
%(simple_type_impl)s
%(entity_implementations)s
"""
lb_implementation = """
#include <set>
#include "../ifcparse/%(schema_name)s.h"
#include "../ifcparse/%(schema_name)s-latebound.h"
#include "../ifcparse/IfcException.h"
#include "../ifcparse/IfcWrite.h"
#include "../ifcparse/IfcWritableEntity.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcEntityDescriptor.h"
using namespace %(schema_name)s;
using namespace IfcParse;
using namespace IfcWrite;
using namespace IfcUtil;
typedef std::map<Type::Enum,IfcEntityDescriptor*> entity_descriptor_map_t;
typedef std::map<Type::Enum,IfcEnumerationDescriptor*> enumeration_descriptor_map_t;
typedef std::map<Type::Enum, std::map<std::string, std::pair<Type::Enum, int> > > inverse_map_t;
typedef std::map<Type::Enum,std::set<int> > derived_map_t;
entity_descriptor_map_t entity_descriptor_map;
enumeration_descriptor_map_t enumeration_descriptor_map;
inverse_map_t inverse_map;
derived_map_t derived_map;
void InitDescriptorMap() {
IfcEntityDescriptor* current;
%(entity_descriptors)s
// Enumerations
IfcEnumerationDescriptor* current_enum;
std::vector<std::string> values;
%(enumeration_descriptors)s
}
void InitInverseMap() {
%(inverse_implementations)s
}
void InitDerivedMap() {
%(derived_field_statements)s
}
int Type::GetAttributeIndex(Enum t, const std::string& a) {
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
else return i->second->getArgumentIndex(a);
}
int Type::GetAttributeCount(Enum t) {
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
else return i->second->getArgumentCount();
}
ArgumentType Type::GetAttributeType(Enum t, unsigned char a) {
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
else return i->second->getArgumentType(a);
}
Type::Enum Type::GetAttributeEntity(Enum t, unsigned char a) {
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
else return i->second->getArgumentEntity(a);
}
const std::string& Type::GetAttributeName(Enum t, unsigned char a) {
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
else return i->second->getArgumentName(a);
}
bool Type::GetAttributeOptional(Enum t, unsigned char a) {
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
else return i->second->getArgumentOptional(a);
}
bool Type::GetAttributeDerived(Enum t, unsigned char a) {
if (derived_map.empty()) ::InitDerivedMap();
std::map<Type::Enum,std::set<int> >::const_iterator i = derived_map.find(t);
return i != derived_map.end() && i->second.find(a) != i->second.end();
}
std::pair<const char*, int> Type::GetEnumerationIndex(Enum t, const std::string& a) {
if (enumeration_descriptor_map.empty()) ::InitDescriptorMap();
std::map<Type::Enum,IfcEnumerationDescriptor*>::const_iterator i = enumeration_descriptor_map.find(t);
if ( i == enumeration_descriptor_map.end() ) throw IfcException("Value not found");
else return i->second->getIndex(a);
}
std::pair<Type::Enum, unsigned> Type::GetInverseAttribute(Enum t, const std::string& a) {
if (inverse_map.empty()) ::InitInverseMap();
inverse_map_t::const_iterator it;
inverse_map_t::mapped_type::const_iterator jt;
while (true) {
it = inverse_map.find(t);
if (it != inverse_map.end()) {
jt = it->second.find(a);
if (jt != it->second.end()) {
return jt->second;
}
}
if ((t = Parent(t)) == -1) break;
}
throw IfcException("Attribute not found");
}
std::set<std::string> Type::GetInverseAttributeNames(Enum t) {
if (inverse_map.empty()) ::InitInverseMap();
inverse_map_t::const_iterator it;
inverse_map_t::mapped_type::const_iterator jt;
std::set<std::string> return_value;
while (true) {
it = inverse_map.find(t);
if (it != inverse_map.end()) {
for (jt = it->second.begin(); jt != it->second.end(); ++jt) {
return_value.insert(jt->first);
}
}
if ((t = Parent(t)) == -1) break;
}
return return_value;
}
void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) {
std::map<Type::Enum, std::set<int> >::const_iterator i = derived_map.find(e->type());
if (i != derived_map.end()) {
for (std::set<int>::const_iterator it = i->second.begin(); it != i->second.end(); ++it) {
e->setArgumentDerived(*it);
}
}
}
"""
entity_descriptor = """ current = entity_descriptor_map[Type::%(type)s] = new IfcEntityDescriptor(Type::%(type)s,%(parent_statement)s);
%(entity_descriptor_attributes)s"""
entity_descriptor_parent = "entity_descriptor_map.find(Type::%(type)s)->second"
entity_descriptor_attribute_without_entity = ' current->add("%(name)s",%(optional)s,%(type)s);'
entity_descriptor_attribute_with_entity = ' current->add("%(name)s",%(optional)s,%(type)s,Type::%(entity_name)s);'
enumeration_descriptor = """ values.clear(); values.reserve(128);
%(enumeration_descriptor_values)s
current_enum = enumeration_descriptor_map[Type::%(type)s] = new IfcEnumerationDescriptor(Type::%(type)s, values);"""
enumeration_descriptor_value = ' values.push_back("%(name)s");'
derived_field_statement = ' {std::set<int> idxs; %(statements)sderived_map[Type::%(type)s] = idxs;}';
derived_field_statement_attrs = 'idxs.insert(%d); '
simpletype = """%(documentation)s
class %(name)s : public %(superclass)s {
public:
virtual IfcUtil::ArgumentType getArgumentType(unsigned int i) const;
virtual Argument* getArgument(unsigned int i) const;
bool is(Type::Enum v) const;
Type::Enum type() const;
static Type::Enum Class();
explicit %(name)s (IfcAbstractEntity* e);
%(name)s (%(type)s v);
operator %(type)s() const;
};
"""
simpletype_impl_comment = "// Function implementations for %(name)s"
simpletype_impl_argument_type = "if (i == 0) { return %(attr_type)s; } else { throw IfcParse::IfcException(\"argument out of range\"); }"
simpletype_impl_argument = "return entity->getArgument(i);"
simpletype_impl_is_with_supertype = "return v == Type::%(class_name)s || %(superclass)s::is(v);"
simpletype_impl_is_without_supertype = "return v == %(class_name)s::Class();"
simpletype_impl_type = "return Type::%(class_name)s;"
simpletype_impl_class = "return Type::%(class_name)s;"
simpletype_impl_explicit_constructor = "entity = e;"
simpletype_impl_constructor = "IfcWritableEntity* e = new IfcWritableEntity(Type::%(class_name)s); e->setArgument(0, v); entity = e;"
simpletype_impl_cast = "return *entity->getArgument(0);"
select = """%(documentation)s
typedef IfcUtil::IfcBaseClass %(name)s;
"""
enumeration = """namespace %(name)s {
%(documentation)s
typedef enum {%(values)s} %(name)s;
const char* ToString(%(name)s v);
%(name)s FromString(const std::string& s);
}
"""
entity = """%(documentation)s
class %(name)s %(superclass)s{
public:
%(attributes)s virtual unsigned int getArgumentCount() const { return %(argument_count)d; }
virtual IfcUtil::ArgumentType getArgumentType(unsigned int i) const {%(argument_type_function_body)s}
virtual Type::Enum getArgumentEntity(unsigned int i) const {%(argument_entity_function_body)s}
virtual const char* getArgumentName(unsigned int i) const {%(argument_name_function_body)s}
virtual Argument* getArgument(unsigned int i) const { return entity->getArgument(i); }
%(inverse)s bool is(Type::Enum v) const;
Type::Enum type() const;
static Type::Enum Class();
%(name)s (IfcAbstractEntity* e);
%(name)s (%(constructor_arguments)s);
typedef IfcTemplatedEntityList< %(name)s > list;
};
"""
enumeration_function="""
const char* %(name)s::ToString(%(name)s v) {
if ( v < 0 || v >= %(max_id)d ) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { %(values)s };
return names[v];
}
%(name)s::%(name)s %(name)s::FromString(const std::string& s) {
%(from_string_statements)s
throw IfcException("Unable to find find keyword in schema");
}
"""
entity_implementation = """// Function implementations for %(name)s
%(attributes)s%(inverse)sbool %(name)s::is(Type::Enum v) const { return v == Type::%(name)s%(parent_type_test)s; }
Type::Enum %(name)s::type() const { return Type::%(name)s; }
Type::Enum %(name)s::Class() { return Type::%(name)s; }
%(name)s::%(name)s(IfcAbstractEntity* e) : %(superclass)s { if (!e) return; if (!e->is(Type::%(name)s)) throw IfcException("Unable to find find keyword in schema"); entity = e; }
%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s { IfcWritableEntity* e = new IfcWritableEntity(Class());%(constructor_implementation)s entity = e; EntityBuffer::Add(this); }
"""
optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s"
function = "%(return_type)s %(class_name)s::%(name)s(%(arguments)s) { %(body)s }"
const_function = "%(return_type)s %(class_name)s::%(name)s(%(arguments)s) const { %(body)s }"
constructor = "%(class_name)s::%(class_name)s(%(arguments)s) { %(body)s }"
constructor_single_initlist = "%(class_name)s::%(class_name)s(%(arguments)s) : %(superclass)s(%(superclass_init)s) { %(body)s }"
cast_function = "%(class_name)s::operator %(return_type)s() const { %(body)s }"
array_type = "std::vector< %(instance_type)s > /*[%(lower)s:%(upper)s]*/"
list_type = "IfcTemplatedEntityList< %(instance_type)s >::ptr"
list_list_type = "IfcTemplatedEntityListList< %(instance_type)s >::ptr"
untyped_list = "IfcEntityList::ptr"
inverse_attr = "IfcTemplatedEntityList< %(entity)s >::ptr %(name)s() const; // INVERSE %(entity)s::%(attribute)s"
enum_from_string_stmt = ' if (s == "%(value)s") return ::%(schema_name)s::%(name)s::%(short_name)s_%(value)s;'
schema_entity_stmt = ' case Type::%(name)s: return new %(name)s(e); break;'
schema_simple_stmt = ' case Type::%(name)s: return new IfcUtil::IfcEntitySelect(e); break;'
string_map_statement = ' string_map["%(uppercase_name)s"%(padding)s] = Type::%(name)s;'
parent_type_stmt = ' if(v==%(name)s%(padding)s) { return %(parent)s; }'
parent_type_test = " || %s::is(v)"
get_attr_stmt_generic = "return *entity->getArgument(%(index)d);"
get_attr_stmt_enum = "return %(type)s::FromString(*entity->getArgument(%(index)d));"
get_attr_stmt_entity = "return (%(type)s)((IfcUtil::IfcBaseClass*)(*entity->getArgument(%(index)d)));"
get_attr_stmt_array = "IfcEntityList::ptr es = *entity->getArgument(%(index)d); return es->as<%(list_instance_type)s>();"
get_attr_stmt_nested_array = "IfcEntityListList::ptr es = *entity->getArgument(%(index)d); return es->as<%(list_instance_type)s>();"
get_attr_stmt_optional = "Argument* arg = entity->getArgument(%%(index)d); if (arg->isNull()) { return boost::none; } else { %s }"
get_attr_stmt_optional_generic = get_attr_stmt_optional % "return *arg;"
get_attr_stmt_optional_enum = get_attr_stmt_optional % "return %(type)s::FromString(*arg);"
get_attr_stmt_optional_entity = get_attr_stmt_optional % "return (%(type)s)((IfcUtil::IfcBaseClass*)(*arg));"
get_attr_stmt_optional_array = get_attr_stmt_optional % "IfcEntityList::ptr es = *arg; return es->as<%(list_instance_type)s>();"
get_attr_stmt_optional_nested_array = get_attr_stmt_optional % "IfcEntityListList::ptr es = *arg; return es->as<%(list_instance_type)s>();"
set_attr_stmt = "IfcWritableEntity* w = entity->isWritable(); if (!w) { entity = w = new IfcWritableEntity(entity); } %s;"
set_attr_stmt_optional = "IfcWritableEntity* w = entity->isWritable(); if (!w) { entity = w = new IfcWritableEntity(entity); } if (v) { %s; } else { w->setArgument(%%(index)d); }"
set_attr_stmt_generic = set_attr_stmt % "w->setArgument(%(index)d,v)"
set_attr_stmt_enum = set_attr_stmt % "w->setArgument(%(index)d,v,%(type)s::ToString(v));"
set_attr_stmt_array = set_attr_stmt % "w->setArgument(%(index)d,v->generalize());"
set_attr_stmt_optional_generic = set_attr_stmt_optional % "w->setArgument(%(index)d,*v)"
set_attr_stmt_optional_enum = set_attr_stmt_optional % "w->setArgument(%(index)d,*v,%(type)s::ToString(*v));"
set_attr_stmt_optional_array = set_attr_stmt_optional % "w->setArgument(%(index)d,(*v)->generalize());"
get_inverse = "return entity->getInverse(Type::%(type)s, %(index)d)->as<%(type)s>();"
constructor_stmt = " e->setArgument(%(index)d,(%(name)s));"
constructor_stmt_enum = " e->setArgument(%(index)d,%(name)s,%(type)s::ToString(%(name)s));"
constructor_stmt_array = " e->setArgument(%(index)d,(%(name)s)->generalize());"
constructor_stmt_optional = " if (%(name)s) {%(stmt)s } else { e->setArgument(%(index)d); }"
constructor_stmt_derived = " e->setArgumentDerived(%(index)d);"
inverse_implementation = " inverse_map[Type::%(type)s].insert(std::make_pair(\"%(name)s\", std::make_pair(Type::%(related_type)s, %(index)d)));"
def multi_line_comment(li):
return ("/// %s"%("\n/// ".join(li))) if len(li) else ""
+81 -12
View File
@@ -36,14 +36,32 @@
#include <TopoDS_Face.hxx>
#include <Geom_Curve.hxx>
#include <gp_Pln.hxx>
#include <TColgp_SequenceOfPnt.hxx>
#include "../ifcparse/IfcParse.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcgeom/IfcGeomElement.h"
#include "../ifcgeom/IfcGeomRepresentation.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"
#define IN_CACHE(T,E,t,e) std::map<int,t>::const_iterator it = cache.T.find(E->entity->id());\
if ( it != cache.T.end() ) { e = it->second; return true; }
#define CACHE(T,E,e) cache.T[E->entity->id()] = e;
namespace IfcGeom {
class Cache {
public:
#include "IfcRegisterCreateCache.h"
std::map<int, SurfaceStyle> Style;
std::map<int, TopoDS_Shape> Shape;
};
class Kernel {
private:
Cache cache;
public:
// Tolerances and settings for various geometrical operations:
enum GeomValue {
// Specifies the deflection of the mesher
@@ -80,15 +98,17 @@ namespace IfcGeom {
};
bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);
bool convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire);
bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result);
bool is_shape_collection(const IfcUtil::IfcBaseClass* L);
bool convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
bool flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse);
bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result);
bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& result);
bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Face& result);
bool convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings, const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes);
bool convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings, const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes);
Ifc2x3::IfcSurfaceStyleShading* get_surface_style(Ifc2x3::IfcRepresentationItem* item);
bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes);
bool convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes);
IfcSchema::IfcSurfaceStyleShading* get_surface_style(IfcSchema::IfcRepresentationItem* item);
bool create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& solid);
bool is_compound(const TopoDS_Shape& shape);
bool is_convex(const TopoDS_Wire& wire);
@@ -96,20 +116,69 @@ namespace IfcGeom {
gp_Pln plane_from_face(const TopoDS_Face& face);
gp_Pnt point_above_plane(const gp_Pln& pln, bool agree=true);
const TopoDS_Shape& ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid);
bool profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face);
bool profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Shape& face);
double shape_volume(const TopoDS_Shape& s);
double face_area(const TopoDS_Face& f);
void apply_tolerance(TopoDS_Shape& s, double t);
void SetValue(GeomValue var, double value);
double GetValue(GeomValue var);
Ifc2x3::IfcProductDefinitionShape* tesselate(TopoDS_Shape& shape, double deflection, IfcEntities es);
void setValue(GeomValue var, double value);
double getValue(GeomValue var);
bool fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape);
void remove_redundant_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.);
std::pair<std::string, double> initializeUnits(IfcSchema::IfcUnitAssignment*);
IfcSchema::IfcObjectDefinition* get_decomposing_entity(IfcSchema::IfcProduct*);
template <typename P>
IfcGeom::BRepElement<P>* create_brep_for_representation_and_product(const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*);
const SurfaceStyle* get_style(const IfcSchema::IfcRepresentationItem* representation_item);
namespace Cache {
void Purge();
void PurgeShapeCache();
template <typename T> std::pair<IfcSchema::IfcSurfaceStyle*, T*> get_surface_style(const IfcSchema::IfcRepresentationItem* representation_item) {
IfcSchema::IfcStyledItem::list::ptr styled_items = representation_item->StyledByItem();
for (IfcSchema::IfcStyledItem::list::it jt = styled_items->begin(); jt != styled_items->end(); ++jt) {
#ifdef USE_IFC4
IfcUtil::IfcAbstractSelect::list::ptr style_assignments = (*jt)->Styles();
for (IfcUtil::IfcAbstractSelect::list::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) {
if (!(*kt)->is(IfcSchema::Type::IfcPresentationStyleAssignment)) {
continue;
}
IfcSchema::IfcPresentationStyleAssignment* style_assignment = (IfcSchema::IfcPresentationStyleAssignment*) *kt;
#else
IfcSchema::IfcPresentationStyleAssignment::list::ptr style_assignments = (*jt)->Styles();
for (IfcSchema::IfcPresentationStyleAssignment::list::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) {
IfcSchema::IfcPresentationStyleAssignment* style_assignment = *kt;
#endif
IfcEntityList::ptr styles = style_assignment->Styles();
for (IfcEntityList::it lt = styles->begin(); lt != styles->end(); ++lt) {
IfcUtil::IfcBaseClass* style = *lt;
if (style->is(IfcSchema::Type::IfcSurfaceStyle)) {
IfcSchema::IfcSurfaceStyle* surface_style = (IfcSchema::IfcSurfaceStyle*) style;
if (surface_style->Side() != IfcSchema::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE) {
IfcEntityList::ptr styles_elements = surface_style->Styles();
for (IfcEntityList::it mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) {
if ((*mt)->is(T::Class())) {
return std::make_pair(surface_style, (T*) *mt);
}
}
}
}
}
}
// StyledByItem is a SET [0:1] OF IfcStyledItem, so we
// break after encountering the first IfcStyledItem
break;
}
return std::make_pair<IfcSchema::IfcSurfaceStyle*, T*>(0,0);
}
#include "IfcRegisterGeomHeader.h"
};
IfcSchema::IfcProductDefinitionShape* tesselate(TopoDS_Shape& shape, double deflection, IfcEntityList::ptr es);
}
#endif
+37 -19
View File
@@ -23,6 +23,8 @@
* *
********************************************************************************/
#include <algorithm>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <gp_Dir.hxx>
@@ -77,43 +79,59 @@
#include "../ifcgeom/IfcGeom.h"
bool IfcGeom::convert(const Ifc2x3::IfcCircle::ptr l, Handle(Geom_Curve)& curve) {
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
if ( r <= 0.0f ) { return false; }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircle* l, Handle(Geom_Curve)& curve) {
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
if ( r < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", l->entity);
return false;
}
gp_Trsf trsf;
Ifc2x3::IfcAxis2Placement placement = l->Position();
if (placement->is(Ifc2x3::Type::IfcAxis2Placement3D)) {
IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)placement,trsf);
IfcSchema::IfcAxis2Placement* placement = l->Position();
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf);
} else {
gp_Trsf2d trsf2d;
IfcGeom::convert((IfcAxis2Placement2D*)placement,trsf2d);
IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d);
trsf = trsf2d;
}
gp_Ax2 ax = gp_Ax2().Transformed(trsf);
curve = new Geom_Circle(ax, r);
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcEllipse::ptr l, Handle(Geom_Curve)& curve) {
double x = l->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT);
double y = l->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT);
if ( x == 0.0f || y == 0.0f || y > x ) { return false; }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcEllipse* l, Handle(Geom_Curve)& curve) {
double x = l->SemiAxis1() * getValue(GV_LENGTH_UNIT);
double y = l->SemiAxis2() * getValue(GV_LENGTH_UNIT);
if (x < ALMOST_ZERO || y < ALMOST_ZERO) {
Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", l->entity);
return false;
}
// Open Cascade does not allow ellipses of which the minor radius
// is greater than the major radius. Hence, in this case, the
// ellipse is rotated. Note that special care needs to be taken
// when creating a trimmed curve off of an ellipse like this.
const bool rotated = y > x;
gp_Trsf trsf;
Ifc2x3::IfcAxis2Placement placement = l->Position();
if (placement->is(Ifc2x3::Type::IfcAxis2Placement3D)) {
IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)placement,trsf);
IfcSchema::IfcAxis2Placement* placement = l->Position();
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf);
} else {
gp_Trsf2d trsf2d;
IfcGeom::convert((Ifc2x3::IfcAxis2Placement2D*)placement,trsf2d);
convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d);
trsf = trsf2d;
}
gp_Ax2 ax = gp_Ax2().Transformed(trsf);
gp_Ax2 ax = gp_Ax2();
if (rotated) {
ax.Rotate(ax.Axis(), M_PI / 2.);
std::swap(x, y);
}
ax.Transform(trsf);
curve = new Geom_Ellipse(ax, x, y);
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcLine::ptr l, Handle(Geom_Curve)& curve) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcLine* l, Handle(Geom_Curve)& curve) {
gp_Pnt pnt;gp_Vec vec;
IfcGeom::convert(l->Pnt(),pnt);
IfcGeom::convert(l->Dir(),vec);
convert(l->Pnt(),pnt);
convert(l->Dir(),vec);
// See note at IfcGeomWires.cpp:237
curve = new Geom_Line(pnt,vec);
return true;
+144
View File
@@ -0,0 +1,144 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef IFCGEOMELEMENT_H
#define IFCGEOMELEMENT_H
#include "../ifcgeom/IfcGeomRepresentation.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
namespace IfcGeom {
template <typename P>
class Matrix {
private:
std::vector<P> _data;
public:
Matrix(const ElementSettings& settings, const gp_Trsf& trsf) {
// Convert the gp_Trsf into a 4x3 Matrix
// Note that in case the CONVERT_BACK_UNITS setting is enabled
// the translation component of the matrix needs to be divided
// by the magnitude of the IFC model length unit because
// internally in IfcOpenShell everything is measured in meters.
for(int i = 1; i < 5; ++i) {
for (int j = 1; j < 4; ++j) {
const double trsf_value = trsf.Value(j,i);
const double matrix_value = i == 4 && settings.convert_back_units()
? trsf_value / settings.unit_magnitude()
: trsf_value;
_data.push_back(static_cast<P>(matrix_value));
}
}
}
const std::vector<P>& data() const { return _data; }
};
template <typename P>
class Transformation {
private:
gp_Trsf trsf;
Matrix<P> _matrix;
public:
Transformation(const ElementSettings& settings, const gp_Trsf& trsf)
: trsf(trsf)
, _matrix(settings, trsf)
{}
const gp_Trsf& data() const { return trsf; }
const Matrix<P>& matrix() const { return _matrix; }
};
template <typename P>
class Element {
private:
int _id;
int _parent_id;
std::string _name;
std::string _type;
std::string _guid;
Transformation<P> _transformation;
public:
int id() const { return _id; }
int parent_id() const { return _parent_id; }
const std::string& name() const { return _name; }
const std::string& type() const { return _type; }
const std::string& guid() const { return _guid; }
const Transformation<P>& transformation() const { return _transformation; }
Element(const ElementSettings& settings, int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf)
: _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _transformation(settings, trsf)
{}
virtual ~Element() {}
};
template <typename P>
class BRepElement : public Element<P> {
private:
Representation::BRep* _geometry;
public:
const Representation::BRep& geometry() const { return *_geometry; }
BRepElement(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf, Representation::BRep* geometry)
: Element<P>(geometry->settings(),id,parent_id,name,type,guid,trsf)
, _geometry(geometry)
{}
virtual ~BRepElement() {
delete _geometry;
}
private:
BRepElement(const BRepElement& other);
BRepElement& operator=(const BRepElement& other);
};
template <typename P>
class TriangulationElement : public Element<P> {
private:
Representation::Triangulation<P>* _geometry;
public:
const Representation::Triangulation<P>& geometry() const { return *_geometry; }
TriangulationElement(const BRepElement<P>& shape_model)
: Element<P>(shape_model)
, _geometry(new Representation::Triangulation<P>(shape_model.geometry()))
{}
virtual ~TriangulationElement() {
delete _geometry;
}
private:
TriangulationElement(const TriangulationElement& other);
TriangulationElement& operator=(const TriangulationElement& other);
};
template <typename P>
class SerializedElement : public Element<P> {
private:
Representation::Serialization* _geometry;
public:
const Representation::Serialization& geometry() const { return *_geometry; }
SerializedElement(const BRepElement<P>& shape_model)
: Element<P>(shape_model)
, _geometry(new Representation::Serialization(shape_model.geometry()))
{}
virtual ~SerializedElement() {
delete _geometry;
}
private:
SerializedElement(const SerializedElement& other);
SerializedElement& operator=(const SerializedElement& other);
};
}
#endif
+634 -82
View File
@@ -50,23 +50,27 @@
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <Geom_OffsetCurve.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <BRepOffsetAPI_Sewing.hxx>
#include <BRepOffsetAPI_MakeOffset.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeShell.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Face.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepBuilderAPI_MakeShell.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <ShapeFix_Shape.hxx>
@@ -76,14 +80,29 @@
#include <TopLoc_Location.hxx>
#include <BRepGProp_Face.hxx>
#include <Standard_Failure.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#ifdef USE_IFC4
#include <Geom_BSplineSurface.hxx>
#include <TColgp_Array2OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Geom_Plane.hxx>
#include <BRepCheck_Face.hxx>
#endif
#include "../ifcgeom/IfcGeom.h"
bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
Ifc2x3::IfcFaceBound::list bounds = l->Bounds();
Ifc2x3::IfcFaceBound::it it = bounds->begin();
Ifc2x3::IfcLoop::ptr loop = (*it)->Bound();
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) {
IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds();
IfcSchema::IfcFaceBound::list::it it = bounds->begin();
IfcSchema::IfcLoop* loop = (*it)->Bound();
TopoDS_Wire outer_wire;
if ( ! IfcGeom::convert_wire(loop,outer_wire) ) return false;
if ( ! convert_wire(loop,outer_wire) ) return false;
BRepBuilderAPI_MakeFace mf (outer_wire);
BRepBuilderAPI_FaceError er = mf.Error();
if ( er == BRepBuilderAPI_NotPlanar ) {
@@ -94,13 +113,13 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
er = mf.Error();
}
if ( er != BRepBuilderAPI_FaceDone ) return false;
if ( bounds->Size() == 1 ) {
if ( bounds->size() == 1 ) {
face = mf.Face();
} else {
for( ++it; it != bounds->end(); ++ it) {
Ifc2x3::IfcLoop::ptr loop = (*it)->Bound();
IfcSchema::IfcLoop* loop = (*it)->Bound();
TopoDS_Wire wire;
if ( ! IfcGeom::convert_wire(loop,wire) ) return false;
if ( ! convert_wire(loop,wire) ) return false;
mf.Add(wire);
}
if ( mf.IsDone() ) {
@@ -118,14 +137,14 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
}
}
if ( IfcGeom::GetValue(GV_FORCE_CCW_FACE_ORIENTATION)>0 ) {
if ( getValue(GV_FORCE_CCW_FACE_ORIENTATION)>0 ) {
// Check the orientation of the face by comparing the
// normal of the topological surface to the Newell's Method's
// normal. Newell's Method is used for the normal calculation
// as a simple edge cross product can give opposite results
// for a concave face boundary.
// Reference: Graphics Gems III p. 231
BRepGProp_Face prop(face);
BRepGProp_Face prop(TopoDS::Face(face));
gp_Vec normal_direction;
gp_Pnt center;
double u1,u2,v1,v2;
@@ -170,9 +189,12 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
// as the topological face normal the face orientation is
// reversed
gp_Vec face_normal2(x,y,z);
if ( face_normal1.Dot(face_normal2) < 0 ) {
TopAbs_Orientation o = face.Orientation();
face.Orientation(o == TopAbs_FORWARD ? TopAbs_REVERSED : TopAbs_FORWARD);
if (face_normal2.Magnitude() > ALMOST_ZERO) {
if ( face_normal1.Dot(face_normal2) < 0 ) {
TopAbs_Orientation o = face.Orientation();
face.Orientation(o == TopAbs_FORWARD ? TopAbs_REVERSED : TopAbs_FORWARD);
}
}
}
@@ -183,19 +205,25 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
// return face_area(face) > 0.0001;
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcArbitraryClosedProfileDef::ptr l, TopoDS_Face& face) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, TopoDS_Shape& face) {
TopoDS_Wire wire;
if ( ! IfcGeom::convert_wire(l->OuterCurve(),wire) ) return false;
return IfcGeom::convert_wire_to_face(wire,face);
if ( ! convert_wire(l->OuterCurve(),wire) ) return false;
TopoDS_Face f;
bool success = convert_wire_to_face(wire, f);
if (success) face = f;
return success;
}
bool IfcGeom::convert(const Ifc2x3::IfcArbitraryProfileDefWithVoids::ptr l, TopoDS_Face& face) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids* l, TopoDS_Shape& face) {
TopoDS_Wire profile;
if ( ! IfcGeom::convert_wire(l->OuterCurve(),profile) ) return false;
if ( ! convert_wire(l->OuterCurve(),profile) ) return false;
BRepBuilderAPI_MakeFace mf(profile);
Ifc2x3::IfcCurve::list voids = l->InnerCurves();
for( Ifc2x3::IfcCurve::it it = voids->begin(); it != voids->end(); ++ it ) {
IfcSchema::IfcCurve::list::ptr voids = l->InnerCurves();
for( IfcSchema::IfcCurve::list::it it = voids->begin(); it != voids->end(); ++ it ) {
TopoDS_Wire hole;
if ( IfcGeom::convert_wire(*it,hole) ) {
if ( convert_wire(*it,hole) ) {
mf.Add(hole);
}
}
@@ -204,116 +232,424 @@ bool IfcGeom::convert(const Ifc2x3::IfcArbitraryProfileDefWithVoids::ptr l, Topo
face = TopoDS::Face(sfs.Shape());
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcRectangleProfileDef::ptr l, TopoDS_Face& face) {
const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
if ( x == 0.0f || y == 0.0f ) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleProfileDef* l, TopoDS_Shape& face) {
const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT);
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
gp_Trsf2d trsf2d;
IfcGeom::convert(l->Position(),trsf2d);
IfcGeom::Kernel::convert(l->Position(),trsf2d);
double coords[8] = {-x,-y,x,-y,x,y,-x,y};
return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face);
return profile_helper(4,coords,0,0,0,trsf2d,face);
}
bool IfcGeom::convert(const Ifc2x3::IfcIShapeProfileDef::ptr l, TopoDS_Face& face) {
const double x = l->OverallWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double y = l->OverallDepth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double d1 = l->WebThickness() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double d2 = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
bool doFillet = l->hasFilletRadius();
double f;
if ( doFillet ) {
f = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
}
if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, TopoDS_Shape& face) {
const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT);
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
const double r = l->RoundingRadius() * getValue(GV_LENGTH_UNIT);
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || r < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
gp_Trsf2d trsf2d;
IfcGeom::convert(l->Position(),trsf2d);
double coords[24] = {-x,-y,x,-y,x,-y+d2,d1,-y+d2,d1,y-d2,x,y-d2,x,y,-x,y,-x,y-d2,-d1,y-d2,-d1,-y+d2,-x,-y+d2};
int fillets[4] = {3,4,9,10};
double radii[4] = {f,f,f,f};
return IfcGeom::profile_helper(12,coords,doFillet ? 4 : 0,fillets,radii,trsf2d,face);
IfcGeom::Kernel::convert(l->Position(),trsf2d);
double coords[8] = {-x,-y, x,-y, x,y, -x,y};
int fillets[4] = {0,1,2,3};
double radii[4] = {r,r,r,r};
return profile_helper(4,coords,4,fillets,radii,trsf2d,face);
}
bool IfcGeom::convert(const Ifc2x3::IfcCShapeProfileDef::ptr l, TopoDS_Face& face) {
const double x = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double y = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double d1 = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double d2 = l->Girth() * IfcGeom::GetValue(GV_LENGTH_UNIT);
bool doFillet = l->hasInternalFilletRadius();
double f1,f2;
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, TopoDS_Shape& face) {
const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT);
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
const double d = l->WallThickness() * getValue(GV_LENGTH_UNIT);
const bool fr1 = l->OuterFilletRadius() ? true : false;
const bool fr2 = l->InnerFilletRadius() ? true : false;
const double r1 = fr1 ? *l->OuterFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.;
const double r2 = fr2 ? *l->InnerFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.;
if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
TopoDS_Face f1;
TopoDS_Face f2;
gp_Trsf2d trsf2d;
IfcGeom::Kernel::convert(l->Position(),trsf2d);
double coords1[8] = {-x ,-y, x ,-y, x, y, -x, y };
double coords2[8] = {-x+d,-y+d, x-d,-y+d, x-d,y-d, -x+d,y-d};
double radii1[4] = {r1,r1,r1,r1};
double radii2[4] = {r2,r2,r2,r2};
int fillets[4] = {0,1,2,3};
bool s1 = profile_helper(4,coords1,fr1 ? 4 : 0,fillets,radii1,trsf2d,f1);
bool s2 = profile_helper(4,coords2,fr2 ? 4 : 0,fillets,radii2,trsf2d,f2);
if (!s1 || !s2) return false;
TopExp_Explorer exp1(f1, TopAbs_WIRE);
TopExp_Explorer exp2(f2, TopAbs_WIRE);
TopoDS_Wire w1 = TopoDS::Wire(exp1.Current());
TopoDS_Wire w2 = TopoDS::Wire(exp2.Current());
BRepBuilderAPI_MakeFace mf(w1, false);
mf.Add(w2);
ShapeFix_Shape sfs(mf.Face());
sfs.Perform();
face = TopoDS::Face(sfs.Shape());
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrapeziumProfileDef* l, TopoDS_Shape& face) {
const double x1 = l->BottomXDim() / 2.0f * getValue(GV_LENGTH_UNIT);
const double w = l->TopXDim() * getValue(GV_LENGTH_UNIT);
const double dx = l->TopXOffset() * getValue(GV_LENGTH_UNIT);
const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT);
if ( x1 < ALMOST_ZERO || w < ALMOST_ZERO || y < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
gp_Trsf2d trsf2d;
IfcGeom::Kernel::convert(l->Position(),trsf2d);
double coords[8] = {-x1,-y, x1,-y, dx+w-x1,y, dx-x1,y};
return profile_helper(4,coords,0,0,0,trsf2d,face);
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcIShapeProfileDef* l, TopoDS_Shape& face) {
const double x1 = l->OverallWidth() / 2.0f * getValue(GV_LENGTH_UNIT);
const double y = l->OverallDepth() / 2.0f * getValue(GV_LENGTH_UNIT);
const double d1 = l->WebThickness() / 2.0f * getValue(GV_LENGTH_UNIT);
const double dy1 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT);
bool doFillet1 = l->FilletRadius() ? true : false;
double f1 = 0.;
if ( doFillet1 ) {
f1 = *l->FilletRadius() * getValue(GV_LENGTH_UNIT);
}
bool doFillet2 = doFillet1;
double x2 = x1, dy2 = dy1, f2 = f1;
if (l->is(IfcSchema::Type::IfcAsymmetricIShapeProfileDef)) {
IfcSchema::IfcAsymmetricIShapeProfileDef* assym = (IfcSchema::IfcAsymmetricIShapeProfileDef*) l;
x2 = assym->TopFlangeWidth() / 2. * getValue(GV_LENGTH_UNIT);
doFillet2 = assym->TopFlangeFilletRadius() ? true : false;
if (doFillet2) {
f2 = *assym->TopFlangeFilletRadius() * getValue(GV_LENGTH_UNIT);
}
if (assym->TopFlangeThickness()) {
dy2 = *assym->TopFlangeThickness() * getValue(GV_LENGTH_UNIT);
}
}
if ( x1 < ALMOST_ZERO || x2 < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || dy1 < ALMOST_ZERO || dy2 < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
gp_Trsf2d trsf2d;
convert(l->Position(),trsf2d);
double coords[24] = {-x1,-y, x1,-y, x1,-y+dy1, d1,-y+dy1, d1,y-dy2, x2,y-dy2, x2,y, -x2,y, -x2,y-dy2, -d1,y-dy2, -d1,-y+dy1, -x1,-y+dy1};
int fillets[4] = {3,4,9,10};
double radii[4] = {f1,f1,f2,f2};
return profile_helper(12,coords,(doFillet1||doFillet2) ? 4 : 0,fillets,radii,trsf2d,face);
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcZShapeProfileDef* l, TopoDS_Shape& face) {
const double x = l->FlangeWidth() * getValue(GV_LENGTH_UNIT);
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
const double dx = l->WebThickness() / 2.0f * getValue(GV_LENGTH_UNIT);
const double dy = l->FlangeThickness() * getValue(GV_LENGTH_UNIT);
bool doFillet = l->FilletRadius() ? true : false;
bool doEdgeFillet = l->EdgeRadius() ? true : false;
double f1 = 0.;
double f2 = 0.;
if ( doFillet ) {
f1 = l->InternalFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
f1 = *l->FilletRadius() * getValue(GV_LENGTH_UNIT);
}
if ( doEdgeFillet ) {
f2 = *l->EdgeRadius() * getValue(GV_LENGTH_UNIT);
}
if ( x == 0.0f || y == 0.0f || dx == 0.0f || dy == 0.0f ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
gp_Trsf2d trsf2d;
IfcGeom::Kernel::convert(l->Position(),trsf2d);
double coords[16] = {-dx,-y, x,-y, x,-y+dy, dx,-y+dy, dx,y, -x,y, -x,y-dy, -dx,y-dy};
int fillets[4] = {2,3,6,7};
double radii[4] = {f2,f1,f2,f1};
return profile_helper(8,coords,(doFillet || doEdgeFillet) ? 4 : 0,fillets,radii,trsf2d,face);
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCShapeProfileDef* l, TopoDS_Shape& face) {
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
const double x = l->Width() / 2.0f * getValue(GV_LENGTH_UNIT);
const double d1 = l->WallThickness() * getValue(GV_LENGTH_UNIT);
const double d2 = l->Girth() * getValue(GV_LENGTH_UNIT);
bool doFillet = l->InternalFilletRadius() ? true : false;
double f1 = 0;
double f2 = 0;
if ( doFillet ) {
f1 = *l->InternalFilletRadius() * getValue(GV_LENGTH_UNIT);
f2 = f1 + d1;
}
if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) {
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
gp_Trsf2d trsf2d;
IfcGeom::convert(l->Position(),trsf2d);
IfcGeom::Kernel::convert(l->Position(),trsf2d);
double coords[24] = {-x,-y,x,-y,x,-y+d2,x-d1,-y+d2,x-d1,-y+d1,-x+d1,-y+d1,-x+d1,y-d1,x-d1,y-d1,x-d1,y-d2,x,y-d2,x,y,-x,y};
int fillets[8] = {0,1,4,5,6,7,10,11};
double radii[8] = {f2,f2,f1,f1,f1,f1,f2,f2};
return IfcGeom::profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face);
return profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face);
}
bool IfcGeom::convert(const Ifc2x3::IfcLShapeProfileDef::ptr l, TopoDS_Face& face) {
const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double x = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double d = l->Thickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
bool doEdgeFillet = l->hasEdgeRadius();
bool doFillet = l->hasFilletRadius();
bool IfcGeom::Kernel::convert(const IfcSchema::IfcLShapeProfileDef* l, TopoDS_Shape& face) {
const bool hasSlope = l->LegSlope() ? true : false;
const bool doEdgeFillet = l->EdgeRadius() ? true : false;
const bool doFillet = l->FilletRadius() ? true : false;
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
const double x = (l->Width() ? *l->Width() : l->Depth()) / 2.0f * getValue(GV_LENGTH_UNIT);
const double d = l->Thickness() * getValue(GV_LENGTH_UNIT);
const double slope = hasSlope ? (*l->LegSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.;
double f1 = 0.0f;
double f2 = 0.0f;
if (doFillet) {
f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
f1 = *l->FilletRadius() * getValue(GV_LENGTH_UNIT);
}
if ( doEdgeFillet) {
f2 = l->EdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
f2 = *l->EdgeRadius() * getValue(GV_LENGTH_UNIT);
}
if ( x == 0.0f || y == 0.0f || d == 0.0f ) {
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
double xx = -x+d;
double xy = -y+d;
double dy1 = 0.;
double dy2 = 0.;
double dx1 = 0.;
double dx2 = 0.;
if (hasSlope) {
dy1 = tan(slope) * x;
dy2 = tan(slope) * (x - d);
dx1 = tan(slope) * y;
dx2 = tan(slope) * (y - d);
const double x1s = x; const double y1s = -y + d - dy1;
const double x1e = -x + d; const double y1e = -y + d + dy2;
const double x2s = -x + d - dx1; const double y2s = y;
const double x2e = -x + d + dx2; const double y2e = -y + d;
const double a1 = y1e - y1s;
const double b1 = x1s - x1e;
const double c1 = a1*x1s + b1*y1s;
const double a2 = y2e - y2s;
const double b2 = x2s - x2e;
const double c2 = a2*x2s + b2*y2s;
const double det = a1*b2 - a2*b1;
if (ALMOST_THE_SAME(det, 0.)) {
Logger::Message(Logger::LOG_NOTICE, "Legs do not intersect for:",l->entity);
return false;
}
xx = (b2*c1 - b1*c2) / det;
xy = (a1*c2 - a2*c1) / det;
}
gp_Trsf2d trsf2d;
convert(l->Position(),trsf2d);
double coords[12] = {-x,-y, x,-y, x,-y+d-dy1, xx, xy, -x+d-dx1,y, -x,y};
int fillets[3] = {2,3,4};
double radii[3] = {f2,f1,f2};
return profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face);
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcUShapeProfileDef* l, TopoDS_Shape& face) {
const bool doEdgeFillet = l->EdgeRadius() ? true : false;
const bool doFillet = l->FilletRadius() ? true : false;
const bool hasSlope = l->FlangeSlope() ? true : false;
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
const double x = l->FlangeWidth() / 2.0f * getValue(GV_LENGTH_UNIT);
const double d1 = l->WebThickness() * getValue(GV_LENGTH_UNIT);
const double d2 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT);
const double slope = hasSlope ? (*l->FlangeSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.;
double dy1 = 0.0f;
double dy2 = 0.0f;
double f1 = 0.0f;
double f2 = 0.0f;
if (doFillet) {
f1 = *l->FilletRadius() * getValue(GV_LENGTH_UNIT);
}
if (doEdgeFillet) {
f2 = *l->EdgeRadius() * getValue(GV_LENGTH_UNIT);
}
if (hasSlope) {
dy1 = (x - d1) * tan(slope);
dy2 = x * tan(slope);
}
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
gp_Trsf2d trsf2d;
IfcGeom::convert(l->Position(),trsf2d);
convert(l->Position(),trsf2d);
double coords[12] = {-x,-y,x,-y,x,-y+d,-x+d,-y+d,-x+d,y,-x,y};
int fillets[3] = {2,3,4};
double radii[3] = {f2,f1,f2};
return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face);
double coords[16] = {-x,-y, x,-y, x,-y+d2-dy2, -x+d1,-y+d2+dy1, -x+d1,y-d2-dy1, x,y-d2+dy2, x,y, -x,y};
int fillets[4] = {2,3,4,5};
double radii[4] = {f2,f1,f1,f2};
return profile_helper(8, coords, (doFillet || doEdgeFillet) ? 4 : 0, fillets, radii, trsf2d, face);
}
bool IfcGeom::convert(const Ifc2x3::IfcCircleProfileDef::ptr l, TopoDS_Face& face) {
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
bool IfcGeom::Kernel::convert(const IfcSchema::IfcTShapeProfileDef* l, TopoDS_Shape& face) {
const bool doFlangeEdgeFillet = l->FlangeEdgeRadius() ? true : false;
const bool doWebEdgeFillet = l->WebEdgeRadius() ? true : false;
const bool doFillet = l->FilletRadius() ? true : false;
const bool hasFlangeSlope = l->FlangeSlope() ? true : false;
const bool hasWebSlope = l->WebSlope() ? true : false;
const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT);
const double x = l->FlangeWidth() / 2.0f * getValue(GV_LENGTH_UNIT);
const double d1 = l->WebThickness() * getValue(GV_LENGTH_UNIT);
const double d2 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT);
const double flangeSlope = hasFlangeSlope ? (*l->FlangeSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.;
const double webSlope = hasWebSlope ? (*l->WebSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.;
if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
double dy1 = 0.0f;
double dy2 = 0.0f;
double dx1 = 0.0f;
double dx2 = 0.0f;
double f1 = 0.0f;
double f2 = 0.0f;
double f3 = 0.0f;
if (doFillet) {
f1 = *l->FilletRadius() * getValue(GV_LENGTH_UNIT);
}
if (doWebEdgeFillet) {
f2 = *l->WebEdgeRadius() * getValue(GV_LENGTH_UNIT);
}
if (doFlangeEdgeFillet) {
f3 = *l->FlangeEdgeRadius() * getValue(GV_LENGTH_UNIT);
}
double xx, xy;
if (hasFlangeSlope) {
dy1 = (x / 2. - d1) * tan(flangeSlope);
dy2 = x / 2. * tan(flangeSlope);
}
if (hasWebSlope) {
dx1 = (y - d2) * tan(webSlope);
dx2 = y * tan(webSlope);
}
if (hasWebSlope || hasFlangeSlope) {
const double x1s = d1/2. - dx2; const double y1s = -y;
const double x1e = d1/2. + dx1; const double y1e = y - d2;
const double x2s = x; const double y2s = y - d2 + dy2;
const double x2e = d1/2.; const double y2e = y - d2 - dy1;
const double a1 = y1e - y1s;
const double b1 = x1s - x1e;
const double c1 = a1*x1s + b1*y1s;
const double a2 = y2e - y2s;
const double b2 = x2s - x2e;
const double c2 = a2*x2s + b2*y2s;
const double det = a1*b2 - a2*b1;
if (ALMOST_THE_SAME(det, 0.)) {
Logger::Message(Logger::LOG_NOTICE, "Web and flange do not intersect for:",l->entity);
return false;
}
xx = (b2*c1 - b1*c2) / det;
xy = (a1*c2 - a2*c1) / det;
} else {
xx = d1 / 2;
xy = y - d2;
}
gp_Trsf2d trsf2d;
convert(l->Position(),trsf2d);
double coords[16] = {d1/2.-dx2,-y, xx,xy, x,y-d2+dy2, x,y, -x,y, -x,y-d2+dy2, -xx,xy, -d1/2.+dx2,-y};
int fillets[6] = {0,1,2,5,6,7};
double radii[6] = {f2,f1,f3,f3,f1,f2};
return profile_helper(8, coords, (doFillet || doWebEdgeFillet || doFlangeEdgeFillet) ? 6 : 0, fillets, radii, trsf2d, face);
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleProfileDef* l, TopoDS_Shape& face) {
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
if ( r == 0.0f ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
gp_Trsf2d trsf;
IfcGeom::convert(l->Position(),trsf);
convert(l->Position(),trsf);
BRepBuilderAPI_MakeWire w;
gp_Ax2 ax = gp_Ax2().Transformed(trsf);
Handle(Geom_Circle) circle = new Geom_Circle(ax, r);
TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(circle);
w.Add(edge);
return IfcGeom::convert_wire_to_face(w,face);
TopoDS_Face f;
bool success = convert_wire_to_face(w, f);
if (success) face = f;
return success;
}
bool IfcGeom::convert(const Ifc2x3::IfcCircleHollowProfileDef::ptr l, TopoDS_Face& face) {
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
const double t = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, TopoDS_Shape& face) {
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
const double t = l->WallThickness() * getValue(GV_LENGTH_UNIT);
if ( r == 0.0f || t == 0.0f ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
@@ -321,7 +657,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCircleHollowProfileDef::ptr l, TopoDS_Fac
}
gp_Trsf2d trsf;
IfcGeom::convert(l->Position(),trsf);
convert(l->Position(),trsf);
gp_Ax2 ax = gp_Ax2().Transformed(trsf);
BRepBuilderAPI_MakeWire outer;
@@ -338,4 +674,220 @@ bool IfcGeom::convert(const Ifc2x3::IfcCircleHollowProfileDef::ptr l, TopoDS_Fac
sfs.Perform();
face = TopoDS::Face(sfs.Shape());
return true;
}
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcEllipseProfileDef* l, TopoDS_Shape& face) {
double rx = l->SemiAxis1() * getValue(GV_LENGTH_UNIT);
double ry = l->SemiAxis2() * getValue(GV_LENGTH_UNIT);
if ( rx < ALMOST_ZERO || ry < ALMOST_ZERO ) {
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
return false;
}
const bool rotated = ry > rx;
gp_Trsf2d trsf;
convert(l->Position(),trsf);
gp_Ax2 ax = gp_Ax2();
if (rotated) {
ax.Rotate(ax.Axis(), M_PI / 2.);
std::swap(rx, ry);
}
ax.Transform(trsf);
BRepBuilderAPI_MakeWire w;
Handle(Geom_Ellipse) ellipse = new Geom_Ellipse(ax, rx, ry);
TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(ellipse);
w.Add(edge);
TopoDS_Face f;
bool success = convert_wire_to_face(w, f);
if (success) face = f;
return success;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCenterLineProfileDef* l, TopoDS_Shape& face) {
const double d = l->Thickness() * getValue(GV_LENGTH_UNIT) / 2.;
TopoDS_Wire wire;
if (!convert_wire(l->Curve(), wire)) return false;
// BRepOffsetAPI_MakeOffset insists on creating circular arc
// segments for joining the curves that constitute the center
// line. This is probably not in accordance with the IFC spec.
// Although it does not specify a method to join segments
// explicitly, it does dictate 'a constant thickness along the
// curve'. Therefore for simple singular wires a quick
// alternative is provided that uses a straight join.
TopExp_Explorer exp(wire, TopAbs_EDGE);
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
exp.Next();
if (!exp.More()) {
double u1, u2;
Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, u1, u2);
Handle(Geom_TrimmedCurve) trim = new Geom_TrimmedCurve(curve, u1, u2);
Handle(Geom_OffsetCurve) c1 = new Geom_OffsetCurve(trim, d, gp::DZ());
Handle(Geom_OffsetCurve) c2 = new Geom_OffsetCurve(trim, -d, gp::DZ());
gp_Pnt c1a, c1b, c2a, c2b;
c1->D0(c1->FirstParameter(), c1a);
c1->D0(c1->LastParameter(), c1b);
c2->D0(c2->FirstParameter(), c2a);
c2->D0(c2->LastParameter(), c2b);
BRepBuilderAPI_MakeWire mw;
mw.Add(BRepBuilderAPI_MakeEdge(c1));
mw.Add(BRepBuilderAPI_MakeEdge(c1a, c2a));
mw.Add(BRepBuilderAPI_MakeEdge(c2));
mw.Add(BRepBuilderAPI_MakeEdge(c2b, c1b));
face = BRepBuilderAPI_MakeFace(mw.Wire());
} else {
BRepOffsetAPI_MakeOffset offset(BRepBuilderAPI_MakeFace(gp_Pln(gp::Origin(), gp::DZ())));
offset.AddWire(wire);
offset.Perform(d);
face = BRepBuilderAPI_MakeFace(TopoDS::Wire(offset));
}
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeProfileDef* l, TopoDS_Shape& face) {
// BRepBuilderAPI_MakeFace mf;
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
IfcSchema::IfcProfileDef::list::ptr profiles = l->Profiles();
bool first = true;
for (IfcSchema::IfcProfileDef::list::it it = profiles->begin(); it != profiles->end(); ++it) {
TopoDS_Face f;
if (convert_face(*it, f)) {
builder.Add(compound, f);
/* TopExp_Explorer exp(f, TopAbs_WIRE);
for (; exp.More(); exp.Next()) {
const TopoDS_Wire& wire = TopoDS::Wire(exp.Current());
if (first) {
mf.Init(BRepBuilderAPI_MakeFace(wire));
} else {
mf.Add(wire);
}
first = false;
} */
}
}
face = compound;
return !face.IsNull();
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcDerivedProfileDef* l, TopoDS_Shape& face) {
TopoDS_Face f;
gp_Trsf2d trsf2d;
if (convert_face(l->ParentProfile(), f) && IfcGeom::Kernel::convert(l->Operator(), trsf2d)) {
gp_Trsf trsf = trsf2d;
face = TopoDS::Face(BRepBuilderAPI_Transform(f, trsf));
return true;
} else {
return false;
}
}
#ifdef USE_IFC4
bool convert_surf(IfcSchema::IfcBSplineSurfaceWithKnots* l, Handle_Geom_Surface& surf) {
SHARED_PTR< IfcTemplatedEntityListList<IfcSchema::IfcCartesianPoint> > cps = l->ControlPointsList();
std::vector<double> uknots = l->UKnots();
std::vector<double> vknots = l->VKnots();
std::vector<int> umults = l->UMultiplicities();
std::vector<int> vmults = l->VMultiplicities();
TColgp_Array2OfPnt Poles (0, cps->size() - 1, 0, (*cps->begin()).size() - 1);
TColStd_Array1OfReal UKnots(0, uknots.size() - 1);
TColStd_Array1OfReal VKnots(0, vknots.size() - 1);
TColStd_Array1OfInteger UMults(0, umults.size() - 1);
TColStd_Array1OfInteger VMults(0, vmults.size() - 1);
Standard_Integer UDegree = l->UDegree();
Standard_Integer VDegree = l->VDegree();
int i = 0, j;
for (IfcTemplatedEntityListList<IfcSchema::IfcCartesianPoint>::outer_it it = cps->begin(); it != cps->end(); ++it, ++i) {
j = 0;
for (IfcTemplatedEntityListList<IfcSchema::IfcCartesianPoint>::inner_it jt = (*it).begin(); jt != (*it).end(); ++jt, ++j) {
IfcSchema::IfcCartesianPoint* p = *jt;
gp_Pnt pnt;
if (!convert(p, pnt)) return false;
Poles(i, j) = pnt;
}
}
i = 0;
for (std::vector<double>::const_iterator it = uknots.begin(); it != uknots.end(); ++it, ++i) {
UKnots(i) = *it;
}
i = 0;
for (std::vector<double>::const_iterator it = vknots.begin(); it != vknots.end(); ++it, ++i) {
VKnots(i) = *it;
}
i = 0;
for (std::vector<int>::const_iterator it = umults.begin(); it != umults.end(); ++it, ++i) {
UMults(i) = *it;
}
i = 0;
for (std::vector<int>::const_iterator it = vmults.begin(); it != vmults.end(); ++it, ++i) {
VMults(i) = *it;
}
surf = new Geom_BSplineSurface(Poles, UKnots, VKnots, UMults, VMults, UDegree, VDegree);
return true;
}
bool convert_surf(IfcSchema::IfcPlane* l, Handle_Geom_Surface& surf) {
gp_Pln pln;
convert(l, pln);
surf = new Geom_Plane(pln);
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcAdvancedFace* l, TopoDS_Shape& face) {
IfcSchema::IfcSurface* s = l->FaceSurface();
Handle_Geom_Surface surf(0);
if (s->is(IfcSchema::Type::IfcBSplineSurfaceWithKnots)) {
convert_surf((IfcSchema::IfcBSplineSurfaceWithKnots*)s, surf);
} else if (s->is(IfcSchema::Type::IfcPlane)) {
convert_surf((IfcSchema::IfcPlane*)s, surf);
} else {
return false;
}
BRepBuilderAPI_MakeFace mf(surf, Precision::Confusion());
IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds();
for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
IfcSchema::IfcLoop* loop = (*it)->Bound();
TopoDS_Wire outer_wire;
if (!convert_wire(loop, outer_wire)) return false;
TopoDS_Face temp = BRepBuilderAPI_MakeFace(surf, outer_wire);
if (BRepCheck_Face(temp).OrientationOfWires() == BRepCheck_BadOrientationOfSubshape) {
outer_wire.Reverse();
ShapeFix_Face fix(BRepBuilderAPI_MakeFace(surf, outer_wire).Face());
fix.FixOrientation();
fix.Perform();
TopoDS_Face temp = fix.Face();
TopExp_Explorer exp(temp, TopAbs_WIRE);
outer_wire = TopoDS::Wire(exp.Current());
}
mf.Add(outer_wire);
}
face = mf.Face();
return true;
}
#endif
+589 -101
View File
@@ -23,7 +23,9 @@
* *
********************************************************************************/
#include <set>
#include <cassert>
#include <algorithm>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
@@ -68,6 +70,7 @@
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <ShapeFix_Shape.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
@@ -86,19 +89,25 @@
#include <BRepGProp_Face.hxx>
#include <BRepMesh.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepTools.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <TopExp.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include "../ifcparse/IfcSIPrefix.h"
#include "../ifcgeom/IfcGeom.h"
bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
BRepOffsetAPI_Sewing builder;
builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMaxTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMinTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
TopExp_Explorer exp(compound,TopAbs_FACE);
if ( ! exp.More() ) return false;
for ( ; exp.More(); exp.Next() ) {
@@ -109,13 +118,13 @@ bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Sh
shape = builder.SewedShape();
try {
ShapeFix_Solid sf_solid;
sf_solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
sf_solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
shape = sf_solid.SolidFromShell(TopoDS::Shell(shape));
} catch(...) {}
return true;
}
bool IfcGeom::is_compound(const TopoDS_Shape& shape) {
bool IfcGeom::Kernel::is_compound(const TopoDS_Shape& shape) {
bool has_solids = TopExp_Explorer(shape,TopAbs_SOLID).More() != 0;
bool has_shells = TopExp_Explorer(shape,TopAbs_SHELL).More() != 0;
bool has_compounds = TopExp_Explorer(shape,TopAbs_COMPOUND).More() != 0;
@@ -123,49 +132,59 @@ bool IfcGeom::is_compound(const TopoDS_Shape& shape) {
return has_compounds && has_faces && !has_solids && !has_shells;
}
const TopoDS_Shape& IfcGeom::ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid) {
const bool is_comp = IfcGeom::is_compound(shape);
const TopoDS_Shape& IfcGeom::Kernel::ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid) {
const bool is_comp = is_compound(shape);
if ( ! is_comp ) return shape;
IfcGeom::create_solid_from_compound(shape,solid);
create_solid_from_compound(shape, solid);
// If the SEW_SHELLS option had been set this precision had been applied
// at the end of the generic convert_shape() call.
const double precision = getValue(GV_PRECISION);
apply_tolerance(solid, precision);
return solid;
}
bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings,
const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes) {
bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
// Iterate over IfcOpeningElements
IfcGeom::IfcRepresentationShapeItems opening_shapes;
unsigned int last_size = 0;
for ( Ifc2x3::IfcRelVoidsElement::it it = openings->begin(); it != openings->end(); ++ it ) {
Ifc2x3::IfcRelVoidsElement::ptr v = *it;
Ifc2x3::IfcFeatureElementSubtraction::ptr fes = v->RelatedOpeningElement();
if ( fes->is(Ifc2x3::Type::IfcOpeningElement) ) {
for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) {
IfcSchema::IfcRelVoidsElement* v = *it;
IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement();
if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) {
// Convert the IfcRepresentation of the IfcOpeningElement
gp_Trsf opening_trsf;
IfcGeom::convert(fes->ObjectPlacement(),opening_trsf);
if (fes->ObjectPlacement()) {
IfcGeom::Kernel::convert(*fes->ObjectPlacement(),opening_trsf);
}
// Move the opening into the coordinate system of the IfcProduct
opening_trsf.PreMultiply(entity_trsf.Inverted());
Ifc2x3::IfcProductRepresentation::ptr prodrep = fes->Representation();
Ifc2x3::IfcRepresentation::list reps = prodrep->Representations();
if (fes->Representation()) {
IfcSchema::IfcProductRepresentation* prodrep = *fes->Representation();
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
for ( Ifc2x3::IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
IfcGeom::convert_shapes(*it2,opening_shapes);
}
for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
convert_shapes(*it2,opening_shapes);
}
const unsigned int current_size = (const unsigned int) opening_shapes.size();
for ( unsigned int i = last_size; i < current_size; ++ i ) {
opening_shapes[i].prepend(opening_trsf);
const unsigned int current_size = (const unsigned int) opening_shapes.size();
for ( unsigned int i = last_size; i < current_size; ++ i ) {
opening_shapes[i].prepend(opening_trsf);
}
last_size = current_size;
}
last_size = current_size;
}
}
// Iterate over the shapes of the IfcProduct
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
TopoDS_Shape entity_shape_solid;
const TopoDS_Shape& entity_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
const gp_GTrsf& entity_shape_gtrsf = it3->Placement();
TopoDS_Shape entity_shape;
if ( entity_shape_gtrsf.Form() == gp_Other ) {
@@ -178,7 +197,7 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
// Iterate over the shapes of the IfcOpeningElements
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) {
TopoDS_Shape opening_shape_solid;
const TopoDS_Shape& opening_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(it4->Shape(),opening_shape_solid);
const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(it4->Shape(),opening_shape_solid);
const gp_GTrsf& opening_shape_gtrsf = it4->Placement();
if ( opening_shape_gtrsf.Form() == gp_Other ) {
Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to opening of:",entity->entity);
@@ -194,27 +213,65 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
Logger::Message(Logger::LOG_WARNING,"Empty opening for:",entity->entity);
original_shape_volume = shape_volume(entity_shape);
}
BRepAlgoAPI_Cut brep_cut(entity_shape,opening_shape);
if ( brep_cut.IsDone() ) {
TopoDS_Shape brep_cut_result = brep_cut;
if (entity_shape.ShapeType() == TopAbs_COMPSOLID) {
// For compound solids process the subtraction for the constituent
// solids individually and write the result back as a compound solid.
TopoDS_CompSolid compound;
BRep_Builder builder;
builder.MakeCompSolid(compound);
TopExp_Explorer exp(entity_shape, TopAbs_SOLID);
for (; exp.More(); exp.Next()) {
BRepAlgoAPI_Cut brep_cut(exp.Current(), opening_shape);
bool added = false;
if ( brep_cut.IsDone() ) {
TopoDS_Shape brep_cut_result = brep_cut;
BRepCheck_Analyzer analyser(brep_cut_result);
bool is_valid = analyser.IsValid() != 0;
if (is_valid) {
TopExp_Explorer exp(brep_cut_result, TopAbs_SOLID);
for (; exp.More(); exp.Next()) {
builder.Add(compound, exp.Current());
added = true;
}
}
}
if (!added) {
// Add the original in case subtraction fails
builder.Add(compound, exp.Current());
} else {
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",entity->entity);
}
}
entity_shape = compound;
} else {
BRepAlgoAPI_Cut brep_cut(entity_shape,opening_shape);
if ( brep_cut.IsDone() ) {
TopoDS_Shape brep_cut_result = brep_cut;
BRepCheck_Analyzer analyser(brep_cut_result);
bool is_valid = analyser.IsValid() != 0;
if ( is_valid ) {
entity_shape = brep_cut;
if ( Logger::Verbosity() >= Logger::LOG_WARNING ) {
const double volume_after_subtraction = shape_volume(entity_shape);
BRepCheck_Analyzer analyser(brep_cut_result);
bool is_valid = analyser.IsValid() != 0;
if ( is_valid ) {
entity_shape = brep_cut;
if ( Logger::Verbosity() >= Logger::LOG_WARNING ) {
const double volume_after_subtraction = shape_volume(entity_shape);
if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) )
Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",entity->entity);
if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) )
Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",entity->entity);
}
} else {
Logger::Message(Logger::LOG_ERROR,"Invalid result from subtraction:",entity->entity);
}
} else {
Logger::Message(Logger::LOG_ERROR,"Invalid result from subtraction:",entity->entity);
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",entity->entity);
}
} else {
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",entity->entity);
}
}
@@ -224,42 +281,46 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
return true;
}
bool IfcGeom::convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings,
const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes) {
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
// Create a compound of all opening shapes in order to speed up the boolean operations
TopoDS_Compound opening_compound;
BRep_Builder builder;
builder.MakeCompound(opening_compound);
for ( Ifc2x3::IfcRelVoidsElement::it it = openings->begin(); it != openings->end(); ++ it ) {
Ifc2x3::IfcRelVoidsElement::ptr v = *it;
Ifc2x3::IfcFeatureElementSubtraction::ptr fes = v->RelatedOpeningElement();
if ( fes->is(Ifc2x3::Type::IfcOpeningElement) ) {
for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) {
IfcSchema::IfcRelVoidsElement* v = *it;
IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement();
if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) {
// Convert the IfcRepresentation of the IfcOpeningElement
gp_Trsf opening_trsf;
IfcGeom::convert(fes->ObjectPlacement(),opening_trsf);
if (fes->ObjectPlacement()) {
IfcGeom::Kernel::convert(*fes->ObjectPlacement(),opening_trsf);
}
// Move the opening into the coordinate system of the IfcProduct
opening_trsf.PreMultiply(entity_trsf.Inverted());
Ifc2x3::IfcProductRepresentation::ptr prodrep = fes->Representation();
Ifc2x3::IfcRepresentation::list reps = prodrep->Representations();
if (fes->Representation()) {
IfcSchema::IfcProductRepresentation* prodrep = *fes->Representation();
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
IfcGeom::IfcRepresentationShapeItems opening_shapes;
IfcGeom::IfcRepresentationShapeItems opening_shapes;
for ( Ifc2x3::IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
IfcGeom::convert_shapes(*it2,opening_shapes);
}
for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
convert_shapes(*it2,opening_shapes);
}
for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) {
gp_GTrsf gtrsf = opening_shapes[i].Placement();
gtrsf.PreMultiply(opening_trsf);
const TopoDS_Shape& opening_shape = gtrsf.Form() == gp_Other
? BRepBuilderAPI_GTransform(opening_shapes[i].Shape(),gtrsf,true).Shape()
: (opening_shapes[i].Shape()).Moved(gtrsf.Trsf());
builder.Add(opening_compound,opening_shape);
for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) {
gp_GTrsf gtrsf = opening_shapes[i].Placement();
gtrsf.PreMultiply(opening_trsf);
const TopoDS_Shape& opening_shape = gtrsf.Form() == gp_Other
? BRepBuilderAPI_GTransform(opening_shapes[i].Shape(),gtrsf,true).Shape()
: (opening_shapes[i].Shape()).Moved(gtrsf.Trsf());
builder.Add(opening_compound,opening_shape);
}
}
}
@@ -268,7 +329,7 @@ bool IfcGeom::convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const
// Iterate over the shapes of the IfcProduct
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
TopoDS_Shape entity_shape_solid;
const TopoDS_Shape& entity_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
const gp_GTrsf& entity_shape_gtrsf = it3->Placement();
TopoDS_Shape entity_shape;
if ( entity_shape_gtrsf.Form() == gp_Other ) {
@@ -301,7 +362,7 @@ bool IfcGeom::convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const
return true;
}
bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) {
bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) {
BRepBuilderAPI_MakeFace mf(wire, false);
BRepBuilderAPI_FaceError er = mf.Error();
if ( er == BRepBuilderAPI_NotPlanar ) {
@@ -315,7 +376,13 @@ bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) {
face = mf.Face();
return true;
}
bool IfcGeom::profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face) {
bool IfcGeom::Kernel::convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire) {
wire = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(curve));
return true;
}
bool IfcGeom::Kernel::profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Shape& face_shape) {
TopoDS_Vertex* vertices = new TopoDS_Vertex[numVerts];
for ( int i = 0; i < numVerts; i ++ ) {
@@ -328,33 +395,40 @@ bool IfcGeom::profile_helper(int numVerts, double* verts, int numFillets, int* f
for ( int i = 0; i < numVerts; i ++ )
w.Add(BRepBuilderAPI_MakeEdge(vertices[i],vertices[(i+1)%numVerts]));
IfcGeom::convert_wire_to_face(w.Wire(),face);
TopoDS_Face face;
convert_wire_to_face(w.Wire(),face);
if ( numFillets ) {
if ( numFillets && *std::max_element(filletRadii, filletRadii + numFillets) > ALMOST_ZERO ) {
BRepFilletAPI_MakeFillet2d fillet (face);
for ( int i = 0; i < numFillets; i ++ ) {
const double radius = filletRadii[i];
if ( radius < 1e-7 ) continue;
if ( radius <= ALMOST_ZERO ) continue;
fillet.AddFillet(vertices[filletIndices[i]],radius);
}
fillet.Build();
face = TopoDS::Face(fillet.Shape());
if (fillet.IsDone()) {
face = TopoDS::Face(fillet.Shape());
} else {
Logger::Message(Logger::LOG_WARNING, "Failed to process profile fillets");
}
}
face_shape = face;
delete[] vertices;
return true;
}
double IfcGeom::shape_volume(const TopoDS_Shape& s) {
double IfcGeom::Kernel::shape_volume(const TopoDS_Shape& s) {
GProp_GProps prop;
BRepGProp::VolumeProperties(s, prop);
return prop.Mass();
}
double IfcGeom::face_area(const TopoDS_Face& f) {
double IfcGeom::Kernel::face_area(const TopoDS_Face& f) {
GProp_GProps prop;
BRepGProp::SurfaceProperties(f,prop);
return prop.Mass();
}
bool IfcGeom::is_convex(const TopoDS_Wire& wire) {
bool IfcGeom::Kernel::is_convex(const TopoDS_Wire& wire) {
for ( TopExp_Explorer exp1(wire,TopAbs_VERTEX); exp1.More(); exp1.Next() ) {
TopoDS_Vertex V1 = TopoDS::Vertex(exp1.Current());
gp_Pnt P1 = BRep_Tool::Pnt(V1);
@@ -369,8 +443,8 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) {
edge_points.push_back(P2);
}
if ( edge_points.size() != 2 ) continue;
if ( edge_points[0].IsEqual(P1,GetValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[1]);
else if ( edge_points[1].IsEqual(P1, GetValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[0]);
if ( edge_points[0].IsEqual(P1,getValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[1]);
else if ( edge_points[1].IsEqual(P1, getValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[0]);
}
// There should be two of these
if ( neighbors.size() != 2 ) return false;
@@ -379,10 +453,10 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) {
for ( TopExp_Explorer exp2(wire,TopAbs_VERTEX); exp2.More(); exp2.Next() ) {
TopoDS_Vertex V2 = TopoDS::Vertex(exp2.Current());
gp_Pnt P2 = BRep_Tool::Pnt(V2);
if ( P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) continue;
if ( P1.IsEqual(P2,getValue(GV_POINT_EQUALITY_TOLERANCE)) ) continue;
bool found = false;
for( std::vector<gp_Pnt>::const_iterator it = neighbors.begin(); it != neighbors.end(); ++ it ) {
if ( (*it).IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) { found = true; break; }
if ( (*it).IsEqual(P2,getValue(GV_POINT_EQUALITY_TOLERANCE)) ) { found = true; break; }
}
if ( ! found ) non_neighbors.push_back(P2);
}
@@ -400,11 +474,11 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) {
}
return true;
}
TopoDS_Shape IfcGeom::halfspace_from_plane(const gp_Pln& pln,const gp_Pnt& cent) {
TopoDS_Shape IfcGeom::Kernel::halfspace_from_plane(const gp_Pln& pln,const gp_Pnt& cent) {
TopoDS_Face face = BRepBuilderAPI_MakeFace(pln).Face();
return BRepPrimAPI_MakeHalfSpace(face,cent).Solid();
}
gp_Pln IfcGeom::plane_from_face(const TopoDS_Face& face) {
gp_Pln IfcGeom::Kernel::plane_from_face(const TopoDS_Face& face) {
BRepGProp_Face prop(face);
Standard_Real u1,u2,v1,v2;
prop.Bounds(u1,u2,v1,v2);
@@ -415,7 +489,7 @@ gp_Pln IfcGeom::plane_from_face(const TopoDS_Face& face) {
prop.Normal(u,v,p,n);
return gp_Pln(p,n);
}
gp_Pnt IfcGeom::point_above_plane(const gp_Pln& pln, bool agree) {
gp_Pnt IfcGeom::Kernel::point_above_plane(const gp_Pln& pln, bool agree) {
if ( agree ) {
return pln.Location().Translated(pln.Axis().Direction());
} else {
@@ -423,7 +497,7 @@ gp_Pnt IfcGeom::point_above_plane(const gp_Pln& pln, bool agree) {
}
}
void IfcGeom::apply_tolerance(TopoDS_Shape& s, double t) {
void IfcGeom::Kernel::apply_tolerance(TopoDS_Shape& s, double t) {
ShapeFix_ShapeTolerance tol;
tol.SetTolerance(s, t);
}
@@ -438,7 +512,7 @@ static double ifc_planeangle_unit = -1.0;
static double force_ccw_face_orientation = -1.0;
static double modelling_precision = 0.00001;
void IfcGeom::SetValue(GeomValue var, double value) {
void IfcGeom::Kernel::setValue(GeomValue var, double value) {
switch (var) {
case GV_DEFLECTION_TOLERANCE:
deflection_tolerance = value;
@@ -472,7 +546,7 @@ void IfcGeom::SetValue(GeomValue var, double value) {
}
}
double IfcGeom::GetValue(GeomValue var) {
double IfcGeom::Kernel::getValue(GeomValue var) {
switch (var) {
case GV_DEFLECTION_TOLERANCE:
return deflection_tolerance;
@@ -501,10 +575,10 @@ double IfcGeom::GetValue(GeomValue var) {
return 0;
}
Ifc2x3::IfcProductDefinitionShape* IfcGeom::tesselate(TopoDS_Shape& shape, double deflection, IfcEntities es) {
BRepMesh::Mesh(shape, deflection);
IfcSchema::IfcProductDefinitionShape* IfcGeom::tesselate(TopoDS_Shape& shape, double deflection, IfcEntityList::ptr es) {
BRepMesh_IncrementalMesh(shape, deflection);
Ifc2x3::IfcFace::list faces (new IfcTemplatedEntityList<Ifc2x3::IfcFace>());
IfcSchema::IfcFace::list::ptr faces (new IfcSchema::IfcFace::list);
for (TopExp_Explorer exp(shape, TopAbs_FACE); exp.More(); exp.Next()) {
const TopoDS_Face& face = TopoDS::Face(exp.Current());
@@ -513,11 +587,11 @@ Ifc2x3::IfcProductDefinitionShape* IfcGeom::tesselate(TopoDS_Shape& shape, doubl
if (! tri.IsNull()) {
const TColgp_Array1OfPnt& nodes = tri->Nodes();
std::vector<Ifc2x3::IfcCartesianPoint*> vertices;
std::vector<IfcSchema::IfcCartesianPoint*> vertices;
for (int i = 1; i <= nodes.Length(); ++i) {
const gp_Pnt& pnt = nodes(i);
gp_Pnt pnt = nodes(i).Transformed(loc);
std::vector<double> xyz; xyz.push_back(pnt.X()); xyz.push_back(pnt.Y()); xyz.push_back(pnt.Z());
Ifc2x3::IfcCartesianPoint* cpnt = new Ifc2x3::IfcCartesianPoint(xyz);
IfcSchema::IfcCartesianPoint* cpnt = new IfcSchema::IfcCartesianPoint(xyz);
vertices.push_back(cpnt);
es->push(cpnt);
}
@@ -525,15 +599,15 @@ Ifc2x3::IfcProductDefinitionShape* IfcGeom::tesselate(TopoDS_Shape& shape, doubl
for (int i = 1; i <= triangles.Length(); ++ i) {
int n1, n2, n3;
triangles(i).Get(n1, n2, n3);
Ifc2x3::IfcCartesianPoint::list points (new IfcTemplatedEntityList<Ifc2x3::IfcCartesianPoint>());
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
points->push(vertices[n1-1]);
points->push(vertices[n2-1]);
points->push(vertices[n3-1]);
Ifc2x3::IfcPolyLoop* loop = new Ifc2x3::IfcPolyLoop(points);
Ifc2x3::IfcFaceOuterBound* bound = new Ifc2x3::IfcFaceOuterBound(loop, face.Orientation() != TopAbs_REVERSED);
Ifc2x3::IfcFaceBound::list bounds (new IfcTemplatedEntityList<Ifc2x3::IfcFaceBound>());
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, face.Orientation() != TopAbs_REVERSED);
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
bounds->push(bound);
Ifc2x3::IfcFace* face = new Ifc2x3::IfcFace(bounds);
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
es->push(loop);
es->push(bound);
es->push(face);
@@ -541,21 +615,21 @@ Ifc2x3::IfcProductDefinitionShape* IfcGeom::tesselate(TopoDS_Shape& shape, doubl
}
}
}
Ifc2x3::IfcOpenShell* shell = new Ifc2x3::IfcOpenShell(faces);
Ifc2x3::IfcConnectedFaceSet::list shells (new IfcTemplatedEntityList<Ifc2x3::IfcConnectedFaceSet>());
IfcSchema::IfcOpenShell* shell = new IfcSchema::IfcOpenShell(faces);
IfcSchema::IfcConnectedFaceSet::list::ptr shells (new IfcSchema::IfcConnectedFaceSet::list);
shells->push(shell);
Ifc2x3::IfcFaceBasedSurfaceModel* surface_model = new Ifc2x3::IfcFaceBasedSurfaceModel(shells);
IfcSchema::IfcFaceBasedSurfaceModel* surface_model = new IfcSchema::IfcFaceBasedSurfaceModel(shells);
Ifc2x3::IfcRepresentation::list reps (new IfcTemplatedEntityList<Ifc2x3::IfcRepresentation>());
Ifc2x3::IfcRepresentationItem::list items (new IfcTemplatedEntityList<Ifc2x3::IfcRepresentationItem>());
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);
items->push(surface_model);
Ifc2x3::IfcShapeRepresentation* rep = new Ifc2x3::IfcShapeRepresentation(
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
0, std::string("Facetation"), std::string("SurfaceModel"), items);
reps->push(rep);
Ifc2x3::IfcProductDefinitionShape* shapedef = new Ifc2x3::IfcProductDefinitionShape(0, 0, reps);
IfcSchema::IfcProductDefinitionShape* shapedef = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
es->push(shell);
es->push(surface_model);
@@ -563,4 +637,418 @@ Ifc2x3::IfcProductDefinitionShape* IfcGeom::tesselate(TopoDS_Shape& shape, doubl
es->push(shapedef);
return shapedef;
}
// Returns the vertex part of an TopoDS_Edge edge that is not TopoDS_Vertex vertex
TopoDS_Vertex find_other(const TopoDS_Edge& edge, const TopoDS_Vertex& vertex) {
TopExp_Explorer exp(edge, TopAbs_VERTEX);
while (exp.More()) {
if (!exp.Current().IsSame(vertex)) {
return TopoDS::Vertex(exp.Current());
}
exp.Next();
}
return TopoDS_Vertex();
}
TopoDS_Edge find_next(const TopTools_IndexedMapOfShape& edge_set, const TopTools_IndexedDataMapOfShapeListOfShape& vertex_to_edges, const TopoDS_Vertex& current, const TopoDS_Edge& previous_edge) {
const TopTools_ListOfShape& edges = vertex_to_edges.FindFromKey(current);
TopTools_ListIteratorOfListOfShape eit;
for (eit.Initialize(edges); eit.More(); eit.Next()) {
const TopoDS_Edge& edge = TopoDS::Edge(eit.Value());
if (edge.IsSame(previous_edge)) continue;
if (edge_set.Contains(edge)) {
return edge;
}
}
return TopoDS_Edge();
}
bool IfcGeom::Kernel::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) {
BRepOffsetAPI_Sewing sew;
sew.Add(shape);
TopTools_IndexedDataMapOfShapeListOfShape edge_to_faces;
TopTools_IndexedDataMapOfShapeListOfShape vertex_to_edges;
std::set<int> visited;
TopTools_IndexedMapOfShape edge_set;
TopExp::MapShapesAndAncestors (shape, TopAbs_EDGE, TopAbs_FACE, edge_to_faces);
const int num_edges = edge_to_faces.Extent();
for (int i = 1; i <= num_edges; ++i) {
const TopTools_ListOfShape& faces = edge_to_faces.FindFromIndex(i);
const int count = faces.Extent();
// Find only the non-manifold edges: Edges that are only part of a
// single face and therefore part of the wire(s) we want to fill.
if (count == 1) {
const TopoDS_Shape& edge = edge_to_faces.FindKey(i);
TopExp::MapShapesAndAncestors (edge, TopAbs_VERTEX, TopAbs_EDGE, vertex_to_edges);
edge_set.Add(edge);
}
}
const int num_verts = vertex_to_edges.Extent();
TopoDS_Vertex first, current;
TopoDS_Edge previous_edge;
// Now loop over all the vertices that are part of the wire(s) to be filled
for (int i = 1; i <= num_verts; ++i) {
first = current = TopoDS::Vertex(vertex_to_edges.FindKey(i));
const bool isSame = first.IsSame(current);
// We keep track of the vertices we already used
if (visited.find(vertex_to_edges.FindIndex(current)) != visited.end()) {
continue;
}
// Given these vertices, try to find closed loops and create new
// wires out of them.
BRepBuilderAPI_MakeWire w;
while (true) {
visited.insert(vertex_to_edges.FindIndex(current));
// Find the edge that the current vertex is part of and points
// away from the previous vertex (null for the first vertex).
TopoDS_Edge edge = find_next(edge_set, vertex_to_edges, current, previous_edge);
if (edge.IsNull()) {
return false;
}
TopoDS_Vertex other = find_other(edge, current);
if (other.IsNull()) {
// Dealing with a conical edge probably, for some reason
// this works better than adding the edge directly.
double u1, u2;
Handle(Geom_Curve) crv = BRep_Tool::Curve(edge, u1, u2);
w.Add(BRepBuilderAPI_MakeEdge(crv, u1, u2));
break;
} else {
w.Add(edge);
}
// See if the starting point of this loop has been reached. Note that
// additional wires after this one potentially will be created.
if (other.IsSame(first)) {
break;
}
previous_edge = edge;
current = other;
}
sew.Add(BRepBuilderAPI_MakeFace(w));
previous_edge.Nullify();
}
sew.Perform();
shape = sew.SewedShape();
try {
ShapeFix_Solid solid;
solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
shape = solid.SolidFromShell(TopoDS::Shell(shape));
} catch(...) {}
return true;
}
bool IfcGeom::Kernel::flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse) {
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
result = TopoDS_Shape();
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
TopoDS_Shape merged;
const TopoDS_Shape& s = it->Shape();
if (fuse) {
ensure_fit_for_subtraction(s, merged);
} else {
merged = s;
}
const gp_GTrsf& trsf = it->Placement();
bool trsf_valid = false;
gp_Trsf _trsf;
try {
_trsf = trsf.Trsf();
trsf_valid = true;
} catch (...) {}
const TopoDS_Shape moved_shape = trsf_valid ? merged.Moved(_trsf) :
BRepBuilderAPI_GTransform(merged,trsf,true).Shape();
if (shapes.size() == 1) {
result = moved_shape;
const double precision = getValue(GV_PRECISION);
apply_tolerance(result, precision);
return true;
}
if (fuse) {
if (result.IsNull()) {
result = moved_shape;
} else {
BRepAlgoAPI_Fuse brep_fuse(result, moved_shape);
if ( brep_fuse.IsDone() ) {
TopoDS_Shape fused = brep_fuse;
ShapeFix_Shape fix(result);
fix.Perform();
result = fix.Shape();
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
if ( is_valid ) {
result = fused;
}
}
}
} else {
builder.Add(compound,moved_shape);
}
}
const bool success = !result.IsNull();
if (success) {
const double precision = getValue(GV_PRECISION);
apply_tolerance(result, precision);
}
return success;
}
void IfcGeom::Kernel::remove_redundant_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol) {
if (tol <= 0.) tol = getValue(GV_POINT_EQUALITY_TOLERANCE);
tol *= tol;
while (true) {
bool removed = false;
int n = polygon.Length() - (closed ? 0 : 1);
for (int i = 1; i <= n; ++i) {
// wrap around to the first point in case of a closed loop
int j = (i % polygon.Length()) + 1;
double dist = polygon.Value(i).SquareDistance(polygon.Value(j));
if (dist < tol) {
// do not remove the first or last point to
// maintain connectivity with other wires
if ((closed && j == 1) || (!closed && j == n)) polygon.Remove(i);
else polygon.Remove(j);
removed = true;
break;
}
}
if (!removed) break;
}
}
template <typename P>
IfcGeom::BRepElement<P>* IfcGeom::Kernel::create_brep_for_representation_and_product(const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product) {
IfcGeom::Representation::BRep* shape;
IfcGeom::IfcRepresentationShapeItems shapes;
if ( !convert_shapes(representation,shapes) ) {
return 0;
}
int parent_id = -1;
try {
IfcSchema::IfcObjectDefinition* parent_object = get_decomposing_entity(product);
if (parent_object) {
parent_id = parent_object->entity->id();
}
} catch (...) {}
const std::string name = product->Name().get_value_or("");
const std::string guid = product->GlobalId();
gp_Trsf trsf;
try {
if (product->ObjectPlacement()) {
convert(*product->ObjectPlacement(),trsf);
}
} catch (...) {}
// Does the IfcElement have any IfcOpenings?
// Note that openings for IfcOpeningElements are not processed
IfcSchema::IfcRelVoidsElement::list::ptr openings;
if ( product->is(IfcSchema::Type::IfcElement) && !product->is(IfcSchema::Type::IfcOpeningElement) ) {
IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product;
openings = element->HasOpenings();
}
// Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements?
if ( product->is(IfcSchema::Type::IfcBuildingElementPart ) ) {
IfcSchema::IfcBuildingElementPart* part = (IfcSchema::IfcBuildingElementPart*)product;
#ifdef USE_IFC4
IfcSchema::IfcRelAggregates::list::ptr decomposes = part->Decomposes();
for ( IfcSchema::IfcRelAggregates::list::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
#else
IfcSchema::IfcRelDecomposes::list::ptr decomposes = part->Decomposes();
for ( IfcSchema::IfcRelDecomposes::list::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
#endif
IfcSchema::IfcObjectDefinition* obdef = (*it)->RelatingObject();
if ( obdef->is(IfcSchema::Type::IfcElement) ) {
IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)obdef;
openings->push(element->HasOpenings());
}
}
}
const std::string product_type = IfcSchema::Type::ToString(product->type());
ElementSettings element_settings(settings, getValue(GV_LENGTH_UNIT), product_type);
if ( !settings.disable_opening_subtractions() && openings && openings->size() ) {
IfcGeom::IfcRepresentationShapeItems opened_shapes;
try {
if ( settings.faster_booleans() ) {
bool succes = convert_openings_fast(product,openings,shapes,trsf,opened_shapes);
if ( ! succes ) {
opened_shapes.clear();
convert_openings(product,openings,shapes,trsf,opened_shapes);
}
} else {
convert_openings(product,openings,shapes,trsf,opened_shapes);
}
} catch(...) {
Logger::Message(Logger::LOG_ERROR,"Error processing openings for:",product->entity);
}
if ( settings.use_world_coords() ) {
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
it->prepend(trsf);
}
trsf = gp_Trsf();
}
shape = new IfcGeom::Representation::BRep(element_settings, representation->entity->id(), opened_shapes);
} else if ( settings.use_world_coords() ) {
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
it->prepend(trsf);
}
trsf = gp_Trsf();
shape = new IfcGeom::Representation::BRep(element_settings, representation->entity->id(), shapes);
} else {
shape = new IfcGeom::Representation::BRep(element_settings, representation->entity->id(), shapes);
}
return new BRepElement<P>(
product->entity->id(),
parent_id,
name,
product_type,
guid,
trsf,
shape
);
}
IfcSchema::IfcObjectDefinition* IfcGeom::Kernel::get_decomposing_entity(IfcSchema::IfcProduct* product) {
IfcSchema::IfcObjectDefinition* parent = 0;
// In case of an opening element, parent to the RelatingBuildingElement
if ( product->is(IfcSchema::Type::IfcOpeningElement ) ) {
IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)product;
IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements();
if ( voids->size() ) {
IfcSchema::IfcRelVoidsElement* ifc_void = *voids->begin();
parent = ifc_void->RelatingBuildingElement();
}
} else if ( product->is(IfcSchema::Type::IfcElement ) ) {
IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product;
IfcSchema::IfcRelFillsElement::list::ptr fills = element->FillsVoids();
// Incase of a RelatedBuildingElement parent to the opening element
if ( fills->size() ) {
for ( IfcSchema::IfcRelFillsElement::list::it it = fills->begin(); it != fills->end(); ++ it ) {
IfcSchema::IfcRelFillsElement* fill = *it;
IfcSchema::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement();
if ( product == ifc_objectdef ) continue;
parent = ifc_objectdef;
}
}
// Else simply parent to the containing structure
if (!parent) {
IfcSchema::IfcRelContainedInSpatialStructure::list::ptr parents = element->ContainedInStructure();
if ( parents->size() ) {
IfcSchema::IfcRelContainedInSpatialStructure* container = *parents->begin();
parent = container->RelatingStructure();
}
}
}
// Parent decompositions to the RelatingObject
if (!parent) {
IfcEntityList::ptr parents = product->entity->getInverse(IfcSchema::Type::IfcRelAggregates, -1);
parents->push(product->entity->getInverse(IfcSchema::Type::IfcRelNests, -1));
for ( IfcEntityList::it it = parents->begin(); it != parents->end(); ++ it ) {
IfcSchema::IfcRelDecomposes* decompose = (IfcSchema::IfcRelDecomposes*)*it;
IfcSchema::IfcObjectDefinition* ifc_objectdef;
#ifdef USE_IFC4
if (decompose->is(IfcSchema::Type::IfcRelAggregates)) {
ifc_objectdef = ((IfcSchema::IfcRelAggregates*)decompose)->RelatingObject();
} else {
continue;
}
#else
ifc_objectdef = decompose->RelatingObject();
#endif
if ( product == ifc_objectdef ) continue;
parent = ifc_objectdef;
}
}
return parent;
}
template IfcGeom::BRepElement<float>* IfcGeom::Kernel::create_brep_for_representation_and_product<float>(const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
template IfcGeom::BRepElement<double>* IfcGeom::Kernel::create_brep_for_representation_and_product<double>(const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
std::pair<std::string, double> IfcGeom::Kernel::initializeUnits(IfcSchema::IfcUnitAssignment* unit_assignment) {
// Set default units, set length to meters, angles to undefined
setValue(IfcGeom::Kernel::GV_LENGTH_UNIT, 1.0);
setValue(IfcGeom::Kernel::GV_PLANEANGLE_UNIT, -1.0);
std::string unit_name = "METER";
double unit_magnitude = 1.;
try {
IfcEntityList::ptr units = unit_assignment->Units();
if (!units || !units->size()) {
Logger::Message(Logger::LOG_ERROR, "No unit information found");
} else {
for ( IfcEntityList::it it = units->begin(); it != units->end(); ++ it ) {
std::string current_unit_name = "";
IfcUtil::IfcBaseClass* base = *it;
IfcSchema::IfcSIUnit* unit = 0;
double value = 1.f;
if ( base->is(IfcSchema::Type::IfcConversionBasedUnit) ) {
IfcSchema::IfcConversionBasedUnit* u = (IfcSchema::IfcConversionBasedUnit*)base;
current_unit_name = u->Name();
IfcSchema::IfcMeasureWithUnit* u2 = u->ConversionFactor();
IfcSchema::IfcUnit* u3 = u2->UnitComponent();
if ( u3->is(IfcSchema::Type::IfcSIUnit) ) {
unit = (IfcSchema::IfcSIUnit*) u3;
}
IfcSchema::IfcValue* v = u2->ValueComponent();
// Quick hack to get the numeric value from an IfcValue:
const double f = *v->entity->getArgument(0);
value *= f;
} else if ( base->is(IfcSchema::Type::IfcSIUnit) ) {
unit = (IfcSchema::IfcSIUnit*)base;
}
if ( unit ) {
if ( unit->Prefix() ) {
value *= IfcParse::IfcSIPrefixToValue(*unit->Prefix());
}
IfcSchema::IfcUnitEnum::IfcUnitEnum type = unit->UnitType();
if ( type == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT ) {
setValue(IfcGeom::Kernel::GV_LENGTH_UNIT,value);
if (current_unit_name.empty()) {
if (unit->Prefix()) {
current_unit_name = IfcSchema::IfcSIPrefix::ToString(*unit->Prefix());
}
current_unit_name += IfcSchema::IfcSIUnitName::ToString(unit->Name());
}
unit_magnitude = value;
unit_name = current_unit_name;
} else if ( type == IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) {
setValue(IfcGeom::Kernel::GV_PLANEANGLE_UNIT, value);
}
}
}
}
} catch (const IfcParse::IfcException& ex) {
std::stringstream ss;
ss << "Failed to determine unit information '" << ex.what() << "'";
Logger::Message(Logger::LOG_ERROR, ss.str());
}
return std::pair<std::string, double>(unit_name, unit_magnitude);
}
+119 -76
View File
@@ -77,28 +77,19 @@
#include "../ifcgeom/IfcGeom.h"
namespace IfcGeom {
namespace Cache {
#include "IfcRegisterCreateCache.h"
}
}
#define IN_CACHE(T,E,t,e) std::map<int,t>::const_iterator it = Cache::T.find(E->entity->id());\
if ( it != Cache::T.end() ) { e = it->second; return true; }
#define CACHE(T,E,e) Cache::T[E->entity->id()] = e;
bool IfcGeom::convert(const Ifc2x3::IfcCartesianPoint::ptr l, gp_Pnt& point) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianPoint* l, gp_Pnt& point) {
IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point)
std::vector<double> xyz = l->Coordinates();
point = gp_Pnt(
xyz.size() ? (xyz[0]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f,
xyz.size() > 1 ? (xyz[1]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f,
xyz.size() > 2 ? (xyz[2]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f
xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f,
xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f,
xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f
);
CACHE(IfcCartesianPoint,l,point)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcDirection::ptr l, gp_Dir& dir) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcDirection* l, gp_Dir& dir) {
IN_CACHE(IfcDirection,l,gp_Dir,dir)
std::vector<double> xyz = l->DirectionRatios();
dir = gp_Dir(
@@ -109,21 +100,23 @@ bool IfcGeom::convert(const Ifc2x3::IfcDirection::ptr l, gp_Dir& dir) {
CACHE(IfcDirection,l,dir)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcVector::ptr l, gp_Vec& v) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcVector* l, gp_Vec& v) {
IN_CACHE(IfcVector,l,gp_Vec,v)
gp_Dir d;
IfcGeom::convert(l->Orientation(),d);
v = l->Magnitude() * IfcGeom::GetValue(GV_LENGTH_UNIT) * d;
IfcGeom::Kernel::convert(l->Orientation(),d);
v = l->Magnitude() * getValue(GV_LENGTH_UNIT) * d;
CACHE(IfcVector,l,v)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcAxis2Placement3D::ptr l, gp_Trsf& trsf) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement3D* l, gp_Trsf& trsf) {
IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf)
gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);gp_Dir refDirection;
IfcGeom::convert(l->Location(),o);
bool hasRef = l->hasRefDirection();
if ( l->hasAxis() ) IfcGeom::convert(l->Axis(),axis);
if ( hasRef ) IfcGeom::convert(l->RefDirection(),refDirection);
IfcGeom::Kernel::convert(l->Location(),o);
bool hasRef = l->RefDirection() ? true : false;
if ( l->Axis() ) IfcGeom::Kernel::convert(*l->Axis(),axis);
if ( hasRef ) IfcGeom::Kernel::convert(*l->RefDirection(),refDirection);
gp_Ax3 ax3;
if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection);
else ax3 = gp_Ax3(o,axis);
@@ -131,57 +124,88 @@ bool IfcGeom::convert(const Ifc2x3::IfcAxis2Placement3D::ptr l, gp_Trsf& trsf) {
CACHE(IfcAxis2Placement3D,l,trsf)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3D::ptr l, gp_Trsf& trsf) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis1Placement* l, gp_Ax1& ax) {
IN_CACHE(IfcAxis1Placement,l,gp_Ax1,ax)
gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);
IfcGeom::Kernel::convert(l->Location(),o);
if ( l->Axis() ) IfcGeom::Kernel::convert(*l->Axis(), axis);
ax = gp_Ax1(o, axis);
CACHE(IfcAxis1Placement,l,ax)
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, gp_Trsf& trsf) {
IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf)
gp_Pnt origin;
IfcGeom::convert(l->LocalOrigin(),origin);
IfcGeom::Kernel::convert(l->LocalOrigin(),origin);
gp_Dir axis1 (1.,0.,0.);
gp_Dir axis2 (0.,1.,0.);
gp_Dir axis3;
if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1);
if ( l->hasAxis2() ) IfcGeom::convert(l->Axis2(),axis2);
if ( l->hasAxis3() ) IfcGeom::convert(l->Axis3(),axis3);
else axis3 = axis1.Crossed(axis2);
gp_Dir axis3 (0.,0.,1.);
if ( l->Axis1() ) IfcGeom::Kernel::convert(*l->Axis1(),axis1);
if ( l->Axis2() ) IfcGeom::Kernel::convert(*l->Axis2(),axis2);
if ( l->Axis3() ) IfcGeom::Kernel::convert(*l->Axis3(),axis3);
gp_Ax3 ax3 (origin,axis3,axis1);
if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse();
trsf.SetTransformation(ax3);
trsf.Invert();
if ( l->hasScale() ) trsf.SetScaleFactor(l->Scale());
if ( l->Scale() ) trsf.SetScaleFactor(*l->Scale());
CACHE(IfcCartesianTransformationOperator3D,l,trsf)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2D::ptr l, gp_Trsf2d& trsf) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator2D* l, gp_Trsf2d& trsf) {
IN_CACHE(IfcCartesianTransformationOperator2D,l,gp_Trsf2d,trsf)
gp_Pnt origin;
IfcGeom::convert(l->LocalOrigin(),origin);
gp_Dir axis1 (1.,0.,0.);
if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1);
const gp_Ax2d ax2d (gp_Pnt2d(origin.X(),origin.Y()),gp_Dir2d(axis1.X(),axis1.Y()));
gp_Dir axis2 (0.,1.,0.);
IfcGeom::Kernel::convert(l->LocalOrigin(),origin);
if ( l->Axis1() ) IfcGeom::Kernel::convert(*l->Axis1(),axis1);
if ( l->Axis2() ) IfcGeom::Kernel::convert(*l->Axis2(),axis2);
const gp_Pnt2d origin2d(origin.X(), origin.Y());
const gp_Dir2d axis12d(axis1.X(), axis1.Y());
const gp_Dir2d axis22d(axis2.X(), axis2.Y());
// A better match to represent the IfcCartesianTransformationOperator2D would
// be the gp_Ax22d, but to my knowledge no easy way exists to convert it into
// a gp_Trsf2d. Easiest would probably be to simply update the underlying
// gp_Mat2d directly.
const gp_Ax2d ax2d (origin2d, axis12d);
trsf.SetTransformation(ax2d);
if ( ax2d.Direction().Rotated(M_PI / 2.).Dot(axis22d) < 0. ) {
gp_Trsf2d mirror; mirror.SetMirror(ax2d);
trsf.Multiply(mirror);
}
trsf.Invert();
if ( l->hasScale() ) trsf.SetScaleFactor(l->Scale());
if ( l->Scale() ) trsf.SetScaleFactor(*l->Scale());
CACHE(IfcCartesianTransformationOperator2D,l,trsf)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3DnonUniform::ptr l, gp_GTrsf& gtrsf) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* l, gp_GTrsf& gtrsf) {
IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf)
gp_Trsf trsf;
gp_Pnt origin;
IfcGeom::convert(l->LocalOrigin(),origin);
IfcGeom::Kernel::convert(l->LocalOrigin(),origin);
gp_Dir axis1 (1.,0.,0.);
gp_Dir axis2 (0.,1.,0.);
gp_Dir axis3;
if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1);
if ( l->hasAxis2() ) IfcGeom::convert(l->Axis2(),axis2);
if ( l->hasAxis3() ) IfcGeom::convert(l->Axis3(),axis3);
else axis3 = axis1.Crossed(axis2);
gp_Dir axis3 (0.,0.,1.);
if ( l->Axis1() ) IfcGeom::Kernel::convert(*l->Axis1(),axis1);
if ( l->Axis2() ) IfcGeom::Kernel::convert(*l->Axis2(),axis2);
if ( l->Axis3() ) IfcGeom::Kernel::convert(*l->Axis3(),axis3);
gp_Ax3 ax3 (origin,axis3,axis1);
if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse();
trsf.SetTransformation(ax3);
trsf.Invert();
const double scale1 = l->hasScale() ? l->Scale() : 1.0f;
const double scale2 = l->hasScale2() ? l->Scale2() : scale1;
const double scale3 = l->hasScale3() ? l->Scale3() : scale1;
const double scale1 = l->Scale() ? *l->Scale() : 1.0f;
const double scale2 = l->Scale2() ? *l->Scale2() : scale1;
const double scale3 = l->Scale3() ? *l->Scale3() : scale1;
gtrsf = gp_GTrsf();
gtrsf.SetValue(1,1,scale1);
gtrsf.SetValue(2,2,scale2);
@@ -190,18 +214,35 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3DnonUnifo
CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gtrsf)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2DnonUniform::ptr l, gp_GTrsf2d& gtrsf) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, gp_GTrsf2d& gtrsf) {
IN_CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gp_GTrsf2d,gtrsf)
gp_Trsf2d trsf;
gp_Pnt origin;
IfcGeom::convert(l->LocalOrigin(),origin);
gp_Dir axis1 (1.,0.,0.);
if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1);
const gp_Ax2d ax2d (gp_Pnt2d(origin.X(),origin.Y()),gp_Dir2d(axis1.X(),axis1.Y()));
gp_Dir axis2 (0.,1.,0.);
IfcGeom::Kernel::convert(l->LocalOrigin(),origin);
if ( l->Axis1() ) IfcGeom::Kernel::convert(*l->Axis1(),axis1);
if ( l->Axis2() ) IfcGeom::Kernel::convert(*l->Axis2(),axis2);
const gp_Pnt2d origin2d(origin.X(), origin.Y());
const gp_Dir2d axis12d(axis1.X(), axis1.Y());
const gp_Dir2d axis22d(axis2.X(), axis2.Y());
const gp_Ax2d ax2d (origin2d, axis12d);
trsf.SetTransformation(ax2d);
if ( ax2d.Direction().Rotated(M_PI / 2.).Dot(axis22d) < 0. ) {
gp_Trsf2d mirror; mirror.SetMirror(ax2d);
trsf.Multiply(mirror);
}
trsf.Invert();
const double scale1 = l->hasScale() ? l->Scale() : 1.0f;
const double scale2 = l->hasScale2() ? l->Scale2() : scale1;
const double scale1 = l->Scale() ? *l->Scale() : 1.0f;
const double scale2 = l->Scale2() ? *l->Scale2() : scale1;
gtrsf = gp_GTrsf2d();
gtrsf.SetValue(1,1,scale1);
gtrsf.SetValue(2,2,scale2);
@@ -209,14 +250,15 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2DnonUnifo
CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gtrsf)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcPlane::ptr pln, gp_Pln& plane) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcPlane* pln, gp_Pln& plane) {
IN_CACHE(IfcPlane,pln,gp_Pln,plane)
Ifc2x3::IfcAxis2Placement3D::ptr l = pln->Position();
IfcSchema::IfcAxis2Placement3D* l = pln->Position();
gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);gp_Dir refDirection;
IfcGeom::convert(l->Location(),o);
bool hasRef = l->hasRefDirection();
if ( l->hasAxis() ) IfcGeom::convert(l->Axis(),axis);
if ( hasRef ) IfcGeom::convert(l->RefDirection(),refDirection);
IfcGeom::Kernel::convert(l->Location(),o);
bool hasRef = l->RefDirection();
if ( l->Axis() ) IfcGeom::Kernel::convert(*l->Axis(),axis);
if ( hasRef ) IfcGeom::Kernel::convert(*l->RefDirection(),refDirection);
gp_Ax3 ax3;
if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection);
else ax3 = gp_Ax3(o,axis);
@@ -224,40 +266,41 @@ bool IfcGeom::convert(const Ifc2x3::IfcPlane::ptr pln, gp_Pln& plane) {
CACHE(IfcPlane,pln,plane)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcAxis2Placement2D::ptr l, gp_Trsf2d& trsf) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement2D* l, gp_Trsf2d& trsf) {
IN_CACHE(IfcAxis2Placement2D,l,gp_Trsf2d,trsf)
gp_Pnt P; gp_Dir V (1,0,0);
IfcGeom::convert(l->Location(),P);
if ( l->hasRefDirection() )
IfcGeom::convert(l->RefDirection(),V);
IfcGeom::Kernel::convert(l->Location(),P);
if ( l->RefDirection() )
IfcGeom::Kernel::convert(*l->RefDirection(),V);
gp_Ax2d axis(gp_Pnt2d(P.X(),P.Y()),gp_Dir2d(V.X(),V.Y()));
trsf.SetTransformation(axis,gp_Ax2d());
CACHE(IfcAxis2Placement2D,l,trsf)
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcObjectPlacement::ptr l, gp_Trsf& trsf) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) {
IN_CACHE(IfcObjectPlacement,l,gp_Trsf,trsf)
if ( ! l->is(Ifc2x3::Type::IfcLocalPlacement) ) return false;
Ifc2x3::IfcLocalPlacement::ptr current = reinterpret_pointer_cast<Ifc2x3::IfcObjectPlacement,Ifc2x3::IfcLocalPlacement>(l);
if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) {
Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l->entity);
return false;
}
IfcSchema::IfcLocalPlacement* current = (IfcSchema::IfcLocalPlacement*)l;
while (1) {
gp_Trsf trsf2;
Ifc2x3::IfcAxis2Placement relplacement = current->RelativePlacement();
if ( relplacement->is(Ifc2x3::Type::IfcAxis2Placement3D) ) {
IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)relplacement,trsf2);
IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement();
if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) {
IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2);
trsf.PreMultiply(trsf2);
}
if ( current->hasPlacementRelTo() ) {
Ifc2x3::IfcObjectPlacement::ptr relto = current->PlacementRelTo();
if ( relto->is(Ifc2x3::Type::IfcLocalPlacement) )
current = reinterpret_pointer_cast<Ifc2x3::IfcObjectPlacement,Ifc2x3::IfcLocalPlacement>(current->PlacementRelTo());
if ( current->PlacementRelTo() ) {
IfcSchema::IfcObjectPlacement* relto = *current->PlacementRelTo();
if ( relto->is(IfcSchema::Type::IfcLocalPlacement) )
current = (IfcSchema::IfcLocalPlacement*) relto;
else break;
} else break;
}
CACHE(IfcObjectPlacement,l,trsf)
return true;
}
void IfcGeom::Cache::Purge() {
#include "IfcRegisterPurgeCache.h"
IfcGeom::Cache::PurgeShapeCache();
}
+493
View File
@@ -0,0 +1,493 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Geometrical data in an IFC file consists of shapes (IfcShapeRepresentation) *
* and instances (SUBTYPE OF IfcBuildingElement e.g. IfcWindow). *
* *
* IfcGeom::Representation::Triangulation is a class that represents a *
* triangulated IfcShapeRepresentation. *
* Triangulation.verts is a 1 dimensional vector of float defining the *
* cartesian coordinates of the vertices of the triangulated shape in the *
* format of [x1,y1,z1,..,xn,yn,zn] *
* Triangulation.faces is a 1 dimensional vector of int containing the *
* indices of the triangles referencing positions in Triangulation.verts *
* Triangulation.edges is a 1 dimensional vector of int in {0,1} that dictates*
* the visibility of the edges that span the faces in Triangulation.faces *
* *
* IfcGeom::Element represents the actual IfcBuildingElements. *
* IfcGeomObject.name is the GUID of the element *
* IfcGeomObject.type is the datatype of the element e.g. IfcWindow *
* IfcGeomObject.mesh is a pointer to an IfcMesh *
* IfcGeomObject.transformation.matrix is a 4x3 matrix that defines the *
* orientation and translation of the mesh in relation to the world origin *
* *
* IfcGeom::Iterator::findContext() *
* finds the most suitable representation contexts. Returns true iff *
* at least a single representation will process successfully *
* *
* IfcGeom::Iterator::get() *
* returns a pointer to the current IfcGeom::Element *
* *
* IfcGeom::Iterator::next() *
* returns true iff a following entity is available for a successive call to *
* IfcGeom::Iterator::get() *
* *
* IfcGeom::Iterator::progress() *
* returns an int in [0..100] that indicates the overall progress *
* *
********************************************************************************/
#ifndef IFCGEOMITERATOR_H
#define IFCGEOMITERATOR_H
#include <map>
#include <set>
#include <vector>
#include <limits>
#include <algorithm>
#include <gp_Mat.hxx>
#include <gp_Mat2d.hxx>
#include <gp_GTrsf.hxx>
#include <gp_GTrsf2d.hxx>
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeom.h"
#include "../ifcgeom/IfcGeomElement.h"
#include "../ifcgeom/IfcGeomMaterial.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"
namespace IfcGeom {
template <typename P>
class Iterator {
private:
Kernel kernel;
IteratorSettings settings;
IfcParse::IfcFile* ifc_file;
// A container and iterator for IfcRepresentations
IfcSchema::IfcRepresentation::list::ptr representations;
IfcSchema::IfcRepresentation::list::it representation_iterator;
// The object is fetched beforehand to be sure that get() returns a valid element
TriangulationElement<P>* current_triangulation;
BRepElement<P>* current_shape_model;
SerializedElement<P>* current_serialization;
// A container and iterator for IfcBuildingElements for the current IfcRepresentation referenced by *representation_iterator
IfcSchema::IfcProduct::list::ptr ifcproducts;
IfcSchema::IfcProduct::list::it ifcproduct_iterator;
int done;
int total;
std::string unit_name;
// double?
P unit_magnitude;
void initUnits() {
IfcSchema::IfcProject::list::ptr projects = ifc_file->entitiesByType<IfcSchema::IfcProject>();
if (projects->size() == 1) {
IfcSchema::IfcProject* project = *projects->begin();
std::pair<std::string, double> length_unit = kernel.initializeUnits(project->UnitsInContext());
unit_name = length_unit.first;
unit_magnitude = static_cast<P>(length_unit.second);
}
}
std::set<IfcSchema::Type::Enum> entities_to_include_or_exclude;
bool include_entities_in_processing;
void populate_set(const std::set<std::string>& include_or_ignore) {
entities_to_include_or_exclude.clear();
for (std::set<std::string>::const_iterator it = include_or_ignore.begin(); it != include_or_ignore.end(); ++it) {
std::string uppercase_type = *it;
for (std::string::iterator c = uppercase_type.begin(); c != uppercase_type.end(); ++c) {
*c = toupper(*c);
}
IfcSchema::Type::Enum ty;
try {
ty = IfcSchema::Type::FromString(uppercase_type);
} catch (const IfcParse::IfcException&) {
std::stringstream ss;
ss << "'" << *it << "' does not name a valid IFC entity";
throw IfcParse::IfcException(ss.str());
}
entities_to_include_or_exclude.insert(ty);
// TODO: Add child classes so that containment in set can be in O(log n)
}
}
public:
bool findContext() {
try {
initUnits();
} catch (...) {}
// Really this should only be 'Model', as per
// the standard 'Design' is deprecated. So,
// just for backwards compatibility:
std::set<std::string> context_types;
context_types.insert("model");
context_types.insert("design");
// DDS likes to output 'model view'
context_types.insert("model view");
double lowest_precision_encountered = std::numeric_limits<double>::infinity();
bool any_precision_encountered = false;
representations = IfcSchema::IfcRepresentation::list::ptr(new IfcSchema::IfcRepresentation::list);
IfcSchema::IfcGeometricRepresentationContext::list::it it;
IfcSchema::IfcGeometricRepresentationSubContext::list::it jt;
IfcSchema::IfcGeometricRepresentationContext::list::ptr contexts =
ifc_file->entitiesByType<IfcSchema::IfcGeometricRepresentationContext>();
IfcSchema::IfcGeometricRepresentationContext::list::ptr filtered_contexts (new IfcSchema::IfcGeometricRepresentationContext::list);
for (it = contexts->begin(); it != contexts->end(); ++it) {
IfcSchema::IfcGeometricRepresentationContext* context = *it;
if (context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) {
// Continue, as the list of subcontexts will be considered
// by the parent's context inverse attributes.
continue;
}
if (context->ContextType()) {
std::string context_type_lc = *context->ContextType();
for (std::string::iterator c = context_type_lc.begin(); c != context_type_lc.end(); ++c) {
*c = tolower(*c);
}
if (context_types.find(context_type_lc) != context_types.end()) {
filtered_contexts->push(context);
}
}
}
if (filtered_contexts->size() == 0) {
filtered_contexts = contexts;
}
for (it = filtered_contexts->begin(); it != filtered_contexts->end(); ++it) {
IfcSchema::IfcGeometricRepresentationContext* context = *it;
representations->push(context->RepresentationsInContext());
if (context->Precision() && *context->Precision() < lowest_precision_encountered) {
lowest_precision_encountered = *context->Precision();
any_precision_encountered = true;
}
IfcSchema::IfcGeometricRepresentationSubContext::list::ptr sub_contexts = context->HasSubContexts();
for (jt = sub_contexts->begin(); jt != sub_contexts->end(); ++jt) {
representations->push((*jt)->RepresentationsInContext());
}
// There is no need for full recursion as the following is governed by the schema:
// WR31: The parent context shall not be another geometric representation sub context.
}
if (any_precision_encountered) {
// Some arbitrary factor that has proven to work better for the models in the set of test files.
lowest_precision_encountered *= 10.;
lowest_precision_encountered *= unit_magnitude;
if (lowest_precision_encountered < 1.e-7) {
Logger::Message(Logger::LOG_WARNING, "Precision lower than 0.0000001 meter not enforced");
kernel.setValue(IfcGeom::Kernel::GV_PRECISION, 1.e-7);
} else {
kernel.setValue(IfcGeom::Kernel::GV_PRECISION, lowest_precision_encountered);
}
} else {
kernel.setValue(IfcGeom::Kernel::GV_PRECISION, 1.e-5);
}
if (representations->size() == 0) return false;
representation_iterator = representations->begin();
ifcproducts.reset();
if (!create()) {
return false;
}
done = 0;
total = representations->size();
return true;
}
int progress() {
return 100 * done / total;
}
const std::string& getUnitName() {
return unit_name;
}
const P getUnitMagnitude() {
return unit_magnitude;
}
const std::string getLog() {
return Logger::GetLog();
}
IfcParse::IfcFile* getFile() {
return ifc_file;
}
void includeEntities(const std::set<std::string>& entities) {
populate_set(entities);
include_entities_in_processing = true;
}
void excludeEntities(const std::set<std::string>& entities) {
populate_set(entities);
include_entities_in_processing = false;
}
private:
// Move to the next IfcRepresentation
void _nextShape() {
ifcproducts.reset();
++ representation_iterator;
++ done;
}
BRepElement<P>* create_shape_model_for_next_entity() {
while ( true ) {
IfcSchema::IfcRepresentation* representation;
// Have we reached the end of our list of representations?
if ( representation_iterator == representations->end() ) {
representations.reset();
return 0;
}
representation = *representation_iterator;
// Has the list of IfcProducts for this representation been initialized?
if (!ifcproducts) {
IfcSchema::IfcProductRepresentation::list::ptr prodreps = representation->OfProductRepresentation();
ifcproducts = IfcSchema::IfcProduct::list::ptr(new IfcSchema::IfcProduct::list);
IfcSchema::IfcProduct::list::ptr unfiltered_products(new IfcSchema::IfcProduct::list);
for ( IfcSchema::IfcProductRepresentation::list::it it = prodreps->begin(); it != prodreps->end(); ++it ) {
if ( (*it)->is(IfcSchema::Type::IfcProductDefinitionShape) ) {
IfcSchema::IfcProductDefinitionShape* pds = (IfcSchema::IfcProductDefinitionShape*)*it;
unfiltered_products->push(pds->ShapeOfProduct());
} else {
// http://buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcrepresentationresource/lexical/ifcproductrepresentation.htm
// IFC2x Edition 3 NOTE Users should not instantiate the entity IfcProductRepresentation from IFC2x Edition 3 onwards.
// It will be changed into an ABSTRACT supertype in future releases of IFC.
// IfcProductRepresentation also lacks the INVERSE relation to IfcProduct
// Let's find the IfcProducts that reference the IfcProductRepresentation anyway
unfiltered_products->push((*it)->entity->getInverse(IfcSchema::Type::IfcProduct, -1)->as<IfcSchema::IfcProduct>());
}
// Filter the products based on the set of entities being included or excluded for
// processing. The set is iterated over te able to filter on subtypes.
for ( IfcSchema::IfcProduct::list::it it = unfiltered_products->begin(); it != unfiltered_products->end(); ++it ) {
bool found = false;
for (std::set<IfcSchema::Type::Enum>::const_iterator jt = entities_to_include_or_exclude.begin(); jt != entities_to_include_or_exclude.end(); ++jt) {
if ((*it)->is(*jt)) {
found = true;
break;
}
}
if (found == include_entities_in_processing) {
ifcproducts->push(*it);
}
}
}
// Does this representation have any IfcProducts?
if (!ifcproducts->size()) {
_nextShape();
continue;
}
ifcproduct_iterator = ifcproducts->begin();
}
// Have we reached the end of our list of IfcProducts?
if ( ifcproduct_iterator == ifcproducts->end() ) {
_nextShape();
continue;
}
IfcSchema::IfcProduct* product = *ifcproduct_iterator;
BRepElement<P>* element = kernel.create_brep_for_representation_and_product<P>(settings, representation, product);
if ( !element ) {
_nextShape();
continue;
}
return element;
}
}
public:
bool next() {
// Free all possible representations of the current geometrical entity
delete current_triangulation;
current_triangulation = 0;
delete current_serialization;
current_serialization = 0;
delete current_shape_model;
current_shape_model = 0;
// Increment the iterator over the list of products using the current
// shape representation
if (ifcproducts) {
++ifcproduct_iterator;
}
return create();
}
Element<P>* get() {
// TODO: Test settings and throw
if (current_triangulation) return current_triangulation;
else if (current_serialization) return current_serialization;
else if (current_shape_model) return current_shape_model;
else return 0;
}
const Element<P>* getObject(int id) {
gp_Trsf trsf;
int parent_id = -1;
std::string instance_type, product_name, product_guid;
try {
const IfcUtil::IfcBaseClass* ifc_entity = ifc_file->entityById(id);
instance_type = IfcSchema::Type::ToString(ifc_entity->type());
if ( ifc_entity->is(IfcSchema::Type::IfcProduct) ) {
IfcSchema::IfcProduct* ifc_product = (IfcSchema::IfcProduct*)ifc_entity;
product_guid = ifc_product->GlobalId();
product_name = ifc_product->hasName() ? ifc_product->Name() : "";
parent_id = -1;
try {
IfcSchema::IfcObjectDefinition* parent_object = kernel.get_decomposing_entity(ifc_product);
if (parent_object) {
parent_id = parent_object->entity->id();
}
} catch (...) {}
try {
kernel.convert(ifc_product->ObjectPlacement(), trsf);
} catch (...) {}
}
} catch(...) {}
ElementSettings element_settings(settings, unit_magnitude, instance_type);
Element<P>* ifc_object = new Element<P>(element_settings, id, parent_id, product_name, instance_type, product_guid, trsf);
return ifc_object;
}
bool create() {
try {
current_shape_model = create_shape_model_for_next_entity();
} catch (...) {}
if (!current_shape_model) return false;
if (settings.use_brep_data()) {
try {
current_serialization = new SerializedElement<P>(*current_shape_model);
} catch (...) {}
return !!current_serialization;
} else if (!settings.disable_triangulation()) {
try {
current_triangulation = new TriangulationElement<P>(*current_shape_model);
} catch (...) {}
return !!current_triangulation;
} else {
return true;
}
}
private:
void initialize() {
current_triangulation = 0;
current_shape_model = 0;
current_serialization = 0;
// Upon initialisation, the (empty) set of entity names,
// should be excluded, or no products would be processed.
include_entities_in_processing = false;
unit_name = "METER";
unit_magnitude = 1.f;
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1);
kernel.setValue(IfcGeom::Kernel::GV_FORCE_CCW_FACE_ORIENTATION, settings.force_ccw_face_orientation() ? 1 : -1);
}
public:
Iterator(const IteratorSettings& settings, IfcParse::IfcFile* file)
: settings(settings)
, ifc_file(file)
{
initialize();
}
Iterator(const IteratorSettings& settings, const std::string& filename)
: settings(settings)
, ifc_file(new IfcParse::IfcFile)
{
ifc_file->Init(filename);
initialize();
}
Iterator(const IteratorSettings& settings, void* data, int length)
: settings(settings)
, ifc_file(new IfcParse::IfcFile)
{
ifc_file->Init(data, length);
initialize();
}
Iterator(const IteratorSettings& settings, std::istream& filestream, int length)
: settings(settings)
, ifc_file(new IfcParse::IfcFile)
{
ifc_file->Init(filestream, length);
initialize();
}
~Iterator() {
// TODO: Correctly implement destructor for IfcFile
delete ifc_file;
delete current_triangulation;
current_triangulation = 0;
delete current_serialization;
current_serialization = 0;
delete current_shape_model;
current_shape_model = 0;
}
};
}
#endif
+172
View File
@@ -0,0 +1,172 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef IFCGEOMITERATORSETTINGS_H
#define IFCGEOMITERATORSETTINGS_H
#include <string>
#include "../ifcparse/IfcException.h"
namespace IfcGeom {
class IteratorSettings {
public:
// Enumeration of setting identifiers. These settings define the
// behaviour of various aspects of IfcOpenShell.
// Specifies whether vertices are welded, meaning that the coordinates
// vector will only contain unique xyz-triplets. This results in a
// manifold mesh which is useful for modelling applications, but might
// result in unwanted shading artifacts in rendering applications.
static const int WELD_VERTICES = 1;
// Specifies whether to apply the local placements of building elements
// directly to the coordinates of the representation mesh rather than
// to represent the local placement in the 4x3 matrix, which will in that
// case be the identity matrix.
static const int USE_WORLD_COORDS = 2;
// Internally IfcOpenShell measures everything in meters. This settings
// specifies whether to convert IfcGeomObjects back to the units in which
// the geometry in the IFC file is specified.
static const int CONVERT_BACK_UNITS = 3;
// Specifies whether to use the Open Cascade BREP format for representation
// items rather than to create triangle meshes. This is useful is IfcOpenShell
// is used as a library in an application that is also built on Open Cascade.
static const int USE_BREP_DATA = 4;
// Specifies whether to sew IfcConnectedFaceSets (open and closed shells) to
// TopoDS_Shells or whether to keep them as a loose collection of faces.
static const int SEW_SHELLS = 5;
// Specifies whether to compose IfcOpeningElements into a single compound
// in order to speed up the processing of opening subtractions.
static const int FASTER_BOOLEANS = 6;
// By default singular faces have no explicitly defined orientation, to
// force faces to be defined CounterClockWise set this to true.
static const int FORCE_CCW_FACE_ORIENTATION = 7;
// Disables the subtraction of IfcOpeningElement representations from
// the related building element representations.
static const int DISABLE_OPENING_SUBTRACTIONS = 8;
// Disables the triangulation of the topological representations. Useful if
// the client application understands Open Cascade's native format.
static const int DISABLE_TRIANGULATION = 9;
// Applies default materials to entity instances without a surface style.
static const int APPLY_DEFAULT_MATERIALS = 10;
// End of settings enumeration.
private:
bool _weld_vertices, _use_world_coords, _convert_back_units, _use_brep_data, _sew_shells, _faster_booleans, _force_ccw_face_orientation, _disable_opening_subtractions, _disable_triangulation, _apply_default_materials;
double _deflection_tolerance;
public:
IteratorSettings()
: _weld_vertices(true)
, _use_world_coords(false)
, _convert_back_units(false)
, _use_brep_data(false)
, _sew_shells(false)
, _faster_booleans(false)
, _force_ccw_face_orientation(false)
, _disable_opening_subtractions(false)
, _disable_triangulation(false)
, _apply_default_materials(false)
// TODO: Make deflection tolerance into a command line argument
// For now, stick to one millimeter. Note that this is independent of the IFC length unit.
, _deflection_tolerance(1.e-3)
{}
const bool& weld_vertices() const { return _weld_vertices; }
bool& weld_vertices() { return _weld_vertices; }
const bool& use_world_coords() const { return _use_world_coords; }
bool& use_world_coords() { return _use_world_coords; }
const bool& convert_back_units() const { return _convert_back_units; }
bool& convert_back_units() { return _convert_back_units; }
const bool& use_brep_data() const { return _use_brep_data; }
bool& use_brep_data() { return _use_brep_data; }
const bool& sew_shells() const { return _sew_shells; }
bool& sew_shells() { return _sew_shells; }
const bool& faster_booleans() const { return _faster_booleans; }
bool& faster_booleans() { return _faster_booleans; }
const bool& force_ccw_face_orientation() const { return _force_ccw_face_orientation; }
bool& force_ccw_face_orientation() { return _force_ccw_face_orientation; }
const bool& disable_opening_subtractions() const { return _disable_opening_subtractions; }
bool& disable_opening_subtractions() { return _disable_opening_subtractions; }
const bool& disable_triangulation() const { return _disable_triangulation; }
bool& disable_triangulation() { return _disable_triangulation; }
const bool& apply_default_materials() const { return _apply_default_materials; }
bool& apply_default_materials() { return _apply_default_materials; }
const double& deflection_tolerance() const { return _deflection_tolerance; }
double& deflection_tolerance() { return _deflection_tolerance; }
void set(int setting, bool value) {
switch (setting) {
case USE_WORLD_COORDS:
_use_world_coords = value;
break;
case WELD_VERTICES:
_weld_vertices = value;
break;
case CONVERT_BACK_UNITS:
_convert_back_units = value;
break;
case USE_BREP_DATA:
_use_brep_data = value;
break;
case FASTER_BOOLEANS:
_faster_booleans = value;
break;
case SEW_SHELLS:
_sew_shells = value;
break;
case FORCE_CCW_FACE_ORIENTATION:
_force_ccw_face_orientation = value;
break;
case DISABLE_OPENING_SUBTRACTIONS:
_disable_opening_subtractions = value;
break;
case DISABLE_TRIANGULATION:
_disable_triangulation = value;
break;
case APPLY_DEFAULT_MATERIALS:
_apply_default_materials = value;
break;
default: throw IfcParse::IfcException("Invalid IteratorSetting");
}
}
};
class ElementSettings : public IteratorSettings {
private:
double _unit_magnitude;
std::string _element_type;
public:
ElementSettings(const IteratorSettings& settings,
double unit_magnitude,
const std::string& element_type)
: IteratorSettings(settings)
, _unit_magnitude(unit_magnitude)
, _element_type(element_type)
{}
const double& unit_magnitude() const { return _unit_magnitude; }
const std::string& element_type() const { return _element_type; }
};
}
#endif
+34
View File
@@ -0,0 +1,34 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "IfcGeomMaterial.h"
static double black[3] = {0.,0.,0.};
IfcGeom::Material::Material(const IfcGeom::SurfaceStyle* style) : style(style) {}
bool IfcGeom::Material::hasDiffuse() const { return style->Diffuse() ? true : false; }
bool IfcGeom::Material::hasSpecular() const { return style->Specular() ? true : false; }
bool IfcGeom::Material::hasTransparency() const { return style->Transparency() ? true : false; }
bool IfcGeom::Material::hasSpecularity() const { return style->Specularity() ? true : false; }
const double* IfcGeom::Material::diffuse() const { if (hasDiffuse()) return &((*style->Diffuse()).R()); else return black; }
const double* IfcGeom::Material::specular() const { if (hasSpecular()) return &((*style->Specular()).R()); else return black; }
double IfcGeom::Material::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; }
double IfcGeom::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); else return 0; }
const std::string IfcGeom::Material::name() const { return style->Name(); }
bool IfcGeom::Material::operator==(const IfcGeom::Material& other) const { return style == other.style; }
+50
View File
@@ -0,0 +1,50 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef IFCGEOMMATERIAL_H
#define IFCGEOMMATERIAL_H
#include <string>
#include "../ifcgeom/IfcGeomRenderStyles.h"
namespace IfcGeom {
class Material {
private:
const IfcGeom::SurfaceStyle* style;
public:
explicit Material(const IfcGeom::SurfaceStyle* style = 0); // TODO default constructor for vector?
// Material(const Material& other);
// Material& operator=(const Material& other);
bool hasDiffuse() const;
bool hasSpecular() const;
bool hasTransparency() const;
bool hasSpecularity() const;
const double* diffuse() const;
const double* specular() const;
double transparency() const;
double specularity() const;
const std::string name() const;
bool operator==(const Material& other) const;
};
}
#endif
-806
View File
@@ -1,806 +0,0 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include <map>
#include <stdexcept>
#include <limits>
#include <gp_Mat.hxx>
#include <gp_Mat2d.hxx>
#include <gp_GTrsf.hxx>
#include <gp_GTrsf2d.hxx>
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include <TopoDS_Compound.hxx>
#include <BRep_Builder.hxx>
#include <BRepTools.hxx>
#include <BRep_Tool.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepMesh.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TShort_Array1OfShortReal.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <StdFail_NotDone.hxx>
#include <BRepGProp_Face.hxx>
#include <BRepBuilderAPI_GTransform.hxx>
#include "../ifcparse/IfcException.h"
#include "../ifcgeom/IfcGeomObjects.h"
#include "../ifcgeom/IfcGeom.h"
// Welds vertices that belong to different faces
static bool weld_vertices = true;
static bool convert_back_units = false;
static bool use_faster_booleans = false;
static bool disable_subtractions = false;
static bool disable_triangulation = false;
int IfcGeomObjects::IfcRepresentationTriangulation::addvert(int material_index, const gp_XYZ& p) {
const float X = convert_back_units ? (float) (p.X() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.X();
const float Y = convert_back_units ? (float) (p.Y() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.Y();
const float Z = convert_back_units ? (float) (p.Z() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.Z();
int i = (int) _verts.size() / 3;
if ( weld_vertices ) {
const VertKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z)));
VertKeyMap::const_iterator it = welds.find(key);
if ( it != welds.end() ) return it->second;
i = (int) welds.size();
welds[key] = i;
}
_verts.push_back(X);
_verts.push_back(Y);
_verts.push_back(Z);
return i;
}
static bool use_world_coords = false;
static bool use_brep_data = false;
static IfcParse::IfcFile* ifc_file = 0;
IfcGeomObjects::IfcRepresentationBrepData::IfcRepresentationBrepData(const IfcRepresentationShapeModel& shapes)
: _id(shapes.getId())
{
try {
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
const TopoDS_Shape& s = it->Shape();
gp_GTrsf trsf = it->Placement();
if (convert_back_units) {
gp_Trsf scale;
scale.SetScaleFactor(1.0 / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT));
trsf.PreMultiply(scale);
}
bool trsf_valid = false;
gp_Trsf _trsf;
try {
_trsf = trsf.Trsf();
trsf_valid = true;
} catch (...) {}
const TopoDS_Shape moved_shape = trsf_valid ? s.Moved(_trsf) :
BRepBuilderAPI_GTransform(s,trsf,true).Shape();
builder.Add(compound,moved_shape);
}
std::stringstream sstream;
BRepTools::Write(compound,sstream);
_brep_data = sstream.str();
} catch(...) {
Logger::Message(Logger::LOG_ERROR,"Failed to serialize shape:",ifc_file->EntityById(_id)->entity);
}
}
IfcGeomObjects::IfcRepresentationTriangulation::IfcRepresentationTriangulation(const IfcRepresentationShapeModel& shapes)
: _id(shapes.getId())
{
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
int surface_style_id = -1;
if (it->hasStyle()) {
Material adapter(&it->Style());
std::vector<Material>::const_iterator jt = std::find(_materials.begin(), _materials.end(), adapter);
if (jt == _materials.end()) {
surface_style_id = _materials.size();
_materials.push_back(adapter);
} else {
surface_style_id = jt - _materials.begin();
}
}
const TopoDS_Shape& s = it->Shape();
const gp_GTrsf& trsf = it->Placement();
// Triangulate the shape
try {
// BRepTools::Clean(s);
BRepMesh::Mesh(s, IfcGeom::GetValue(IfcGeom::GV_DEFLECTION_TOLERANCE));
} catch(...) {
Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape:",ifc_file->EntityById(_id)->entity);
continue;
}
TopExp_Explorer exp;
// Iterates over the faces of the shape
for ( exp.Init(s,TopAbs_FACE); exp.More(); exp.Next() ) {
TopoDS_Face face = TopoDS::Face(exp.Current());
TopLoc_Location loc;
Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face,loc);
if ( ! tri.IsNull() ) {
// A 3x3 matrix to rotate the vertex normals
const gp_Mat rotation_matrix = trsf.VectorialPart();
// Keep track of the number of times an edge is used
// Manifold edges (i.e. edges used twice) are deemed invisible
std::map<std::pair<int,int>,int> edgecount;
std::vector<std::pair<int,int> > edges_temp;
const TColgp_Array1OfPnt& nodes = tri->Nodes();
const TColgp_Array1OfPnt2d& uvs = tri->UVNodes();
std::vector<gp_XYZ> coords;
BRepGProp_Face prop(face);
std::map<int,int> dict;
// Vertex normals are only calculated if vertices are not welded
const bool calculate_normals = ! weld_vertices;
for( int i = 1; i <= nodes.Length(); ++ i ) {
coords.push_back(nodes(i).Transformed(loc).XYZ());
trsf.Transforms(*coords.rbegin());
dict[i] = addvert(surface_style_id, *coords.rbegin());
if ( calculate_normals ) {
const gp_Pnt2d& uv = uvs(i);
gp_Pnt p;
gp_Vec normal_direction;
prop.Normal(uv.X(),uv.Y(),p,normal_direction);
gp_Dir normal = gp_Dir(normal_direction.XYZ() * rotation_matrix);
_normals.push_back((float)normal.X());
_normals.push_back((float)normal.Y());
_normals.push_back((float)normal.Z());
}
}
const Poly_Array1OfTriangle& triangles = tri->Triangles();
for( int i = 1; i <= triangles.Length(); ++ i ) {
int n1,n2,n3;
if ( face.Orientation() == TopAbs_REVERSED )
triangles(i).Get(n3,n2,n1);
else triangles(i).Get(n1,n2,n3);
/* An alternative would be to calculate normals based
* on the coordinates of the mesh vertices */
/*
const gp_XYZ pt1 = coords[n1-1];
const gp_XYZ pt2 = coords[n2-1];
const gp_XYZ pt3 = coords[n3-1];
const gp_XYZ v1 = pt2-pt1;
const gp_XYZ v2 = pt3-pt2;
gp_Dir normal = gp_Dir(v1^v2);
_normals.push_back((float)normal.X());
_normals.push_back((float)normal.Y());
_normals.push_back((float)normal.Z());
*/
_faces.push_back(dict[n1]);
_faces.push_back(dict[n2]);
_faces.push_back(dict[n3]);
_material_ids.push_back(surface_style_id);
addedge(n1,n2,edgecount,edges_temp);
addedge(n2,n3,edgecount,edges_temp);
addedge(n3,n1,edgecount,edges_temp);
}
for ( std::vector<std::pair<int,int> >::const_iterator it = edges_temp.begin(); it != edges_temp.end(); ++it ) {
_edges.push_back(edgecount[*it]==1);
}
}
}
}
}
IfcGeomObjects::IfcObject::IfcObject(
int id,
int parent_id,
const std::string& name,
const std::string& type,
const std::string& guid,
const gp_Trsf& trsf)
: _id(id)
, _parent_id(parent_id)
, _name(name)
, _type(type)
, _guid(guid)
{
// Convert the gp_Trsf into a 4x3 Matrix
for( int i = 1; i < 5; ++ i )
for ( int j = 1; j < 4; ++ j )
_matrix.push_back((float)trsf.Value(j,i));
}
IfcGeomObjects::IfcGeomShapeModelObject::IfcGeomShapeModelObject(
int id,
int parent_id,
const std::string& name,
const std::string& type,
const std::string& guid,
const gp_Trsf& trsf,
IfcRepresentationShapeModel* shapes)
: IfcObject(id,parent_id,name,type,guid,trsf)
, _mesh(shapes)
{}
IfcGeomObjects::IfcGeomBrepDataObject::IfcGeomBrepDataObject(
const IfcGeomShapeModelObject& shape_model)
: IfcObject(shape_model)
, _mesh(new IfcRepresentationBrepData(shape_model.mesh()))
{}
IfcGeomObjects::IfcGeomObject::IfcGeomObject(
const IfcGeomShapeModelObject& shape_model)
: IfcObject(shape_model)
, _mesh(new IfcRepresentationTriangulation(shape_model.mesh()))
{}
// A container and iterator for IfcShapeRepresentations
static Ifc2x3::IfcShapeRepresentation::list shapereps;
static Ifc2x3::IfcShapeRepresentation::it shaperep_iterator;
// The object is fetched beforehand to be positive an entity actually exists
static IfcGeomObjects::IfcGeomObject* current_geom_obj = 0;
static IfcGeomObjects::IfcGeomShapeModelObject* current_shape_model_obj = 0;
static IfcGeomObjects::IfcGeomBrepDataObject* current_brep_data_obj = 0;
// A container and iterator for IfcBuildingElements for the current IfcShapeRepresentation referenced by *shaperep_iterator
static Ifc2x3::IfcProduct::list entities;
static Ifc2x3::IfcProduct::it ifcproduct_iterator;
static int done;
static int total;
// Move the the next IfcShapeRepresentation
void _nextShape() {
entities.reset();
++ shaperep_iterator;
++ done;
}
int _getParentId(const Ifc2x3::IfcProduct::ptr ifc_product) {
int parent_id = -1;
// In case of an opening element, parent to the RelatingBuildingElement
if ( ifc_product->is(Ifc2x3::Type::IfcOpeningElement ) ) {
Ifc2x3::IfcOpeningElement::ptr opening = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcOpeningElement>(ifc_product);
Ifc2x3::IfcRelVoidsElement::list voids = opening->VoidsElements();
if ( voids->Size() ) {
Ifc2x3::IfcRelVoidsElement::ptr ifc_void = *voids->begin();
parent_id = ifc_void->RelatingBuildingElement()->entity->id();
}
} else if ( ifc_product->is(Ifc2x3::Type::IfcElement ) ) {
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcElement>(ifc_product);
Ifc2x3::IfcRelFillsElement::list fills = element->FillsVoids();
// Incase of a RelatedBuildingElement parent to the opening element
if ( fills->Size() ) {
for ( Ifc2x3::IfcRelFillsElement::it it = fills->begin(); it != fills->end(); ++ it ) {
Ifc2x3::IfcRelFillsElement::ptr fill = *it;
Ifc2x3::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement();
if ( ifc_product == ifc_objectdef ) continue;
parent_id = ifc_objectdef->entity->id();
}
}
// Else simply parent to the containing structure
if ( parent_id == -1 ) {
Ifc2x3::IfcRelContainedInSpatialStructure::list parents = element->ContainedInStructure();
if ( parents->Size() ) {
Ifc2x3::IfcRelContainedInSpatialStructure::ptr parent = *parents->begin();
parent_id = parent->RelatingStructure()->entity->id();
}
}
}
// Parent decompositions to the RelatingObject
if ( parent_id == -1 ) {
IfcEntities parents = ifc_product->entity->getInverse(Ifc2x3::Type::IfcRelAggregates);
parents->push(ifc_product->entity->getInverse(Ifc2x3::Type::IfcRelNests));
for ( IfcEntityList::it it = parents->begin(); it != parents->end(); ++ it ) {
Ifc2x3::IfcRelDecomposes::ptr decompose = reinterpret_pointer_cast<IfcBaseClass,Ifc2x3::IfcRelDecomposes>(*it);
Ifc2x3::IfcObjectDefinition* ifc_objectdef = decompose->RelatingObject();
if ( ifc_product == ifc_objectdef ) continue;
parent_id = ifc_objectdef->entity->id();
}
}
return parent_id;
}
IfcGeomObjects::IfcGeomShapeModelObject* create_shape_model_for_next_entity() {
while ( true ) {
Ifc2x3::IfcShapeRepresentation::ptr shaperep;
// Have we reached the end of our list of representations?
if ( shaperep_iterator == shapereps->end() ) {
shapereps.reset();
return 0;
}
shaperep = *shaperep_iterator;
// Has the list of IfcProducts for this representation been initialized?
if ( ! entities ) {
if ( shaperep->hasRepresentationIdentifier() ) {
const std::string representation_identifier = shaperep->RepresentationIdentifier();
if ( shaperep->hasRepresentationType() && representation_identifier == "IAI" && shaperep->RepresentationType() != "BoundingBox" ) {
// Allow for Ifc 2x compatibility
} else if ( representation_identifier != "Body" &&
representation_identifier != "Facetation" ) {
_nextShape();
continue;
}
}
Ifc2x3::IfcProductRepresentation::list prodreps = shaperep->OfProductRepresentation();
entities = Ifc2x3::IfcProduct::list( new IfcTemplatedEntityList<Ifc2x3::IfcProduct>() );
for ( Ifc2x3::IfcProductRepresentation::it it = prodreps->begin(); it != prodreps->end(); ++it ) {
if ( (*it)->is(Ifc2x3::Type::IfcProductDefinitionShape) ) {
Ifc2x3::IfcProductDefinitionShape::ptr pds = reinterpret_pointer_cast<Ifc2x3::IfcProductRepresentation,Ifc2x3::IfcProductDefinitionShape>(*it);
entities->push(pds->ShapeOfProduct());
} else {
// http://buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcrepresentationresource/lexical/ifcproductrepresentation.htm
// IFC2x Edition 3 NOTE Users should not instantiate the entity IfcProductRepresentation from IFC2x Edition 3 onwards.
// It will be changed into an ABSTRACT supertype in future releases of IFC.
// IfcProductRepresentation also lacks the INVERSE relation to IfcProduct
// Let's find the IfcProducts that reference the IfcProductRepresentation anyway
IfcEntities products = (*it)->entity->getInverse(Ifc2x3::Type::IfcProduct);
for ( IfcEntityList::it it = products->begin(); it != products->end(); ++ it ) {
entities->push(reinterpret_pointer_cast<IfcBaseClass,Ifc2x3::IfcProduct>(*it));
}
}
}
// Does this representation have any IfcProducts?
if ( ! entities->Size() ) {
_nextShape();
continue;
}
ifcproduct_iterator = entities->begin();
}
// Have we reached the end of our list of IfcProducts?
if ( ifcproduct_iterator == entities->end() ) {
_nextShape();
continue;
}
IfcGeomObjects::IfcRepresentationShapeModel* shape;
IfcGeom::IfcRepresentationShapeItems shapes;
if ( !IfcGeom::convert_shapes(shaperep,shapes) ) {
_nextShape();
continue;
}
Ifc2x3::IfcProduct::ptr ifc_product = *ifcproduct_iterator;
int parent_id = -1;
try {
parent_id = _getParentId(ifc_product);
} catch (...) {}
const std::string name = ifc_product->hasName() ? ifc_product->Name() : "";
const std::string guid = ifc_product->GlobalId();
gp_Trsf trsf;
try {
IfcGeom::convert(ifc_product->ObjectPlacement(),trsf);
} catch (...) {}
// Does the IfcElement have any IfcOpenings?
// Note that openings for IfcOpeningElements are not processed
Ifc2x3::IfcRelVoidsElement::list openings = Ifc2x3::IfcRelVoidsElement::list();
if ( ifc_product->is(Ifc2x3::Type::IfcElement) && !ifc_product->is(Ifc2x3::Type::IfcOpeningElement) ) {
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcElement>(ifc_product);
openings = element->HasOpenings();
}
// Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements?
if ( ifc_product->is(Ifc2x3::Type::IfcBuildingElementPart ) ) {
Ifc2x3::IfcBuildingElementPart::ptr part = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcBuildingElementPart>(ifc_product);
Ifc2x3::IfcRelDecomposes::list decomposes = part->Decomposes();
for ( Ifc2x3::IfcRelDecomposes::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
Ifc2x3::IfcObjectDefinition::ptr obdef = (*it)->RelatingObject();
if ( obdef->is(Ifc2x3::Type::IfcElement) ) {
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcObjectDefinition,Ifc2x3::IfcElement>(obdef);
openings->push(element->HasOpenings());
}
}
}
if ( !disable_subtractions && openings && openings->Size() ) {
IfcGeom::IfcRepresentationShapeItems opened_shapes;
try {
if ( use_faster_booleans ) {
bool succes = IfcGeom::convert_openings_fast(ifc_product,openings,shapes,trsf,opened_shapes);
if ( ! succes ) {
opened_shapes.clear();
IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes);
}
} else {
IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes);
}
} catch(...) {
Logger::Message(Logger::LOG_ERROR,"Error processing openings for:",ifc_product->entity);
}
if ( use_world_coords ) {
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
it->prepend(trsf);
}
trsf = gp_Trsf();
}
shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),opened_shapes);
} else if ( use_world_coords ) {
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
it->prepend(trsf);
}
trsf = gp_Trsf();
shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),shapes);
} else {
shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),shapes);
}
return new IfcGeomObjects::IfcGeomShapeModelObject(ifc_product->entity->id(), parent_id, name,
Ifc2x3::Type::ToString(ifc_product->type()), guid, trsf, shape);
}
}
bool try_and_create_representations_for_current_entity() {
current_shape_model_obj = create_shape_model_for_next_entity();
if (current_shape_model_obj == 0) {
return false;
}
if (use_brep_data) {
current_brep_data_obj = new IfcGeomObjects::IfcGeomBrepDataObject(*current_shape_model_obj);
if (current_brep_data_obj == 0) {
return false;
}
}
if (!disable_triangulation) {
current_geom_obj = new IfcGeomObjects::IfcGeomObject(*current_shape_model_obj);
if (current_geom_obj == 0) {
return false;
}
}
return true;
}
bool IfcGeomObjects::Next() {
// Free all possible representations of the current geometrical entity
delete current_geom_obj;
delete current_brep_data_obj;
delete current_shape_model_obj;
current_geom_obj = 0;
current_brep_data_obj = 0;
current_shape_model_obj = 0;
// Increment the iterator over the list of products using the current
// shape representation
if (entities) {
++ifcproduct_iterator;
}
return try_and_create_representations_for_current_entity();
}
static std::vector<IfcGeomObjects::IfcObject*> returned_objects;
bool IfcGeomObjects::CleanUp() {
// TODO: Correctly implement destructor for IfcFile
delete ifc_file;
IfcGeom::Cache::Purge();
std::vector<IfcGeomObjects::IfcObject*>::const_iterator it;
for (it = returned_objects.begin(); it != returned_objects.end(); ++ it ) {
delete *it;
}
returned_objects.clear();
return true;
}
const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
IfcObject* ifc_object = 0;
try {
const IfcParse::IfcEntity& ifc_entity = ifc_file->EntityById(id);
if ( ifc_entity->is(Ifc2x3::Type::IfcProduct) ) {
Ifc2x3::IfcProduct::ptr ifc_product = reinterpret_pointer_cast<IfcUtil::IfcBaseClass,Ifc2x3::IfcProduct>(ifc_entity);
int parent_id = -1;
try {
parent_id = _getParentId(ifc_product);
} catch (...) {}
const std::string name = ifc_product->hasName() ? ifc_product->Name() : "";
gp_Trsf trsf;
try {
IfcGeom::convert(ifc_product->ObjectPlacement(),trsf);
} catch (...) {}
ifc_object = new IfcObject(ifc_product->entity->id(),parent_id,name,
Ifc2x3::Type::ToString(ifc_product->type()),ifc_product->GlobalId(),trsf);
}
} catch(...) {}
if ( !ifc_object ) ifc_object = new IfcObject(-1,-1,"","","",gp_Trsf());
returned_objects.push_back(ifc_object);
return ifc_object;
}
const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() {
if (disable_triangulation) {
throw std::runtime_error("No triangulation available");
}
return current_geom_obj;
}
const IfcGeomObjects::IfcGeomShapeModelObject* IfcGeomObjects::GetShapeModel() {
return current_shape_model_obj;
}
const IfcGeomObjects::IfcGeomBrepDataObject* IfcGeomObjects::GetBrepData() {
if (!use_brep_data) {
throw std::runtime_error("No BRep data available");
}
return current_brep_data_obj;
}
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v ) {
if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_EXA ) return (double) 1e18;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PETA ) return (double) 1e15;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_TERA ) return (double) 1e12;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_GIGA ) return (double) 1e9;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MEGA ) return (double) 1e6;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_KILO ) return (double) 1e3;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_HECTO ) return (double) 1e2;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECA ) return (double) 1;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECI ) return (double) 1e-1;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_CENTI ) return (double) 1e-2;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MILLI ) return (double) 1e-3;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MICRO ) return (double) 1e-6;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_NANO ) return (double) 1e-9;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PICO ) return (double) 1e-12;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_FEMTO ) return (double) 1e-15;
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_ATTO ) return (double) 1e-18;
else return 1.0f;
}
void IfcGeomObjects::InitPrecision() {
Ifc2x3::IfcGeometricRepresentationContext::list rep_contexts = ifc_file->EntitiesByType<Ifc2x3::IfcGeometricRepresentationContext>();
// Currently, IfcGeometricRepresentationContext aren't used as much as they should be
// in the evaluation of shape representations, hence, we try to find the one with the
// lowest precision. Typically, a value of 1e-5 is encountered. This value is applied
// to all TopoDS_Shapes generated by one of the IfcGeom::convert() functions.
// TODO: Many of the empirically found tolerances should probably be substituted by
// one that is defined in the model file.
double lowest_precision_encountered = std::numeric_limits<double>::infinity();
bool any_precision_encountered = false;
for (Ifc2x3::IfcGeometricRepresentationContext::it it = rep_contexts->begin(); it != rep_contexts->end(); ++it) {
Ifc2x3::IfcGeometricRepresentationContext* rep_context = *it;
if (rep_context->is(Ifc2x3::Type::IfcGeometricRepresentationSubContext)) continue;
if (rep_context->hasPrecision()) {
const double precision = rep_context->Precision();
if (precision < lowest_precision_encountered) {
any_precision_encountered = true;
lowest_precision_encountered = precision;
}
}
}
if (any_precision_encountered) {
IfcGeom::SetValue(IfcGeom::GV_PRECISION, lowest_precision_encountered);
}
}
static std::string unit_name = "METER";
static float unit_magnitude = 1.0f;
void IfcGeomObjects::InitUnits() {
// Set default units, set length to meters, angles to undefined
IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,1.0);
IfcGeom::SetValue(IfcGeom::GV_PLANEANGLE_UNIT,-1.0);
Ifc2x3::IfcUnitAssignment::list unit_assignments = ifc_file->EntitiesByType<Ifc2x3::IfcUnitAssignment>();
IfcUtil::IfcAbstractSelect::list units = IfcUtil::IfcAbstractSelect::list();
if ( unit_assignments->Size() ) {
Ifc2x3::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin();
units = unit_assignment->Units();
}
if ( ! units ) {
// No units eh... Since tolerances and deflection are specified internally in meters
// we will try to find another indication of the model size.
Ifc2x3::IfcExtrudedAreaSolid::list extrusions = ifc_file->EntitiesByType<Ifc2x3::IfcExtrudedAreaSolid>();
if ( ! extrusions->Size() ) return;
double max_height = -1.0f;
for ( Ifc2x3::IfcExtrudedAreaSolid::it it = extrusions->begin(); it != extrusions->end(); ++ it ) {
const double depth = (*it)->Depth();
if ( depth > max_height ) max_height = depth;
}
if ( max_height > 100.0f ) IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,0.001);
return;
}
try {
for ( IfcUtil::IfcAbstractSelect::it it = units->begin(); it != units->end(); ++ it ) {
std::string current_unit_name = "";
const IfcUtil::IfcAbstractSelect::ptr base = *it;
Ifc2x3::IfcSIUnit::ptr unit = Ifc2x3::IfcSIUnit::ptr();
double value = 1.0f;
if ( base->is(Ifc2x3::Type::IfcConversionBasedUnit) ) {
const Ifc2x3::IfcConversionBasedUnit::ptr u = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcConversionBasedUnit>(base);
current_unit_name = u->Name();
const Ifc2x3::IfcMeasureWithUnit::ptr u2 = u->ConversionFactor();
Ifc2x3::IfcUnit u3 = u2->UnitComponent();
if ( u3->is(Ifc2x3::Type::IfcSIUnit) ) {
unit = (Ifc2x3::IfcSIUnit*) u3;
}
Ifc2x3::IfcValue v = u2->ValueComponent();
IfcUtil::IfcArgumentSelect* v2 = (IfcUtil::IfcArgumentSelect*) v;
const double f = *v2->wrappedValue();
value *= f;
} else if ( base->is(Ifc2x3::Type::IfcSIUnit) ) {
unit = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcSIUnit>(base);
}
if ( unit ) {
if ( unit->hasPrefix() ) {
value *= UnitPrefixToValue(unit->Prefix());
}
Ifc2x3::IfcUnitEnum::IfcUnitEnum type = unit->UnitType();
if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_LENGTHUNIT ) {
IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,value);
if (current_unit_name.empty()) {
if (unit->hasPrefix()) {
current_unit_name = Ifc2x3::IfcSIPrefix::ToString(unit->Prefix());
}
current_unit_name += Ifc2x3::IfcSIUnitName::ToString(unit->Name());
}
unit_magnitude = value;
unit_name = current_unit_name;
} else if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) {
IfcGeom::SetValue(IfcGeom::GV_PLANEANGLE_UNIT,value);
}
}
}
} catch ( IfcException ex ) {
Logger::Message(Logger::LOG_ERROR,ex.what());
}
}
bool IfcGeomObjects::Init(const std::string fn) {
return IfcGeomObjects::Init(fn, 0, 0);
}
bool _Init() {
IfcGeomObjects::InitUnits();
IfcGeomObjects::InitPrecision();
shapereps = ifc_file->EntitiesByType<Ifc2x3::IfcShapeRepresentation>();
if ( ! shapereps ) return false;
shaperep_iterator = shapereps->begin();
entities.reset();
if (!try_and_create_representations_for_current_entity()) {
return false;
}
done = 0;
total = shapereps->Size();
return true;
}
bool IfcGeomObjects::Init(const std::string fn, std::ostream* log1, std::ostream* log2) {
Logger::SetOutput(log1,log2);
ifc_file = new IfcParse::IfcFile();
if ( !ifc_file->Init(fn) ) return false;
return _Init();
}
bool IfcGeomObjects::Init(std::istream& f, int len, std::ostream* log1, std::ostream* log2) {
Logger::SetOutput(log1,log2);
ifc_file = new IfcParse::IfcFile();
if ( !ifc_file->Init(f, len) ) return false;
return _Init();
}
bool IfcGeomObjects::Init(void* data, int len) {
Logger::SetOutput(0,0);
ifc_file = new IfcParse::IfcFile();
if ( !ifc_file->Init(data, len) ) return false;
return _Init();
}
void IfcGeomObjects::Settings(int setting, bool value) {
switch ( setting ) {
case USE_WORLD_COORDS:
use_world_coords = value;
break;
case WELD_VERTICES:
weld_vertices = value;
break;
case CONVERT_BACK_UNITS:
convert_back_units = value;
break;
case USE_BREP_DATA:
use_brep_data = value;
break;
case FASTER_BOOLEANS:
use_faster_booleans = value;
break;
case SEW_SHELLS:
IfcGeom::SetValue(IfcGeom::GV_MAX_FACES_TO_SEW,value ? 1000 : -1);
break;
case FORCE_CCW_FACE_ORIENTATION:
IfcGeom::SetValue(IfcGeom::GV_FORCE_CCW_FACE_ORIENTATION,value ? 1 : -1);
break;
case DISABLE_OPENING_SUBTRACTIONS:
disable_subtractions = value;
break;
case DISABLE_TRIANGULATION:
disable_triangulation = value;
break;
}
}
int IfcGeomObjects::Progress() {
return 100 * done / total;
}
const std::string& IfcGeomObjects::GetUnitName() {
return unit_name;
}
const float IfcGeomObjects::GetUnitMagnitude() {
return unit_magnitude;
}
const std::string IfcGeomObjects::GetLog() {
return Logger::GetLog();
}
IfcParse::IfcFile* IfcGeomObjects::GetFile() {
return ifc_file;
}
static double black[3] = {0,0,0};
IfcGeomObjects::Material::Material(const IfcGeom::SurfaceStyle* style) : style(style) {}
bool IfcGeomObjects::Material::hasDiffuse() const { return style->Diffuse(); }
bool IfcGeomObjects::Material::hasSpecular() const { return style->Specular(); }
bool IfcGeomObjects::Material::hasTransparency() const { return style->Transparency(); }
bool IfcGeomObjects::Material::hasSpecularity() const { return style->Specularity(); }
const double* IfcGeomObjects::Material::diffuse() const { if (hasDiffuse()) return &((*style->Diffuse()).R()); else return black; }
const double* IfcGeomObjects::Material::specular() const { if (hasSpecular()) return &((*style->Specular()).R()); else return black; }
double IfcGeomObjects::Material::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; }
double IfcGeomObjects::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); else return 0; }
const std::string IfcGeomObjects::Material::name() const { return style->Name(); }
bool IfcGeomObjects::Material::operator==(const IfcGeomObjects::Material& other) const { return style == other.style; }
int IfcGeomObjects::IfcRepresentationBrepData::id() const { return _id; }
const std::string& IfcGeomObjects::IfcRepresentationBrepData::brep_data() const { return _brep_data; }
int IfcGeomObjects::IfcRepresentationTriangulation::id() const { return _id; }
const std::vector<float>& IfcGeomObjects::IfcRepresentationTriangulation::verts() const { return _verts; }
const std::vector<int>& IfcGeomObjects::IfcRepresentationTriangulation::faces() const { return _faces; }
const std::vector<int>& IfcGeomObjects::IfcRepresentationTriangulation::edges() const { return _edges; }
const std::vector<float>& IfcGeomObjects::IfcRepresentationTriangulation::normals() const { return _normals; }
const std::vector<int>& IfcGeomObjects::IfcRepresentationTriangulation::material_ids() const { return _material_ids; }
const std::vector<IfcGeomObjects::Material>& IfcGeomObjects::IfcRepresentationTriangulation::materials() const { return _materials; }
int IfcGeomObjects::IfcObject::id() const { return _id; }
int IfcGeomObjects::IfcObject::parent_id() const { return _parent_id; }
const std::string& IfcGeomObjects::IfcObject::name() const { return _name; }
const std::string& IfcGeomObjects::IfcObject::type() const { return _type; }
const std::string& IfcGeomObjects::IfcObject::guid() const { return _guid; }
const std::vector<float>& IfcGeomObjects::IfcObject::matrix() const { return _matrix; }
const IfcGeomObjects::IfcRepresentationShapeModel& IfcGeomObjects::IfcGeomShapeModelObject::mesh() const { return *_mesh; }
const IfcGeomObjects::IfcRepresentationTriangulation& IfcGeomObjects::IfcGeomObject::mesh() const { return *_mesh; }
const IfcGeomObjects::IfcRepresentationBrepData& IfcGeomObjects::IfcGeomBrepDataObject::mesh() const { return *_mesh; }
-286
View File
@@ -1,286 +0,0 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Geometrical data in an IFC file consists of shapes (IfcShapeRepresentation) *
* and instances (SUBTYPE OF IfcBuildingElement e.g. IfcWindow). *
* *
* IfcMesh is a class that represents a triangulated IfcShapeRepresentation. *
* IfcMesh.verts is a 1 dimensional vector of float defining the cartesian *
* coordinates of the vertices of the triangulated shape in the format of *
* [x1,y1,z1,..,xn,yn,zn] *
* IfcMesh.faces is a 1 dimensional vector of int containing the indices of *
* the triangles referencing positions in IfcMesh.verts *
* IfcMesh.edges is a 1 dimensional vector of int in {0,1} that dictates *
* the visibility of the edges that span the faces in IfcMesh.faces *
* *
* IfcGeomObject represents the actual IfcBuildingElements. *
* IfcGeomObject.name is the GUID of the element *
* IfcGeomObject.type is the datatype of the element e.g. IfcWindow *
* IfcGeomObject.mesh is a pointer to an IfcMesh *
* IfcGeomObject.matrix is a 4x3 matrix that defines the orientation and *
* translation of the mesh in relation to the world origin *
* *
* Init(char* fn) parses the IFC file in fn, returns true on succes. *
* *
* Get() returns a pointer to the current IfcGeomObject *
* *
* Next() returns true if there is an entity yet available *
* *
* Progress() returns an int in [0..100] that indicates the overall progress *
* *
********************************************************************************/
#ifndef IFCOBJECTS_H
#define IFCOBJECTS_H
#include <map>
#include <vector>
#include <algorithm>
#include <gp_Mat.hxx>
#include <gp_Mat2d.hxx>
#include <gp_GTrsf.hxx>
#include <gp_GTrsf2d.hxx>
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include "../ifcparse/IfcParse.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"
namespace IfcGeomObjects {
// Enumeration of setting identifiers. These settings define the
// behaviour of various aspects of IfcOpenShell.
// Specifies whether vertices are welded, meaning that the coordinates
// vector will only contain unique xyz-triplets. This results in a
// manifold mesh which is useful for modelling applications, but might
// result in unwanted shading artifacts in rendering applications.
const int WELD_VERTICES = 1;
// Specifies whether to apply the local placements of building elements
// directly to the coordinates of the representation mesh rather than
// to represent the local placement in the 4x3 matrix, which will in that
// case be the identity matrix.
const int USE_WORLD_COORDS = 2;
// Internally IfcOpenShell measures everything in meters. This settings
// specifies whether to convert IfcGeomObjects back to the units in which
// the geometry in the IFC file is specified.
const int CONVERT_BACK_UNITS = 3;
// Specifies whether to use the Open Cascade BREP format for representation
// items rather than to create triangle meshes. This is useful is IfcOpenShell
// is used as a library in an application that is also built on Open Cascade.
const int USE_BREP_DATA = 4;
// Specifies whether to sew IfcConnectedFaceSets (open and closed shells) to
// TopoDS_Shells or whether to keep them as a loose collection of faces.
const int SEW_SHELLS = 5;
// Specifies whether to compose IfcOpeningElements into a single compound
// in order to speed up the processing of opening subtractions.
const int FASTER_BOOLEANS = 6;
// By default singular faces have no explicitly defined orientation, to
// force faces to be defined CounterClockWise set this to true.
const int FORCE_CCW_FACE_ORIENTATION = 7;
// Disables the subtraction of IfcOpeningElement representations from
// the related building element representations.
const int DISABLE_OPENING_SUBTRACTIONS = 8;
// Disables the triangulation of the topological representations. Useful if
// the client application understands Open Cascade's native format.
const int DISABLE_TRIANGULATION = 9;
// End of settings enumeration.
// A nested pair of floats and a material index to be able to store an XYZ coordinate in a map.
// TODO: Make this a std::tuple when compilers add support for that.
typedef std::pair<int, std::pair<float,std::pair<float,float> > > VertKey;
typedef std::map<VertKey,int> VertKeyMap;
typedef std::pair<int,int> Edge;
class Material {
private:
const IfcGeom::SurfaceStyle* style;
public:
explicit Material(const IfcGeom::SurfaceStyle* style);
// Material(const Material& other);
// Material& operator=(const Material& other);
bool hasDiffuse() const;
bool hasSpecular() const;
bool hasTransparency() const;
bool hasSpecularity() const;
const double* diffuse() const;
const double* specular() const;
double transparency() const;
double specularity() const;
const std::string name() const;
bool operator==(const Material& other) const;
};
class IfcRepresentationShapeModel {
private:
unsigned int id;
const IfcGeom::IfcRepresentationShapeItems shapes;
IfcRepresentationShapeModel(const IfcRepresentationShapeModel& other);
IfcRepresentationShapeModel& operator=(const IfcRepresentationShapeModel& other);
public:
IfcRepresentationShapeModel(unsigned int id, const IfcGeom::IfcRepresentationShapeItems& shapes)
: id(id)
, shapes(shapes)
{}
virtual ~IfcRepresentationShapeModel() {}
IfcGeom::IfcRepresentationShapeItems::const_iterator begin() const { return shapes.begin(); }
IfcGeom::IfcRepresentationShapeItems::const_iterator end() const { return shapes.end(); }
const unsigned int& getId() const { return id; }
};
class IfcRepresentationBrepData {
private:
int _id;
std::string _brep_data;
public:
int id() const;
const std::string& brep_data() const;
IfcRepresentationBrepData(const IfcRepresentationShapeModel& s);
virtual ~IfcRepresentationBrepData() {}
private:
IfcRepresentationBrepData();
IfcRepresentationBrepData(const IfcRepresentationBrepData&);
IfcRepresentationBrepData& operator=(const IfcRepresentationBrepData&);
};
class IfcRepresentationTriangulation {
private:
int _id;
std::vector<float> _verts;
std::vector<int> _faces;
std::vector<int> _edges;
std::vector<float> _normals;
std::vector<int> _material_ids;
std::vector<Material> _materials;
VertKeyMap welds;
public:
int id() const;
const std::vector<float>& verts() const;
const std::vector<int>& faces() const;
const std::vector<int>& edges() const;
const std::vector<float>& normals() const;
const std::vector<int>& material_ids() const;
const std::vector<Material>& materials() const;
IfcRepresentationTriangulation(const IfcRepresentationShapeModel& s);
virtual ~IfcRepresentationTriangulation() {}
private:
int addvert(int material_index, const gp_XYZ& p);
inline void addedge(int n1, int n2, std::map<std::pair<int,int>,int>& edgecount, std::vector<std::pair<int,int> >& edges_temp) {
const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) );
if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1;
else edgecount[e] ++;
edges_temp.push_back(e);
}
IfcRepresentationTriangulation();
IfcRepresentationTriangulation(const IfcRepresentationTriangulation&);
IfcRepresentationTriangulation& operator=(const IfcRepresentationTriangulation&);
};
class IfcObject {
private:
int _id;
int _parent_id;
std::string _name;
std::string _type;
std::string _guid;
std::vector<float> _matrix;
public:
int id() const;
int parent_id() const;
const std::string& name() const;
const std::string& type() const;
const std::string& guid() const;
const std::vector<float>& matrix() const;
IfcObject(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf);
virtual ~IfcObject() {}
};
class IfcGeomShapeModelObject : public IfcObject {
private:
IfcRepresentationShapeModel* _mesh;
public:
const IfcRepresentationShapeModel& mesh() const;
IfcGeomShapeModelObject(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf, IfcRepresentationShapeModel* mesh);
virtual ~IfcGeomShapeModelObject() {
delete _mesh;
}
private:
IfcGeomShapeModelObject(const IfcGeomShapeModelObject& other);
IfcGeomShapeModelObject& operator=(const IfcGeomShapeModelObject& other);
};
class IfcGeomObject : public IfcObject {
private:
IfcRepresentationTriangulation* _mesh;
public:
const IfcRepresentationTriangulation& mesh() const;
IfcGeomObject(const IfcGeomShapeModelObject& shape_model);
virtual ~IfcGeomObject() {
delete _mesh;
}
private:
IfcGeomObject(const IfcGeomObject& other);
IfcGeomObject& operator=(const IfcGeomObject& other);
};
class IfcGeomBrepDataObject : public IfcObject {
private:
IfcRepresentationBrepData* _mesh;
public:
const IfcRepresentationBrepData& mesh() const;
IfcGeomBrepDataObject(const IfcGeomShapeModelObject& shape_model);
virtual ~IfcGeomBrepDataObject() {
delete _mesh;
}
private:
IfcGeomBrepDataObject(const IfcGeomBrepDataObject& other);
IfcGeomBrepDataObject& operator=(const IfcGeomBrepDataObject& other);
};
bool Init(const std::string fn);
bool Init(void* data, int len);
bool Init(const std::string fn, std::ostream* log1= 0, std::ostream* log2= 0);
bool Init(std::istream& f, int len, std::ostream* log1= 0, std::ostream* log2= 0);
void Settings(int setting, bool value);
void InitUnits();
void InitPrecision();
const IfcGeomObject* Get();
const IfcObject* GetObject(int id);
const IfcGeomBrepDataObject* GetBrepData();
const IfcGeomShapeModelObject* GetShapeModel();
bool Next();
int Progress();
const std::string& GetUnitName();
const float GetUnitMagnitude();
const std::string GetLog();
IfcParse::IfcFile* GetFile();
bool CleanUp();
}
#endif
+37 -44
View File
@@ -19,18 +19,9 @@
#include <map>
#include "IfcGeomRenderStyles.h"
#include "IfcGeom.h"
namespace IfcGeom {
namespace Cache {
std::map<int,SurfaceStyle> Style;
void PurgeStyleCache() {
Style.clear();
}
}
}
bool process_colour(Ifc2x3::IfcColourRgb* colour, std::tr1::array<double, 3>& rgb) {
bool process_colour(IfcSchema::IfcColourRgb* colour, std::tr1::array<double, 3>& rgb) {
if (colour != 0) {
rgb[0] = colour->Red();
rgb[1] = colour->Green();
@@ -39,39 +30,39 @@ bool process_colour(Ifc2x3::IfcColourRgb* colour, std::tr1::array<double, 3>& rg
return colour != 0;
}
bool process_colour(IfcUtil::IfcArgumentSelect* factor, std::tr1::array<double, 3>& rgb) {
bool process_colour(IfcSchema::IfcNormalisedRatioMeasure* factor, std::tr1::array<double, 3>& rgb) {
if (factor != 0) {
const double f = *factor->wrappedValue();
const double f = *factor;
rgb[0] = rgb[1] = rgb[2] = f;
}
return factor != 0;
}
bool process_colour(Ifc2x3::IfcColourOrFactor colour_or_factor, std::tr1::array<double, 3>& rgb) {
bool process_colour(IfcSchema::IfcColourOrFactor* colour_or_factor, std::tr1::array<double, 3>& rgb) {
if (colour_or_factor == 0) {
return false;
} else if (colour_or_factor->is(Ifc2x3::Type::IfcColourRgb)) {
return process_colour(static_cast<Ifc2x3::IfcColourRgb*>(colour_or_factor), rgb);
} else if (colour_or_factor->is(Ifc2x3::Type::IfcNormalisedRatioMeasure)) {
return process_colour(static_cast<IfcUtil::IfcArgumentSelect*>(colour_or_factor), rgb);
} else if (colour_or_factor->is(IfcSchema::Type::IfcColourRgb)) {
return process_colour(static_cast<IfcSchema::IfcColourRgb*>(colour_or_factor), rgb);
} else if (colour_or_factor->is(IfcSchema::Type::IfcNormalisedRatioMeasure)) {
return process_colour(static_cast<IfcSchema::IfcNormalisedRatioMeasure*>(colour_or_factor), rgb);
} else {
return false;
}
}
const IfcGeom::SurfaceStyle* IfcGeom::get_style(Ifc2x3::IfcRepresentationItem* item) {
std::pair<Ifc2x3::IfcSurfaceStyle*, Ifc2x3::IfcSurfaceStyleShading*> shading_styles = get_surface_style<Ifc2x3::IfcSurfaceStyleShading>(item);
const IfcGeom::SurfaceStyle* IfcGeom::Kernel::get_style(const IfcSchema::IfcRepresentationItem* item) {
std::pair<IfcSchema::IfcSurfaceStyle*, IfcSchema::IfcSurfaceStyleShading*> shading_styles = get_surface_style<IfcSchema::IfcSurfaceStyleShading>(item);
if (shading_styles.second == 0) {
return 0;
}
int surface_style_id = shading_styles.first->entity->id();
std::map<int,SurfaceStyle>::const_iterator it = Cache::Style.find(surface_style_id);
if (it != Cache::Style.end()) {
std::map<int,SurfaceStyle>::const_iterator it = cache.Style.find(surface_style_id);
if (it != cache.Style.end()) {
return &(it->second);
}
SurfaceStyle surface_style;
if (shading_styles.first->hasName()) {
surface_style = SurfaceStyle(surface_style_id, shading_styles.first->Name());
if (shading_styles.first->Name()) {
surface_style = SurfaceStyle(surface_style_id, *shading_styles.first->Name());
} else {
surface_style = SurfaceStyle(surface_style_id);
}
@@ -79,41 +70,41 @@ const IfcGeom::SurfaceStyle* IfcGeom::get_style(Ifc2x3::IfcRepresentationItem* i
if (process_colour(shading_styles.second->SurfaceColour(), rgb)) {
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
}
if (shading_styles.second->is(Ifc2x3::Type::IfcSurfaceStyleRendering)) {
Ifc2x3::IfcSurfaceStyleRendering* rendering_style = static_cast<Ifc2x3::IfcSurfaceStyleRendering*>(shading_styles.second);
if (rendering_style->hasDiffuseColour() && process_colour(rendering_style->DiffuseColour(), rgb)) {
if (shading_styles.second->is(IfcSchema::Type::IfcSurfaceStyleRendering)) {
IfcSchema::IfcSurfaceStyleRendering* rendering_style = static_cast<IfcSchema::IfcSurfaceStyleRendering*>(shading_styles.second);
if (rendering_style->DiffuseColour() && process_colour(*rendering_style->DiffuseColour(), rgb)) {
SurfaceStyle::ColorComponent diffuse = surface_style.Diffuse().get_value_or(SurfaceStyle::ColorComponent(1,1,1));
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(diffuse.R() * rgb[0], diffuse.G() * rgb[1], diffuse.B() * rgb[2]));
}
if (rendering_style->hasDiffuseTransmissionColour()) {
if (rendering_style->DiffuseTransmissionColour()) {
// Not supported
}
if (rendering_style->hasReflectionColour()) {
if (rendering_style->ReflectionColour()) {
// Not supported
}
if (rendering_style->hasSpecularColour() && process_colour(rendering_style->SpecularColour(), rgb)) {
if (rendering_style->SpecularColour() && process_colour(*rendering_style->SpecularColour(), rgb)) {
surface_style.Specular().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
}
if (rendering_style->hasSpecularHighlight()) {
IfcUtil::IfcArgumentSelect* highlight = static_cast<IfcUtil::IfcArgumentSelect*>(rendering_style->SpecularHighlight());
if (highlight->is(Ifc2x3::Type::IfcSpecularRoughness)) {
double roughness = *highlight->wrappedValue();
if (rendering_style->SpecularHighlight()) {
IfcSchema::IfcSpecularHighlightSelect* highlight = *rendering_style->SpecularHighlight();
if (highlight->is(IfcSchema::Type::IfcSpecularRoughness)) {
double roughness = *((IfcSchema::IfcSpecularRoughness*)highlight);
if (roughness >= 1e-9) {
surface_style.Specularity().reset(1.0 / roughness);
}
} else if (highlight->is(Ifc2x3::Type::IfcSpecularRoughness)) {
surface_style.Specularity().reset(*highlight->wrappedValue());
} else if (highlight->is(IfcSchema::Type::IfcSpecularExponent)) {
surface_style.Specularity().reset(*((IfcSchema::IfcSpecularExponent*)highlight));
}
}
if (rendering_style->hasTransmissionColour()) {
if (rendering_style->TransmissionColour()) {
// Not supported
}
if (rendering_style->hasTransparency()) {
const double d = rendering_style->Transparency();
if (rendering_style->Transparency()) {
const double d = *rendering_style->Transparency();
surface_style.Transparency().reset(d);
}
}
return &(Cache::Style[surface_style_id] = surface_style);
return &(cache.Style[surface_style_id] = surface_style);
}
static std::map<std::string, IfcGeom::SurfaceStyle> default_materials;
@@ -161,9 +152,11 @@ void InitDefaultMaterials() {
const IfcGeom::SurfaceStyle* IfcGeom::get_default_style(const std::string& s) {
if (!default_materials_initialized) InitDefaultMaterials();
std::map<std::string, IfcGeom::SurfaceStyle>::const_iterator it = default_materials.find(s);
if (it == default_materials.end()) return &default_material;
else {
const IfcGeom::SurfaceStyle& surface_style = it->second;
return &surface_style;
if (it == default_materials.end()) {
default_materials.insert(std::make_pair(s, IfcGeom::SurfaceStyle(s)));
default_materials[s].Diffuse().reset(*default_material.Diffuse());
it = default_materials.find(s);
}
const IfcGeom::SurfaceStyle& surface_style = it->second;
return &surface_style;
}
+18 -53
View File
@@ -26,7 +26,11 @@
#include <array>
#endif
#ifdef USE_IFC4
#include "../ifcparse/Ifc4.h"
#else
#include "../ifcparse/Ifc2x3.h"
#endif
namespace IfcGeom {
class SurfaceStyle {
@@ -52,10 +56,20 @@ namespace IfcGeom {
boost::optional<double> transparency;
boost::optional<double> specularity;
public:
SurfaceStyle() {}
SurfaceStyle(int id) : id(id) {}
SurfaceStyle() {
this->name = "IfcSurfaceStyleShading";
}
SurfaceStyle(int id) : id(id) {
std::stringstream sstr;
sstr << "IfcSurfaceStyleShading_" << id;
this->name = sstr.str();
}
SurfaceStyle(const std::string& name) : name(name) {}
SurfaceStyle(int id, const std::string& name) : id(id), name(name) {}
SurfaceStyle(int id, const std::string& name) : id(id) {
std::stringstream sstr;
sstr << id << "_" << name;
this->name = sstr.str();
}
// Not used at this point. In fact, equality testing in the current
// architecture can just as easily be accomplished by comparing the
@@ -71,21 +85,7 @@ namespace IfcGeom {
}
}
const std::string Name() const {
if (name && id) {
std::stringstream sstr;
sstr << (*id) << "_" << (*name);
return sstr.str();
} else if (name) {
return *name;
} else if (id) {
std::stringstream sstr;
sstr << "IfcSurfaceStyleShading_" << (*id);
return sstr.str();
} else {
return "IfcSurfaceStyleShading";
}
}
const std::string& Name() const { return *name; }
const boost::optional<ColorComponent>& Diffuse() const { return diffuse; }
const boost::optional<ColorComponent>& Specular() const { return specular; }
@@ -97,42 +97,7 @@ namespace IfcGeom {
boost::optional<double>& Specularity() { return specularity; }
};
template <typename T> std::pair<Ifc2x3::IfcSurfaceStyle*, T*> get_surface_style(Ifc2x3::IfcRepresentationItem* representation_item) {
Ifc2x3::IfcStyledItem::list styled_items = representation_item->StyledByItem();
for (Ifc2x3::IfcStyledItem::it jt = styled_items->begin(); jt != styled_items->end(); ++jt) {
Ifc2x3::IfcPresentationStyleAssignment::list style_assignments = (*jt)->Styles();
for (Ifc2x3::IfcPresentationStyleAssignment::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) {
IfcAbstractSelect::list styles = (*kt)->Styles();
for (IfcAbstractSelect::it lt = styles->begin(); lt != styles->end(); ++lt) {
IfcAbstractSelect::ptr style = *lt;
if (style->is(Ifc2x3::Type::IfcSurfaceStyle)) {
Ifc2x3::IfcSurfaceStyle* surface_style = (Ifc2x3::IfcSurfaceStyle*) style;
if (surface_style->Side() != Ifc2x3::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE) {
IfcAbstractSelect::list styles_elements = surface_style->Styles();
for (IfcAbstractSelect::it mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) {
if ((*mt)->is(T::Class())) {
return std::make_pair(surface_style, (T*) *mt);
}
}
}
}
}
}
// StyledByItem is a SET [0:1] OF IfcStyledItem, so we
// break after encountering the first IfcStyledItem
break;
}
return std::make_pair<Ifc2x3::IfcSurfaceStyle*, T*>(0,0);
}
const SurfaceStyle* get_style(Ifc2x3::IfcRepresentationItem* representation_item);
const SurfaceStyle* get_default_style(const std::string& ifc_type);
namespace Cache {
void PurgeStyleCache();
}
}
#endif
+59
View File
@@ -0,0 +1,59 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRep_Builder.hxx>
#include <TopoDS_Compound.hxx>
#include <BRepBuilderAPI_GTransform.hxx>
#include "../ifcgeom/IfcGeom.h"
#include "IfcGeomRepresentation.h"
IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
: Representation(brep.settings())
, _id(brep.getId())
{
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
const TopoDS_Shape& s = it->Shape();
gp_GTrsf trsf = it->Placement();
if (settings().convert_back_units()) {
gp_Trsf scale;
scale.SetScaleFactor(1.0 / settings().unit_magnitude());
trsf.PreMultiply(scale);
}
bool trsf_valid = false;
gp_Trsf _trsf;
try {
_trsf = trsf.Trsf();
trsf_valid = true;
} catch (...) {}
const TopoDS_Shape moved_shape = trsf_valid ? s.Moved(_trsf) :
BRepBuilderAPI_GTransform(s,trsf,true).Shape();
builder.Add(compound,moved_shape);
}
std::stringstream sstream;
BRepTools::Write(compound,sstream);
_brep_data = sstream.str();
}
+272
View File
@@ -0,0 +1,272 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef IFCGEOMREPRESENTATION_H
#define IFCGEOMREPRESENTATION_H
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepGProp_Face.hxx>
#include <Poly_Triangulation.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TopExp_Explorer.hxx>
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../ifcgeom/IfcGeomMaterial.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"
namespace IfcGeom {
namespace Representation {
class Representation {
protected:
const ElementSettings _settings;
public:
explicit Representation(const ElementSettings& settings)
: _settings(settings)
{}
const ElementSettings& settings() const { return _settings; }
virtual ~Representation() {}
};
class BRep : public Representation {
private:
unsigned int id;
const IfcGeom::IfcRepresentationShapeItems shapes;
BRep(const BRep& other);
BRep& operator=(const BRep& other);
public:
BRep(const ElementSettings& settings, unsigned int id, const IfcGeom::IfcRepresentationShapeItems& shapes)
: Representation(settings)
, id(id)
, shapes(shapes)
{}
virtual ~BRep() {}
IfcGeom::IfcRepresentationShapeItems::const_iterator begin() const { return shapes.begin(); }
IfcGeom::IfcRepresentationShapeItems::const_iterator end() const { return shapes.end(); }
const unsigned int& getId() const { return id; }
};
class Serialization : public Representation {
private:
int _id;
std::string _brep_data;
public:
int id() const { return _id; }
const std::string& brep_data() const { return _brep_data; }
Serialization(const BRep& brep);
virtual ~Serialization() {}
private:
Serialization();
Serialization(const Serialization&);
Serialization& operator=(const Serialization&);
};
template <typename P>
class Triangulation : public Representation {
private:
// A nested pair of floats and a material index to be able to store an XYZ coordinate in a map.
// TODO: Make this a std::tuple when compilers add support for that.
typedef typename std::pair<P, std::pair<P, P> > Coordinate;
typedef typename std::pair<int, Coordinate> VertexKey;
typedef std::map<VertexKey, int> VertexKeyMap;
typedef std::pair<int, int> Edge;
int _id;
std::vector<P> _verts;
std::vector<int> _faces;
std::vector<int> _edges;
std::vector<P> _normals;
std::vector<int> _material_ids;
std::vector<Material> _materials;
VertexKeyMap welds;
public:
int id() const { return _id; }
const std::vector<P>& verts() const { return _verts; }
const std::vector<int>& faces() const { return _faces; }
const std::vector<int>& edges() const { return _edges; }
const std::vector<P>& normals() const { return _normals; }
const std::vector<int>& material_ids() const { return _material_ids; }
const std::vector<Material>& materials() const { return _materials; }
Triangulation(const BRep& shape_model)
: Representation(shape_model.settings())
, _id(shape_model.getId())
{
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shape_model.begin(); it != shape_model.end(); ++ it ) {
int surface_style_id = -1;
if (it->hasStyle()) {
Material adapter(&it->Style());
std::vector<Material>::const_iterator jt = std::find(_materials.begin(), _materials.end(), adapter);
if (jt == _materials.end()) {
surface_style_id = _materials.size();
_materials.push_back(adapter);
} else {
surface_style_id = jt - _materials.begin();
}
}
if (settings().apply_default_materials() && surface_style_id == -1) {
Material material(IfcGeom::get_default_style(settings().element_type()));
std::vector<Material>::const_iterator it = std::find(_materials.begin(), _materials.end(), material);
if (it == _materials.end()) {
surface_style_id = _materials.size();
_materials.push_back(material);
} else {
surface_style_id = it - _materials.begin();
}
}
const TopoDS_Shape& s = it->Shape();
const gp_GTrsf& trsf = it->Placement();
// Triangulate the shape
try {
BRepMesh_IncrementalMesh(s, settings().deflection_tolerance());
} catch(...) {
// TODO: Catch outside
// Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape:",ifc_file->entityById(_id)->entity);
Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape");
continue;
}
TopExp_Explorer exp;
// Iterates over the faces of the shape
for ( exp.Init(s,TopAbs_FACE); exp.More(); exp.Next() ) {
TopoDS_Face face = TopoDS::Face(exp.Current());
TopLoc_Location loc;
Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face,loc);
if ( ! tri.IsNull() ) {
// A 3x3 matrix to rotate the vertex normals
const gp_Mat rotation_matrix = trsf.VectorialPart();
// Keep track of the number of times an edge is used
// Manifold edges (i.e. edges used twice) are deemed invisible
std::map<std::pair<int,int>,int> edgecount;
std::vector<std::pair<int,int> > edges_temp;
const TColgp_Array1OfPnt& nodes = tri->Nodes();
const TColgp_Array1OfPnt2d& uvs = tri->UVNodes();
std::vector<gp_XYZ> coords;
BRepGProp_Face prop(face);
std::map<int,int> dict;
// Vertex normals are only calculated if vertices are not welded
const bool calculate_normals = !settings().weld_vertices();
for( int i = 1; i <= nodes.Length(); ++ i ) {
coords.push_back(nodes(i).Transformed(loc).XYZ());
trsf.Transforms(*coords.rbegin());
dict[i] = addVertex(surface_style_id, *coords.rbegin());
if ( calculate_normals ) {
const gp_Pnt2d& uv = uvs(i);
gp_Pnt p;
gp_Vec normal_direction;
prop.Normal(uv.X(),uv.Y(),p,normal_direction);
gp_Vec normal(0., 0., 0.);
if (normal_direction.Magnitude() > ALMOST_ZERO) {
normal = gp_Dir(normal_direction.XYZ() * rotation_matrix);
}
_normals.push_back((float)normal.X());
_normals.push_back((float)normal.Y());
_normals.push_back((float)normal.Z());
}
}
const Poly_Array1OfTriangle& triangles = tri->Triangles();
for( int i = 1; i <= triangles.Length(); ++ i ) {
int n1,n2,n3;
if ( face.Orientation() == TopAbs_REVERSED )
triangles(i).Get(n3,n2,n1);
else triangles(i).Get(n1,n2,n3);
/* An alternative would be to calculate normals based
* on the coordinates of the mesh vertices */
/*
const gp_XYZ pt1 = coords[n1-1];
const gp_XYZ pt2 = coords[n2-1];
const gp_XYZ pt3 = coords[n3-1];
const gp_XYZ v1 = pt2-pt1;
const gp_XYZ v2 = pt3-pt2;
gp_Dir normal = gp_Dir(v1^v2);
_normals.push_back((float)normal.X());
_normals.push_back((float)normal.Y());
_normals.push_back((float)normal.Z());
*/
_faces.push_back(dict[n1]);
_faces.push_back(dict[n2]);
_faces.push_back(dict[n3]);
_material_ids.push_back(surface_style_id);
addEdge(n1,n2,edgecount,edges_temp);
addEdge(n2,n3,edgecount,edges_temp);
addEdge(n3,n1,edgecount,edges_temp);
}
for ( std::vector<std::pair<int,int> >::const_iterator it = edges_temp.begin(); it != edges_temp.end(); ++it ) {
_edges.push_back(edgecount[*it]==1);
}
}
}
}
}
virtual ~Triangulation() {}
private:
// Welds vertices that belong to different faces
int addVertex(int material_index, const gp_XYZ& p) {
const P X = static_cast<P>(settings().convert_back_units() ? (p.X() / settings().unit_magnitude()) : p.X());
const P Y = static_cast<P>(settings().convert_back_units() ? (p.Y() / settings().unit_magnitude()) : p.Y());
const P Z = static_cast<P>(settings().convert_back_units() ? (p.Z() / settings().unit_magnitude()) : p.Z());
int i = (int) _verts.size() / 3;
if (settings().weld_vertices()) {
const VertexKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z)));
typename VertexKeyMap::const_iterator it = welds.find(key);
if ( it != welds.end() ) return it->second;
i = (int) welds.size();
welds[key] = i;
}
_verts.push_back(X);
_verts.push_back(Y);
_verts.push_back(Z);
return i;
}
inline void addEdge(int n1, int n2, std::map<std::pair<int,int>,int>& edgecount, std::vector<std::pair<int,int> >& edges_temp) {
const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) );
if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1;
else edgecount[e] ++;
edges_temp.push_back(e);
}
Triangulation();
Triangulation(const Triangulation&);
Triangulation& operator=(const Triangulation&);
};
}
}
#endif
+620 -106
View File
@@ -35,6 +35,7 @@
#include <gp_GTrsf2d.hxx>
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include <gp_Ax1.hxx>
#include <gp_Ax3.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Pln.hxx>
@@ -44,12 +45,17 @@
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Geom_Line.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <BRepOffsetAPI_Sewing.hxx>
#include <BRepOffsetAPI_MakePipe.hxx>
#include <BRepOffsetAPI_MakePipeShell.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
@@ -62,10 +68,21 @@
#include <TopExp_Explorer.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepPrimAPI_MakeRevol.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepPrimAPI_MakeCone.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeWedge.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepBuilderAPI_MakeShell.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <ShapeFix_Shape.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
@@ -74,61 +91,160 @@
#include <TopLoc_Location.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <Standard_Version.hxx>
#include "../ifcgeom/IfcGeom.h"
bool IfcGeom::convert(const Ifc2x3::IfcExtrudedAreaSolid::ptr l, TopoDS_Shape& shape) {
TopoDS_Face face;
if ( ! IfcGeom::convert_face(l->SweptArea(),face) ) return false;
const double height = l->Depth() * IfcGeom::GetValue(GV_LENGTH_UNIT);
bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& shape) {
TopoDS_Shape face;
if ( !convert_face(l->SweptArea(),face) ) return false;
const double height = l->Depth() * getValue(GV_LENGTH_UNIT);
gp_Trsf trsf;
IfcGeom::convert(l->Position(),trsf);
IfcGeom::Kernel::convert(l->Position(),trsf);
gp_Dir dir;
convert(l->ExtrudedDirection(),dir);
shape = BRepPrimAPI_MakePrism(face,height*dir);
shape.Nullify();
if (face.ShapeType() == TopAbs_COMPOUND) {
// For compounds (most likely the result of a IfcCompositeProfileDef)
// create a compound solid shape.
TopExp_Explorer exp(face, TopAbs_FACE);
TopoDS_CompSolid compound;
BRep_Builder builder;
builder.MakeCompSolid(compound);
int num_faces_extruded = 0;
for (; exp.More(); exp.Next(), ++num_faces_extruded) {
builder.Add(compound, BRepPrimAPI_MakePrism(exp.Current(), height*dir));
}
if (num_faces_extruded) {
shape = compound;
}
}
if (shape.IsNull()) {
shape = BRepPrimAPI_MakePrism(face, height*dir);
}
shape.Move(trsf);
return ! shape.IsNull();
}
bool IfcGeom::convert(const Ifc2x3::IfcFacetedBrep::ptr l, IfcRepresentationShapeItems& shape) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfLinearExtrusion* l, TopoDS_Shape& shape) {
TopoDS_Wire wire;
if ( !convert_wire(l->SweptCurve(), wire) ) {
TopoDS_Face face;
if ( !convert_face(l->SweptCurve(),face) ) return false;
TopExp_Explorer exp(face, TopAbs_WIRE);
wire = TopoDS::Wire(exp.Current());
}
const double height = l->Depth() * getValue(GV_LENGTH_UNIT);
gp_Trsf trsf;
IfcGeom::Kernel::convert(l->Position(),trsf);
gp_Dir dir;
convert(l->ExtrudedDirection(),dir);
shape = BRepPrimAPI_MakePrism(wire, height*dir);
shape.Move(trsf);
return !shape.IsNull();
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfRevolution* l, TopoDS_Shape& shape) {
TopoDS_Wire wire;
if ( !convert_wire(l->SweptCurve(), wire) ) {
TopoDS_Face face;
if ( !convert_face(l->SweptCurve(),face) ) return false;
TopExp_Explorer exp(face, TopAbs_WIRE);
wire = TopoDS::Wire(exp.Current());
}
gp_Ax1 ax1;
IfcGeom::Kernel::convert(l->AxisPosition(), ax1);
gp_Trsf trsf;
IfcGeom::Kernel::convert(l->Position(),trsf);
shape = BRepPrimAPI_MakeRevol(wire, ax1);
shape.Move(trsf);
return !shape.IsNull();
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_Shape& shape) {
const double ang = l->Angle() * getValue(GV_PLANEANGLE_UNIT);
TopoDS_Face face;
if ( ! convert_face(l->SweptArea(),face) ) return false;
gp_Ax1 ax1;
IfcGeom::Kernel::convert(l->Axis(), ax1);
gp_Trsf trsf;
IfcGeom::Kernel::convert(l->Position(),trsf);
if (ang >= M_PI * 2. - ALMOST_ZERO) {
shape = BRepPrimAPI_MakeRevol(face, ax1);
} else {
shape = BRepPrimAPI_MakeRevol(face, ax1, ang);
}
shape.Move(trsf);
return !shape.IsNull();
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFacetedBrep* l, IfcRepresentationShapeItems& shape) {
TopoDS_Shape s;
if (IfcGeom::convert_shape(l->Outer(),s) ) {
shape.push_back(IfcRepresentationShapeItem(s, get_style(l->Outer())));
const SurfaceStyle* collective_style = get_style(l);
if (convert_shape(l->Outer(),s) ) {
const SurfaceStyle* indiv_style = get_style(l->Outer());
shape.push_back(IfcRepresentationShapeItem(s, indiv_style ? indiv_style : collective_style));
return true;
}
return false;
}
bool IfcGeom::convert(const Ifc2x3::IfcFaceBasedSurfaceModel::ptr l, IfcRepresentationShapeItems& shapes) {
Ifc2x3::IfcConnectedFaceSet::list facesets = l->FbsmFaces();
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
IfcSchema::IfcConnectedFaceSet::list::ptr facesets = l->FbsmFaces();
const SurfaceStyle* collective_style = get_style(l);
for( Ifc2x3::IfcConnectedFaceSet::it it = facesets->begin(); it != facesets->end(); ++ it ) {
for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) {
TopoDS_Shape s;
const SurfaceStyle* shell_style = get_style(*it);
if (IfcGeom::convert_shape(*it,s)) {
if (convert_shape(*it,s)) {
shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style));
}
}
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcHalfSpaceSolid::ptr l, TopoDS_Shape& shape) {
Ifc2x3::IfcSurface::ptr surface = l->BaseSurface();
if ( ! surface->is(Ifc2x3::Type::IfcPlane) ) {
// Not implemented
bool IfcGeom::Kernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, TopoDS_Shape& shape) {
IfcSchema::IfcSurface* surface = l->BaseSurface();
if ( ! surface->is(IfcSchema::Type::IfcPlane) ) {
Logger::Message(Logger::LOG_ERROR, "Unsupported BaseSurface:", surface->entity);
return false;
}
gp_Pln pln;
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcSurface,Ifc2x3::IfcPlane>(surface),pln);
IfcGeom::Kernel::convert((IfcSchema::IfcPlane*)surface,pln);
const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction());
shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid();
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr l, TopoDS_Shape& shape) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, TopoDS_Shape& shape) {
TopoDS_Shape halfspace;
if ( ! IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcPolygonalBoundedHalfSpace,Ifc2x3::IfcHalfSpaceSolid>(l),halfspace) ) return false;
if ( ! IfcGeom::Kernel::convert((IfcSchema::IfcHalfSpaceSolid*)l,halfspace) ) return false;
TopoDS_Wire wire;
if ( ! IfcGeom::convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false;
if ( ! convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false;
gp_Trsf trsf;
convert(l->Position(),trsf);
TopoDS_Shape prism = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,200));
@@ -137,86 +253,160 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr l, TopoDS_
shape = BRepAlgoAPI_Common(halfspace,prism);
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcShellBasedSurfaceModel::ptr l, IfcRepresentationShapeItems& shapes) {
IfcUtil::IfcAbstractSelect::list shells = l->SbsmBoundary();
bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
IfcEntityList::ptr shells = l->SbsmBoundary();
const SurfaceStyle* collective_style = get_style(l);
for( IfcUtil::IfcAbstractSelect::it it = shells->begin(); it != shells->end(); ++ it ) {
for( IfcEntityList::it it = shells->begin(); it != shells->end(); ++ it ) {
TopoDS_Shape s;
const SurfaceStyle* shell_style = 0;
if ((*it)->is(Ifc2x3::Type::IfcRepresentationItem)) {
shell_style = get_style((Ifc2x3::IfcRepresentationItem*)*it);
if ((*it)->is(IfcSchema::Type::IfcRepresentationItem)) {
shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it);
}
if (IfcGeom::convert_shape(*it,s)) {
if (convert_shape(*it,s)) {
shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style));
}
}
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shape& shape) {
TopoDS_Shape s1, s2;
TopoDS_Wire boundary_wire;
Ifc2x3::IfcBooleanOperand operand1 = l->FirstOperand();
Ifc2x3::IfcBooleanOperand operand2 = l->SecondOperand();
bool is_halfspace = operand2->is(Ifc2x3::Type::IfcHalfSpaceSolid);
if ( ! IfcGeom::convert_shape(operand1,s1) )
return false;
bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) {
TopoDS_Shape s1, s2;
IfcRepresentationShapeItems items1, items2;
TopoDS_Wire boundary_wire;
IfcSchema::IfcBooleanOperand* operand1 = l->FirstOperand();
IfcSchema::IfcBooleanOperand* operand2 = l->SecondOperand();
bool is_halfspace = operand2->is(IfcSchema::Type::IfcHalfSpaceSolid);
if ( is_shape_collection(operand1) ) {
if (!(convert_shapes(operand1, items1) && flatten_shape_list(items1, s1, true))) {
return false;
}
} else {
if ( ! convert_shape(operand1, s1) ) {
return false;
}
{ TopoDS_Solid temp_solid;
s1 = ensure_fit_for_subtraction(s1, temp_solid); }
}
const double first_operand_volume = shape_volume(s1);
if ( first_operand_volume <= ALMOST_ZERO )
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",l->FirstOperand()->entity);
if ( !IfcGeom::convert_shape(l->SecondOperand(),s2) ) {
bool shape2_processed = false;
if ( is_shape_collection(operand2) ) {
shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true);
} else {
shape2_processed = convert_shape(operand2,s2);
if (shape2_processed && !is_halfspace) {
TopoDS_Solid temp_solid;
s2 = ensure_fit_for_subtraction(s2, temp_solid);
}
}
if (!shape2_processed) {
shape = s1;
Logger::Message(Logger::LOG_ERROR,"Failed to convert SecondOperand of:",l->entity);
return true;
}
if ( ! is_halfspace ) {
if (!is_halfspace) {
const double second_operand_volume = shape_volume(s2);
if ( second_operand_volume <= ALMOST_ZERO )
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",operand2->entity);
}
bool valid_cut = false;
BRepAlgoAPI_Cut brep_cut(s1,s2);
if ( brep_cut.IsDone() ) {
TopoDS_Shape result = brep_cut;
const IfcSchema::IfcBooleanOperator::IfcBooleanOperator op = l->Operator();
ShapeFix_Shape fix(result);
fix.Perform();
result = fix.Shape();
if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) {
bool valid_cut = false;
BRepAlgoAPI_Cut brep_cut(s1,s2);
if ( brep_cut.IsDone() ) {
TopoDS_Shape result = brep_cut;
ShapeFix_Shape fix(result);
try {
fix.Perform();
result = fix.Shape();
} catch (...) {
Logger::Message(Logger::LOG_WARNING, "Shape healing failed on boolean result", l->entity);
}
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
if ( is_valid ) {
shape = result;
valid_cut = true;
}
}
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
if ( is_valid ) {
shape = result;
valid_cut = true;
}
}
if ( valid_cut ) {
const double volume_after_subtraction = shape_volume(shape);
if ( ALMOST_THE_SAME(first_operand_volume,volume_after_subtraction) )
Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",l->entity);
} else {
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",l->entity);
shape = s1;
}
if ( valid_cut ) {
const double volume_after_subtraction = shape_volume(shape);
if ( ALMOST_THE_SAME(first_operand_volume,volume_after_subtraction) )
Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",l->entity);
} else {
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",l->entity);
shape = s1;
}
return true;
return true;
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) {
BRepAlgoAPI_Fuse brep_fuse(s1,s2);
if ( brep_fuse.IsDone() ) {
TopoDS_Shape result = brep_fuse;
ShapeFix_Shape fix(result);
fix.Perform();
result = fix.Shape();
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
if ( is_valid ) {
shape = result;
return true;
}
}
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) {
BRepAlgoAPI_Common brep_common(s1,s2);
if ( brep_common.IsDone() ) {
TopoDS_Shape result = brep_common;
ShapeFix_Shape fix(result);
fix.Perform();
result = fix.Shape();
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
if ( is_valid ) {
shape = result;
return true;
}
}
}
return false;
}
bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& shape) {
Ifc2x3::IfcFace::list faces = l->CfsFaces();
bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& shape) {
IfcSchema::IfcFace::list::ptr faces = l->CfsFaces();
bool facesAdded = false;
const unsigned int num_faces = faces->Size();
if ( num_faces < GetValue(GV_MAX_FACES_TO_SEW) ) {
const unsigned int num_faces = faces->size();
bool valid_shell = false;
if ( num_faces < getValue(GV_MAX_FACES_TO_SEW) ) {
BRepOffsetAPI_Sewing builder;
builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMaxTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMinTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) {
TopoDS_Face face;
if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) {
bool converted_face = false;
try {
converted_face = convert_face(*it,face);
} catch (...) {}
if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) {
builder.Add(face);
facesAdded = true;
} else {
@@ -224,20 +414,38 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
}
}
if ( ! facesAdded ) return false;
builder.Perform();
shape = builder.SewedShape();
try {
ShapeFix_Solid solid;
solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
shape = solid.SolidFromShell(TopoDS::Shell(shape));
builder.Perform();
shape = builder.SewedShape();
valid_shell = BRepCheck_Analyzer(shape).IsValid();
} catch(...) {}
} else {
if (valid_shell) {
try {
ShapeFix_Solid solid;
solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
TopoDS_Solid solid_shape = solid.SolidFromShell(TopoDS::Shell(shape));
if (!solid_shape.IsNull()) {
try {
BRepClass3d_SolidClassifier classifier(solid_shape);
shape = solid_shape;
} catch (...) {}
}
} catch(...) {}
} else {
Logger::Message(Logger::LOG_WARNING,"Failed to sew faceset:",l->entity);
}
}
if (!valid_shell) {
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) {
TopoDS_Face face;
if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) {
bool converted_face = false;
try {
converted_face = convert_face(*it,face);
} catch (...) {}
if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) {
builder.Add(compound,face);
facesAdded = true;
} else {
@@ -249,56 +457,362 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
}
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcMappedItem::ptr l, IfcRepresentationShapeItems& shapes) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentationShapeItems& shapes) {
gp_GTrsf gtrsf;
Ifc2x3::IfcCartesianTransformationOperator::ptr transform = l->MappingTarget();
if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3DnonUniform) ) {
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcCartesianTransformationOperator,
Ifc2x3::IfcCartesianTransformationOperator3DnonUniform>(transform),gtrsf);
} else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator2DnonUniform) ) {
IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget();
if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) {
IfcGeom::Kernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf);
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) {
Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity);
return false;
} else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3D) ) {
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) {
gp_Trsf trsf;
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcCartesianTransformationOperator,
Ifc2x3::IfcCartesianTransformationOperator3D>(transform),trsf);
IfcGeom::Kernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf);
gtrsf = trsf;
} else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator2D) ) {
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) {
gp_Trsf2d trsf_2d;
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcCartesianTransformationOperator,
Ifc2x3::IfcCartesianTransformationOperator2D>(transform),trsf_2d);
IfcGeom::Kernel::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,trsf_2d);
gtrsf = (gp_Trsf) trsf_2d;
}
Ifc2x3::IfcRepresentationMap::ptr map = l->MappingSource();
Ifc2x3::IfcAxis2Placement placement = map->MappingOrigin();
IfcSchema::IfcRepresentationMap* map = l->MappingSource();
IfcSchema::IfcAxis2Placement* placement = map->MappingOrigin();
gp_Trsf trsf;
if (placement->is(Ifc2x3::Type::IfcAxis2Placement3D)) {
IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)placement,trsf);
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf);
} else {
gp_Trsf2d trsf_2d;
IfcGeom::convert((Ifc2x3::IfcAxis2Placement2D*)placement,trsf_2d);
IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d);
trsf = trsf_2d;
}
gtrsf.Multiply(trsf);
const unsigned int previous_size = (const unsigned int) shapes.size();
bool b = IfcGeom::convert_shapes(map->MappedRepresentation(),shapes);
bool b = convert_shapes(map->MappedRepresentation(),shapes);
for ( unsigned int i = previous_size; i < shapes.size(); ++ i ) {
shapes[i].append(gtrsf);
}
return b;
}
bool IfcGeom::convert(const Ifc2x3::IfcShapeRepresentation::ptr l, IfcRepresentationShapeItems& shapes) {
Ifc2x3::IfcRepresentationItem::list items = l->Items();
if ( ! items->Size() ) return false;
for ( Ifc2x3::IfcRepresentationItem::it it = items->begin(); it != items->end(); ++ it ) {
Ifc2x3::IfcRepresentationItem* representation_item = *it;
if ( IfcGeom::is_shape_collection(representation_item) ) IfcGeom::convert_shapes(*it,shapes);
else {
TopoDS_Shape s;
if (IfcGeom::convert_shape(representation_item,s)) {
shapes.push_back(IfcRepresentationShapeItem(s, get_style(representation_item)));
bool IfcGeom::Kernel::convert(const IfcSchema::IfcShapeRepresentation* l, IfcRepresentationShapeItems& shapes) {
IfcSchema::IfcRepresentationItem::list::ptr items = l->Items();
bool part_succes = false;
if ( items->size() ) {
for ( IfcSchema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++ it ) {
IfcSchema::IfcRepresentationItem* representation_item = *it;
if ( is_shape_collection(representation_item) ) {
part_succes |= convert_shapes(*it, shapes);
} else {
TopoDS_Shape s;
if (convert_shape(representation_item,s)) {
shapes.push_back(IfcRepresentationShapeItem(s, get_style(representation_item)));
part_succes |= true;
}
}
}
}
return part_succes;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresentationShapeItems& shapes) {
IfcEntityList::ptr elements = l->Elements();
if ( !elements->size() ) return false;
bool part_succes = false;
const IfcGeom::SurfaceStyle* parent_style = get_style(l);
for ( IfcEntityList::it it = elements->begin(); it != elements->end(); ++ it ) {
IfcSchema::IfcGeometricSetSelect* element = *it;
if (element->is(IfcSchema::Type::IfcSurface)) {
IfcSchema::IfcSurface* surface = (IfcSchema::IfcSurface*) element;
TopoDS_Shape s;
if (convert_shape(surface, s)) {
part_succes = true;
const IfcGeom::SurfaceStyle* style = get_style(surface);
shapes.push_back(IfcRepresentationShapeItem(s, style ? style : parent_style));
}
}
}
return part_succes;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcBlock* l, TopoDS_Shape& shape) {
const double dx = l->XLength() * getValue(GV_LENGTH_UNIT);
const double dy = l->YLength() * getValue(GV_LENGTH_UNIT);
const double dz = l->ZLength() * getValue(GV_LENGTH_UNIT);
BRepPrimAPI_MakeBox builder(dx, dy, dz);
gp_Trsf trsf;
IfcGeom::Kernel::convert(l->Position(),trsf);
shape = builder.Solid().Moved(trsf);
return true;
}
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularPyramid* l, TopoDS_Shape& shape) {
const double dx = l->XLength() * getValue(GV_LENGTH_UNIT);
const double dy = l->YLength() * getValue(GV_LENGTH_UNIT);
const double dz = l->Height() * getValue(GV_LENGTH_UNIT);
BRepPrimAPI_MakeWedge builder(dx, dz, dy, dx / 2., dy / 2., dx / 2., dy / 2.);
gp_Trsf trsf1, trsf2;
trsf2.SetValues(
1, 0, 0, 0,
0, 0, 1, 0,
0, 1, 0, 0
#if OCC_VERSION_HEX < 0x60800
, Precision::Angular(), Precision::Confusion()
#endif
);
IfcGeom::Kernel::convert(l->Position(), trsf1);
shape = BRepBuilderAPI_Transform(builder.Solid(), trsf1 * trsf2);
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRightCircularCylinder* l, TopoDS_Shape& shape) {
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
const double h = l->Height() * getValue(GV_LENGTH_UNIT);
BRepPrimAPI_MakeCylinder builder(r, h);
gp_Trsf trsf;
IfcGeom::Kernel::convert(l->Position(),trsf);
shape = builder.Solid().Moved(trsf);
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRightCircularCone* l, TopoDS_Shape& shape) {
const double r = l->BottomRadius() * getValue(GV_LENGTH_UNIT);
const double h = l->Height() * getValue(GV_LENGTH_UNIT);
BRepPrimAPI_MakeCone builder(r, 0., h);
gp_Trsf trsf;
IfcGeom::Kernel::convert(l->Position(),trsf);
shape = builder.Solid().Moved(trsf);
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcSphere* l, TopoDS_Shape& shape) {
const double r = l->Radius() * getValue(GV_LENGTH_UNIT);
BRepPrimAPI_MakeSphere builder(r);
gp_Trsf trsf;
IfcGeom::Kernel::convert(l->Position(),trsf);
shape = builder.Solid().Moved(trsf);
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCsgSolid* l, TopoDS_Shape& shape) {
return convert_shape(l->TreeRootExpression(), shape);
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCurveBoundedPlane* l, TopoDS_Shape& face) {
gp_Pln pln;
IfcGeom::Kernel::convert(l->BasisSurface(), pln);
gp_Trsf trsf;
trsf.SetTransformation(pln.Position());
TopoDS_Wire outer;
convert_wire(l->OuterBoundary(), outer);
BRepBuilderAPI_MakeFace mf (outer);
mf.Add(outer);
IfcSchema::IfcCurve::list::ptr inner = l->InnerBoundaries();
for (IfcSchema::IfcCurve::list::it it = inner->begin(); it != inner->end(); ++it) {
TopoDS_Wire inner;
convert_wire(*it, inner);
mf.Add(inner);
}
ShapeFix_Shape sfs(mf.Face());
sfs.Perform();
face = TopoDS::Face(sfs.Shape()).Moved(trsf);
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularTrimmedSurface* l, TopoDS_Shape& face) {
if (!l->BasisSurface()->is(IfcSchema::Type::IfcPlane)) {
Logger::Message(Logger::LOG_ERROR, "Unsupported BasisSurface:", l->BasisSurface()->entity);
return false;
}
gp_Pln pln;
IfcGeom::Kernel::convert((IfcSchema::IfcPlane*) l->BasisSurface(), pln);
BRepBuilderAPI_MakeFace mf(pln, l->U1(), l->U2(), l->V1(), l->V2());
face = mf.Face();
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_Shape& shape) {
gp_Trsf directrix, position;
TopoDS_Shape face;
TopoDS_Wire wire, section;
if (!l->ReferenceSurface()->is(IfcSchema::Type::IfcPlane)) {
Logger::Message(Logger::LOG_WARNING, "Reference surface not supported", l->ReferenceSurface()->entity);
return false;
}
if (!IfcGeom::Kernel::convert(l->Position(), position) ||
!convert_face(l->SweptArea(), face) ||
!convert_wire(l->Directrix(), wire) ) {
return false;
}
gp_Pln pln;
gp_Pnt directrix_origin;
gp_Vec directrix_tangent;
bool directrix_on_plane = true;
IfcGeom::Kernel::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln);
// As per Informal propositions 2: The Directrix shall lie on the ReferenceSurface.
// This is not always the case with the test files in the repository. I am not sure
// how to deal with this and whether my interpretation of the propositions is
// correct. However, if it has been asserted that the vertices of the directrix do
// not conform to the ReferenceSurface, the ReferenceSurface is ignored.
{
for (TopExp_Explorer exp(wire, TopAbs_VERTEX); exp.More(); exp.Next()) {
if (pln.Distance(BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()))) > ALMOST_ZERO) {
directrix_on_plane = false;
Logger::Message(Logger::LOG_WARNING, "The Directrix does not lie on the ReferenceSurface", l->entity);
break;
}
}
}
{
TopExp_Explorer exp(wire, TopAbs_EDGE);
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
double u0, u1;
Handle(Geom_Curve) crv = BRep_Tool::Curve(edge, u0, u1);
crv->D1(u0, directrix_origin, directrix_tangent);
}
if (pln.Axis().Direction().IsNormal(directrix_tangent, Precision::Approximation()) && directrix_on_plane) {
directrix.SetTransformation(gp_Ax3(directrix_origin, directrix_tangent, pln.Axis().Direction()), gp::XOY());
} else {
directrix.SetTransformation(gp_Ax3(directrix_origin, directrix_tangent), gp::XOY());
}
face = BRepBuilderAPI_Transform(face, directrix);
// NB: Note that StartParam and EndParam param are ignored and the assumption is
// made that the parametric range over which to be swept matches the IfcCurve in
// its entirety.
BRepOffsetAPI_MakePipeShell builder(wire);
{ TopExp_Explorer exp(face, TopAbs_WIRE);
section = TopoDS::Wire(exp.Current()); }
builder.Add(section);
builder.SetTransitionMode(BRepBuilderAPI_RightCorner);
if (directrix_on_plane) {
builder.SetMode(pln.Axis().Direction());
}
builder.Build();
builder.MakeSolid();
shape = builder.Shape();
shape.Move(position);
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcSweptDiskSolid* l, TopoDS_Shape& shape) {
TopoDS_Wire wire, section1, section2;
bool hasInnerRadius = l->InnerRadius() ? true : false;
if (!convert_wire(l->Directrix(), wire)) {
return false;
}
gp_Ax2 directrix;
{
gp_Pnt directrix_origin;
gp_Vec directrix_tangent;
TopExp_Explorer exp(wire, TopAbs_EDGE);
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
double u0, u1;
Handle(Geom_Curve) crv = BRep_Tool::Curve(edge, u0, u1);
crv->D1(u0, directrix_origin, directrix_tangent);
directrix = gp_Ax2(directrix_origin, directrix_tangent);
}
const double r1 = l->Radius() * getValue(GV_LENGTH_UNIT);
Handle(Geom_Circle) circle = new Geom_Circle(directrix, r1);
section1 = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(circle));
if (hasInnerRadius) {
const double r2 = (*l->InnerRadius()) * getValue(GV_LENGTH_UNIT);
if (r2 < getValue(GV_PRECISION)) {
// Subtraction of pipes with small radii is unstable.
hasInnerRadius = false;
} else {
Handle(Geom_Circle) circle = new Geom_Circle(directrix, r2);
section2 = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(circle));
}
}
// NB: Note that StartParam and EndParam param are ignored and the assumption is
// made that the parametric range over which to be swept matches the IfcCurve in
// its entirety.
// NB2: Contrary to IfcSurfaceCurveSweptAreaSolid the transition mode has been
// set to create round corners as this has proven to work better with the types
// of directrices encountered, which do not necessarily conform to a surface.
{ BRepOffsetAPI_MakePipeShell builder(wire);
builder.Add(section1);
builder.SetTransitionMode(BRepBuilderAPI_RoundCorner);
builder.Build();
builder.MakeSolid();
shape = builder.Shape(); }
if (hasInnerRadius) {
BRepOffsetAPI_MakePipeShell builder(wire);
builder.Add(section2);
builder.SetTransitionMode(BRepBuilderAPI_RoundCorner);
builder.Build();
builder.MakeSolid();
TopoDS_Shape inner = builder.Shape();
BRepAlgoAPI_Cut brep_cut(shape, inner);
bool is_valid = false;
if (brep_cut.IsDone()) {
TopoDS_Shape result = brep_cut;
ShapeFix_Shape fix(result);
fix.Perform();
result = fix.Shape();
is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
if (is_valid) {
shape = result;
}
}
if (!is_valid) {
Logger::Message(Logger::LOG_WARNING, "Failed to subtract inner radius void for:", l->entity);
}
}
return true;
}
#ifdef USE_IFC4
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCylindricalSurface* l, TopoDS_Shape& face) {
gp_Trsf trsf;
IfcGeom::Kernel::convert(l->Position(),trsf);
face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius()), getValue(GV_PRECISION)).Face().Moved(trsf);
return true;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcAdvancedBrep* l, TopoDS_Shape& shape) {
return convert(l->Outer(), shape);
}
#endif
+215 -77
View File
@@ -47,15 +47,18 @@
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Geom_Line.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <BRepOffsetAPI_Sewing.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeShell.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
@@ -63,31 +66,29 @@
#include <TopoDS_Wire.hxx>
#include <TopoDS_Face.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <TopTools_ListOfShape.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepBuilderAPI_MakeShell.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepOffsetAPI_Sewing.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <BRepFilletAPI_MakeFillet2d.hxx>
#include <BRep_Tool.hxx>
#include <ShapeFix_Shape.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeFix_Solid.hxx>
#include <BRepFilletAPI_MakeFillet2d.hxx>
#include <TopLoc_Location.hxx>
#include <BRep_Tool.hxx>
#include "../ifcgeom/IfcGeom.h"
bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire) {
if ( IfcGeom::GetValue(GV_PLANEANGLE_UNIT)<0 ) {
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) {
if ( getValue(GV_PLANEANGLE_UNIT)<0 ) {
Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity);
// Temporarily pretend we do have unit information
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,1.0);
setValue(GV_PLANEANGLE_UNIT,1.0);
bool succes_radians = false;
bool succes_degrees = false;
@@ -97,17 +98,17 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
// First try radians
TopoDS_Wire wire_radians, wire_degrees;
try {
succes_radians = IfcGeom::convert(l,wire_radians);
succes_radians = IfcGeom::Kernel::convert(l,wire_radians);
} catch (...) {}
// Now try degrees
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,0.0174532925199433);
setValue(GV_PLANEANGLE_UNIT,0.0174532925199433);
try {
succes_degrees = IfcGeom::convert(l,wire_degrees);
succes_degrees = IfcGeom::Kernel::convert(l,wire_degrees);
} catch (...) {}
// Restore to unknown unit state
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,-1.0);
setValue(GV_PLANEANGLE_UNIT,-1.0);
if ( succes_degrees && ! succes_radians ) {
use_degrees = true;
@@ -138,19 +139,19 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
return use_radians || use_degrees;
}
Ifc2x3::IfcCompositeCurveSegment::list segments = l->Segments();
IfcSchema::IfcCompositeCurveSegment::list::ptr segments = l->Segments();
BRepBuilderAPI_MakeWire w;
//TopoDS_Vertex last_vertex;
for( Ifc2x3::IfcCompositeCurveSegment::it it = segments->begin(); it != segments->end(); ++ it ) {
const Ifc2x3::IfcCurve::ptr curve = (*it)->ParentCurve();
for( IfcSchema::IfcCompositeCurveSegment::list::it it = segments->begin(); it != segments->end(); ++ it ) {
IfcSchema::IfcCurve* curve = (*it)->ParentCurve();
TopoDS_Wire wire2;
if ( ! IfcGeom::convert_wire(curve,wire2) ) {
if ( !convert_wire(curve,wire2) ) {
Logger::Message(Logger::LOG_ERROR,"Failed to convert curve:",curve->entity);
continue;
}
if ( ! (*it)->SameSense() ) wire2.Reverse();
ShapeFix_ShapeTolerance FTol;
FTol.SetTolerance(wire2, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_WIRE);
FTol.SetTolerance(wire2, getValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_WIRE);
/*if ( it != segments->begin() ) {
TopExp_Explorer exp (wire2,TopAbs_VERTEX);
const TopoDS_Vertex& first_vertex = TopoDS::Vertex(exp.Current());
@@ -171,15 +172,16 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
wire = w.Wire();
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
Ifc2x3::IfcCurve::ptr basis_curve = l->BasisCurve();
bool isConic = basis_curve->is(Ifc2x3::Type::IfcConic);
double parameterFactor = isConic ? IfcGeom::GetValue(GV_PLANEANGLE_UNIT) : IfcGeom::GetValue(GV_LENGTH_UNIT);
bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) {
IfcSchema::IfcCurve* basis_curve = l->BasisCurve();
bool isConic = basis_curve->is(IfcSchema::Type::IfcConic);
double parameterFactor = isConic ? getValue(GV_PLANEANGLE_UNIT) : getValue(GV_LENGTH_UNIT);
Handle(Geom_Curve) curve;
if ( ! IfcGeom::convert_curve(basis_curve,curve) ) return false;
bool trim_cartesian = l->MasterRepresentation() == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN;
IfcUtil::IfcAbstractSelect::list trims1 = l->Trim1();
IfcUtil::IfcAbstractSelect::list trims2 = l->Trim2();
if ( !convert_curve(basis_curve,curve) ) return false;
bool trim_cartesian = l->MasterRepresentation() == IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN;
IfcEntityList::ptr trims1 = l->Trim1();
IfcEntityList::ptr trims2 = l->Trim2();
bool trimmed1 = false;
bool trimmed2 = false;
unsigned sense_agreement = l->SenseAgreement() ? 0 : 1;
@@ -188,24 +190,24 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
bool has_flts[2] = {false,false};
bool has_pnts[2] = {false,false};
BRepBuilderAPI_MakeWire w;
for ( IfcUtil::IfcAbstractSelect::it it = trims1->begin(); it != trims1->end(); it ++ ) {
const IfcUtil::IfcAbstractSelect::ptr i = *it;
if ( i->is(Ifc2x3::Type::IfcCartesianPoint) ) {
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnts[sense_agreement] );
for ( IfcEntityList::it it = trims1->begin(); it != trims1->end(); it ++ ) {
IfcUtil::IfcBaseClass* i = *it;
if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) {
IfcGeom::Kernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[sense_agreement] );
has_pnts[sense_agreement] = true;
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) ) {
const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
} else if ( i->is(IfcSchema::Type::IfcParameterValue) ) {
const double value = *((IfcSchema::IfcParameterValue*)i);
flts[sense_agreement] = value * parameterFactor;
has_flts[sense_agreement] = true;
}
}
for ( IfcUtil::IfcAbstractSelect::it it = trims2->begin(); it != trims2->end(); it ++ ) {
const IfcUtil::IfcAbstractSelect::ptr i = *it;
if ( i->is(Ifc2x3::Type::IfcCartesianPoint) ) {
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnts[1-sense_agreement] );
for ( IfcEntityList::it it = trims2->begin(); it != trims2->end(); it ++ ) {
IfcUtil::IfcBaseClass* i = *it;
if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) {
IfcGeom::Kernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[1-sense_agreement] );
has_pnts[1-sense_agreement] = true;
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) ) {
const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
} else if ( i->is(IfcSchema::Type::IfcParameterValue) ) {
const double value = *((IfcSchema::IfcParameterValue*)i);
flts[1-sense_agreement] = value * parameterFactor;
has_flts[1-sense_agreement] = true;
}
@@ -213,15 +215,15 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
trim_cartesian &= has_pnts[0] && has_pnts[1];
bool trim_cartesian_failed = !trim_cartesian;
if ( trim_cartesian ) {
if ( pnts[0].Distance(pnts[1]) < GetValue(GV_WIRE_CREATION_TOLERANCE) ) {
if ( pnts[0].Distance(pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE) ) {
Logger::Message(Logger::LOG_WARNING,"Skipping segment with length below tolerance level:",l->entity);
return false;
}
ShapeFix_ShapeTolerance FTol;
TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(pnts[0]);
TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(pnts[1]);
FTol.SetTolerance(v1, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX);
FTol.SetTolerance(v2, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX);
FTol.SetTolerance(v1, getValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX);
FTol.SetTolerance(v2, getValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX);
BRepBuilderAPI_MakeEdge e (curve,v1,v2);
if ( ! e.IsDone() ) {
BRepBuilderAPI_EdgeError err = e.Error();
@@ -238,11 +240,21 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
// is defined by an IfcCartesianPoint and an IfcVector with Magnitude. Because
// the vector is normalised when passed to Geom_Line constructor the magnitude
// needs to be factored in with the IfcParameterValue here.
if ( basis_curve->is(Ifc2x3::Type::IfcLine) ) {
Ifc2x3::IfcLine* line = static_cast<Ifc2x3::IfcLine*>(basis_curve);
if ( basis_curve->is(IfcSchema::Type::IfcLine) ) {
IfcSchema::IfcLine* line = static_cast<IfcSchema::IfcLine*>(basis_curve);
const double magnitude = line->Dir()->Magnitude();
flts[0] *= magnitude; flts[1] *= magnitude;
}
if ( basis_curve->is(IfcSchema::Type::IfcEllipse) ) {
IfcSchema::IfcEllipse* ellipse = static_cast<IfcSchema::IfcEllipse*>(basis_curve);
double x = ellipse->SemiAxis1() * getValue(GV_LENGTH_UNIT);
double y = ellipse->SemiAxis2() * getValue(GV_LENGTH_UNIT);
const bool rotated = y > x;
if (rotated) {
flts[0] -= M_PI / 2.;
flts[1] -= M_PI / 2.;
}
}
if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],(double)(M_PI*2.0)),0.0f) ) {
w.Add(BRepBuilderAPI_MakeEdge(curve));
} else {
@@ -259,41 +271,167 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
return false;
}
}
bool IfcGeom::convert(const Ifc2x3::IfcPolyline::ptr l, TopoDS_Wire& result) {
Ifc2x3::IfcCartesianPoint::list points = l->Points();
BRepBuilderAPI_MakeWire w;
gp_Pnt P1;gp_Pnt P2;
for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
IfcGeom::convert(*it,P2);
if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) )
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
P1 = P2;
bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& result) {
IfcSchema::IfcCartesianPoint::list::ptr points = l->Points();
// Parse and store the points in a sequence
TColgp_SequenceOfPnt polygon;
for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) {
gp_Pnt pnt;
IfcGeom::Kernel::convert(*it, pnt);
polygon.Append(pnt);
}
// Remove points that are too close to one another
remove_redundant_points_from_loop(polygon, false);
BRepBuilderAPI_MakePolygon w;
for (int i = 1; i <= polygon.Length(); ++i) {
w.Add(polygon.Value(i));
}
result = w.Wire();
return true;
}
bool IfcGeom::convert(const Ifc2x3::IfcPolyLoop::ptr l, TopoDS_Wire& result) {
Ifc2x3::IfcCartesianPoint::list points = l->Polygon();
BRepBuilderAPI_MakeWire w;
gp_Pnt P1;gp_Pnt P2;gp_Pnt F;
int count = 0;
for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
IfcGeom::convert(*it,P2);
if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) ) {
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
count ++;
} else if ( ! count ) F = P2;
P1 = P2;
}
if ( !P1.IsEqual(F,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) {
w.Add(BRepBuilderAPI_MakeEdge(P1,F));
count ++;
}
if ( count < 3 ) return false;
bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& result) {
IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon();
result = w.Wire();
// Parse and store the points in a sequence
TColgp_SequenceOfPnt polygon;
for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) {
gp_Pnt pnt;
IfcGeom::Kernel::convert(*it, pnt);
polygon.Append(pnt);
}
// A loop should consist of at least three vertices
int original_count = polygon.Length();
if (original_count < 3) {
Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity);
return false;
}
// Remove points that are too close to one another
remove_redundant_points_from_loop(polygon, true);
int count = polygon.Length();
if (original_count - count != 0) {
std::stringstream ss; ss << (original_count - count) << " edges removed for:";
Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity);
}
if (count < 3) {
Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity);
return false;
}
BRepBuilderAPI_MakePolygon w;
for (int i = 1; i <= polygon.Length(); ++i) {
w.Add(polygon.Value(i));
}
w.Close();
result = w.Wire();
return true;
}
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryOpenProfileDef* l, TopoDS_Wire& result) {
return convert_wire(l->Curve(), result);
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& result) {
IfcSchema::IfcPoint* pnt1 = ((IfcSchema::IfcVertexPoint*) l->EdgeStart())->VertexGeometry();
IfcSchema::IfcPoint* pnt2 = ((IfcSchema::IfcVertexPoint*) l->EdgeEnd())->VertexGeometry();
if (!pnt1->is(IfcSchema::Type::IfcCartesianPoint) || !pnt2->is(IfcSchema::Type::IfcCartesianPoint)) {
Logger::Message(Logger::LOG_ERROR, "Only IfcCartesianPoints are supported for VertexGeometry", l->entity);
return false;
}
gp_Pnt p1, p2;
if (!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) ||
!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2))
{
return false;
}
BRepBuilderAPI_MakeWire mw;
Handle_Geom_Curve crv;
// The lack of a clear separation between topological and geometrical entities
// is starting to get problematic. If the underlying curve is bounded it is
// assumed that a topological wire can be crafted from it. After which an
// attempt is made to reconstruct it from the individual curves and the vertices
// of the IfcEdgeCurve.
const bool is_bounded = l->EdgeGeometry()->is(IfcSchema::Type::IfcBoundedCurve);
if (!is_bounded && convert_curve(l->EdgeGeometry(), crv)) {
mw.Add(BRepBuilderAPI_MakeEdge(crv, p1, p2));
result = mw;
return true;
} else if (is_bounded && convert_wire(l->EdgeGeometry(), result)) {
if (!l->SameSense()) std::swap(pnt1, pnt2);
TopExp_Explorer exp(result, TopAbs_EDGE);
bool first = true;
while (exp.More()) {
const TopoDS_Edge& ed = TopoDS::Edge(exp.Current());
Standard_Real u1, u2;
Handle(Geom_Curve) ecrv = BRep_Tool::Curve(ed, u1, u2);
exp.Next();
const bool last = !exp.More();
first = false;
if (first && last) {
mw.Add(BRepBuilderAPI_MakeEdge(ecrv, p1, p2));
} else if (first) {
gp_Pnt pu;
ecrv->D0(u2, pu);
mw.Add(BRepBuilderAPI_MakeEdge(ecrv, p1, pu));
} else if (last) {
gp_Pnt pu;
ecrv->D0(u1, pu);
mw.Add(BRepBuilderAPI_MakeEdge(ecrv, pu, p2));
} else {
mw.Add(BRepBuilderAPI_MakeEdge(ecrv, u1, u2));
}
}
result = mw;
return true;
} else {
return false;
}
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& result) {
IfcSchema::IfcOrientedEdge::list::ptr li = l->EdgeList();
BRepBuilderAPI_MakeWire mw;
for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) {
IfcSchema::IfcOrientedEdge* e = *it;
IfcSchema::IfcPoint* pnt1 = ((IfcSchema::IfcVertexPoint*) e->EdgeStart())->VertexGeometry();
IfcSchema::IfcPoint* pnt2 = ((IfcSchema::IfcVertexPoint*) e->EdgeEnd())->VertexGeometry();
if (!pnt1->is(IfcSchema::Type::IfcCartesianPoint) || !pnt2->is(IfcSchema::Type::IfcCartesianPoint)) {
Logger::Message(Logger::LOG_ERROR, "Only IfcCartesianPoints are supported for VertexGeometry", l->entity);
return false;
}
gp_Pnt p1, p2;
if (!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) ||
!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2))
{
return false;
}
mw.Add(BRepBuilderAPI_MakeEdge(p1, p2));
continue;
IfcSchema::IfcEdge* base = e->EdgeElement();
TopoDS_Wire w;
if (convert_wire(e->EdgeElement(), w)) {
if (!e->Orientation()) w.Reverse();
mw.Add(w);
}
}
result = mw;
return true;
}
+21 -21
View File
@@ -19,54 +19,54 @@
#include "IfcGeom.h"
namespace IfcGeom {
namespace Cache {
std::map<int,TopoDS_Shape> Shape;
void PurgeShapeCache() {
Shape.clear();
}
}
}
using namespace Ifc2x3;
using namespace IfcSchema;
using namespace IfcUtil;
bool IfcGeom::convert_shapes(const IfcBaseClass* l, IfcRepresentationShapeItems& r) {
bool IfcGeom::Kernel::convert_shapes(const IfcBaseClass* l, IfcRepresentationShapeItems& r) {
#include "IfcRegisterConvertShapes.h"
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
return false;
}
bool IfcGeom::is_shape_collection(const IfcBaseClass* l) {
bool IfcGeom::Kernel::is_shape_collection(const IfcBaseClass* l) {
#include "IfcRegisterIsShapeCollection.h"
return false;
}
bool IfcGeom::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) {
bool IfcGeom::Kernel::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) {
const unsigned int id = l->entity->id();
bool success = false;
bool processed = false;
std::map<int,TopoDS_Shape>::const_iterator it = Cache::Shape.find(id);
if ( it != Cache::Shape.end() ) { r = it->second; return true; }
std::map<int,TopoDS_Shape>::const_iterator it = cache.Shape.find(id);
if ( it != cache.Shape.end() ) { r = it->second; return true; }
#include "IfcRegisterConvertShape.h"
if ( processed ) {
const double precision = IfcGeom::GetValue(GV_PRECISION);
IfcGeom::apply_tolerance(r, precision);
Cache::Shape[id] = r;
const double precision = getValue(GV_PRECISION);
apply_tolerance(r, precision);
cache.Shape[id] = r;
} else {
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
}
return success;
}
bool IfcGeom::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) {
bool IfcGeom::Kernel::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) {
#include "IfcRegisterConvertWire.h"
Handle(Geom_Curve) curve;
if (IfcGeom::Kernel::convert_curve(l, curve)) {
return IfcGeom::Kernel::convert_curve_to_wire(curve, r);
}
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
return false;
}
bool IfcGeom::convert_face(const IfcBaseClass* l, TopoDS_Face& r) {
bool IfcGeom::Kernel::convert_face(const IfcBaseClass* l, TopoDS_Shape& r) {
#include "IfcRegisterConvertFace.h"
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
return false;
}
bool IfcGeom::convert_curve(const IfcBaseClass* l, Handle(Geom_Curve)& r) {
bool IfcGeom::Kernel::convert_curve(const IfcBaseClass* l, Handle(Geom_Curve)& r) {
#include "IfcRegisterConvertCurve.h"
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
return false;
+38 -4
View File
@@ -41,34 +41,67 @@
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcParse.h"
using namespace Ifc2x3;
SHAPES(IfcShellBasedSurfaceModel);
SHAPES(IfcFaceBasedSurfaceModel);
SHAPES(IfcShapeRepresentation);
SHAPES(IfcMappedItem);
SHAPES(IfcFacetedBrep);
SHAPES(IfcGeometricSet);
#ifdef USE_IFC4
SHAPE(IfcCylindricalSurface);
SHAPE(IfcAdvancedBrep);
#endif
SHAPE(IfcExtrudedAreaSolid);
SHAPE(IfcRevolvedAreaSolid);
SHAPE(IfcConnectedFaceSet);
SHAPE(IfcBooleanClippingResult);
SHAPE(IfcBooleanResult);
SHAPE(IfcPolygonalBoundedHalfSpace);
SHAPE(IfcHalfSpaceSolid);
SHAPE(IfcSurfaceOfLinearExtrusion);
SHAPE(IfcSurfaceOfRevolution);
SHAPE(IfcBlock);
SHAPE(IfcRectangularPyramid);
SHAPE(IfcRightCircularCylinder);
SHAPE(IfcRightCircularCone);
SHAPE(IfcSphere);
SHAPE(IfcCsgSolid);
SHAPE(IfcCurveBoundedPlane);
SHAPE(IfcRectangularTrimmedSurface);
SHAPE(IfcSurfaceCurveSweptAreaSolid);
SHAPE(IfcSweptDiskSolid);
#ifdef USE_IFC4
FACE(IfcAdvancedFace);
#endif
FACE(IfcArbitraryProfileDefWithVoids);
FACE(IfcArbitraryClosedProfileDef);
FACE(IfcRoundedRectangleProfileDef);
FACE(IfcRectangleHollowProfileDef);
FACE(IfcRectangleProfileDef);
FACE(IfcIShapeProfileDef);
FACE(IfcTrapeziumProfileDef)
FACE(IfcCShapeProfileDef);
// IfcAsymmetricIShapeProfileDef included
FACE(IfcIShapeProfileDef);
FACE(IfcLShapeProfileDef);
FACE(IfcTShapeProfileDef);
FACE(IfcUShapeProfileDef);
FACE(IfcZShapeProfileDef);
FACE(IfcCircleHollowProfileDef);
FACE(IfcCircleProfileDef);
FACE(IfcEllipseProfileDef);
FACE(IfcCenterLineProfileDef);
FACE(IfcCompositeProfileDef);
FACE(IfcDerivedProfileDef);
FACE(IfcFace);
WIRE(IfcEdgeCurve);
WIRE(IfcEdgeLoop);
WIRE(IfcPolyline);
WIRE(IfcPolyLoop);
WIRE(IfcCompositeCurve);
WIRE(IfcTrimmedCurve);
WIRE(IfcArbitraryOpenProfileDef);
CURVE(IfcCircle);
CURVE(IfcEllipse);
@@ -78,6 +111,7 @@ CLASS(IfcCartesianPoint,gp_Pnt);
CLASS(IfcDirection,gp_Dir);
CLASS(IfcAxis2Placement2D,gp_Trsf2d);
CLASS(IfcAxis2Placement3D,gp_Trsf);
CLASS(IfcAxis1Placement,gp_Ax1);
CLASS(IfcCartesianTransformationOperator2DnonUniform,gp_GTrsf2d);
CLASS(IfcCartesianTransformationOperator3DnonUniform,gp_GTrsf);
CLASS(IfcCartesianTransformationOperator2D,gp_Trsf2d);
+1 -1
View File
@@ -2,7 +2,7 @@
#define SHAPES(T) \
if ( l->is(T::Class()) ) { \
try { \
return IfcGeom::convert((T*)l,r); \
return convert((T*)l,r); \
} catch (...) { } \
Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \
return false; \
+2 -2
View File
@@ -1,9 +1,9 @@
#include "IfcRegisterUndef.h"
#define CLASS(T,V) bool convert(const T::ptr L, V& r);
#define CLASS(T,V) bool convert(const IfcSchema::T* L, V& r);
#define SHAPES(T) CLASS(T,IfcRepresentationShapeItems)
#define SHAPE(T) CLASS(T,TopoDS_Shape)
#define WIRE(T) CLASS(T,TopoDS_Wire)
#define FACE(T) CLASS(T,TopoDS_Face)
#define FACE(T) CLASS(T,TopoDS_Shape)
#define CURVE(T) CLASS(T,Handle(Geom_Curve))
#include "IfcRegisterDef.h"
+345
View File
@@ -0,0 +1,345 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* This examples exposes the IfcOpenShell API through a command-based stdin *
* interface *
* *
********************************************************************************/
#include <iostream>
#include <boost/cstdint.hpp>
#if defined(_WIN32) && !defined(__CYGWIN__)
#define SET_BINARY_STREAMS
#endif
#ifdef SET_BINARY_STREAMS
#include <io.h>
#include <fcntl.h>
#endif
#include "../ifcgeom/IfcGeomIterator.h"
using namespace boost;
template <typename T>
T sread(std::istream& s) {
char buf[sizeof(T)];
s.read(buf, sizeof(T));
return *((T*)buf);
}
template <>
std::string sread(std::istream& s) {
int32_t len = sread<int32_t>(s);
char* buf = new char[len + 1];
s.read(buf, len);
buf[len] = 0;
while (len++ % 4) s.get();
std::string str(buf);
delete buf;
return str;
}
static std::streambuf *stdout_orig, *stdout_redir;
template <typename T>
void swrite(std::ostream& s, T t) {
char buf[sizeof(T)];
memcpy(buf, &t, sizeof(T));
s.write(buf, sizeof(T));
}
template <>
void swrite(std::ostream& s, std::string t) {
int32_t len = t.size();
swrite(s, len);
s.write(t.c_str(), len);
while (len++ % 4) s.put(0);
}
class Command {
protected:
virtual void read_content(std::istream& s) = 0;
virtual void write_content(std::ostream& s) = 0;
int32_t iden;
int32_t len;
public:
void read(std::istream& s) {
len = sread<int32_t>(s);
read_content(s);
}
void write(std::ostream& s) {
std::cout.rdbuf(stdout_orig);
swrite(s, iden);
std::ostringstream oss;
write_content(oss);
swrite(s, oss.str());
s.flush();
std::cout.rdbuf(stdout_redir);
}
Command(int32_t iden) : iden(iden) {}
};
const int32_t HELLO = 0xff00;
const int32_t IFC_MODEL = HELLO + 1;
const int32_t GET = IFC_MODEL + 1;
const int32_t ENTITY = GET + 1;
const int32_t MORE = ENTITY + 1;
const int32_t NEXT = MORE + 1;
const int32_t BYE = NEXT + 1;
const int32_t GET_LOG = BYE + 1;
const int32_t LOG = GET_LOG + 1;
class Hello : public Command {
private:
std::string str;
protected:
void read_content(std::istream& s) {
str = sread<std::string>(s);
}
void write_content(std::ostream& s) {
swrite(s, str);
}
public:
const std::string& string() { return str; }
Hello() : Command(HELLO), str("IfcOpenShell-" IFCOPENSHELL_VERSION) {}
};
class More : public Command {
private:
bool more;
protected:
void read_content(std::istream& s) {
more = sread<int32_t>(s) == 1;
}
void write_content(std::ostream& s) {
swrite<int32_t>(s, more ? 1 : 0);
}
public:
More(bool more) : Command(MORE), more(more) {}
};
class IfcModel : public Command {
private:
std::string str;
protected:
void read_content(std::istream& s) {
str = sread<std::string>(s);
}
void write_content(std::ostream& s) {
swrite(s, str);
}
public:
const std::string& string() { return str; }
IfcModel() : Command(IFC_MODEL) {};
};
class Get : public Command {
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {}
public:
Get() : Command(GET) {};
};
class GetLog : public Command {
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {}
public:
GetLog() : Command(GET_LOG) {};
};
class WriteLog : public Command {
private:
std::string str;
protected:
void read_content(std::istream& s) {
str = sread<std::string>(s);
}
void write_content(std::ostream& s) {
swrite(s, str);
}
public:
WriteLog(const std::string& str) : Command(LOG), str(str) {};
};
class Entity : public Command {
private:
const IfcGeom::TriangulationElement<float>* geom;
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {
swrite<int32_t>(s, geom->id());
swrite(s, geom->guid());
swrite(s, geom->name());
swrite(s, geom->type());
swrite<int32_t>(s, geom->parent_id());
const std::vector<float>& m = geom->transformation().matrix().data();
const float matrix_array[16] = {
m[0], m[3], m[6], m[ 9],
m[1], m[4], m[7], m[10],
m[2], m[5], m[8], m[11],
0, 0, 0, 1
};
swrite(s, std::string((char*)matrix_array, 16 * sizeof(float)));
swrite<int32_t>(s, geom->geometry().id());
swrite(s, std::string((char*)geom->geometry().verts().data(), geom->geometry().verts().size() * sizeof(float)));
swrite(s, std::string((char*)geom->geometry().normals().data(), geom->geometry().normals().size() * sizeof(float)));
{ std::vector<int32_t> indices;
for (std::vector<int>::const_iterator it = geom->geometry().faces().begin(); it != geom->geometry().faces().end(); ++it) {
indices.push_back(*it);
}
swrite(s, std::string((char*) indices.data(), indices.size() * sizeof(int32_t))); }
{ std::vector<float> diffuse_color_array;
for (std::vector<IfcGeom::Material>::const_iterator it = geom->geometry().materials().begin(); it != geom->geometry().materials().end(); ++it) {
const IfcGeom::Material& m = *it;
if (m.hasDiffuse()) {
const double* color = m.diffuse();
diffuse_color_array.push_back(static_cast<float>(color[0]));
diffuse_color_array.push_back(static_cast<float>(color[1]));
diffuse_color_array.push_back(static_cast<float>(color[2]));
} else {
diffuse_color_array.push_back(0.f);
diffuse_color_array.push_back(0.f);
diffuse_color_array.push_back(0.f);
}
if (m.hasTransparency()) {
diffuse_color_array.push_back(static_cast<float>(1. - m.transparency()));
} else {
diffuse_color_array.push_back(1.f);
}
}
swrite(s, std::string((char*) diffuse_color_array.data(), diffuse_color_array.size() * sizeof(float))); }
{ std::vector<int32_t> material_indices;
for (std::vector<int>::const_iterator it = geom->geometry().material_ids().begin(); it != geom->geometry().material_ids().end(); ++it) {
material_indices.push_back(*it);
}
swrite(s, std::string((char*) material_indices.data(), material_indices.size() * sizeof(int32_t))); }
}
public:
Entity(const IfcGeom::TriangulationElement<float>* geom) : Command(ENTITY), geom(geom) {};
};
class Next : public Command {
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {}
public:
Next() : Command(NEXT) {};
};
class Bye : public Command {
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {}
public:
Bye() : Command(BYE) {};
};
int main (int argc, char** argv) {
if (sizeof(float) != 4 || sizeof(int32_t) != 4) {
return 1;
}
// Redirect stdout to this stream, so that involuntary
// writes to stdout do not interfere with our protocol.
std::ostringstream oss;
stdout_redir = oss.rdbuf();
stdout_orig = std::cout.rdbuf();
std::cout.rdbuf(stdout_redir);
#ifdef SET_BINARY_STREAMS
_setmode(_fileno(stdout), _O_BINARY);
std::cout.setf(std::ios_base::binary);
_setmode(_fileno(stdin), _O_BINARY);
std::cin.setf(std::ios_base::binary);
#endif
bool has_more = false;
IfcGeom::Iterator<float>* iterator = 0;
Hello().write(std::cout);
int exit_code = 0;
while (1) {
const int32_t msg_type = sread<int32_t>(std::cin);
switch (msg_type) {
case IFC_MODEL: {
IfcModel m; m.read(std::cin);
std::string::size_type len = m.string().size();
char* data = new char[len];
memcpy(data, m.string().c_str(), len);
IfcGeom::IteratorSettings settings;
settings.use_world_coords() = false;
settings.weld_vertices() = false;
settings.convert_back_units() = true;
settings.force_ccw_face_orientation() = true;
iterator = new IfcGeom::Iterator<float>(settings, data, len);
has_more = iterator->findContext();
More(has_more).write(std::cout);
continue;
}
case GET: {
Get g; g.read(std::cin);
if (!has_more) {
exit_code = 1;
break;
}
const IfcGeom::TriangulationElement<float>* geom = static_cast<const IfcGeom::TriangulationElement<float>*>(iterator->get());
Entity(geom).write(std::cout);
continue;
}
case NEXT: {
Next n; n.read(std::cin);
has_more = iterator->next();
if (!has_more) {
delete iterator;
iterator = 0;
}
More(has_more).write(std::cout);
continue;
}
case GET_LOG: {
GetLog gl; gl.read(std::cin);
WriteLog(iterator->getLog()).write(std::cout);
continue;
}
case BYE: {
Bye().write(std::cout);
exit_code = 0;
break;
}
default:
exit_code = 1;
break;
}
break;
}
std::cout.rdbuf(stdout_orig);
return exit_code;
}
+24 -23
View File
@@ -22,7 +22,7 @@
#include <istdplug.h>
#include "../ifcmax/IfcMax.h"
#include "../ifcgeom/IfcGeomObjects.h"
#include "../ifcgeom/IfcGeomIterator.h"
static const int NUM_MATERIAL_SLOTS = 24;
@@ -119,7 +119,7 @@ Mtl* FindMaterialByName(MtlBaseLib* library, const std::string& material_name) {
return m;
}
Mtl* FindOrCreateMaterial(MtlBaseLib* library, Interface* max_interface, int& slot, const IfcGeomObjects::Material& material) {
Mtl* FindOrCreateMaterial(MtlBaseLib* library, Interface* max_interface, int& slot, const IfcGeom::Material& material) {
Mtl* m = FindMaterialByName(library, material.name());
if (m == 0) {
StdMat2* stdm = NewDefaultStdMat();
@@ -148,7 +148,7 @@ Mtl* FindOrCreateMaterial(MtlBaseLib* library, Interface* max_interface, int& sl
return m;
}
Mtl* ComposeMultiMaterial(std::map<std::vector<std::string>, Mtl*>& multi_mats, MtlBaseLib* library, Interface* max_interface, int& slot, const std::vector<IfcGeomObjects::Material>& materials, const std::string& object_type, const std::vector<int>& material_ids) {
Mtl* ComposeMultiMaterial(std::map<std::vector<std::string>, Mtl*>& multi_mats, MtlBaseLib* library, Interface* max_interface, int& slot, const std::vector<IfcGeom::Material>& materials, const std::string& object_type, const std::vector<int>& material_ids) {
std::vector<std::string> material_names;
bool needs_default = std::find(material_ids.begin(), material_ids.end(), -1) != material_ids.end();
if (needs_default) {
@@ -200,9 +200,10 @@ Mtl* ComposeMultiMaterial(std::map<std::vector<std::string>, Mtl*>& multi_mats,
int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, BOOL suppressPrompts) {
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,false);
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,true);
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS,true);
IfcGeom::IteratorSettings settings;
settings.use_world_coords() = false;
settings.weld_vertices() = true;
settings.sew_shells() = true;
#ifdef _UNICODE
int fn_buffer_size = WideCharToMultiByte(CP_UTF8, 0, name, -1, 0, 0, 0, 0);
@@ -212,7 +213,9 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
const char* fn_mb = name;
#endif
if ( ! IfcGeomObjects::Init(fn_mb,0,0) ) return false;
IfcGeom::Iterator<float> iterator(settings, fn_mb);
if (!iterator.findContext()) return false;
itfc->ProgressStart(_T("Importing file..."), TRUE, fn, NULL);
@@ -222,30 +225,29 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
std::map<std::vector<std::string>, Mtl*> material_cache;
do{
const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get();
const IfcGeom::TriangulationElement<float>* o = static_cast<const IfcGeom::TriangulationElement<float>*>(iterator.get());
TSTR o_type = S(o->type());
TSTR o_guid = S(o->guid());
Mtl *m = ComposeMultiMaterial(material_cache, mats, itfc, slot, o->mesh().materials(), o->type(), o->mesh().material_ids());
Mtl *m = ComposeMultiMaterial(material_cache, mats, itfc, slot, o->geometry().materials(), o->type(), o->geometry().material_ids());
TriObject* tri = CreateNewTriObject();
const int numVerts = o->mesh().verts().size()/3;
const int numVerts = o->geometry().verts().size()/3;
tri->mesh.setNumVerts(numVerts);
for( int i = 0; i < numVerts; i ++ ) {
tri->mesh.setVert(i,o->mesh().verts()[3*i+0],o->mesh().verts()[3*i+1],o->mesh().verts()[3*i+2]);
tri->mesh.setVert(i,o->geometry().verts()[3*i+0],o->geometry().verts()[3*i+1],o->geometry().verts()[3*i+2]);
}
const int numFaces = o->mesh().faces().size()/3;
const int numFaces = o->geometry().faces().size()/3;
tri->mesh.setNumFaces(numFaces);
bool needs_default = std::find(o->mesh().material_ids().begin(), o->mesh().material_ids().end(), -1) != o->mesh().material_ids().end();
bool needs_default = std::find(o->geometry().material_ids().begin(), o->geometry().material_ids().end(), -1) != o->geometry().material_ids().end();
for( int i = 0; i < numFaces; i ++ ) {
tri->mesh.faces[i].setVerts(o->mesh().faces()[3*i+0],o->mesh().faces()[3*i+1],o->mesh().faces()[3*i+2]);
tri->mesh.faces[i].setEdgeVisFlags(o->mesh().edges()[3*i+0],o->mesh().edges()[3*i+1],o->mesh().edges()[3*i+2]);
MtlID mtlid = o->mesh().material_ids()[i];
tri->mesh.faces[i].setVerts(o->geometry().faces()[3*i+0],o->geometry().faces()[3*i+1],o->geometry().faces()[3*i+2]);
tri->mesh.faces[i].setEdgeVisFlags(o->geometry().edges()[3*i+0],o->geometry().edges()[3*i+1],o->geometry().edges()[3*i+2]);
MtlID mtlid = o->geometry().material_ids()[i];
if (needs_default) mtlid ++;
tri->mesh.faces[i].setMatID(mtlid);
}
@@ -267,15 +269,14 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
if (m) {
node->GetINode()->SetMtl(m);
}
node->SetTransform(0,Matrix3 ( Point3(o->matrix()[0],o->matrix()[1],o->matrix()[2]),Point3(o->matrix()[3],o->matrix()[4],o->matrix()[5]),
Point3(o->matrix()[6],o->matrix()[7],o->matrix()[8]),Point3(o->matrix()[9],o->matrix()[10],o->matrix()[11]) ));
const std::vector<float>& matrix_data = o->transformation().matrix().data();
node->SetTransform(0,Matrix3 ( Point3(matrix_data[0],matrix_data[1],matrix_data[2]),Point3(matrix_data[3],matrix_data[4],matrix_data[5]),
Point3(matrix_data[6],matrix_data[7],matrix_data[8]),Point3(matrix_data[9],matrix_data[10],matrix_data[11]) ));
impitfc->AddNodeToScene(node);
itfc->ProgressUpdate(IfcGeomObjects::Progress(),true,_T(""));
itfc->ProgressUpdate(iterator.progress(), true, _T(""));
} while ( IfcGeomObjects::Next() );
IfcGeomObjects::CleanUp();
} while (iterator.next());
itfc->ProgressEnd();
@@ -0,0 +1,133 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import os
import sys
import platform
import functools
import itertools
from functools import reduce
from . import guid
python_distribution = os.path.join(platform.system().lower(),
platform.architecture()[0],
'python%s.%s' % platform.python_version_tuple()[:2])
sys.path.append(os.path.abspath(os.path.join(
os.path.dirname(__file__),
'lib', python_distribution)))
try:
from . import ifcopenshell_wrapper
except:
raise ImportError("IfcOpenShell not built for '%s'" % python_distribution)
class entity_instance(object):
def __init__(self, e):
super(entity_instance, self).__setattr__('wrapped_data', e)
def __getattr__(self, name):
try: return entity_instance.wrap_value(self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name)))
except:
try: return entity_instance.wrap_value(self.wrapped_data.get_inverse(name))
except: raise AttributeError("entity instance of type '%s' has no attribute '%s'"%(self.wrapped_data.is_a(), name))
@staticmethod
def map_value(v):
if isinstance(v, entity_instance): return v.wrapped_data
elif isinstance(v, (tuple, list)) and len(v):
classes = list(map(type, v))
if float in classes: return ifcopenshell_wrapper.double_vector(v)
elif int in classes: return ifcopenshell_wrapper.int_vector(v)
elif str in classes: return ifcopenshell_wrapper.string_vector(v)
elif entity_instance in classes: return list(map(lambda e: e.wrapped_data, v))
return v
@staticmethod
def wrap_value(v):
wrap = lambda e: entity_instance(e)
if isinstance(v, ifcopenshell_wrapper.entity_instance): return wrap(v)
elif isinstance(v, (tuple, list)) and len(v):
classes = list(map(type, v))
if ifcopenshell_wrapper.entity_instance in classes: return list(map(wrap, v))
return v
def attribute_type(self, attr):
attr_idx = attr if isinstance(attr, int) else self.wrapped_data.get_argument_index(attr)
return self.wrapped_data.get_argument_type(attr_idx)
def attribute_name(self, attr_idx):
return self.wrapped_data.get_argument_name(attr_idx)
def __setattr__(self, key, value):
self[self.wrapped_data.get_argument_index(key)] = value
def __getitem__(self, key):
return entity_instance.wrap_value(self.wrapped_data.get_argument(key))
def __setitem__(self, idx, value):
self.wrapped_data.set_argument(idx, entity_instance.map_value(value))
def __len__(self): return len(self.wrapped_data)
def __repr__(self): return repr(self.wrapped_data)
def is_a(self, *args): return self.wrapped_data.is_a(*args)
def id(self): return self.wrapped_data.id()
def __dir__(self):
return sorted(set(itertools.chain(
dir(type(self)),
self.wrapped_data.get_attribute_names(),
self.wrapped_data.get_inverse_attribute_names()
)))
class file(object):
def __init__(self, f=None):
self.wrapped_data = f or ifcopenshell_wrapper.file(True)
def create_entity(self,type,*args,**kwargs):
e = entity_instance(ifcopenshell_wrapper.entity_instance(type))
attrs = list(enumerate(args)) + \
[(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
for idx, arg in attrs: e[idx] = arg
self.wrapped_data.add(e.wrapped_data)
e.wrapped_data.this.disown()
return e
def __getattr__(self, attr):
if attr[0:6] == 'create': return functools.partial(self.create_entity,attr[6:])
else: return getattr(self.wrapped_data, attr)
def __getitem__(self, key):
if isinstance(key, int):
return entity_instance(self.wrapped_data.by_id(key))
elif isinstance(key, str):
return entity_instance(self.wrapped_data.by_guid(key))
def add(self, inst):
inst.wrapped_data.this.disown()
return entity_instance(self.wrapped_data.add(inst.wrapped_data))
def by_type(self, type):
return [entity_instance(e) for e in self.wrapped_data.by_type(type)]
def traverse(self, inst):
return [entity_instance(e) for e in self.wrapped_data.traverse(inst.wrapped_data)]
def remove(self, inst):
return self.wrapped_data.remove(inst.wrapped_data)
def __iter__(self):
return iter(self[id] for id in self.wrapped_data.entity_names())
def open(fn=None):
return file(ifcopenshell_wrapper.open(os.path.abspath(fn))) if fn else file()
def create_entity(type,*args,**kwargs):
e = entity_instance(ifcopenshell_wrapper.entity_instance(type))
attrs = list(enumerate(args)) + \
[(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
for idx, arg in attrs: e[idx] = arg
return e
@@ -0,0 +1,82 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import os
import sys
from .. import ifcopenshell_wrapper
def has_occ():
try: import OCC.BRepTools
except: return False
return True
has_occ = has_occ()
wrap_shape_creation = lambda settings, shape: shape
if has_occ:
import occ_utils as utils
wrap_shape_creation = lambda settings, shape: utils.create_shape_from_serialization(shape) if getattr(settings, 'use_python_opencascade', False) else shape
# Subclass the settings module to provide an additional
# setting to enable pythonOCC when available
class settings(ifcopenshell_wrapper.settings):
if has_occ:
USE_PYTHON_OPENCASCADE = -1
def set(self, *args):
setting, value = args
if setting == settings.USE_PYTHON_OPENCASCADE:
self.set(settings.USE_BREP_DATA, value)
self.set(settings.USE_WORLD_COORDS, value)
self.set(settings.DISABLE_TRIANGULATION, value)
self.use_python_opencascade = value
else:
ifcopenshell_wrapper.settings.set(self, *args)
# Hide templating precision to the user by choosing based on Python's
# internal float type. This is probably always going to be a double.
for ty in (ifcopenshell_wrapper.iterator_single_precision, ifcopenshell_wrapper.iterator_double_precision):
if ty.mantissa_size() == sys.float_info.mant_dig:
_iterator = ty
# Make sure people are able to use python's platform agnostic paths
class iterator(_iterator):
def __init__(self, settings, filename):
self.settings = settings
_iterator.__init__(self, settings, os.path.abspath(filename))
if has_occ:
def get(self):
return wrap_shape_creation(self.settings, _iterator.get(self))
def create_shape(settings, inst):
return wrap_shape_creation(settings, ifcopenshell_wrapper.create_shape(settings, inst.wrapped_data))
def iterate(settings, filename):
it = iterator(settings, filename)
if it.findContext():
while True:
yield it.get()
if not it.next(): break
@@ -0,0 +1,66 @@
import random
from collections import namedtuple
import OCC.gp
import OCC.V3d
import OCC.Quantity
import OCC.BRepTools
import OCC.Display.SimpleGui
tuple = namedtuple('shape', ('data', 'geometry'))
handle, main_loop, add_menu, add_function_to_menu = None, None, None, None
def initialize_display():
global handle, main_loop, add_menu, add_function_to_menu
handle, main_loop, add_menu, add_function_to_menu = OCC.Display.SimpleGui.init_display()
def setup():
viewer_handle = handle.GetViewer()
viewer = viewer_handle.GetObject()
while True:
viewer.InitActiveLights()
try: active_light = viewer.ActiveLight()
except: break
viewer.DelLight(active_light)
viewer.NextActiveLights()
for dir in [(1,2,-3), (-2,-1,1)]:
light = OCC.V3d.V3d_DirectionalLight(viewer_handle)
light.SetDirection(*dir)
viewer.SetLightOn(light.GetHandle())
setup()
return handle
def display_shape(shape, clr=None):
if not clr:
r = lambda: random.random() * 0.3 + 0.7
clr = OCC.Quantity.Quantity_Color(r(), r(), r(), OCC.Quantity.Quantity_TOC_RGB)
return handle.DisplayShape(shape, color=clr, update=True)
def set_shape_transparency(ais, t):
handle.Context.SetTransparency(ais, t)
def get_bounding_box_center(bbox):
bbmin = [0.]*3; bbmax = [0.]*3
bbmin[0], bbmin[1], bbmin[2], bbmax[0], bbmax[1], bbmax[2] = bbox.Get()
return OCC.gp.gp_Pnt(*map(lambda xy: (xy[0]+xy[1])/2., zip(bbmin, bbmax)))
def create_shape_from_serialization(brep_object):
brep_data, occ_shape = None, None
try: brep_data = brep_object.geometry.brep_data
except: pass
if not brep_data: return tuple(brep_object, None)
try:
ss = OCC.BRepTools.BRepTools_ShapeSet()
ss.ReadFromString(brep_data)
occ_shape = ss.Shape(ss.NbShapes())
except: pass
return tuple(brep_object, occ_shape)
@@ -0,0 +1,43 @@
###############################################################################
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
###############################################################################
import string
from functools import reduce
chars = string.digits + string.ascii_uppercase + string.ascii_lowercase + '_$'
def compress(g):
bs = [int(g[i:i+2], 16) for i in range(0, len(g), 2)]
def b64(v, l=4):
return ''.join([chars[(v // (64**i))%64] for i in range(l)][::-1])
return ''.join([b64(bs[0], 2)] + [b64((bs[i] << 16) + (bs[i+1] << 8) + bs[i+2]) for i in range(1,16,3)])
def expand(g):
def b64(v):
return reduce(lambda a, b: a * 64 + b, map(lambda c: chars.index(c), v))
bs = [b64(g[0:2])]
for i in range(5):
d = b64(g[2+4*i:6+4*i])
bs += [(d >> (8*(2-j)))%256 for j in range(3)]
return ''.join(['%02x'%b for b in bs])
def split(g):
return '{%s-%s-%s-%s-%s}'%(g[:8], g[8:12], g[12:16], g[16:20], g[20:])
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* This file has been generated from IFC2X3_TC1.exp. Do not make modifications *
* but instead modify the python script that has been used to generate this. *
* *
********************************************************************************/
#ifndef IFC2X3RT_H
#define IFC2X3RT_H
#define IfcSchema Ifc2x3
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcEntityDescriptor.h"
#include "../ifcparse/IfcWritableEntity.h"
namespace Ifc2x3 {
namespace Type {
int GetAttributeCount(Enum t);
int GetAttributeIndex(Enum t, const std::string& a);
IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a);
Enum GetAttributeEntity(Enum t, unsigned char a);
const std::string& GetAttributeName(Enum t, unsigned char a);
bool GetAttributeOptional(Enum t, unsigned char a);
bool GetAttributeDerived(Enum t, unsigned char a);
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
std::set<std::string> GetInverseAttributeNames(Enum t);
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
}}
#endif
+8149 -6341
View File
File diff suppressed because one or more lines are too long
+11644 -12168
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* This file has been generated from IFC4.exp. Do not make modifications *
* but instead modify the python script that has been used to generate this. *
* *
********************************************************************************/
#ifndef IFC4RT_H
#define IFC4RT_H
#define IfcSchema Ifc4
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcEntityDescriptor.h"
#include "../ifcparse/IfcWritableEntity.h"
namespace Ifc4 {
namespace Type {
int GetAttributeCount(Enum t);
int GetAttributeIndex(Enum t, const std::string& a);
IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a);
Enum GetAttributeEntity(Enum t, unsigned char a);
const std::string& GetAttributeName(Enum t, unsigned char a);
bool GetAttributeOptional(Enum t, unsigned char a);
bool GetAttributeDerived(Enum t, unsigned char a);
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
std::set<std::string> GetInverseAttributeNames(Enum t);
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
}}
#endif
+16212
View File
File diff suppressed because one or more lines are too long
+53504
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -30,7 +30,7 @@
#include "../ifcparse/IfcCharacterDecoder.h"
#include "../ifcparse/IfcException.h"
#include "../ifcparse/IfcFile.h"
#include "../ifcparse/IfcSpfStream.h"
#define FIRST_SOLIDUS (1 << 1)
#define PAGE (1 << 2)
+1 -1
View File
@@ -36,7 +36,7 @@
typedef unsigned int UChar32;
#endif
#include "../ifcparse/IfcFile.h"
#include "../ifcparse/IfcSpfStream.h"
namespace IfcParse {
+132
View File
@@ -0,0 +1,132 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef IFCENTITYDESCRIPTOR_H
#define IFCENTITYDESCRIPTOR_H
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#include "../ifcparse/SharedPointer.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcException.h"
#ifdef USE_IFC4
#include "../ifcparse/Ifc4enum.h"
#else
#include "../ifcparse/Ifc2x3enum.h"
#endif
namespace IfcUtil {
class IfcEnumerationDescriptor {
private:
IfcSchema::Type::Enum type;
std::vector<std::string> values;
public:
IfcEnumerationDescriptor(IfcSchema::Type::Enum type, const std::vector<std::string>& values)
: type(type), values(values) {}
std::pair<const char*, int> getIndex(const std::string& value) const {
std::vector<std::string>::const_iterator it = std::find(values.begin(), values.end(), value);
if (it != values.end()) {
return std::make_pair(it->c_str(), std::distance(it, values.begin()));
} else {
throw IfcParse::IfcException("Invalid enumeration value");
}
}
const std::vector<std::string>& getValues() {
return values;
}
IfcSchema::Type::Enum getType() {
return type;
}
};
class IfcEntityDescriptor {
public:
class IfcArgumentDescriptor
{
public:
std::string name;
bool optional;
ArgumentType argument_type;
IfcSchema::Type::Enum data_type;
IfcArgumentDescriptor(const std::string& name, bool optional, ArgumentType argument_type, IfcSchema::Type::Enum data_type)
: name(name), optional(optional), argument_type(argument_type), data_type(data_type) {}
};
private:
IfcSchema::Type::Enum type;
IfcEntityDescriptor* parent;
std::vector<IfcArgumentDescriptor> arguments;
unsigned argument_start() const {
return parent ? parent->getArgumentCount() : 0;
}
const IfcArgumentDescriptor& get_argument(unsigned i) const {
if (i < arguments.size()) return arguments[i];
else throw IfcParse::IfcException("Argument out of range");
}
public:
IfcEntityDescriptor(IfcSchema::Type::Enum type, IfcEntityDescriptor* parent)
: type(type), parent(parent) {}
void add(const std::string& name, bool optional, ArgumentType argument_type, IfcSchema::Type::Enum data_type = IfcSchema::Type::UNDEFINED) {
arguments.push_back(IfcArgumentDescriptor(name, optional, argument_type, data_type));
}
unsigned getArgumentCount() const {
return (parent ? parent->getArgumentCount() : 0) + arguments.size();
}
const std::string& getArgumentName(unsigned i) const {
const unsigned a = argument_start();
return i < a
? parent->getArgumentName(i)
: get_argument(i-a).name;
}
ArgumentType getArgumentType(unsigned i) const {
const unsigned a = argument_start();
return i < a
? parent->getArgumentType(i)
: get_argument(i-a).argument_type;
}
bool getArgumentOptional(unsigned i) const {
const unsigned a = argument_start();
return i < a
? parent->getArgumentOptional(i)
: get_argument(i-a).optional;
}
IfcSchema::Type::Enum getArgumentEntity(unsigned i) const {
const unsigned a = argument_start();
return i < a
? parent->getArgumentEntity(i)
: get_argument(i-a).data_type;
}
unsigned getArgumentIndex(const std::string& s) const {
unsigned a = argument_start();
for(std::vector<IfcArgumentDescriptor>::const_iterator i = arguments.begin(); i != arguments.end(); ++i) {
if (i->name == s) return a;
a++;
}
if (parent) return parent->getArgumentIndex(s);
throw IfcParse::IfcException(std::string("Argument ") + s + " not found on " + IfcSchema::Type::ToString(type));
}
};
}
#endif
+113 -56
View File
@@ -1,4 +1,4 @@
/********************************************************************************
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
@@ -16,66 +16,123 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Reads a file in chunks of BUF_SIZE and provides functions to access its *
* contents randomly and character by character *
* *
********************************************************************************/
#ifndef IFCFILE_H
#define IFCFILE_H
#include <fstream>
#include <string>
#include <map>
#include <set>
// As of IfcOpenShell version 0.3.0 the paging functionality, which
// loads a file on disk into multiple chunks, has been disabled.
// It proved to be an inefficient way of working with large files,
// as often these did not facilitate to be parsed in a sequential
// manner efficiently. To enable the paging functionality uncomment
// the following statement.
// #define BUF_SIZE (8 * 1024 * 1024)
#include "../ifcparse/IfcParse.h"
#include "../ifcparse/IfcSpfHeader.h"
namespace IfcParse {
/// The IfcSpfStream class represents a ISO 10303-21 IFC-SPF file in memory.
/// The file is interpreted as a sequence of tokens which are lazily
/// interpreted only when requested. If the size of the file is
/// larger than BUF_SIZE, the file is split into seperate pages, of
/// which only one is simultaneously kept in memory, for files
/// that define their entities not in a sequential nature, this is
/// detrimental for the performance of the parser.
class IfcSpfStream {
private:
FILE* stream;
char* buffer;
unsigned int ptr;
unsigned int len;
void ReadBuffer(bool inc=true);
#ifdef BUF_SIZE
unsigned int offset;
bool paging;
#endif
public:
bool valid;
bool eof;
unsigned int size;
IfcSpfStream(const std::string& fn);
IfcSpfStream(std::istream& f, int len);
IfcSpfStream(void* data, int len);
/// Returns the character at the cursor
char Peek();
/// Returns the character at specified offset
char Read(unsigned int offset);
/// Increment the file cursor and reads new page if necessary
void Inc();
void Close();
/// Moves the file cursor to an arbitrary offset in the file
void Seek(unsigned int offset);
/// Returns the cursor position
unsigned int Tell();
};
/// This class provides several static convenience functions and variables
/// and provide access to the entities in an IFC file
class IfcFile {
public:
typedef std::map<IfcSchema::Type::Enum, IfcEntityList::ptr> entities_by_type_t;
typedef std::map<unsigned int, IfcUtil::IfcBaseClass*> entity_by_id_t;
typedef std::map<std::string, IfcSchema::IfcRoot*> entity_by_guid_t;
typedef std::map<unsigned int, IfcEntityList::ptr> entities_by_ref_t;
typedef std::map<unsigned int, unsigned int> offset_by_id_t;
typedef entity_by_id_t::const_iterator const_iterator;
private:
typedef std::map<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*> entity_entity_map_t;
bool _create_latebound_entities;
entity_by_id_t byid;
entities_by_type_t bytype;
entities_by_ref_t byref;
entity_by_guid_t byguid;
offset_by_id_t offsets;
entity_entity_map_t entity_file_map;
unsigned int lastId;
unsigned int MaxId;
IfcSpfHeader _header;
void setDefaultHeaderValues();
void traverse(IfcUtil::IfcBaseClass*, std::set<IfcUtil::IfcBaseClass*>& visited, IfcEntityList::ptr list, int level, int max_level);
public:
IfcParse::IfcSpfLexer* tokens;
IfcParse::IfcSpfStream* stream;
IfcFile(bool create_latebound_entities = false);
~IfcFile();
/// Returns the first entity in the file, this probably is the entity
/// with the lowest id (EXPRESS ENTITY_INSTANCE_NAME)
const_iterator begin() const;
/// Returns the last entity in the file, this probably is the entity
/// with the highest id (EXPRESS ENTITY_INSTANCE_NAME)
const_iterator end() const;
/// Returns all entities in the file that match the template argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
template <class T>
typename T::list::ptr entitiesByType() {
IfcEntityList::ptr untyped_list = entitiesByType(T::Class());
if (untyped_list) {
return untyped_list->as<T>();
} else {
return typename T::list::ptr(new typename T::list);
}
}
/// Returns all entities in the file that match the positional argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
IfcEntityList::ptr entitiesByType(IfcSchema::Type::Enum t);
/// Returns all entities in the file that match the positional argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
IfcEntityList::ptr entitiesByType(const std::string& t);
/// Returns all entities in the file that reference the id
IfcEntityList::ptr entitiesByReference(int id);
/// Returns the entity with the specified id
IfcUtil::IfcBaseClass* entityById(int id);
/// Returns the entity with the specified GlobalId
IfcSchema::IfcRoot* entityByGuid(const std::string& guid);
/// Performs a depth-first traversal, returning all entity instance
/// attributes as a flat list. NB: includes the root instance specified
/// in the first function argument.
IfcEntityList::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level=-1);
bool Init(const std::string& fn);
bool Init(std::istream& fn, int len);
bool Init(void* data, int len);
bool Init(IfcParse::IfcSpfStream* f);
IfcEntityList::ptr getInverse(int instance_id, IfcSchema::Type::Enum type, int attribute_index);
unsigned int FreshId() { return ++MaxId; }
IfcUtil::IfcBaseClass* addEntity(IfcUtil::IfcBaseClass* entity);
void addEntities(IfcEntityList::ptr es);
void removeEntity(IfcUtil::IfcBaseClass* entity);
const IfcSpfHeader& header() const { return _header; }
IfcSpfHeader& header() { return _header; }
std::string createTimestamp() const;
bool create_latebound_entities() const { return _create_latebound_entities; }
std::pair<IfcSchema::IfcNamedUnit*, double> getUnit(IfcSchema::IfcUnitEnum::IfcUnitEnum);
};
}
#endif
#endif
+3 -19
View File
@@ -26,23 +26,17 @@
#include <time.h>
#include <stdlib.h>
#define HAS_BOOST_UUID
#ifdef HAS_BOOST_UUID
#include <algorithm>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#endif
#include "IfcWrite.h"
#include "../ifcparse/IfcWrite.h"
#include "../ifcparse/IfcException.h"
static const char* chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$";
#ifdef HAS_BOOST_UUID
// Converts an unsigned integer into a base64 string of length l
std::string base64(unsigned v, int l) {
std::string r;
@@ -64,7 +58,7 @@ unsigned from_base64(const std::string& s) {
for ( std::string::const_iterator i = s.begin()+zeros; i != s.end(); ++ i ) {
r *= 64;
const char* c = strchr(chars,*i);
if ( !c ) throw IfcException("Failed to decode GlobalId");
if ( !c ) throw IfcParse::IfcException("Failed to decode GlobalId");
r += (c-chars);
}
return r;
@@ -95,10 +89,7 @@ void expand(const std::string& s, std::vector<unsigned char>& v) {
// A random number generator for the UUID
static boost::uuids::basic_random_generator<boost::mt19937> gen;
#endif
IfcWrite::IfcGuidHelper::IfcGuidHelper() {
#ifdef HAS_BOOST_UUID
boost::uuids::uuid u = gen();
std::vector<unsigned char> v(u.size());
std::copy(u.begin(), u.end(), v.begin());
@@ -108,13 +99,6 @@ IfcWrite::IfcGuidHelper::IfcGuidHelper() {
expand(data,v2);
boost::uuids::uuid u2;
std::copy(v2.begin(), v2.end(), u2.begin());
#else
if ( ! seeded ) { srand((unsigned int)time(0)); seeded = true; }
data.resize(length);
for ( unsigned int i = 0; i < length; ++ i ) {
data[i] = chars[rand()%strlen(chars)];
}
#endif
}
IfcWrite::IfcGuidHelper::operator std::string() const {
return data;
+338 -191
View File
@@ -29,358 +29,505 @@
#include "../ifcparse/IfcHierarchyHelper.h"
Ifc2x3::IfcAxis2Placement3D* IfcHierarchyHelper::addPlacement3d(
IfcSchema::IfcAxis2Placement3D* IfcHierarchyHelper::addPlacement3d(
double ox, double oy, double oz,
double zx, double zy, double zz,
double xx, double xy, double xz)
{
Ifc2x3::IfcDirection* x = addTriplet<Ifc2x3::IfcDirection>(xx, xy, xz);
Ifc2x3::IfcDirection* z = addTriplet<Ifc2x3::IfcDirection>(zx, zy, zz);
Ifc2x3::IfcCartesianPoint* o = addTriplet<Ifc2x3::IfcCartesianPoint>(ox, oy, oz);
Ifc2x3::IfcAxis2Placement3D* p3d = new Ifc2x3::IfcAxis2Placement3D(o, z, x);
AddEntity(p3d);
IfcSchema::IfcDirection* x = addTriplet<IfcSchema::IfcDirection>(xx, xy, xz);
IfcSchema::IfcDirection* z = addTriplet<IfcSchema::IfcDirection>(zx, zy, zz);
IfcSchema::IfcCartesianPoint* o = addTriplet<IfcSchema::IfcCartesianPoint>(ox, oy, oz);
IfcSchema::IfcAxis2Placement3D* p3d = new IfcSchema::IfcAxis2Placement3D(o, z, x);
addEntity(p3d);
return p3d;
}
Ifc2x3::IfcAxis2Placement2D* IfcHierarchyHelper::addPlacement2d(
IfcSchema::IfcAxis2Placement2D* IfcHierarchyHelper::addPlacement2d(
double ox, double oy,
double xx, double xy)
{
Ifc2x3::IfcDirection* x = addDoublet<Ifc2x3::IfcDirection>(xx, xy);
Ifc2x3::IfcCartesianPoint* o = addDoublet<Ifc2x3::IfcCartesianPoint>(ox, oy);
Ifc2x3::IfcAxis2Placement2D* p2d = new Ifc2x3::IfcAxis2Placement2D(o, x);
AddEntity(p2d);
IfcSchema::IfcDirection* x = addDoublet<IfcSchema::IfcDirection>(xx, xy);
IfcSchema::IfcCartesianPoint* o = addDoublet<IfcSchema::IfcCartesianPoint>(ox, oy);
IfcSchema::IfcAxis2Placement2D* p2d = new IfcSchema::IfcAxis2Placement2D(o, x);
addEntity(p2d);
return p2d;
}
Ifc2x3::IfcLocalPlacement* IfcHierarchyHelper::addLocalPlacement(
IfcSchema::IfcLocalPlacement* IfcHierarchyHelper::addLocalPlacement(IfcSchema::IfcObjectPlacement* parent,
double ox, double oy, double oz,
double zx, double zy, double zz,
double xx, double xy, double xz)
{
Ifc2x3::IfcLocalPlacement* lp = new Ifc2x3::IfcLocalPlacement(0,
IfcSchema::IfcLocalPlacement* lp = new IfcSchema::IfcLocalPlacement(parent,
addPlacement3d(ox, oy, oz, zx, zy, zz, xx, xy, xz));
AddEntity(lp);
addEntity(lp);
return lp;
}
Ifc2x3::IfcOwnerHistory* IfcHierarchyHelper::addOwnerHistory() {
Ifc2x3::IfcPerson* person = new Ifc2x3::IfcPerson(boost::none, boost::none, std::string(""),
IfcSchema::IfcOwnerHistory* IfcHierarchyHelper::addOwnerHistory() {
IfcSchema::IfcPerson* person = new IfcSchema::IfcPerson(boost::none, boost::none, std::string(""),
boost::none, boost::none, boost::none, boost::none, boost::none);
Ifc2x3::IfcOrganization* organization = new Ifc2x3::IfcOrganization(boost::none,
IfcSchema::IfcOrganization* organization = new IfcSchema::IfcOrganization(boost::none,
"IfcOpenShell", boost::none, boost::none, boost::none);
Ifc2x3::IfcPersonAndOrganization* person_and_org = new Ifc2x3::IfcPersonAndOrganization(person, organization, boost::none);
Ifc2x3::IfcApplication* application = new Ifc2x3::IfcApplication(organization,
IfcSchema::IfcPersonAndOrganization* person_and_org = new IfcSchema::IfcPersonAndOrganization(person, organization, boost::none);
IfcSchema::IfcApplication* application = new IfcSchema::IfcApplication(organization,
IFCOPENSHELL_VERSION, "IfcOpenShell", "IfcOpenShell");
int timestamp = (int) time(0);
Ifc2x3::IfcOwnerHistory* owner_hist = new Ifc2x3::IfcOwnerHistory(person_and_org, application,
boost::none, Ifc2x3::IfcChangeActionEnum::IfcChangeAction_ADDED, boost::none, person_and_org, application, timestamp);
IfcSchema::IfcOwnerHistory* owner_hist = new IfcSchema::IfcOwnerHistory(person_and_org, application,
boost::none, IfcSchema::IfcChangeActionEnum::IfcChangeAction_ADDED, timestamp, person_and_org, application, timestamp);
AddEntity(person);
AddEntity(organization);
AddEntity(person_and_org);
AddEntity(application);
AddEntity(owner_hist);
addEntity(person);
addEntity(organization);
addEntity(person_and_org);
addEntity(application);
addEntity(owner_hist);
return owner_hist;
}
Ifc2x3::IfcProject* IfcHierarchyHelper::addProject(Ifc2x3::IfcOwnerHistory* owner_hist) {
Ifc2x3::IfcRepresentationContext::list rep_contexts (new IfcTemplatedEntityList<Ifc2x3::IfcRepresentationContext>());
Ifc2x3::IfcGeometricRepresentationContext* rep_context = new Ifc2x3::IfcGeometricRepresentationContext(
std::string("Plan"), std::string("Model"), 3, 1e-5, addPlacement3d(), addTriplet<Ifc2x3::IfcDirection>(0, 1, 0));
IfcSchema::IfcProject* IfcHierarchyHelper::addProject(IfcSchema::IfcOwnerHistory* owner_hist) {
IfcSchema::IfcRepresentationContext::list::ptr rep_contexts (new IfcSchema::IfcRepresentationContext::list);
rep_contexts->push(rep_context);
IfcEntities units (new IfcEntityList());
Ifc2x3::IfcDimensionalExponents* dimexp = new Ifc2x3::IfcDimensionalExponents(0, 0, 0, 0, 0, 0, 0);
Ifc2x3::IfcSIUnit* unit1 = new Ifc2x3::IfcSIUnit(Ifc2x3::IfcUnitEnum::IfcUnit_LENGTHUNIT,
Ifc2x3::IfcSIPrefix::IfcSIPrefix_MILLI, Ifc2x3::IfcSIUnitName::IfcSIUnitName_METRE);
Ifc2x3::IfcSIUnit* unit2a = new Ifc2x3::IfcSIUnit(Ifc2x3::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT,
boost::none, Ifc2x3::IfcSIUnitName::IfcSIUnitName_RADIAN);
Ifc2x3::IfcMeasureWithUnit* unit2b = new Ifc2x3::IfcMeasureWithUnit(
new IfcWrite::IfcSelectHelper(0.017453293, Ifc2x3::Type::IfcPlaneAngleMeasure), unit2a);
Ifc2x3::IfcConversionBasedUnit* unit2 = new Ifc2x3::IfcConversionBasedUnit(dimexp,
Ifc2x3::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT, "Degrees", unit2b);
IfcEntityList::ptr units (new IfcEntityList);
IfcSchema::IfcDimensionalExponents* dimexp = new IfcSchema::IfcDimensionalExponents(0, 0, 0, 0, 0, 0, 0);
IfcSchema::IfcSIUnit* unit1 = new IfcSchema::IfcSIUnit(IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT,
IfcSchema::IfcSIPrefix::IfcSIPrefix_MILLI, IfcSchema::IfcSIUnitName::IfcSIUnitName_METRE);
IfcSchema::IfcSIUnit* unit2a = new IfcSchema::IfcSIUnit(IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT,
boost::none, IfcSchema::IfcSIUnitName::IfcSIUnitName_RADIAN);
IfcSchema::IfcMeasureWithUnit* unit2b = new IfcSchema::IfcMeasureWithUnit(
new IfcSchema::IfcPlaneAngleMeasure(0.017453293), unit2a);
IfcSchema::IfcConversionBasedUnit* unit2 = new IfcSchema::IfcConversionBasedUnit(dimexp,
IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT, "Degrees", unit2b);
units->push(unit1);
units->push(unit2);
Ifc2x3::IfcUnitAssignment* unit_assignment = new Ifc2x3::IfcUnitAssignment(units);
IfcSchema::IfcUnitAssignment* unit_assignment = new IfcSchema::IfcUnitAssignment(units);
Ifc2x3::IfcProject* project = new Ifc2x3::IfcProject(IfcWrite::IfcGuidHelper(), owner_hist, boost::none, boost::none,
IfcSchema::IfcProject* project = new IfcSchema::IfcProject(IfcWrite::IfcGuidHelper(), owner_hist, boost::none, boost::none,
boost::none, boost::none, boost::none, rep_contexts, unit_assignment);
AddEntity(rep_context);
AddEntity(dimexp);
AddEntity(unit1);
AddEntity(unit2a);
AddEntity(unit2b);
AddEntity(unit2);
AddEntity(unit_assignment);
AddEntity(project);
addEntity(dimexp);
addEntity(unit1);
addEntity(unit2a);
addEntity(unit2b);
addEntity(unit2);
addEntity(unit_assignment);
addEntity(project);
return project;
}
void IfcHierarchyHelper::relatePlacements(Ifc2x3::IfcProduct* parent, Ifc2x3::IfcProduct* product) {
Ifc2x3::IfcObjectPlacement* place = product->hasObjectPlacement() ? product->ObjectPlacement() : 0;
if (place && place->is(Ifc2x3::Type::IfcLocalPlacement)) {
Ifc2x3::IfcLocalPlacement* local_place = (Ifc2x3::IfcLocalPlacement*) place;
if (parent->hasObjectPlacement()) {
local_place->setPlacementRelTo(parent->ObjectPlacement());
void IfcHierarchyHelper::relatePlacements(IfcSchema::IfcProduct* parent, IfcSchema::IfcProduct* product) {
IfcSchema::IfcObjectPlacement* place = product->ObjectPlacement() ? (*product->ObjectPlacement()) : 0;
if (place && place->is(IfcSchema::Type::IfcLocalPlacement)) {
IfcSchema::IfcLocalPlacement* local_place = (IfcSchema::IfcLocalPlacement*) place;
if (parent->ObjectPlacement()) {
local_place->PlacementRelTo(*parent->ObjectPlacement());
}
}
}
Ifc2x3::IfcSite* IfcHierarchyHelper::addSite(Ifc2x3::IfcProject* proj, Ifc2x3::IfcOwnerHistory* owner_hist) {
IfcSchema::IfcSite* IfcHierarchyHelper::addSite(IfcSchema::IfcProject* proj, IfcSchema::IfcOwnerHistory* owner_hist) {
if (! owner_hist) {
owner_hist = getSingle<Ifc2x3::IfcOwnerHistory>();
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
}
if (! owner_hist) {
owner_hist = addOwnerHistory();
}
if (! proj) {
proj = getSingle<Ifc2x3::IfcProject>();
proj = getSingle<IfcSchema::IfcProject>();
}
if (! proj) {
proj = addProject(owner_hist);
}
Ifc2x3::IfcSite* site = new Ifc2x3::IfcSite(IfcWrite::IfcGuidHelper(), owner_hist, boost::none,
boost::none, boost::none, addLocalPlacement(), 0, boost::none,
Ifc2x3::IfcElementCompositionEnum::IfcElementComposition_ELEMENT,
boost::none, boost::none, boost::none, boost::none, 0);
IfcSchema::IfcSite* site = new IfcSchema::IfcSite(IfcWrite::IfcGuidHelper(), owner_hist, boost::none,
boost::none, boost::none, addLocalPlacement(), boost::none, boost::none,
IfcSchema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT,
boost::none, boost::none, boost::none, boost::none, boost::none);
AddEntity(site);
addRelatedObject<Ifc2x3::IfcRelAggregates>(proj, site);
addEntity(site);
addRelatedObject<IfcSchema::IfcRelAggregates>(proj, site);
return site;
}
Ifc2x3::IfcBuilding* IfcHierarchyHelper::addBuilding(Ifc2x3::IfcSite* site, Ifc2x3::IfcOwnerHistory* owner_hist) {
IfcSchema::IfcBuilding* IfcHierarchyHelper::addBuilding(IfcSchema::IfcSite* site, IfcSchema::IfcOwnerHistory* owner_hist) {
if (! owner_hist) {
owner_hist = getSingle<Ifc2x3::IfcOwnerHistory>();
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
}
if (! owner_hist) {
owner_hist = addOwnerHistory();
}
if (! site) {
site = getSingle<Ifc2x3::IfcSite>();
site = getSingle<IfcSchema::IfcSite>();
}
if (! site) {
site = addSite(0, owner_hist);
}
Ifc2x3::IfcBuilding* building = new Ifc2x3::IfcBuilding(IfcWrite::IfcGuidHelper(), owner_hist, boost::none, boost::none, boost::none,
addLocalPlacement(), 0, boost::none, Ifc2x3::IfcElementCompositionEnum::IfcElementComposition_ELEMENT,
boost::none, boost::none, 0);
IfcSchema::IfcBuilding* building = new IfcSchema::IfcBuilding(IfcWrite::IfcGuidHelper(), owner_hist, boost::none, boost::none, boost::none,
addLocalPlacement(), boost::none, boost::none, IfcSchema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT,
boost::none, boost::none, boost::none);
AddEntity(building);
addRelatedObject<Ifc2x3::IfcRelAggregates>(site, building);
addEntity(building);
addRelatedObject<IfcSchema::IfcRelAggregates>(site, building);
relatePlacements(site, building);
return building;
}
Ifc2x3::IfcBuildingStorey* IfcHierarchyHelper::addBuildingStorey(Ifc2x3::IfcBuilding* building,
Ifc2x3::IfcOwnerHistory* owner_hist)
IfcSchema::IfcBuildingStorey* IfcHierarchyHelper::addBuildingStorey(IfcSchema::IfcBuilding* building,
IfcSchema::IfcOwnerHistory* owner_hist)
{
if (! owner_hist) {
owner_hist = getSingle<Ifc2x3::IfcOwnerHistory>();
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
}
if (! owner_hist) {
owner_hist = addOwnerHistory();
}
if (! building) {
building = getSingle<Ifc2x3::IfcBuilding>();
building = getSingle<IfcSchema::IfcBuilding>();
}
if (! building) {
building = addBuilding(0, owner_hist);
}
Ifc2x3::IfcBuildingStorey* storey = new Ifc2x3::IfcBuildingStorey(IfcWrite::IfcGuidHelper(),
owner_hist, boost::none, boost::none, boost::none, addLocalPlacement(), 0, boost::none,
Ifc2x3::IfcElementCompositionEnum::IfcElementComposition_ELEMENT, boost::none);
IfcSchema::IfcBuildingStorey* storey = new IfcSchema::IfcBuildingStorey(IfcWrite::IfcGuidHelper(),
owner_hist, boost::none, boost::none, boost::none, addLocalPlacement(), boost::none, boost::none,
IfcSchema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT, boost::none);
AddEntity(storey);
addRelatedObject<Ifc2x3::IfcRelAggregates>(building, storey);
addEntity(storey);
addRelatedObject<IfcSchema::IfcRelAggregates>(building, storey);
relatePlacements(building, storey);
return storey;
}
Ifc2x3::IfcBuildingStorey* IfcHierarchyHelper::addBuildingProduct(Ifc2x3::IfcProduct* product,
Ifc2x3::IfcBuildingStorey* storey, Ifc2x3::IfcOwnerHistory* owner_hist)
IfcSchema::IfcBuildingStorey* IfcHierarchyHelper::addBuildingProduct(IfcSchema::IfcProduct* product,
IfcSchema::IfcBuildingStorey* storey, IfcSchema::IfcOwnerHistory* owner_hist)
{
if (! owner_hist) {
owner_hist = getSingle<Ifc2x3::IfcOwnerHistory>();
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
}
if (! owner_hist) {
owner_hist = addOwnerHistory();
}
if (! storey) {
storey = getSingle<Ifc2x3::IfcBuildingStorey>();
storey = getSingle<IfcSchema::IfcBuildingStorey>();
}
if (! storey) {
storey = addBuildingStorey(0, owner_hist);
}
AddEntity(product);
addRelatedObject<Ifc2x3::IfcRelContainedInSpatialStructure>(storey, product);
relatePlacements(storey, product);
addEntity(product);
// CV-2x3-158: Don't add decompositions directly to a building storey
bool is_decomposition = false;
#ifdef USE_IFC4
IfcSchema::IfcRelAggregates::list::ptr decomposes = product->Decomposes();
for (IfcSchema::IfcRelAggregates::list::it it = decomposes->begin(); it != decomposes->end(); ++it) {
#else
IfcSchema::IfcRelDecomposes::list::ptr decomposes = product->Decomposes();
for (IfcSchema::IfcRelDecomposes::list::it it = decomposes->begin(); it != decomposes->end(); ++it) {
#endif
if ((*it)->RelatingObject() != product) {
is_decomposition = true;
break;
}
}
if (!is_decomposition) {
addRelatedObject<IfcSchema::IfcRelContainedInSpatialStructure>(storey, product);
relatePlacements(storey, product);
}
return storey;
}
void IfcHierarchyHelper::addExtrudedPolyline(Ifc2x3::IfcShapeRepresentation* rep, const std::vector<std::pair<double, double> >& points, double h,
Ifc2x3::IfcAxis2Placement2D* place, Ifc2x3::IfcAxis2Placement3D* place2,
Ifc2x3::IfcDirection* dir, Ifc2x3::IfcRepresentationContext* context)
void IfcHierarchyHelper::addExtrudedPolyline(IfcSchema::IfcShapeRepresentation* rep, const std::vector<std::pair<double, double> >& points, double h,
IfcSchema::IfcAxis2Placement2D* place, IfcSchema::IfcAxis2Placement3D* place2,
IfcSchema::IfcDirection* dir, IfcSchema::IfcRepresentationContext* context)
{
Ifc2x3::IfcCartesianPoint::list cartesian_points (new IfcTemplatedEntityList<Ifc2x3::IfcCartesianPoint>());
IfcSchema::IfcCartesianPoint::list::ptr cartesian_points (new IfcSchema::IfcCartesianPoint::list);
for (std::vector<std::pair<double, double> >::const_iterator i = points.begin(); i != points.end(); ++i) {
cartesian_points->push(addDoublet<Ifc2x3::IfcCartesianPoint>(i->first, i->second));
cartesian_points->push(addDoublet<IfcSchema::IfcCartesianPoint>(i->first, i->second));
}
if (cartesian_points->Size()) cartesian_points->push(*cartesian_points->begin());
Ifc2x3::IfcPolyline* line = new Ifc2x3::IfcPolyline(cartesian_points);
Ifc2x3::IfcArbitraryClosedProfileDef* profile = new Ifc2x3::IfcArbitraryClosedProfileDef(
Ifc2x3::IfcProfileTypeEnum::IfcProfileType_AREA, boost::none, line);
if (cartesian_points->size()) cartesian_points->push(*cartesian_points->begin());
IfcSchema::IfcPolyline* line = new IfcSchema::IfcPolyline(cartesian_points);
IfcSchema::IfcArbitraryClosedProfileDef* profile = new IfcSchema::IfcArbitraryClosedProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, boost::none, line);
Ifc2x3::IfcExtrudedAreaSolid* solid = new Ifc2x3::IfcExtrudedAreaSolid(
profile, place2 ? place2 : addPlacement3d(), dir ? dir : addTriplet<Ifc2x3::IfcDirection>(0, 0, 1), h);
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(
profile, place2 ? place2 : addPlacement3d(), dir ? dir : addTriplet<IfcSchema::IfcDirection>(0, 0, 1), h);
Ifc2x3::IfcRepresentationItem::list items = rep->Items();
IfcSchema::IfcRepresentationItem::list::ptr items = rep->Items();
items->push(solid);
rep->setItems(items);
rep->Items(items);
AddEntity(line);
AddEntity(profile);
AddEntity(solid);
addEntity(line);
addEntity(profile);
addEntity(solid);
}
Ifc2x3::IfcProductDefinitionShape* IfcHierarchyHelper::addExtrudedPolyline(const std::vector<std::pair<double, double> >& points, double h,
Ifc2x3::IfcAxis2Placement2D* place, Ifc2x3::IfcAxis2Placement3D* place2, Ifc2x3::IfcDirection* dir,
Ifc2x3::IfcRepresentationContext* context)
IfcSchema::IfcProductDefinitionShape* IfcHierarchyHelper::addExtrudedPolyline(const std::vector<std::pair<double, double> >& points, double h,
IfcSchema::IfcAxis2Placement2D* place, IfcSchema::IfcAxis2Placement3D* place2, IfcSchema::IfcDirection* dir,
IfcSchema::IfcRepresentationContext* context)
{
Ifc2x3::IfcRepresentation::list reps (new IfcTemplatedEntityList<Ifc2x3::IfcRepresentation>());
Ifc2x3::IfcRepresentationItem::list items (new IfcTemplatedEntityList<Ifc2x3::IfcRepresentationItem>());
Ifc2x3::IfcShapeRepresentation* rep = new Ifc2x3::IfcShapeRepresentation(context
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(context
? context
: getSingle<Ifc2x3::IfcRepresentationContext>(), std::string("Body"), std::string("SweptSolid"), items);
: getRepresentationContext("Model"), std::string("Body"), std::string("SweptSolid"), items);
reps->push(rep);
Ifc2x3::IfcProductDefinitionShape* shape = new Ifc2x3::IfcProductDefinitionShape(0, 0, reps);
AddEntity(rep);
AddEntity(shape);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
addEntity(rep);
addEntity(shape);
addExtrudedPolyline(rep, points, h, place, place2, dir, context);
return shape;
}
void IfcHierarchyHelper::addBox(Ifc2x3::IfcShapeRepresentation* rep, double w, double d, double h,
Ifc2x3::IfcAxis2Placement2D* place, Ifc2x3::IfcAxis2Placement3D* place2,
Ifc2x3::IfcDirection* dir, Ifc2x3::IfcRepresentationContext* context)
void IfcHierarchyHelper::addBox(IfcSchema::IfcShapeRepresentation* rep, double w, double d, double h,
IfcSchema::IfcAxis2Placement2D* place, IfcSchema::IfcAxis2Placement3D* place2,
IfcSchema::IfcDirection* dir, IfcSchema::IfcRepresentationContext* context)
{
if (false) {
Ifc2x3::IfcRectangleProfileDef* profile = new Ifc2x3::IfcRectangleProfileDef(
Ifc2x3::IfcProfileTypeEnum::IfcProfileType_AREA, 0, place ? place : addPlacement2d(), w, d);
Ifc2x3::IfcExtrudedAreaSolid* solid = new Ifc2x3::IfcExtrudedAreaSolid(profile,
place2 ? place2 : addPlacement3d(), dir ? dir : addTriplet<Ifc2x3::IfcDirection>(0, 0, 1), h);
IfcSchema::IfcRectangleProfileDef* profile = new IfcSchema::IfcRectangleProfileDef(
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, boost::none, place ? place : addPlacement2d(), w, d);
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(profile,
place2 ? place2 : addPlacement3d(), dir ? dir : addTriplet<IfcSchema::IfcDirection>(0, 0, 1), h);
AddEntity(profile);
AddEntity(solid);
Ifc2x3::IfcRepresentationItem::list items = rep->Items();
addEntity(profile);
addEntity(solid);
IfcSchema::IfcRepresentationItem::list::ptr items = rep->Items();
items->push(solid);
rep->setItems(items);
rep->Items(items);
} else {
std::vector<std::pair<double, double> > points;
points.push_back(std::pair<double, double>(-w/2, -d/2));
points.push_back(std::pair<double, double>(w/2, -d/2));
points.push_back(std::pair<double, double>(w/2, d/2));
points.push_back(std::pair<double, double>(-w/2, d/2));
points.push_back(*points.begin());
// The call to addExtrudedPolyline() closes the polyline
addExtrudedPolyline(rep, points, h, place, place2, dir, context);
}
}
Ifc2x3::IfcProductDefinitionShape* IfcHierarchyHelper::addBox(double w, double d, double h, Ifc2x3::IfcAxis2Placement2D* place,
Ifc2x3::IfcAxis2Placement3D* place2, Ifc2x3::IfcDirection* dir, Ifc2x3::IfcRepresentationContext* context)
void IfcHierarchyHelper::addAxis(IfcSchema::IfcShapeRepresentation* rep, double l, IfcSchema::IfcRepresentationContext* context) {
IfcSchema::IfcCartesianPoint* p1 = addDoublet<IfcSchema::IfcCartesianPoint>(-l / 2., 0.);
IfcSchema::IfcCartesianPoint* p2 = addDoublet<IfcSchema::IfcCartesianPoint>(+l / 2., 0.);
IfcSchema::IfcCartesianPoint::list::ptr pts(new IfcSchema::IfcCartesianPoint::list);
pts->push(p1); pts->push(p2);
IfcSchema::IfcPolyline* poly = new IfcSchema::IfcPolyline(pts);
addEntity(poly);
IfcSchema::IfcRepresentationItem::list::ptr items = rep->Items();
items->push(poly);
rep->Items(items);
}
IfcSchema::IfcProductDefinitionShape* IfcHierarchyHelper::addBox(double w, double d, double h, IfcSchema::IfcAxis2Placement2D* place,
IfcSchema::IfcAxis2Placement3D* place2, IfcSchema::IfcDirection* dir, IfcSchema::IfcRepresentationContext* context)
{
Ifc2x3::IfcRepresentation::list reps (new IfcTemplatedEntityList<Ifc2x3::IfcRepresentation>());
Ifc2x3::IfcRepresentationItem::list items (new IfcTemplatedEntityList<Ifc2x3::IfcRepresentationItem>());
Ifc2x3::IfcShapeRepresentation* rep = new Ifc2x3::IfcShapeRepresentation(
context ? context : getSingle<Ifc2x3::IfcRepresentationContext>(), std::string("Body"), std::string("SweptSolid"), items);
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
context ? context : getRepresentationContext("Model"), std::string("Body"), std::string("SweptSolid"), items);
reps->push(rep);
Ifc2x3::IfcProductDefinitionShape* shape = new Ifc2x3::IfcProductDefinitionShape(0, 0, reps);
AddEntity(rep);
AddEntity(shape);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, reps);
addEntity(rep);
addEntity(shape);
addBox(rep, w, d, h, place, place2, dir, context);
return shape;
}
void IfcHierarchyHelper::clipRepresentation(Ifc2x3::IfcProductRepresentation* shape,
Ifc2x3::IfcAxis2Placement3D* place, bool agree)
IfcSchema::IfcProductDefinitionShape* IfcHierarchyHelper::addAxisBox(double w, double d, double h, IfcSchema::IfcRepresentationContext* context)
{
Ifc2x3::IfcPlane* plane = new Ifc2x3::IfcPlane(place);
Ifc2x3::IfcHalfSpaceSolid* half_space = new Ifc2x3::IfcHalfSpaceSolid(plane, agree);
Ifc2x3::IfcRepresentation::list reps = shape->Representations();
for (Ifc2x3::IfcRepresentation::it j = reps->begin(); j != reps->end(); ++j) {
Ifc2x3::IfcRepresentation* rep = *j;
if (rep->RepresentationIdentifier() != "Body") continue;
rep->setRepresentationType("Clipping");
Ifc2x3::IfcRepresentationItem::list items = rep->Items();
Ifc2x3::IfcRepresentationItem::list new_items (new IfcTemplatedEntityList<Ifc2x3::IfcRepresentationItem>());
AddEntity(plane);
AddEntity(half_space);
for (Ifc2x3::IfcRepresentationItem::it i = items->begin(); i != items->end(); ++i) {
Ifc2x3::IfcRepresentationItem* item = *i;
Ifc2x3::IfcBooleanClippingResult* clip = new Ifc2x3::IfcBooleanClippingResult(
Ifc2x3::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE, item, half_space);
AddEntity(clip);
new_items->push(clip);
}
rep->setItems(new_items);
IfcSchema::IfcRepresentation::list::ptr reps(new IfcSchema::IfcRepresentation::list);
IfcSchema::IfcRepresentationItem::list::ptr body_items(new IfcSchema::IfcRepresentationItem::list);
IfcSchema::IfcRepresentationItem::list::ptr axis_items(new IfcSchema::IfcRepresentationItem::list);
IfcSchema::IfcShapeRepresentation* body_rep = new IfcSchema::IfcShapeRepresentation(
context ? context : getRepresentationContext("Model"), std::string("Body"), std::string("SweptSolid"), body_items);
IfcSchema::IfcShapeRepresentation* axis_rep = new IfcSchema::IfcShapeRepresentation(
context ? context : getRepresentationContext("Plan"), std::string("Axis"), std::string("Curve2D"), axis_items);
reps->push(axis_rep);
reps->push(body_rep);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, reps);
addEntity(shape);
addEntity(body_rep);
addBox(body_rep, w, d, h, 0, 0, 0, context);
addEntity(axis_rep);
addAxis(axis_rep, w);
return shape;
}
void IfcHierarchyHelper::clipRepresentation(IfcSchema::IfcProductRepresentation* shape,
IfcSchema::IfcAxis2Placement3D* place, bool agree)
{
IfcSchema::IfcRepresentation::list::ptr reps = shape->Representations();
for (IfcSchema::IfcRepresentation::list::it j = reps->begin(); j != reps->end(); ++j) {
clipRepresentation(*j, place, agree);
}
}
Ifc2x3::IfcPresentationStyleAssignment* IfcHierarchyHelper::setSurfaceColour(
Ifc2x3::IfcProductRepresentation* shape, double r, double g, double b, double a)
void IfcHierarchyHelper::clipRepresentation(IfcSchema::IfcRepresentation* rep,
IfcSchema::IfcAxis2Placement3D* place, bool agree)
{
Ifc2x3::IfcColourRgb* colour = new Ifc2x3::IfcColourRgb(boost::none, r, g, b);
Ifc2x3::IfcSurfaceStyleRendering* rendering = a == 1.0
? new Ifc2x3::IfcSurfaceStyleRendering(colour, boost::none, boost::none, boost::none, boost::none, boost::none,
boost::none, boost::none, Ifc2x3::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT)
: new Ifc2x3::IfcSurfaceStyleRendering(colour, 1.0-a, boost::none, boost::none, boost::none, boost::none,
boost::none, boost::none, Ifc2x3::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT);
if (!rep->RepresentationIdentifier() || *rep->RepresentationIdentifier() != "Body") return;
IfcSchema::IfcPlane* plane = new IfcSchema::IfcPlane(place);
IfcSchema::IfcHalfSpaceSolid* half_space = new IfcSchema::IfcHalfSpaceSolid(plane, agree);
addEntity(plane);
addEntity(half_space);
rep->RepresentationType(std::string("Clipping"));
IfcSchema::IfcRepresentationItem::list::ptr items = rep->Items();
IfcSchema::IfcRepresentationItem::list::ptr new_items (new IfcSchema::IfcRepresentationItem::list);
for (IfcSchema::IfcRepresentationItem::list::it i = items->begin(); i != items->end(); ++i) {
IfcSchema::IfcRepresentationItem* item = *i;
IfcSchema::IfcBooleanClippingResult* clip = new IfcSchema::IfcBooleanClippingResult(
IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE, item, half_space);
addEntity(clip);
new_items->push(clip);
}
rep->Items(new_items);
}
IfcEntities styles(new IfcEntityList());
IfcSchema::IfcPresentationStyleAssignment* IfcHierarchyHelper::addStyleAssignment(double r, double g, double b, double a) {
IfcSchema::IfcColourRgb* colour = new IfcSchema::IfcColourRgb(boost::none, r, g, b);
IfcSchema::IfcSurfaceStyleRendering* rendering = a == 1.0
? new IfcSchema::IfcSurfaceStyleRendering(colour, boost::none, boost::none, boost::none, boost::none, boost::none,
boost::none, boost::none, IfcSchema::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT)
: new IfcSchema::IfcSurfaceStyleRendering(colour, 1.0-a, boost::none, boost::none, boost::none, boost::none,
boost::none, boost::none, IfcSchema::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT);
IfcEntityList::ptr styles(new IfcEntityList());
styles->push(rendering);
Ifc2x3::IfcSurfaceStyle* surface_style = new Ifc2x3::IfcSurfaceStyle(
boost::none, Ifc2x3::IfcSurfaceSide::IfcSurfaceSide_BOTH, styles);
IfcEntities surface_styles(new IfcEntityList());
IfcSchema::IfcSurfaceStyle* surface_style = new IfcSchema::IfcSurfaceStyle(
boost::none, IfcSchema::IfcSurfaceSide::IfcSurfaceSide_BOTH, styles);
IfcEntityList::ptr surface_styles(new IfcEntityList());
surface_styles->push(surface_style);
Ifc2x3::IfcPresentationStyleAssignment* style_assignment =
new Ifc2x3::IfcPresentationStyleAssignment(surface_styles);
AddEntity(colour);
AddEntity(rendering);
AddEntity(surface_style);
AddEntity(style_assignment);
IfcSchema::IfcPresentationStyleAssignment* style_assignment =
new IfcSchema::IfcPresentationStyleAssignment(surface_styles);
addEntity(colour);
addEntity(rendering);
addEntity(surface_style);
addEntity(style_assignment);
return style_assignment;
}
IfcSchema::IfcPresentationStyleAssignment* IfcHierarchyHelper::setSurfaceColour(
IfcSchema::IfcProductRepresentation* shape, double r, double g, double b, double a)
{
IfcSchema::IfcPresentationStyleAssignment* style_assignment = addStyleAssignment(r, g, b, a);
setSurfaceColour(shape, style_assignment);
return style_assignment;
}
void IfcHierarchyHelper::setSurfaceColour(Ifc2x3::IfcProductRepresentation* shape,
Ifc2x3::IfcPresentationStyleAssignment* style_assignment)
IfcSchema::IfcPresentationStyleAssignment* IfcHierarchyHelper::setSurfaceColour(
IfcSchema::IfcRepresentation* shape, double r, double g, double b, double a)
{
Ifc2x3::IfcPresentationStyleAssignment::list style_assignments (new IfcTemplatedEntityList<Ifc2x3::IfcPresentationStyleAssignment>());
style_assignments->push(style_assignment);
Ifc2x3::IfcRepresentation::list reps = shape->Representations();
for (Ifc2x3::IfcRepresentation::it j = reps->begin(); j != reps->end(); ++j) {
Ifc2x3::IfcRepresentation* rep = *j;
if (rep->RepresentationIdentifier() != "Body" && rep->RepresentationIdentifier() != "Facetation") continue;
Ifc2x3::IfcRepresentationItem::list items = rep->Items();
for (Ifc2x3::IfcRepresentationItem::it i = items->begin(); i != items->end(); ++i) {
Ifc2x3::IfcRepresentationItem* item = *i;
Ifc2x3::IfcStyledItem* styled_item = new Ifc2x3::IfcStyledItem(item, style_assignments, boost::none);
AddEntity(styled_item);
}
IfcSchema::IfcPresentationStyleAssignment* style_assignment = addStyleAssignment(r, g, b, a);
setSurfaceColour(shape, style_assignment);
return style_assignment;
}
void IfcHierarchyHelper::setSurfaceColour(IfcSchema::IfcProductRepresentation* shape,
IfcSchema::IfcPresentationStyleAssignment* style_assignment)
{
IfcSchema::IfcRepresentation::list::ptr reps = shape->Representations();
for (IfcSchema::IfcRepresentation::list::it j = reps->begin(); j != reps->end(); ++j) {
setSurfaceColour(*j, style_assignment);
}
}
void IfcHierarchyHelper::setSurfaceColour(IfcSchema::IfcRepresentation* rep,
IfcSchema::IfcPresentationStyleAssignment* style_assignment)
{
#ifdef USE_IFC4
IfcEntityList::ptr style_assignments (new IfcEntityList);
#else
IfcSchema::IfcPresentationStyleAssignment::list::ptr style_assignments (new IfcSchema::IfcPresentationStyleAssignment::list);
#endif
style_assignments->push(style_assignment);
IfcSchema::IfcRepresentationItem::list::ptr items = rep->Items();
for (IfcSchema::IfcRepresentationItem::list::it i = items->begin(); i != items->end(); ++i) {
IfcSchema::IfcRepresentationItem* item = *i;
IfcSchema::IfcStyledItem* styled_item = new IfcSchema::IfcStyledItem(item, style_assignments, boost::none);
addEntity(styled_item);
}
}
IfcSchema::IfcProductDefinitionShape* IfcHierarchyHelper::addMappedItem(
IfcSchema::IfcShapeRepresentation* rep,
IfcSchema::IfcCartesianTransformationOperator3D* transform,
IfcSchema::IfcProductDefinitionShape* def)
{
IfcSchema::IfcRepresentationMap::list::ptr maps = rep->RepresentationMap();
IfcSchema::IfcRepresentationMap* map;
if (maps->size() == 1) {
map = *maps->begin();
} else {
map = new IfcSchema::IfcRepresentationMap(addPlacement3d(), rep);
addEntity(map);
}
IfcSchema::IfcRepresentation::list::ptr representations(new IfcSchema::IfcRepresentation::list);
if (def) representations = def->Representations();
if (!transform) {
transform = new IfcSchema::IfcCartesianTransformationOperator3D(boost::none, boost::none, addTriplet<IfcSchema::IfcCartesianPoint>(0,0,0), boost::none, boost::none);
addEntity(transform);
}
IfcSchema::IfcMappedItem* item = new IfcSchema::IfcMappedItem(map, transform);
IfcSchema::IfcRepresentationItem::list::ptr items(new IfcSchema::IfcRepresentationItem::list);
items->push(item);
IfcSchema::IfcRepresentation* new_rep = new IfcSchema::IfcShapeRepresentation(rep->ContextOfItems(), boost::none, std::string("MappedRepresentation"), items);
if (rep->RepresentationIdentifier()) {
new_rep->RepresentationIdentifier(*rep->RepresentationIdentifier());
}
addEntity(item);
addEntity(new_rep);
representations->push(new_rep);
if (!def) {
def = new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, representations);
addEntity(def);
} else {
def->Representations(representations);
}
return def;
}
IfcSchema::IfcProductDefinitionShape* IfcHierarchyHelper::addMappedItem(
IfcSchema::IfcShapeRepresentation::list::ptr reps,
IfcSchema::IfcCartesianTransformationOperator3D* transform)
{
IfcSchema::IfcProductDefinitionShape* def = 0;
for (IfcSchema::IfcShapeRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
def = addMappedItem(*it, transform, def);
}
return def;
}
IfcSchema::IfcShapeRepresentation* IfcHierarchyHelper::addEmptyRepresentation(const std::string& repid, const std::string& reptype) {
IfcSchema::IfcRepresentationItem::list::ptr items(new IfcSchema::IfcRepresentationItem::list);
IfcSchema::IfcShapeRepresentation* shape_rep = new IfcSchema::IfcShapeRepresentation(getRepresentationContext(reptype == "Curve2D" ? "Plan" : "Model"), repid, reptype, items);
addEntity(shape_rep);
return shape_rep;
}
IfcSchema::IfcGeometricRepresentationContext* IfcHierarchyHelper::getRepresentationContext(const std::string& s) {
std::map<std::string, IfcSchema::IfcGeometricRepresentationContext*>::const_iterator it = contexts.find(s);
if (it != contexts.end()) return it->second;
else {
IfcSchema::IfcProject* project = getSingle<IfcSchema::IfcProject>();
IfcSchema::IfcRepresentationContext::list::ptr project_contexts = project->RepresentationContexts();
IfcSchema::IfcGeometricRepresentationContext* context = new IfcSchema::IfcGeometricRepresentationContext(
boost::none, s, 3, 1e-5, addPlacement3d(), addDoublet<IfcSchema::IfcDirection>(0, 1));
addEntity(context);
project_contexts->push(context);
project->RepresentationContexts(project_contexts);
return contexts[s] = context;
}
}
+90 -55
View File
@@ -28,7 +28,13 @@
#ifndef IFCHIERARCHYHELPER_H
#define IFCHIERARCHYHELPER_H
#include <map>
#ifdef USE_IFC4
#include "../ifcparse/Ifc4.h"
#else
#include "../ifcparse/Ifc2x3.h"
#endif
#include "../ifcparse/IfcFile.h"
#include "../ifcparse/IfcWrite.h"
@@ -38,7 +44,7 @@ public:
T* addTriplet(double x, double y, double z) {
std::vector<double> a; a.push_back(x); a.push_back(y); a.push_back(z);
T* t = new T(a);
AddEntity(t);
addEntity(t);
return t;
}
@@ -46,125 +52,154 @@ public:
T* addDoublet(double x, double y) {
std::vector<double> a; a.push_back(x); a.push_back(y);
T* t = new T(a);
AddEntity(t);
addEntity(t);
return t;
}
template <class T>
T* getSingle() {
typename T::list ts = EntitiesByType<T>();
if (ts->Size() != 1) return 0;
typename T::list::ptr ts = entitiesByType<T>();
if (ts->size() != 1) return 0;
return *ts->begin();
}
Ifc2x3::IfcAxis2Placement3D* addPlacement3d(double ox=0.0, double oy=0.0, double oz=0.0,
IfcSchema::IfcAxis2Placement3D* addPlacement3d(double ox=0.0, double oy=0.0, double oz=0.0,
double zx=0.0, double zy=0.0, double zz=1.0,
double xx=1.0, double xy=0.0, double xz=0.0);
Ifc2x3::IfcAxis2Placement2D* addPlacement2d(double ox=0.0, double oy=0.0,
IfcSchema::IfcAxis2Placement2D* addPlacement2d(double ox=0.0, double oy=0.0,
double xx=1.0, double xy=0.0);
Ifc2x3::IfcLocalPlacement* addLocalPlacement(double ox=0.0, double oy=0.0, double oz=0.0,
IfcSchema::IfcLocalPlacement* addLocalPlacement(IfcSchema::IfcObjectPlacement* parent = 0,
double ox=0.0, double oy=0.0, double oz=0.0,
double zx=0.0, double zy=0.0, double zz=1.0,
double xx=1.0, double xy=0.0, double xz=0.0);
template <class T>
void addRelatedObject(Ifc2x3::IfcObjectDefinition* related_object,
Ifc2x3::IfcObjectDefinition* relating_object, Ifc2x3::IfcOwnerHistory* owner_hist = 0)
void addRelatedObject(IfcSchema::IfcObjectDefinition* related_object,
IfcSchema::IfcObjectDefinition* relating_object, IfcSchema::IfcOwnerHistory* owner_hist = 0)
{
typename T::list li = EntitiesByType<T>();
typename T::list::ptr li = entitiesByType<T>();
bool found = false;
for (typename T::it i = li->begin(); i != li->end(); ++i) {
for (typename T::list::it i = li->begin(); i != li->end(); ++i) {
T* rel = *i;
if (rel->RelatingObject() == relating_object) {
Ifc2x3::IfcObjectDefinition::list products = rel->RelatedObjects();
IfcSchema::IfcObjectDefinition::list::ptr products = rel->RelatedObjects();
products->push(related_object);
rel->setRelatedObjects(products);
rel->RelatedObjects(products);
found = true;
break;
}
}
if (! found) {
if (! owner_hist) {
owner_hist = getSingle<Ifc2x3::IfcOwnerHistory>();
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
}
if (! owner_hist) {
owner_hist = addOwnerHistory();
}
Ifc2x3::IfcObjectDefinition::list relating_objects (new IfcTemplatedEntityList<Ifc2x3::IfcObjectDefinition>());
IfcSchema::IfcObjectDefinition::list::ptr relating_objects (new IfcTemplatedEntityList<IfcSchema::IfcObjectDefinition>());
relating_objects->push(relating_object);
T* t = new T(IfcWrite::IfcGuidHelper(), owner_hist, boost::none, boost::none, related_object, relating_objects);
AddEntity(t);
addEntity(t);
}
}
Ifc2x3::IfcOwnerHistory* addOwnerHistory();
Ifc2x3::IfcProject* addProject(Ifc2x3::IfcOwnerHistory* owner_hist = 0);
void relatePlacements(Ifc2x3::IfcProduct* parent, Ifc2x3::IfcProduct* product);
Ifc2x3::IfcSite* addSite(Ifc2x3::IfcProject* proj = 0, Ifc2x3::IfcOwnerHistory* owner_hist = 0);
Ifc2x3::IfcBuilding* addBuilding(Ifc2x3::IfcSite* site = 0, Ifc2x3::IfcOwnerHistory* owner_hist = 0);
IfcSchema::IfcOwnerHistory* addOwnerHistory();
IfcSchema::IfcProject* addProject(IfcSchema::IfcOwnerHistory* owner_hist = 0);
void relatePlacements(IfcSchema::IfcProduct* parent, IfcSchema::IfcProduct* product);
IfcSchema::IfcSite* addSite(IfcSchema::IfcProject* proj = 0, IfcSchema::IfcOwnerHistory* owner_hist = 0);
IfcSchema::IfcBuilding* addBuilding(IfcSchema::IfcSite* site = 0, IfcSchema::IfcOwnerHistory* owner_hist = 0);
Ifc2x3::IfcBuildingStorey* addBuildingStorey(Ifc2x3::IfcBuilding* building = 0,
Ifc2x3::IfcOwnerHistory* owner_hist = 0);
IfcSchema::IfcBuildingStorey* addBuildingStorey(IfcSchema::IfcBuilding* building = 0,
IfcSchema::IfcOwnerHistory* owner_hist = 0);
Ifc2x3::IfcBuildingStorey* addBuildingProduct(Ifc2x3::IfcProduct* product,
Ifc2x3::IfcBuildingStorey* storey = 0, Ifc2x3::IfcOwnerHistory* owner_hist = 0);
IfcSchema::IfcBuildingStorey* addBuildingProduct(IfcSchema::IfcProduct* product,
IfcSchema::IfcBuildingStorey* storey = 0, IfcSchema::IfcOwnerHistory* owner_hist = 0);
void addExtrudedPolyline(Ifc2x3::IfcShapeRepresentation* rep, const std::vector<std::pair<double, double> >& points, double h,
Ifc2x3::IfcAxis2Placement2D* place=0, Ifc2x3::IfcAxis2Placement3D* place2=0,
Ifc2x3::IfcDirection* dir=0, Ifc2x3::IfcRepresentationContext* context=0);
void addExtrudedPolyline(IfcSchema::IfcShapeRepresentation* rep, const std::vector<std::pair<double, double> >& points, double h,
IfcSchema::IfcAxis2Placement2D* place=0, IfcSchema::IfcAxis2Placement3D* place2=0,
IfcSchema::IfcDirection* dir=0, IfcSchema::IfcRepresentationContext* context=0);
Ifc2x3::IfcProductDefinitionShape* addExtrudedPolyline(const std::vector<std::pair<double, double> >& points, double h,
Ifc2x3::IfcAxis2Placement2D* place=0, Ifc2x3::IfcAxis2Placement3D* place2=0, Ifc2x3::IfcDirection* dir=0,
Ifc2x3::IfcRepresentationContext* context=0);
IfcSchema::IfcProductDefinitionShape* addExtrudedPolyline(const std::vector<std::pair<double, double> >& points, double h,
IfcSchema::IfcAxis2Placement2D* place=0, IfcSchema::IfcAxis2Placement3D* place2=0, IfcSchema::IfcDirection* dir=0,
IfcSchema::IfcRepresentationContext* context=0);
void addBox(Ifc2x3::IfcShapeRepresentation* rep, double w, double d, double h,
Ifc2x3::IfcAxis2Placement2D* place=0, Ifc2x3::IfcAxis2Placement3D* place2=0,
Ifc2x3::IfcDirection* dir=0, Ifc2x3::IfcRepresentationContext* context=0);
void addBox(IfcSchema::IfcShapeRepresentation* rep, double w, double d, double h,
IfcSchema::IfcAxis2Placement2D* place=0, IfcSchema::IfcAxis2Placement3D* place2=0,
IfcSchema::IfcDirection* dir=0, IfcSchema::IfcRepresentationContext* context=0);
Ifc2x3::IfcProductDefinitionShape* addBox(double w, double d, double h, Ifc2x3::IfcAxis2Placement2D* place=0,
Ifc2x3::IfcAxis2Placement3D* place2=0, Ifc2x3::IfcDirection* dir=0, Ifc2x3::IfcRepresentationContext* context=0);
IfcSchema::IfcProductDefinitionShape* addBox(double w, double d, double h, IfcSchema::IfcAxis2Placement2D* place=0,
IfcSchema::IfcAxis2Placement3D* place2=0, IfcSchema::IfcDirection* dir=0, IfcSchema::IfcRepresentationContext* context=0);
void clipRepresentation(Ifc2x3::IfcProductRepresentation* shape,
Ifc2x3::IfcAxis2Placement3D* place, bool agree);
void addAxis(IfcSchema::IfcShapeRepresentation* rep, double l, IfcSchema::IfcRepresentationContext* context=0);
Ifc2x3::IfcPresentationStyleAssignment* setSurfaceColour(Ifc2x3::IfcProductRepresentation* shape,
IfcSchema::IfcProductDefinitionShape* addAxisBox(double w, double d, double h, IfcSchema::IfcRepresentationContext* context=0);
void clipRepresentation(IfcSchema::IfcProductRepresentation* shape,
IfcSchema::IfcAxis2Placement3D* place, bool agree);
void clipRepresentation(IfcSchema::IfcRepresentation* shape,
IfcSchema::IfcAxis2Placement3D* place, bool agree);
IfcSchema::IfcPresentationStyleAssignment* addStyleAssignment(double r, double g, double b, double a=1.0);
IfcSchema::IfcPresentationStyleAssignment* setSurfaceColour(IfcSchema::IfcProductRepresentation* shape,
double r, double g, double b, double a=1.0);
void setSurfaceColour(Ifc2x3::IfcProductRepresentation* shape,
Ifc2x3::IfcPresentationStyleAssignment* style_assignment);
IfcSchema::IfcPresentationStyleAssignment* setSurfaceColour(IfcSchema::IfcRepresentation* shape,
double r, double g, double b, double a=1.0);
void setSurfaceColour(IfcSchema::IfcProductRepresentation* shape,
IfcSchema::IfcPresentationStyleAssignment* style_assignment);
void setSurfaceColour(IfcSchema::IfcRepresentation* shape,
IfcSchema::IfcPresentationStyleAssignment* style_assignment);
IfcSchema::IfcProductDefinitionShape* addMappedItem(IfcSchema::IfcShapeRepresentation*,
IfcSchema::IfcCartesianTransformationOperator3D* transform = 0,
IfcSchema::IfcProductDefinitionShape* def = 0);
IfcSchema::IfcProductDefinitionShape* addMappedItem(IfcSchema::IfcShapeRepresentation::list::ptr,
IfcSchema::IfcCartesianTransformationOperator3D* transform = 0);
IfcSchema::IfcShapeRepresentation* addEmptyRepresentation(const std::string& repid = "Body", const std::string& reptype = "SweptSolid");
IfcSchema::IfcGeometricRepresentationContext* getRepresentationContext(const std::string&);
private:
std::map<std::string, IfcSchema::IfcGeometricRepresentationContext*> contexts;
};
template <>
inline void IfcHierarchyHelper::addRelatedObject <Ifc2x3::IfcRelContainedInSpatialStructure> (Ifc2x3::IfcObjectDefinition* related_object,
Ifc2x3::IfcObjectDefinition* relating_object, Ifc2x3::IfcOwnerHistory* owner_hist)
inline void IfcHierarchyHelper::addRelatedObject <IfcSchema::IfcRelContainedInSpatialStructure> (IfcSchema::IfcObjectDefinition* related_object,
IfcSchema::IfcObjectDefinition* relating_object, IfcSchema::IfcOwnerHistory* owner_hist)
{
Ifc2x3::IfcRelContainedInSpatialStructure::list li = EntitiesByType<Ifc2x3::IfcRelContainedInSpatialStructure>();
IfcSchema::IfcRelContainedInSpatialStructure::list::ptr li = entitiesByType<IfcSchema::IfcRelContainedInSpatialStructure>();
bool found = false;
for (Ifc2x3::IfcRelContainedInSpatialStructure::it i = li->begin(); i != li->end(); ++i) {
Ifc2x3::IfcRelContainedInSpatialStructure* rel = *i;
for (IfcSchema::IfcRelContainedInSpatialStructure::list::it i = li->begin(); i != li->end(); ++i) {
IfcSchema::IfcRelContainedInSpatialStructure* rel = *i;
if (rel->RelatingStructure() == relating_object) {
Ifc2x3::IfcProduct::list products = rel->RelatedElements();
products->push((Ifc2x3::IfcProduct*)related_object);
rel->setRelatedElements(products);
IfcSchema::IfcProduct::list::ptr products = rel->RelatedElements();
products->push((IfcSchema::IfcProduct*)related_object);
rel->RelatedElements(products);
found = true;
break;
}
}
if (! found) {
if (! owner_hist) {
owner_hist = getSingle<Ifc2x3::IfcOwnerHistory>();
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
}
if (! owner_hist) {
owner_hist = addOwnerHistory();
}
Ifc2x3::IfcProduct::list relating_objects (new IfcTemplatedEntityList<Ifc2x3::IfcProduct>());
relating_objects->push((Ifc2x3::IfcProduct*)relating_object);
Ifc2x3::IfcRelContainedInSpatialStructure* t = new Ifc2x3::IfcRelContainedInSpatialStructure(IfcWrite::IfcGuidHelper(), owner_hist,
boost::none, boost::none, relating_objects, (Ifc2x3::IfcSpatialStructureElement*)related_object);
IfcSchema::IfcProduct::list::ptr relating_objects (new IfcTemplatedEntityList<IfcSchema::IfcProduct>());
relating_objects->push((IfcSchema::IfcProduct*)relating_object);
IfcSchema::IfcRelContainedInSpatialStructure* t = new IfcSchema::IfcRelContainedInSpatialStructure(IfcWrite::IfcGuidHelper(), owner_hist,
boost::none, boost::none, relating_objects, (IfcSchema::IfcSpatialStructureElement*)related_object);
AddEntity(t);
addEntity(t);
}
}
+234
View File
@@ -0,0 +1,234 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include <sstream>
#include "../ifcparse/IfcWritableEntity.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcWrite.h"
#ifdef USE_IFC4
#include "../ifcparse/Ifc4-latebound.h"
#else
#include "../ifcparse/Ifc2x3-latebound.h"
#endif
#include "IfcLateBoundEntity.h"
using namespace IfcUtil;
IfcWrite::IfcWritableEntity* IfcParse::IfcLateBoundEntity::writable_entity() {
IfcWrite::IfcWritableEntity* e;
if (entity->isWritable()) {
e = (IfcWrite::IfcWritableEntity*) entity;
} else {
entity = e = new IfcWrite::IfcWritableEntity(entity);
}
return e;
}
IfcParse::IfcLateBoundEntity::IfcLateBoundEntity(const std::string& s) {
std::string S = s;
for (std::string::iterator i = S.begin(); i != S.end(); ++i ) *i = toupper(*i);
_type = IfcSchema::Type::FromString(S);
entity = new IfcWrite::IfcWritableEntity(_type);
for (unsigned i = 0; i < getArgumentCount(); ++i) {
// Side effect of this is that a NULL attribute is created.
entity->getArgument(i);
}
IfcSchema::Type::PopulateDerivedFields(writable_entity());
}
IfcParse::IfcLateBoundEntity::IfcLateBoundEntity(IfcAbstractEntity* e) {
entity = e;
_type = e->type();
}
unsigned int IfcParse::IfcLateBoundEntity::id() const {
if (entity->file) {
return static_cast<unsigned int>(entity->id());
} else {
throw IfcException("Entity not bound to a file");
}
}
bool IfcParse::IfcLateBoundEntity::is(IfcSchema::Type::Enum v) const {
IfcSchema::Type::Enum _ty = _type;
if (v == _ty) return true;
while (_ty != -1) {
_ty = IfcSchema::Type::Parent(_ty);
if (v == _ty) return true;
}
return false;
}
std::string IfcParse::IfcLateBoundEntity::is_a() const {
return IfcSchema::Type::ToString(_type);
}
bool IfcParse::IfcLateBoundEntity::is_a(const std::string& s) const {
std::string S = s;
for (std::string::iterator i = S.begin(); i != S.end(); ++i ) *i = toupper(*i);
return is(IfcSchema::Type::FromString(S));
}
IfcSchema::Type::Enum IfcParse::IfcLateBoundEntity::type() const {
return _type;
}
unsigned int IfcParse::IfcLateBoundEntity::getArgumentCount() const {
return IfcSchema::Type::GetAttributeCount(_type);
}
IfcUtil::ArgumentType IfcParse::IfcLateBoundEntity::getArgumentType(unsigned int i) const {
return IfcSchema::Type::GetAttributeDerived(_type, i)
? IfcUtil::Argument_DERIVED
: IfcSchema::Type::GetAttributeType(_type,i);
}
IfcSchema::Type::Enum IfcParse::IfcLateBoundEntity::getArgumentEntity(unsigned int i) const {
return IfcSchema::Type::GetAttributeEntity(_type, i);
}
Argument* IfcParse::IfcLateBoundEntity::getArgument(unsigned int i) const {
return entity->getArgument(i);
}
const char* IfcParse::IfcLateBoundEntity::getArgumentName(unsigned int i) const {
return IfcSchema::Type::GetAttributeName(_type,i).c_str();
}
bool IfcParse::IfcLateBoundEntity::getArgumentOptionality(unsigned int i) const {
return IfcSchema::Type::GetAttributeOptional(_type, i);
}
void IfcParse::IfcLateBoundEntity::invalid_argument(unsigned int i, const std::string& t) {
const std::string arg_name = IfcSchema::Type::GetAttributeName(_type,i);
throw IfcException(t + " is not a valid type for '" + arg_name + "'");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i) {
bool is_optional = IfcSchema::Type::GetAttributeOptional(_type, i);
if (is_optional) {
writable_entity()->setArgument(i);
} else invalid_argument(i,"NULL");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, int v) {
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
if (arg_type == Argument_INT) {
writable_entity()->setArgument(i,v);
} else if ( (arg_type == Argument_BOOL) && ( (v == 0) || (v == 1) ) ) {
writable_entity()->setArgument(i, v == 1);
} else invalid_argument(i,"INT");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, bool v) {
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
if (arg_type == Argument_BOOL) {
writable_entity()->setArgument(i,v);
} else invalid_argument(i,"BOOL");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, double v) {
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
if (arg_type == Argument_DOUBLE) {
writable_entity()->setArgument(i,v);
} else invalid_argument(i,"DOUBLE");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, const std::string& a) {
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
if (arg_type == Argument_STRING) {
writable_entity()->setArgument(i,a);
} else if (arg_type == Argument_ENUMERATION) {
std::pair<const char*, int> enum_data = IfcSchema::Type::GetEnumerationIndex(IfcSchema::Type::GetAttributeEntity(_type, i), a);
writable_entity()->setArgument(i, enum_data.second, enum_data.first);
} else invalid_argument(i,"STRING");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, const std::vector<int>& v) {
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
if (arg_type == Argument_VECTOR_INT) {
writable_entity()->setArgument(i,v);
} else invalid_argument(i,"LIST of INT");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, const std::vector<double>& v) {
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
if (arg_type == Argument_VECTOR_DOUBLE) {
writable_entity()->setArgument(i,v);
} else invalid_argument(i,"LIST of DOUBLE");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, const std::vector<std::string>& v) {
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
if (arg_type == Argument_VECTOR_STRING) {
writable_entity()->setArgument(i,v);
} else invalid_argument(i,"LIST of STRING");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, IfcParse::IfcLateBoundEntity* v) {
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
if (arg_type == Argument_ENTITY) {
writable_entity()->setArgument(i,v);
} else invalid_argument(i,"ENTITY");
}
void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, IfcEntityList::ptr v) {
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
if (arg_type == Argument_ENTITY_LIST) {
writable_entity()->setArgument(i,v);
} else invalid_argument(i,"LIST of ENTITY");
}
std::pair<IfcUtil::ArgumentType,Argument*> IfcParse::IfcLateBoundEntity::get_argument(unsigned i) {
return std::pair<IfcUtil::ArgumentType,Argument*>(getArgumentType(i),getArgument(i));
}
std::pair<IfcUtil::ArgumentType,Argument*> IfcParse::IfcLateBoundEntity::get_argument(const std::string& a) {
return get_argument(IfcSchema::Type::GetAttributeIndex(_type,a));
}
unsigned IfcParse::IfcLateBoundEntity::getArgumentIndex(const std::string& a) const {
return IfcSchema::Type::GetAttributeIndex(_type,a);
}
std::string IfcParse::IfcLateBoundEntity::toString() {
return entity->toString(false);
}
IfcEntityList::ptr IfcParse::IfcLateBoundEntity::get_inverse(const std::string& a) {
std::pair<IfcSchema::Type::Enum, unsigned> inv = IfcSchema::Type::GetInverseAttribute(_type, a);
return entity->getInverse(inv.first, inv.second);
}
bool IfcParse::IfcLateBoundEntity::is_valid() {
const unsigned arg_count = getArgumentCount();
bool valid = true;
std::ostringstream oss;
oss << "Argument ";
for (unsigned i = 0; i < arg_count; ++i) {
bool is_null = true;
try {
const Argument& arg = *getArgument(i);
is_null = arg.isNull();
} catch(IfcException) {}
if (!IfcSchema::Type::GetAttributeOptional(_type,i) && is_null) {
if (!valid) {
oss << ", ";
}
oss << "\"" << getArgumentName(i) << "\"";
valid = false;
}
}
oss << " not optional";
if (!valid) {
throw IfcException(oss.str());
}
return valid;
}
std::vector<std::string> IfcParse::IfcLateBoundEntity::getAttributeNames() const {
std::vector<std::string> return_value;
return_value.reserve(getArgumentCount());
for (unsigned i = 0; i < getArgumentCount(); ++i) {
return_value.push_back(getArgumentName(i));
}
return return_value;
}
std::vector<std::string> IfcParse::IfcLateBoundEntity::getInverseAttributeNames() const {
std::vector<std::string> return_value;
std::set<std::string> values = IfcSchema::Type::GetInverseAttributeNames(_type);
std::copy(values.begin(), values.end(), std::back_inserter(return_value));
return return_value;
}
+85
View File
@@ -0,0 +1,85 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef IFCLATEBOUNDENTITY_H
#define IFCLATEBOUNDENTITY_H
#include <string>
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcWrite.h"
#include "../ifcparse/IfcWritableEntity.h"
namespace IfcParse {
// TODO: Somehow these methods should become part of IfcBaseEntity directly so
// that in the IfcFile class the distinction what entity type to be created is
// no longer necessary and weird diagonal casts when creating geometry from
// IfcLateBoundEntities are eliminated.
class IfcLateBoundEntity : public IfcUtil::IfcBaseEntity {
private:
IfcSchema::Type::Enum _type;
IfcWrite::IfcWritableEntity* writable_entity();
void invalid_argument(unsigned int i, const std::string& t);
public:
IfcLateBoundEntity(const std::string& s);
IfcLateBoundEntity(IfcAbstractEntity* e);
bool is(IfcSchema::Type::Enum v) const;
IfcSchema::Type::Enum type() const;
bool is_a(const std::string& s) const;
std::string is_a() const;
unsigned int id() const;
unsigned int getArgumentCount() const;
IfcUtil::ArgumentType getArgumentType(unsigned int i) const;
IfcSchema::Type::Enum getArgumentEntity(unsigned int i) const;
Argument* getArgument(unsigned int i) const;
const char* getArgumentName(unsigned int i) const;
unsigned getArgumentIndex(const std::string& a) const;
bool getArgumentOptionality(unsigned int i) const;
IfcEntityList::ptr get_inverse(const std::string& a);
std::vector<std::string> getAttributeNames() const;
std::vector<std::string> getInverseAttributeNames() const;
void setArgument(unsigned int i);
void setArgument(unsigned int i, int v);
void setArgument(unsigned int i, bool v);
void setArgument(unsigned int i, double v);
void setArgument(unsigned int i, const std::string& v);
void setArgument(unsigned int i, const std::vector<int>& v);
void setArgument(unsigned int i, const std::vector<double>& v);
void setArgument(unsigned int i, const std::vector<std::string>& v);
void setArgument(unsigned int i, IfcLateBoundEntity* v);
void setArgument(unsigned int i, IfcEntityList::ptr v);
std::string toString();
// TODO: Write as SWIG extension methods?
std::pair<IfcUtil::ArgumentType,Argument*> get_argument(unsigned i);
std::pair<IfcUtil::ArgumentType,Argument*> get_argument(const std::string& a);
bool is_valid();
};
}
#endif
+773 -242
View File
File diff suppressed because it is too large Load Diff
+70 -130
View File
@@ -20,14 +20,14 @@
/********************************************************************************
* *
* This file provides functions for loading an IFC file into memory and access *
* its entities either by ID, by an Ifc2x3::Type or by reference *
* its entities either by ID, by an IfcSchema::Type or by reference *
* *
********************************************************************************/
#ifndef IFCPARSE_H
#define IFCPARSE_H
#define IFCOPENSHELL_VERSION "0.4.0-dev"
#define IFCOPENSHELL_VERSION "0.5.0-dev"
#include <string>
#include <sstream>
@@ -40,19 +40,22 @@
#include "../ifcparse/SharedPointer.h"
#include "../ifcparse/IfcCharacterDecoder.h"
#include "../ifcparse/IfcUtil.h"
#ifdef USE_IFC4
#include "../ifcparse/Ifc4.h"
#else
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/IfcFile.h"
#endif
#include "../ifcparse/IfcSpfStream.h"
namespace IfcParse {
class Entity;
class Entities;
class IfcFile;
typedef Entity* EntityPtr;
typedef SHARED_PTR<Entities> EntitiesPtr;
class IfcSpfLexer;
class Tokens;
typedef std::pair<Tokens*,unsigned> Token;
typedef std::pair<IfcSpfLexer*, unsigned> Token;
/// Provides functions to convert Tokens to binary data
/// Tokens are merely offsets to where they can be read in the file
@@ -66,12 +69,18 @@ namespace IfcParse {
static bool isString(const Token& t);
/// Returns whether the token can be interpreted as an identifier
static bool isIdentifier(const Token& t);
/// Returns whether the token can be interpreted as an syntactical operator
/// Returns whether the token can be interpreted as a syntactical operator
static bool isOperator(const Token& t, char op = 0);
/// Returns whether the token can be interpreted as an enumerated value
static bool isEnumeration(const Token& t);
/// Returns whether the token can be interpreted as an datatype name
static bool isDatatype(const Token& t);
/// Returns whether the token can be interpreted as a datatype name
static bool isKeyword(const Token& t);
/// Returns whether the token can be interpreted as an integer
static bool isInt(const Token& t);
/// Returns whether the token can be interpreted as a boolean
static bool isBool(const Token& t);
/// Returns whether the token can be interpreted as a floating point number
static bool isFloat(const Token& t);
/// Returns the token interpreted as an integer
static int asInt(const Token& t);
/// Returns the token interpreted as an boolean (.T. or .F.)
@@ -88,20 +97,22 @@ namespace IfcParse {
// Functions for creating Tokens from an arbitary file offset
// The first 4 bits are reserved for Tokens of type ()=,;$*
//
Token TokenPtr(Tokens* tokens, unsigned int offset);
Token TokenPtr(IfcSpfLexer* tokens, unsigned int offset);
Token TokenPtr(char c);
Token TokenPtr();
/// A stream of tokens to be read from a IfcSpfStream.
class Tokens {
class IfcSpfLexer {
private:
IfcCharacterDecoder* decoder;
unsigned int skipWhitespace();
unsigned int skipComment();
public:
IfcSpfStream* stream;
IfcFile* file;
Tokens(IfcSpfStream* s, IfcFile* f);
IfcSpfLexer(IfcSpfStream* s, IfcFile* f);
Token Next();
~Tokens();
~IfcSpfLexer();
std::string TokenString(unsigned int offset);
};
@@ -110,11 +121,15 @@ namespace IfcParse {
/// ==========
class ArgumentList: public Argument {
private:
std::vector<ArgumentPtr> list;
void Push(ArgumentPtr l);
std::vector<Argument*> list;
void push(Argument* l);
public:
ArgumentList(Tokens* t, std::vector<unsigned int>& ids);
~ArgumentList();
void read(IfcSpfLexer* t, std::vector<unsigned int>& ids);
IfcUtil::ArgumentType type() const;
operator int() const;
operator bool() const;
operator double() const;
@@ -122,11 +137,14 @@ namespace IfcParse {
operator std::vector<double>() const;
operator std::vector<int>() const;
operator std::vector<std::string>() const;
operator IfcUtil::IfcSchemaEntity() const;
//operator IfcUtil::IfcAbstractSelect::ptr() const;
operator IfcEntities() const;
unsigned int Size() const;
ArgumentPtr operator [] (unsigned int i) const;
operator IfcUtil::IfcBaseClass*() const;
operator IfcEntityList::ptr() const;
operator IfcEntityListList::ptr() const;
unsigned int size() const;
Argument* operator [] (unsigned int i) const;
void set(unsigned int i, Argument*);
std::string toString(bool upper=false) const;
bool isNull() const;
};
@@ -140,6 +158,9 @@ namespace IfcParse {
public:
Token token;
TokenArgument(const Token& t);
IfcUtil::ArgumentType type() const;
operator int() const;
operator bool() const;
operator double() const;
@@ -147,11 +168,11 @@ namespace IfcParse {
operator std::vector<double>() const;
operator std::vector<int>() const;
operator std::vector<std::string>() const;
operator IfcUtil::IfcSchemaEntity() const;
//operator IfcUtil::IfcAbstractSelect::ptr() const;
operator IfcEntities() const;
unsigned int Size() const;
ArgumentPtr operator [] (unsigned int i) const;
operator IfcUtil::IfcBaseClass*() const;
operator IfcEntityList::ptr() const;
operator IfcEntityListList::ptr() const;
unsigned int size() const;
Argument* operator [] (unsigned int i) const;
std::string toString(bool upper=false) const;
bool isNull() const;
};
@@ -161,10 +182,13 @@ namespace IfcParse {
/// ===================== =====================
class EntityArgument : public Argument {
private:
IfcUtil::IfcArgumentSelect* entity;
IfcUtil::IfcBaseClass* entity;
public:
EntityArgument(Ifc2x3::Type::Enum ty, const Token& t);
EntityArgument(const Token& t);
~EntityArgument();
IfcUtil::ArgumentType type() const;
operator int() const;
operator bool() const;
operator double() const;
@@ -172,11 +196,11 @@ namespace IfcParse {
operator std::vector<double>() const;
operator std::vector<int>() const;
operator std::vector<std::string>() const;
operator IfcUtil::IfcSchemaEntity() const;
//operator IfcUtil::IfcAbstractSelect::ptr() const;
operator IfcEntities() const;
unsigned int Size() const;
ArgumentPtr operator [] (unsigned int i) const;
operator IfcUtil::IfcBaseClass*() const;
operator IfcEntityList::ptr() const;
operator IfcEntityListList::ptr() const;
unsigned int size() const;
Argument* operator [] (unsigned int i) const;
std::string toString(bool upper=false) const;
bool isNull() const;
};
@@ -186,9 +210,8 @@ namespace IfcParse {
/// ============================
class Entity : public IfcAbstractEntity {
private:
//IfcFile* file;
ArgumentPtr args;
Ifc2x3::Type::Enum _type;
mutable ArgumentList* args;
mutable IfcSchema::Type::Enum _type;
public:
/// The EXPRESS ENTITY_INSTANCE_NAME
unsigned int _id;
@@ -197,101 +220,18 @@ namespace IfcParse {
Entity(unsigned int i, IfcFile* t);
Entity(unsigned int i, IfcFile* t, unsigned int o);
~Entity();
IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL);
IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a);
void Load(std::vector<unsigned int>& ids, bool seek=false);
ArgumentPtr getArgument (unsigned int i);
unsigned int getArgumentCount();
std::string toString(bool upper=false);
std::string datatype();
Ifc2x3::Type::Enum type() const;
bool is(Ifc2x3::Type::Enum v) const;
IfcEntityList::ptr getInverse(IfcSchema::Type::Enum type, int attribute_index);
void Load(std::vector<unsigned int>& ids, bool seek=false) const;
Argument* getArgument (unsigned int i);
unsigned int getArgumentCount() const;
std::string toString(bool upper=false) const;
std::string datatype() const;
IfcSchema::Type::Enum type() const;
bool is(IfcSchema::Type::Enum v) const;
unsigned int id();
bool isWritable();
IfcWrite::IfcWritableEntity* isWritable();
};
typedef IfcUtil::IfcSchemaEntity IfcEntity;
//typedef IfcEntities IfcEntities;
typedef std::map<Ifc2x3::Type::Enum,IfcEntities> MapEntitiesByType;
typedef std::map<unsigned int,IfcEntity> MapEntityById;
typedef std::map<std::string,Ifc2x3::IfcRoot::ptr> MapEntityByGuid;
typedef std::map<unsigned int,IfcEntities> MapEntitiesByRef;
typedef std::map<unsigned int,unsigned int> MapOffsetById;
/// This class provides several static convenience functions and variables
/// and provide access to the entities in an IFC file
class IfcFile {
private:
MapEntityById byid;
MapEntitiesByType bytype;
MapEntitiesByRef byref;
MapEntityByGuid byguid;
MapOffsetById offsets;
unsigned int lastId;
unsigned int MaxId;
std::string _filename;
std::string _timestamp;
std::string _author;
std::string _author_email;
std::string _author_organisation;
void initTimestamp();
public:
typedef MapEntityById::const_iterator const_iterator;
IfcFile();
~IfcFile();
/// Returns the first entity in the file, this probably is the entity with the lowest id (EXPRESS ENTITY_INSTANCE_NAME)
const_iterator begin() const;
/// Returns the last entity in the file, this probably is the entity with the highes id (EXPRESS ENTITY_INSTANCE_NAME)
const_iterator end() const;
IfcParse::IfcSpfStream* file;
IfcParse::Tokens* tokens;
/// Returns all entities in the file that match the template argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
template <class T>
typename T::list EntitiesByType() {
IfcEntities e = EntitiesByType(T::Class());
typename T::list l ( new IfcTemplatedEntityList<T>() );
if ( e && e->Size() )
for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) {
l->push(reinterpret_pointer_cast<IfcUtil::IfcBaseClass,T>(*it));
}
return l;
}
/// Returns all entities in the file that match the positional argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
IfcEntities EntitiesByType(Ifc2x3::Type::Enum t);
/// Returns all entities in the file that match the positional argument.
/// NOTE: This also returns subtypes of the requested type, for example:
/// IfcWall will also return IfcWallStandardCase entities
IfcEntities EntitiesByType(const std::string& t);
/// Returns all entities in the file that reference the id
IfcEntities EntitiesByReference(int id);
/// Returns the entity with the specified id
IfcEntity EntityById(int id);
/// Returns the entity with the specified GlobalId
Ifc2x3::IfcRoot::ptr EntityByGuid(const std::string& guid);
bool Init(const std::string& fn);
bool Init(std::istream& fn, int len);
bool Init(void* data, int len);
bool Init(IfcParse::IfcSpfStream* f);
unsigned int FreshId() { MaxId ++; return MaxId; }
void AddEntity(IfcUtil::IfcSchemaEntity e);
void AddEntities(IfcEntities es);
void filename(const std::string& s);
std::string filename() const;
void timestamp(const std::string& s);
std::string timestamp() const;
void author(const std::string& name, const std::string& email, const std::string& organisation);
std::string authorName() const;
std::string authorEmail() const;
std::string authorOrganisation() const;
};
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v );
}
std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f);
+39
View File
@@ -0,0 +1,39 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "IfcSIPrefix.h"
double IfcParse::IfcSIPrefixToValue(IfcSchema::IfcSIPrefix::IfcSIPrefix v) {
if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_EXA ) return 1.e18;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PETA ) return 1.e15;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_TERA ) return 1.e12;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_GIGA ) return 1.e9;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MEGA ) return 1.e6;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_KILO ) return 1.e3;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_HECTO ) return 1.e2;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_DECA ) return 1.;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_DECI ) return 1.e-1;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_CENTI ) return 1.e-2;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MILLI ) return 1.e-3;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MICRO ) return 1.e-6;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_NANO ) return 1.e-9;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PICO ) return 1.e-12;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_FEMTO ) return 1.e-15;
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_ATTO ) return 1.e-18;
else return 1.;
}
+29
View File
@@ -0,0 +1,29 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef IFCSIPREFIX
#define IFCSIPREFIX
#include "../ifcparse/IfcParse.h"
namespace IfcParse {
double IfcSIPrefixToValue(IfcSchema::IfcSIPrefix::IfcSIPrefix v);
}
#endif
+150
View File
@@ -0,0 +1,150 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "../ifcparse/IfcParse.h"
#include "IfcSpfHeader.h"
static const char * const ISO_10303_21 = "ISO-10303-21";
static const char * const HEADER = "HEADER";
static const char * const FILE_DESCRIPTION = "FILE_DESCRIPTION";
static const char * const FILE_NAME = "FILE_NAME";
static const char * const FILE_SCHEMA = "FILE_SCHEMA";
static const char * const FILE_POPULATION = "FILE_POPULATION";
static const char * const SECTION_LANGUAGE = "SECTION_LANGUAGE";
static const char * const SECTION_CONTEXT = "SECTION_CONTEXT";
static const char * const ENDSEC = "ENDSEC";
static const char * const DATA = "DATA";
using namespace IfcParse;
void IfcSpfHeader::readSemicolon() {
if (!TokenFunc::isOperator(_lexer->Next(), ';')) {
throw IfcException(std::string("Expected ;"));
}
}
void IfcSpfHeader::readParen() {
if (!TokenFunc::isOperator(_lexer->Next(), '(')) {
throw IfcException(std::string("Expected ("));
}
}
void IfcSpfHeader::readTerminal(const std::string& term, Trail trail) {
if (TokenFunc::asString(_lexer->Next()) != term) {
throw IfcException(std::string("Expected " + term));
}
if (trail == TRAILING_SEMICOLON) {
readSemicolon();
} else if (trail == TRAILING_PAREN) {
readParen();
}
}
void IfcSpfHeader::read() {
readTerminal(ISO_10303_21, TRAILING_SEMICOLON);
readTerminal(HEADER, TRAILING_SEMICOLON);
readTerminal(FILE_DESCRIPTION, TRAILING_PAREN);
delete _file_description;
_file_description = new FileDescription(_lexer);
readSemicolon();
readTerminal(FILE_NAME, TRAILING_PAREN);
delete _file_name;
_file_name = new FileName(_lexer);
readSemicolon();
readTerminal(FILE_SCHEMA, TRAILING_PAREN);
delete _file_schema;
_file_schema = new FileSchema(_lexer);
readSemicolon();
}
bool IfcSpfHeader::tryRead() {
try {
read();
return true;
} catch(const IfcException&) {
return false;
}
}
void IfcSpfHeader::write(std::ostream& os) const {
os << ISO_10303_21 << ";" << "\n";
os << HEADER << ";" << "\n";
os << file_description().toString(true) << "\n";
os << file_name().toString(true) << "\n";
os << file_schema().toString(true) << "\n";
os << ENDSEC << ";" << "\n";
os << DATA << ";" << "\n";
}
const FileDescription& IfcSpfHeader::file_description() const {
if (_file_description) {
return *_file_description;
} else {
throw IfcException("File description not set");
}
}
const FileName& IfcSpfHeader::file_name() const {
if (_file_name) {
return *_file_name;
} else {
throw IfcException("File name not set");
}
}
const FileSchema& IfcSpfHeader::file_schema() const {
if (_file_schema) {
return *_file_schema;
} else {
throw IfcException("File schema not set");
}
}
FileDescription& IfcSpfHeader::file_description() {
if (_file_description) {
return *_file_description;
} else {
throw IfcException("File description not set");
}
}
FileName& IfcSpfHeader::file_name() {
if (_file_name) {
return *_file_name;
} else {
throw IfcException("File name not set");
}
}
FileSchema& IfcSpfHeader::file_schema() {
if (_file_schema) {
return *_file_schema;
} else {
throw IfcException("File schema not set");
}
}
FileDescription::FileDescription(IfcSpfLexer* lexer) : HeaderEntity(FILE_DESCRIPTION, lexer) {}
FileName::FileName(IfcSpfLexer* lexer) : HeaderEntity(FILE_NAME, lexer) {}
FileSchema::FileSchema(IfcSpfLexer* lexer) : HeaderEntity(FILE_SCHEMA, lexer) {}
+186
View File
@@ -0,0 +1,186 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef IFCSPFHEADER_H
#define IFCSPFHEADER_H
#include "../ifcparse/IfcSpfStream.h"
#include "../ifcparse/IfcWrite.h"
namespace IfcParse {
class HeaderEntity : public IfcAbstractEntity {
private:
ArgumentList* _list;
const char * const _datatype;
protected:
HeaderEntity(const char * const datatype, IfcSpfLexer* lexer)
: _datatype(datatype), _list(0)
{
std::vector<unsigned int> ids;
_list = new ArgumentList();
if (lexer) {
_list->read(lexer, ids);
}
}
~HeaderEntity() {
delete _list;
}
void setArgument(unsigned int i, const std::string& s) {
IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument(this);
argument->set(s);
_list->set(i, argument);
}
void setArgument(unsigned int i, const std::vector<std::string>& s) {
IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument(this);
argument->set(s);
_list->set(i, argument);
}
public:
Argument* getArgument(unsigned int i) const {
return (*_list)[i];
}
Argument* getArgument(unsigned int i) {
return (*_list)[i];
}
IfcEntityList::ptr getInverse(IfcSchema::Type::Enum type, int attribute_index) {
return IfcEntityList::ptr(new IfcEntityList);
}
std::string datatype() const {
return _datatype;
}
unsigned int getArgumentCount() const {
return _list->size();
}
IfcSchema::Type::Enum type() const {
return (IfcSchema::Type::Enum) -1;
}
bool is(IfcSchema::Type::Enum v) const {
return false;
}
std::string toString(bool upper=false) const {
std::stringstream ss;
ss << _datatype << _list->toString(upper) << ";";
return ss.str();
}
unsigned int id() {
return 0;
}
IfcWrite::IfcWritableEntity* isWritable() {
return 0;
}
};
class FileDescription : public HeaderEntity {
public:
explicit FileDescription(IfcSpfLexer* = 0);
std::vector<std::string> description() const { return *getArgument(0); }
std::string implementation_level() const { return *getArgument(1); }
void description(const std::vector<std::string>& value) { setArgument(0, value); }
void implementation_level(const std::string& value) { setArgument(1, value); }
};
class FileName : public HeaderEntity {
public:
explicit FileName(IfcSpfLexer* = 0);
std::string name() const { return *getArgument(0); }
std::string time_stamp() const { return *getArgument(1); }
std::vector<std::string> author() const { return *getArgument(2); }
std::vector<std::string> organization() const { return *getArgument(3); }
std::string preprocessor_version() const { return *getArgument(4); }
std::string originating_system() const { return *getArgument(5); }
std::string authorization() const { return *getArgument(6); }
void name(const std::string& value) { setArgument(0, value); }
void time_stamp(const std::string& value) { setArgument(1, value); }
void author(const std::vector<std::string>& value) { setArgument(2, value); }
void organization(const std::vector<std::string>& value) { setArgument(3, value); }
void preprocessor_version(const std::string& value) { setArgument(4, value); }
void originating_system(const std::string& value) { setArgument(5, value); }
void authorization(const std::string& value) { setArgument(6, value); }
};
class FileSchema : public HeaderEntity {
public:
explicit FileSchema(IfcSpfLexer* = 0);
std::vector<std::string> schema_identifiers() const { return *getArgument(0); }
void schema_identifiers(const std::vector<std::string>& value) { setArgument(0, value); }
};
class IfcSpfHeader {
private:
IfcSpfLexer* _lexer;
FileDescription* _file_description;
FileName* _file_name;
FileSchema* _file_schema;
void readParen();
void readSemicolon();
enum Trail {
TRAILING_SEMICOLON,
TRAILING_PAREN,
NONE
};
void readTerminal(const std::string& term, Trail trail);
public:
explicit IfcSpfHeader(IfcSpfLexer* lexer = 0)
: _lexer(lexer), _file_description(0), _file_name(0), _file_schema(0)
{
_file_description = new FileDescription();
_file_name = new FileName();
_file_schema = new FileSchema();
}
IfcSpfLexer* lexer() { return _lexer; }
void lexer(IfcSpfLexer* l) { _lexer = l; }
void read();
bool tryRead();
void write(std::ostream& os) const;
const FileDescription& file_description() const;
const FileName& file_name() const;
const FileSchema& file_schema() const;
FileDescription& file_description();
FileName& file_name();
FileSchema& file_schema();
};
}
#endif
+81
View File
@@ -0,0 +1,81 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/*********************************************************************************
* *
* Reads a file in chunks of BUF_SIZE and provides functions to access its *
* contents randomly and character by character *
* *
********************************************************************************/
#ifndef IFCSPFSTREAM_H
#define IFCSPFSTREAM_H
#include <fstream>
#include <string>
// As of IfcOpenShell version 0.3.0 the paging functionality, which
// loads a file on disk into multiple chunks, has been disabled.
// It proved to be an inefficient way of working with large files,
// as often these did not facilitate to be parsed in a sequential
// manner efficiently. To enable the paging functionality uncomment
// the following statement.
// #define BUF_SIZE (8 * 1024 * 1024)
namespace IfcParse {
/// The IfcSpfStream class represents a ISO 10303-21 IFC-SPF file in memory.
/// The file is interpreted as a sequence of tokens which are lazily
/// interpreted only when requested. If the size of the file is
/// larger than BUF_SIZE, the file is split into seperate pages, of
/// which only one is simultaneously kept in memory, for files
/// that define their entities not in a sequential nature, this is
/// detrimental for the performance of the parser.
class IfcSpfStream {
private:
FILE* stream;
char* buffer;
unsigned int ptr;
unsigned int len;
void ReadBuffer(bool inc=true);
#ifdef BUF_SIZE
unsigned int offset;
bool paging;
#endif
public:
bool valid;
bool eof;
unsigned int size;
IfcSpfStream(const std::string& fn);
IfcSpfStream(std::istream& f, int len);
IfcSpfStream(void* data, int len);
/// Returns the character at the cursor
char Peek();
/// Returns the character at specified offset
char Read(unsigned int offset);
/// Increment the file cursor and reads new page if necessary
void Inc();
void Close();
/// Moves the file cursor to an arbitrary offset in the file
void Seek(unsigned int offset);
/// Returns the cursor position
unsigned int Tell();
};
}
#endif
+58 -31
View File
@@ -17,51 +17,57 @@
* *
********************************************************************************/
#include "IfcUtil.h"
#include <iostream>
#include <algorithm>
void IfcEntityList::push(IfcUtil::IfcSchemaEntity l) {
#include "../ifcparse/IfcException.h"
#include "IfcUtil.h"
void IfcEntityList::push(IfcUtil::IfcBaseClass* l) {
if ( l ) ls.push_back(l);
}
void IfcEntityList::push(IfcEntities l) {
void IfcEntityList::push(const IfcEntityList::ptr& l) {
for( it i = l->begin(); i != l->end(); ++i ) {
if ( *i ) ls.push_back(*i);
}
}
int IfcEntityList::Size() const { return (unsigned int) ls.size(); }
unsigned int IfcEntityList::size() const { return (unsigned int) ls.size(); }
IfcEntityList::it IfcEntityList::begin() { return ls.begin(); }
IfcEntityList::it IfcEntityList::end() { return ls.end(); }
IfcUtil::IfcSchemaEntity IfcEntityList::operator[] (int i) {
IfcUtil::IfcBaseClass* IfcEntityList::operator[] (int i) {
return ls[i];
}
IfcEntities IfcEntityList::getInverse(Ifc2x3::Type::Enum c) {
IfcEntities l = IfcEntities(new IfcEntityList());
for( it i = begin(); i != end(); ++i ) {
l->push((*i)->entity->getInverse(c));
}
return l;
bool IfcEntityList::contains(IfcUtil::IfcBaseClass* instance) const {
return std::find(ls.begin(), ls.end(), instance) != ls.end();
}
IfcEntities IfcEntityList::getInverse(Ifc2x3::Type::Enum c, int ar, const std::string& a) {
IfcEntities l = IfcEntities(new IfcEntityList());
for( it i = begin(); i != end(); ++i ) {
l->push((*i)->entity->getInverse(c,ar,a));
void IfcEntityList::remove(IfcUtil::IfcBaseClass* instance) {
std::vector<IfcUtil::IfcBaseClass*>::iterator it;
while ((it = std::find(ls.begin(), ls.end(), instance)) != ls.end()) {
ls.erase(it);
}
return l;
}
bool IfcUtil::IfcEntitySelect::is(Ifc2x3::Type::Enum v) const { return entity->is(v); }
Ifc2x3::Type::Enum IfcUtil::IfcEntitySelect::type() const { return entity->type(); }
IfcUtil::IfcEntitySelect::IfcEntitySelect(IfcSchemaEntity b) { entity = b->entity; }
IfcUtil::IfcEntitySelect::IfcEntitySelect(IfcAbstractEntityPtr e) { entity = e; }
bool IfcUtil::IfcEntitySelect::isSimpleType() { return false; }
IfcUtil::IfcEntitySelect::~IfcEntitySelect() { delete entity; }
IfcEntityList::ptr IfcEntityList::filtered(const std::set<IfcSchema::Type::Enum>& entities) {
IfcEntityList::ptr return_value(new IfcEntityList);
for (it it = begin(); it != end(); ++it) {
bool contained = false;
for (std::set<IfcSchema::Type::Enum>::const_iterator jt = entities.begin(); jt != entities.end(); ++jt) {
if ((*it)->is(*jt)) {
contained = true;
break;
}
}
if (!contained) {
return_value->push(*it);
}
}
return return_value;
}
bool IfcUtil::IfcArgumentSelect::is(Ifc2x3::Type::Enum v) const { return _type == v; }
Ifc2x3::Type::Enum IfcUtil::IfcArgumentSelect::type() const { return _type; }
IfcUtil::IfcArgumentSelect::IfcArgumentSelect(Ifc2x3::Type::Enum t, ArgumentPtr a) { _type = t; arg = a; }
ArgumentPtr IfcUtil::IfcArgumentSelect::wrappedValue() { return arg; }
bool IfcUtil::IfcArgumentSelect::isSimpleType() { return true; }
IfcUtil::IfcArgumentSelect::~IfcArgumentSelect() { delete arg; }
unsigned int IfcUtil::IfcBaseType::getArgumentCount() const { return 1; }
Argument* IfcUtil::IfcBaseType::getArgument(unsigned int i) const { return entity->getArgument(i); }
const char* IfcUtil::IfcBaseType::getArgumentName(unsigned int i) const { if (i == 0) { return "wrappedValue"; } else { throw IfcParse::IfcException("argument out of range"); } }
void Logger::SetOutput(std::ostream* l1, std::ostream* l2) {
log1 = l1;
@@ -70,7 +76,7 @@ void Logger::SetOutput(std::ostream* l1, std::ostream* l2) {
log2 = &log_stream;
}
}
void Logger::Message(Logger::Severity type, const std::string& message, const IfcAbstractEntityPtr entity) {
void Logger::Message(Logger::Severity type, const std::string& message, IfcAbstractEntity* entity) {
if ( log2 && type >= verbosity ) {
(*log2) << "[" << severity_strings[type] << "] " << message << std::endl;
if ( entity ) (*log2) << entity->toString() << std::endl;
@@ -98,4 +104,25 @@ std::ostream* Logger::log1 = 0;
std::ostream* Logger::log2 = 0;
std::stringstream Logger::log_stream;
Logger::Severity Logger::verbosity = Logger::LOG_NOTICE;
const char* Logger::severity_strings[] = { "Notice","Warning","Error" };
const char* Logger::severity_strings[] = { "Notice","Warning","Error" };
static const char* const argument_type_string[] = {
"NULL",
"DERIVED",
"INT",
"BOOL",
"DOUBLE",
"STRING",
"VECTOR_INT",
"VECTOR_DOUBLE",
"VECTOR_STRING",
"ENUMERATION",
"ENTITY",
"ENTITY_LIST",
"ENTITY_LIST_LIST",
"UNKNOWN"
};
const char* IfcUtil::ArgumentTypeToString(ArgumentType argument_type) {
return argument_type_string[static_cast<int>(argument_type)];
}
+190 -103
View File
@@ -20,137 +20,226 @@
#ifndef IFCUTIL_H
#define IFCUTIL_H
#include <set>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include "../ifcparse/SharedPointer.h"
#ifdef USE_IFC4
#include "../ifcparse/Ifc4enum.h"
#else
#include "../ifcparse/Ifc2x3enum.h"
class IfcAbstractEntity;
//typedef SHARED_PTR<IfcAbstractEntity> IfcAbstractEntityPtr;
typedef IfcAbstractEntity* IfcAbstractEntityPtr;
class IfcEntityList;
typedef SHARED_PTR<IfcEntityList> IfcEntities;
#endif
class Argument;
//typedef SHARED_PTR<Argument> ArgumentPtr;
typedef Argument* ArgumentPtr;
template <class F, class T>
inline T* reinterpret_pointer_cast(F* from) {
return (T*)from;
//SHARED_PTR<void> v = std::tr1::static_pointer_cast<void,F>(from);
//return std::tr1::static_pointer_cast<T,void>(v);
class IfcEntityList;
class IfcEntityListList;
class IfcAbstractEntity;
namespace IfcWrite {
class IfcWritableEntity;
}
namespace IfcUtil {
enum ArgumentType {
Argument_INT, Argument_BOOL, Argument_DOUBLE, Argument_STRING, Argument_VECTOR_INT, Argument_VECTOR_DOUBLE, Argument_VECTOR_STRING, Argument_ENTITY, Argument_ENTITY_LIST, Argument_ENUMERATION, Argument_UNKNOWN
Argument_NULL,
Argument_DERIVED,
Argument_INT,
Argument_BOOL,
Argument_DOUBLE,
Argument_STRING,
Argument_VECTOR_INT,
Argument_VECTOR_DOUBLE,
Argument_VECTOR_STRING,
Argument_ENUMERATION,
Argument_ENTITY,
Argument_ENTITY_LIST,
Argument_ENTITY_LIST_LIST,
Argument_UNKNOWN
};
}
namespace IfcUtil {
const char* ArgumentTypeToString(ArgumentType argument_type);
class IfcBaseClass {
public:
IfcAbstractEntityPtr entity;
virtual bool is(Ifc2x3::Type::Enum v) const = 0;
virtual Ifc2x3::Type::Enum type() const = 0;
};
class IfcBaseClass {
public:
IfcAbstractEntity* entity;
virtual bool is(IfcSchema::Type::Enum v) const = 0;
virtual IfcSchema::Type::Enum type() const = 0;
class IfcBaseEntity : public IfcBaseClass {
public:
virtual unsigned int getArgumentCount() const = 0;
virtual ArgumentType getArgumentType(unsigned int i) const = 0;
virtual ArgumentPtr getArgument(unsigned int i) const = 0;
virtual const char* getArgumentName(unsigned int i) const = 0;
};
virtual unsigned int getArgumentCount() const = 0;
virtual ArgumentType getArgumentType(unsigned int i) const = 0;
virtual IfcSchema::Type::Enum getArgumentEntity(unsigned int i) const = 0;
virtual Argument* getArgument(unsigned int i) const = 0;
virtual const char* getArgumentName(unsigned int i) const = 0;
};
//typedef SHARED_PTR<IfcBaseClass> IfcSchemaEntity;
typedef IfcBaseClass* IfcSchemaEntity;
class IfcBaseEntity : public IfcBaseClass {
};
// TODO: Investigate whether these should be template classes instead
class IfcBaseType : public IfcBaseEntity {
public:
unsigned int getArgumentCount() const;
Argument* getArgument(unsigned int i) const;
const char* getArgumentName(unsigned int i) const;
IfcSchema::Type::Enum getArgumentEntity(unsigned int i) const { return IfcSchema::Type::UNDEFINED; }
};
}
template <class T>
class IfcTemplatedEntityList;
class IfcEntityList {
std::vector<IfcUtil::IfcSchemaEntity> ls;
std::vector<IfcUtil::IfcBaseClass*> ls;
public:
typedef std::vector<IfcUtil::IfcSchemaEntity>::const_iterator it;
IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL);
IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a);
void push(IfcUtil::IfcSchemaEntity l);
void push(IfcEntities l);
typedef SHARED_PTR<IfcEntityList> ptr;
typedef std::vector<IfcUtil::IfcBaseClass*>::const_iterator it;
void push(IfcUtil::IfcBaseClass* l);
void push(const ptr& l);
it begin();
it end();
IfcUtil::IfcSchemaEntity operator[] (int i);
int Size() const;
IfcUtil::IfcBaseClass* operator[] (int i);
unsigned int size() const;
bool contains(IfcUtil::IfcBaseClass*) const;
template <class U>
typename U::list as() {
typename U::list r(new IfcTemplatedEntityList<U>());
for ( it i = begin(); i != end(); ++ i ) if ((*i)->is(U::Class())) r->push((U*)*i);
typename U::list::ptr as() {
typename U::list::ptr r(new typename U::list);
const bool all = U::Class() == IfcSchema::Type::UNDEFINED;
for ( it i = begin(); i != end(); ++ i ) if (all || (*i)->is(U::Class())) r->push((U*)*i);
return r;
}
void remove(IfcUtil::IfcBaseClass*);
IfcEntityList::ptr filtered(const std::set<IfcSchema::Type::Enum>& entities);
};
template <class T>
class IfcTemplatedEntityList {
std::vector<T*> ls;
public:
typedef SHARED_PTR< IfcTemplatedEntityList<T> > ptr;
typedef typename std::vector<T*>::const_iterator it;
inline void push(T* t) {if (t) ls.push_back(t);}
inline void push(SHARED_PTR< IfcTemplatedEntityList<T> > t) { for ( typename T::it it = t->begin(); it != t->end(); ++it ) push(*it); }
inline it begin() { return ls.begin(); }
inline it end() { return ls.end(); }
inline unsigned int Size() const { return (unsigned int) ls.size(); }
IfcEntities generalize() {
IfcEntities r (new IfcEntityList());
void push(T* t) {if (t) ls.push_back(t);}
void push(ptr t) { for ( typename T::list::it it = t->begin(); it != t->end(); ++it ) push(*it); }
it begin() { return ls.begin(); }
it end() { return ls.end(); }
unsigned int size() const { return (unsigned int) ls.size(); }
IfcEntityList::ptr generalize() {
IfcEntityList::ptr r (new IfcEntityList());
for ( it i = begin(); i != end(); ++ i ) r->push(*i);
return r;
}
bool contains(T* t) const { return std::find(ls.begin(), ls.end(), t) != ls.end(); }
template <class U>
typename U::list as() {
typename U::list r(new IfcTemplatedEntityList<U>());
for ( it i = begin(); i != end(); ++ i ) if ((*i)->is(U::Class())) r->push(*i);
typename U::list::ptr as() {
typename U::list::ptr r(new typename U::list);
const bool all = U::Class() == IfcSchema::Type::UNDEFINED;
for ( it i = begin(); i != end(); ++ i ) if (all || (*i)->is(U::Class())) r->push((U*)*i);
return r;
}
void remove(T* t) {
typename std::vector<T*>::iterator it;
while ((it = std::find(ls.begin(), ls.end(), t)) != ls.end()) {
ls.erase(it);
}
}
};
template <class T>
class IfcTemplatedEntityListList;
class IfcEntityListList {
std::vector< std::vector<IfcUtil::IfcBaseClass*> > ls;
public:
typedef SHARED_PTR< IfcEntityListList > ptr;
typedef std::vector< std::vector<IfcUtil::IfcBaseClass*> >::const_iterator outer_it;
typedef std::vector<IfcUtil::IfcBaseClass*>::const_iterator inner_it;
void push(const std::vector<IfcUtil::IfcBaseClass*>& l) {
ls.push_back(l);
}
void push(const IfcEntityList::ptr& l) {
std::vector<IfcUtil::IfcBaseClass*> li;
for (std::vector<IfcUtil::IfcBaseClass*>::const_iterator jt = l->begin(); jt != l->end(); ++jt) {
li.push_back(*jt);
}
push(li);
}
outer_it begin() const { return ls.begin(); }
outer_it end() const { return ls.end(); }
int size() const { return ls.size(); }
int totalSize() const {
int accum = 0;
for (outer_it it = begin(); it != end(); ++it) {
accum += it->size();
}
return accum;
}
bool contains(IfcUtil::IfcBaseClass* instance) const {
for (outer_it it = begin(); it != end(); ++it) {
const std::vector<IfcUtil::IfcBaseClass*>& inner = *it;
if (std::find(inner.begin(), inner.end(), instance) != inner.end()) {
return true;
}
}
return false;
}
template <class U>
typename IfcTemplatedEntityListList<U>::ptr as() {
typename IfcTemplatedEntityListList<U>::ptr r(new IfcTemplatedEntityListList<U>);
const bool all = U::Class() == IfcSchema::Type::UNDEFINED;
for (outer_it outer = begin(); outer != end(); ++ outer) {
const std::vector<IfcUtil::IfcBaseClass*>& from = *outer;
typename std::vector<U*> to;
for (inner_it inner = from.begin(); inner != from.end(); ++ inner) {
if (all || (*inner)->is(U::Class())) to.push_back((U*)*inner);
}
r->push(to);
}
return r;
}
};
namespace IfcUtil {
class IfcAbstractSelect : public IfcBaseClass {
public:
typedef SHARED_PTR< IfcTemplatedEntityList<IfcAbstractSelect> > list;
typedef IfcTemplatedEntityList<IfcAbstractSelect>::it it;
typedef IfcAbstractSelect* ptr;
virtual bool isSimpleType() = 0;
};
class IfcEntitySelect : public IfcAbstractSelect {
public:
typedef IfcEntitySelect* ptr;
IfcEntitySelect(IfcSchemaEntity b);
IfcEntitySelect(IfcAbstractEntityPtr e);
~IfcEntitySelect();
bool is(Ifc2x3::Type::Enum v) const;
Ifc2x3::Type::Enum type() const;
bool isSimpleType();
};
class IfcArgumentSelect : public IfcAbstractSelect {
Ifc2x3::Type::Enum _type;
ArgumentPtr arg;
public:
typedef IfcArgumentSelect* ptr;
IfcArgumentSelect(Ifc2x3::Type::Enum t, ArgumentPtr a);
~IfcArgumentSelect();
ArgumentPtr wrappedValue();
bool is(Ifc2x3::Type::Enum v) const;
Ifc2x3::Type::Enum type() const;
bool isSimpleType();
};
}
template <class T>
class IfcTemplatedEntityListList {
std::vector< std::vector<T*> > ls;
public:
typedef typename SHARED_PTR< IfcTemplatedEntityListList<T> > ptr;
typedef typename std::vector< std::vector<T*> >::const_iterator outer_it;
typedef typename std::vector<T*>::const_iterator inner_it;
void push(const std::vector<T*>& t) {ls.push_back(t);}
outer_it begin() { return ls.begin(); }
outer_it end() { return ls.end(); }
int size() const { return ls.size(); }
int totalSize() const {
int accum = 0;
for (outer_it it = begin(); it != end(); ++it) {
accum += it->size();
}
return accum;
}
bool contains(T* t) const {
for (outer_it it = begin(); it != end(); ++it) {
const std::vector<T*>& inner = *it;
if (std::find(inner.begin(), inner.end(), t) != inner.end()) {
return true;
}
}
return false;
}
IfcEntityListList::ptr generalize() {
IfcEntityListList::ptr r (new IfcEntityListList());
for (outer_it outer = begin(); outer != end(); ++ outer) {
const std::vector<T*>& from = *outer;
std::vector<IfcUtil::IfcBaseClass*> to;
for (inner_it inner = from.begin(); inner != from.end(); ++ inner) {
to.push_back(*inner);
}
r->push(to);
}
return r;
}
};
namespace IfcParse {
class IfcFile;
@@ -158,8 +247,7 @@ namespace IfcParse {
class Argument {
public:
//void* file;
//public:
virtual IfcUtil::ArgumentType type() const = 0;
virtual operator int() const = 0;
virtual operator bool() const = 0;
virtual operator double() const = 0;
@@ -167,11 +255,11 @@ public:
virtual operator std::vector<double>() const = 0;
virtual operator std::vector<int>() const = 0;
virtual operator std::vector<std::string>() const = 0;
virtual operator IfcUtil::IfcSchemaEntity() const = 0;
//virtual operator IfcUtil::IfcAbstractSelect::ptr() const = 0;
virtual operator IfcEntities() const = 0;
virtual unsigned int Size() const = 0;
virtual ArgumentPtr operator [] (unsigned int i) const = 0;
virtual operator IfcUtil::IfcBaseClass*() const = 0;
virtual operator IfcEntityList::ptr() const = 0;
virtual operator IfcEntityListList::ptr() const = 0;
virtual unsigned int size() const = 0;
virtual Argument* operator [] (unsigned int i) const = 0;
virtual std::string toString(bool upper=false) const = 0;
virtual bool isNull() const = 0;
virtual ~Argument() {};
@@ -180,17 +268,16 @@ public:
class IfcAbstractEntity {
public:
IfcParse::IfcFile* file;
virtual IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL) = 0;
virtual IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a) = 0;
virtual std::string datatype() = 0;
virtual ArgumentPtr getArgument (unsigned int i) = 0;
virtual unsigned int getArgumentCount() = 0;
virtual IfcEntityList::ptr getInverse(IfcSchema::Type::Enum type, int attribute_index) = 0;
virtual std::string datatype() const = 0;
virtual Argument* getArgument (unsigned int i) = 0;
virtual unsigned int getArgumentCount() const = 0;
virtual ~IfcAbstractEntity() {};
virtual Ifc2x3::Type::Enum type() const = 0;
virtual bool is(Ifc2x3::Type::Enum v) const = 0;
virtual std::string toString(bool upper=false) = 0;
virtual IfcSchema::Type::Enum type() const = 0;
virtual bool is(IfcSchema::Type::Enum v) const = 0;
virtual std::string toString(bool upper=false) const = 0;
virtual unsigned int id() = 0;
virtual bool isWritable() = 0;
virtual IfcWrite::IfcWritableEntity* isWritable() = 0;
};
class Logger {
@@ -209,7 +296,7 @@ public:
static void Verbosity(Severity v);
static Severity Verbosity();
/// Log a message to the output stream
static void Message(Severity type, const std::string& message, const IfcAbstractEntityPtr entity=0);
static void Message(Severity type, const std::string& message, IfcAbstractEntity* entity=0);
static void Status(const std::string& message, bool new_line=true);
static void ProgressBar(int progress);
static std::string GetLog();
+18 -15
View File
@@ -39,36 +39,39 @@ namespace IfcWrite {
class IfcWritableEntity : public IfcAbstractEntity {
private:
std::map<int,bool> writemask;
std::map<int,ArgumentPtr> args;
Ifc2x3::Type::Enum _type;
std::map<int,Argument*> args;
IfcSchema::Type::Enum _type;
int* _id;
bool arg_writable(int i);
void arg_writable(int i, bool b);
template <typename T> void _setArgument(int i, const T&);
public:
IfcWritableEntity(Ifc2x3::Type::Enum t);
IfcWritableEntity(IfcSchema::Type::Enum t);
~IfcWritableEntity();
int setId(int i=-1);
IfcWritableEntity(IfcAbstractEntity* e);
IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL);
IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a);
std::string datatype();
ArgumentPtr getArgument (unsigned int i);
unsigned int getArgumentCount();
Ifc2x3::Type::Enum type() const;
bool is(Ifc2x3::Type::Enum v) const;
std::string toString(bool upper=false);
IfcEntityList::ptr getInverse(IfcSchema::Type::Enum type, int attribute_index);
std::string datatype() const;
Argument* getArgument (unsigned int i);
unsigned int getArgumentCount() const;
IfcSchema::Type::Enum type() const;
bool is(IfcSchema::Type::Enum v) const;
std::string toString(bool upper=false) const;
unsigned int id();
bool isWritable();
void setArgument(int i);
IfcWritableEntity* isWritable();
void setArgument(int i);
void setArgument(int i, Argument* a);
void setArgumentDerived(int i);
void setArgument(int i,bool v);
void setArgument(int i,int v);
void setArgument(int i,int v, const char* c);
void setArgument(int i,const std::string& v);
void setArgument(int i,double v);
void setArgument(int i,IfcUtil::IfcSchemaEntity v);
void setArgument(int i,IfcEntities v);
void setArgument(int i,IfcUtil::IfcBaseClass* v);
void setArgument(int i,IfcEntityList::ptr v);
void setArgument(int i,IfcEntityListList::ptr v);
void setArgument(int i,const std::vector<double>& v);
void setArgument(int i,const std::vector<std::string>& v);
void setArgument(int i,const std::vector<int>& v);
+216 -123
View File
@@ -17,14 +17,24 @@
* *
********************************************************************************/
#include <iomanip>
#include <locale>
#include "../ifcparse/IfcParse.h"
#include "../ifcparse/IfcWrite.h"
#include "../ifcparse/IfcWritableEntity.h"
#include "../ifcparse/IfcCharacterDecoder.h"
#include "../ifcparse/IfcFile.h"
#ifdef USE_IFC4
#include "../ifcparse/Ifc4-latebound.h"
#else
#include "../ifcparse/Ifc2x3-latebound.h"
#endif
using namespace IfcWrite;
IfcWritableEntity::IfcWritableEntity(Ifc2x3::Type::Enum t) {
IfcWritableEntity::IfcWritableEntity(IfcSchema::Type::Enum t) {
_type = t;
_id = 0;
file = 0;
@@ -33,65 +43,70 @@ IfcWritableEntity::~IfcWritableEntity() {
delete _id;
}
int IfcWritableEntity::setId(int i) {
return *(_id = new int(i > 0 ? i : file->FreshId()));
if (i > 0) {
delete _id;
return *(_id = new int(i));
} else {
if (_id) { return *_id; }
else {
delete _id;
return *(_id = new int(file->FreshId()));
}
}
}
IfcWritableEntity::IfcWritableEntity(IfcAbstractEntity* e)
{
file = e->file;
_type = e->type();
delete _id;
_id = new int(e->id());
const unsigned int count = e->getArgumentCount();
for ( unsigned int i = 0; i < count; ++ i ) {
args[i] = e->getArgument(i);
writemask[i] = false;
this->setArgument(i, e->getArgument(i));
}
}
// TODO: Reove redundancy with IfcParse::Entity
IfcEntities IfcWritableEntity::getInverse(Ifc2x3::Type::Enum c) {
IfcEntities l = IfcEntities(new IfcEntityList());
int id = _id ? *_id : setId();
IfcEntities all = file->EntitiesByReference(id);
if ( ! all ) return l;
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
if ( c == Ifc2x3::Type::ALL || (*it)->is(c) ) {
l->push(*it);
}
}
return l;
}
IfcEntities IfcWritableEntity::getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a) {
IfcEntities l = IfcEntities(new IfcEntityList());
IfcEntities all = getInverse(c);
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
const std::string s = *(*it)->entity->getArgument(i);
if ( s == a ) {
l->push(*it);
}
}
return l;
}
std::string IfcWritableEntity::datatype() { return Ifc2x3::Type::ToString(_type); }
ArgumentPtr IfcWritableEntity::getArgument (unsigned int i) { if ( i >= getArgumentCount() ) throw IfcParse::IfcException("Argument not set"); return args[i]; }
unsigned int IfcWritableEntity::getArgumentCount() {return args.size(); }
Ifc2x3::Type::Enum IfcWritableEntity::type() const { return _type; }
bool IfcWritableEntity::is(Ifc2x3::Type::Enum v) const { return _type == v; }
std::string IfcWritableEntity::toString(bool upper) {
IfcEntityList::ptr IfcWritableEntity::getInverse(IfcSchema::Type::Enum type, int attribute_index) {
if (file) {
int id = _id ? *_id : setId();
return file->getInverse(id, type, attribute_index);
} else {
throw IfcParse::IfcException("Instance not part of a file");
}
}
std::string IfcWritableEntity::datatype() const { return IfcSchema::Type::ToString(_type); }
Argument* IfcWritableEntity::getArgument (unsigned int i) {
if (args[i] == 0) {
_setArgument(i, boost::none);
}
return args[i];
}
unsigned int IfcWritableEntity::getArgumentCount() const {return args.size(); }
IfcSchema::Type::Enum IfcWritableEntity::type() const { return _type; }
bool IfcWritableEntity::is(IfcSchema::Type::Enum v) const { return _type == v; }
std::string IfcWritableEntity::toString(bool upper) const {
std::stringstream ss;
ss.imbue(std::locale::classic());
std::string dt = datatype();
if ( upper ) {
if (upper) {
for (std::string::iterator p = dt.begin(); p != dt.end(); ++p ) *p = toupper(*p);
}
if ( _id ) ss << "#" << *_id;
ss << "=" << dt << "(";
for ( std::map<int,ArgumentPtr>::const_iterator it = args.begin(); it != args.end(); ++ it ) {
if (_id && !IfcSchema::Type::IsSimple(type())) {
ss << "#" << *_id;
ss << "=";
}
ss << dt << "(";
for (std::map<int,Argument*>::const_iterator it = args.begin(); it != args.end(); ++ it) {
if ( it != args.begin() ) ss << ",";
const ArgumentPtr a = it->second;
const Argument* a = it->second;
ss << it->second->toString(upper);
}
ss << ")";
return ss.str();
}
unsigned int IfcWritableEntity::id() {
@@ -100,7 +115,7 @@ unsigned int IfcWritableEntity::id() {
}
return *_id;
}
bool IfcWritableEntity::isWritable() { return true; }
IfcWritableEntity* IfcWritableEntity::isWritable() { return this; }
bool IfcWritableEntity::arg_writable(int i) {
std::map<int,bool>::const_iterator it = writemask.find(i);
if ( it == writemask.end() ) return false;
@@ -121,6 +136,79 @@ template <typename T> void IfcWritableEntity::_setArgument(int i, const T& t) {
void IfcWritableEntity::setArgument(int i) {
_setArgument(i, boost::none);
}
void IfcWritableEntity::setArgument(int i, Argument* a) {
IfcWrite::IfcWriteArgument* wa = new IfcWrite::IfcWriteArgument(this);
IfcUtil::ArgumentType attr_type = a->type();
switch(attr_type) {
case IfcUtil::Argument_NULL:
this->setArgument(i);
break;
case IfcUtil::Argument_DERIVED:
this->setArgumentDerived(i);
break;
case IfcUtil::Argument_INT:
this->setArgument(i, static_cast<int>(*a));
break;
case IfcUtil::Argument_BOOL:
this->setArgument(i, static_cast<bool>(*a));
break;
case IfcUtil::Argument_DOUBLE:
this->setArgument(i, static_cast<double>(*a));
break;
case IfcUtil::Argument_STRING:
this->setArgument(i, static_cast<std::string>(*a));
break;
case IfcUtil::Argument_VECTOR_INT: {
std::vector<int> attr_value = *a;
this->setArgument(i, attr_value); }
break;
case IfcUtil::Argument_VECTOR_DOUBLE: {
std::vector<double> attr_value = *a;
this->setArgument(i, attr_value); }
break;
case IfcUtil::Argument_VECTOR_STRING: {
std::vector<std::string> attr_value = *a;
this->setArgument(i, attr_value); }
break;
case IfcUtil::Argument_ENUMERATION: {
IfcSchema::Type::Enum ty = IfcSchema::Type::GetAttributeEntity(_type, i);
std::string enum_literal = a->toString();
// Remove leading and trailing '.'
enum_literal = enum_literal.substr(1, enum_literal.size() - 2);
std::pair<const char*, int> enum_ref = IfcSchema::Type::GetEnumerationIndex(ty, enum_literal);
this->setArgument(i, enum_ref.second, enum_ref.first); }
break;
case IfcUtil::Argument_ENTITY: {
this->setArgument(i, static_cast<IfcUtil::IfcBaseClass*>(*a)); }
break;
case IfcUtil::Argument_ENTITY_LIST: {
IfcEntityList::ptr instances = *a;
IfcEntityList::ptr mapped_instances(new IfcEntityList);
for (IfcEntityList::it it = instances->begin(); it != instances->end(); ++it) {
mapped_instances->push(*it);
}
this->setArgument(i, mapped_instances); }
break;
case IfcUtil::Argument_ENTITY_LIST_LIST: {
IfcEntityListList::ptr instances = *a;
IfcEntityListList::ptr mapped_instances(new IfcEntityListList);
for (IfcEntityListList::outer_it it = instances->begin(); it != instances->end(); ++it) {
std::vector<IfcUtil::IfcBaseClass*> inner;
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
inner.push_back(*jt);
}
mapped_instances->push(inner);
}
this->setArgument(i, mapped_instances); }
break;
case IfcUtil::Argument_UNKNOWN:
throw IfcParse::IfcException("Unknown argument encountered");
break;
}
}
void IfcWritableEntity::setArgumentDerived(int i) {
_setArgument(i, IfcWriteArgument::Derived());
}
@@ -139,14 +227,21 @@ void IfcWritableEntity::setArgument(int i,const std::string& v){
void IfcWritableEntity::setArgument(int i,double v){
_setArgument(i, v);
}
void IfcWritableEntity::setArgument(int i,IfcUtil::IfcSchemaEntity v){
void IfcWritableEntity::setArgument(int i,IfcUtil::IfcBaseClass* v){
if ( v ) {
_setArgument(i, v);
} else {
_setArgument(i, boost::none);
}
}
void IfcWritableEntity::setArgument(int i,IfcEntities v){
void IfcWritableEntity::setArgument(int i,IfcEntityList::ptr v){
if ( v.get() ) {
_setArgument(i, v);
} else {
_setArgument(i, boost::none);
}
}
void IfcWritableEntity::setArgument(int i,IfcEntityListList::ptr v){
if ( v.get() ) {
_setArgument(i, v);
} else {
@@ -175,8 +270,9 @@ public:
int operator()(const std::vector<double>& i) const { return i.size(); }
int operator()(const std::vector<std::string>& i) const { return i.size(); }
int operator()(const IfcWriteArgument::EnumerationReference& i) const { return -1; }
int operator()(const IfcUtil::IfcSchemaEntity& i) const { return -1; }
int operator()(const IfcEntities& i) const { return i->Size(); }
int operator()(const IfcUtil::IfcBaseClass* const& i) const { return -1; }
int operator()(const IfcEntityList::ptr& i) const { return i->size(); }
int operator()(const IfcEntityListList::ptr& i) const { return i->size(); }
};
class StringBuilderVisitor : public boost::static_visitor<void> {
@@ -195,7 +291,8 @@ private:
// REAL = [ SIGN ] DIGIT { DIGIT } "." { DIGIT } [ "E" [ SIGN ] DIGIT { DIGIT } ] .
std::string format_double(const double& d) {
std::ostringstream oss;
oss << d;
oss.imbue(std::locale::classic());
oss << std::setprecision(15) << d;
const std::string str = oss.str();
oss.str("");
std::string::size_type e = str.find('e');
@@ -213,14 +310,6 @@ private:
}
return oss.str();
}
void serialize_double(const std::vector<double>& i) {
data << "(";
for (std::vector<double>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) data << ",";
data << format_double(*it);
}
data << ")";
}
bool upper;
public:
StringBuilderVisitor(std::ostringstream& stream, bool upper = false)
@@ -232,24 +321,27 @@ public:
void operator()(const double& i) { data << format_double(i); }
void operator()(const std::string& i) {
std::string s = i;
if (upper) s = IfcCharacterEncoder(s);
data << s;
if (upper) {
data << static_cast<std::string>(IfcCharacterEncoder(s));
} else {
data << '\'' << s << '\'';
}
}
void operator()(const std::vector<int>& i) { serialize(i); }
void operator()(const std::vector<double>& i) { serialize_double(i); }
void operator()(const std::vector<std::string>& i) { serialize(i); }
void operator()(const std::vector<int>& i);
void operator()(const std::vector<double>& i);
void operator()(const std::vector<std::string>& i);
void operator()(const IfcWriteArgument::EnumerationReference& i) {
data << "." << i.enumeration_value << ".";
}
void operator()(const IfcUtil::IfcSchemaEntity& i) {
void operator()(const IfcUtil::IfcBaseClass* const& i) {
IfcAbstractEntity* e = i->entity;
if ( Ifc2x3::Type::IsSimple(e->type()) ) {
if ( IfcSchema::Type::IsSimple(e->type()) ) {
data << e->toString(upper);
} else {
data << "#" << e->id();
}
}
void operator()(const IfcEntities& i) {
void operator()(const IfcEntityList::ptr& i) {
data << "(";
for (IfcEntityList::it it = i->begin(); it != i->end(); ++it) {
if (it != i->begin()) data << ",";
@@ -257,27 +349,77 @@ public:
}
data << ")";
}
void operator()(const IfcEntityListList::ptr& i) {
data << "(";
for (IfcEntityListList::outer_it outer_it = i->begin(); outer_it != i->end(); ++outer_it) {
data << "(";
if (outer_it != i->begin()) data << ",";
for (IfcEntityListList::inner_it inner_it = outer_it->begin(); inner_it != outer_it->end(); ++inner_it) {
if (inner_it != outer_it->begin()) data << ",";
(*this)(*inner_it);
}
data << ")";
}
data << ")";
}
operator std::string() { return data.str(); }
};
template <>
void StringBuilderVisitor::serialize(const std::vector<std::string>& i) {
data << "(";
for (std::vector<std::string>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) data << ",";
if (upper) {
std::string s = IfcCharacterEncoder(*it);
data << s;
} else {
data << *it;
}
}
data << ")";
}
template <>
void StringBuilderVisitor::serialize(const std::vector<double>& i) {
data << "(";
for (std::vector<double>::const_iterator it = i.begin(); it != i.end(); ++it) {
if (it != i.begin()) data << ",";
data << format_double(*it);
}
data << ")";
}
void StringBuilderVisitor::operator()(const std::vector<int>& i) { serialize(i); }
void StringBuilderVisitor::operator()(const std::vector<double>& i) { serialize(i); }
void StringBuilderVisitor::operator()(const std::vector<std::string>& i) { serialize(i); }
IfcWriteArgument::operator int() const { return as<int>(); }
IfcWriteArgument::operator bool() const { return as<bool>(); }
IfcWriteArgument::operator double() const { return as<double>(); }
IfcWriteArgument::operator std::string() const { return as<std::string>(); }
IfcWriteArgument::operator std::string() const {
if (type() == IfcUtil::Argument_ENUMERATION) {
return as<EnumerationReference>().enumeration_value;
}
return as<std::string>();
}
IfcWriteArgument::operator std::vector<double>() const { return as<std::vector<double> >(); }
IfcWriteArgument::operator std::vector<int>() const { return as<std::vector<int> >(); }
IfcWriteArgument::operator std::vector<std::string>() const { return as<std::vector<std::string > >(); }
IfcWriteArgument::operator IfcUtil::IfcSchemaEntity() const { return as<IfcUtil::IfcSchemaEntity>(); }
IfcWriteArgument::operator IfcEntities() const { return as<IfcEntities>(); }
bool IfcWriteArgument::isNull() const { return argumentType() == argument_type_null; }
ArgumentPtr IfcWriteArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); }
IfcWriteArgument::operator IfcUtil::IfcBaseClass*() const { return as<IfcUtil::IfcBaseClass*>(); }
IfcWriteArgument::operator IfcEntityList::ptr() const { return as<IfcEntityList::ptr>(); }
IfcWriteArgument::operator IfcEntityListList::ptr() const { throw; }
bool IfcWriteArgument::isNull() const { return type() == IfcUtil::Argument_NULL; }
Argument* IfcWriteArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); }
std::string IfcWriteArgument::toString(bool upper) const {
std::ostringstream str;
str.imbue(std::locale::classic());
StringBuilderVisitor v(str, upper);
container.apply_visitor(v);
return v;
}
unsigned int IfcWriteArgument::Size() const {
unsigned int IfcWriteArgument::size() const {
SizeVisitor v;
const int size = container.apply_visitor(v);
if (size == -1) {
@@ -286,74 +428,25 @@ unsigned int IfcWriteArgument::Size() const {
return size;
}
}
IfcWriteArgument::argument_type IfcWriteArgument::argumentType() const {
return static_cast<argument_type>(container.which());
}
IfcEntities IfcSelectHelperEntity::getInverse(Ifc2x3::Type::Enum,int,const std::string &) {throw IfcParse::IfcException("Invalid cast");}
IfcEntities IfcSelectHelperEntity::getInverse(Ifc2x3::Type::Enum) {throw IfcParse::IfcException("Invalid cast");}
std::string IfcSelectHelperEntity::datatype() { return Ifc2x3::Type::ToString(_type); }
ArgumentPtr IfcSelectHelperEntity::getArgument(unsigned int i) {
if ( i != 0 ) throw IfcParse::IfcException("Invalid cast");
return arg;
IfcUtil::ArgumentType IfcWriteArgument::type() const {
return static_cast<IfcUtil::ArgumentType>(container.which());
}
unsigned int IfcSelectHelperEntity::getArgumentCount() { return 1; }
Ifc2x3::Type::Enum IfcSelectHelperEntity::type() const { return _type; }
bool IfcSelectHelperEntity::is(Ifc2x3::Type::Enum t) const { return _type == t; }
std::string IfcSelectHelperEntity::toString(bool upper) {
std::stringstream ss;
std::string dt = datatype();
if ( upper ) {
for (std::string::iterator p = dt.begin(); p != dt.end(); ++p ) *p = toupper(*p);
}
ss << dt << "(" << arg->toString(upper) << ")";
return ss.str();
}
unsigned int IfcSelectHelperEntity::id() { throw IfcParse::IfcException("Invalid cast"); }
bool IfcSelectHelperEntity::isWritable() { throw IfcParse::IfcException("Invalid cast"); }
IfcSelectHelper::IfcSelectHelper(const std::string& v, Ifc2x3::Type::Enum t) {
IfcWriteArgument* a = new IfcWriteArgument(0);
a->set(v);
this->entity = new IfcSelectHelperEntity(t,a);
}
IfcSelectHelper::IfcSelectHelper(const char* const v, Ifc2x3::Type::Enum t) {
IfcWriteArgument* a = new IfcWriteArgument(0);
a->set<std::string>(v);
this->entity = new IfcSelectHelperEntity(t,a);
}
IfcSelectHelper::IfcSelectHelper(int v, Ifc2x3::Type::Enum t) {
IfcWriteArgument* a = new IfcWriteArgument(0);
a->set(v);
this->entity = new IfcSelectHelperEntity(t,a);
}
IfcSelectHelper::IfcSelectHelper(double v, Ifc2x3::Type::Enum t) {
IfcWriteArgument* a = new IfcWriteArgument(0);
a->set(v);
this->entity = new IfcSelectHelperEntity(t,a);
}
IfcSelectHelper::IfcSelectHelper(bool v, Ifc2x3::Type::Enum t) {
IfcWriteArgument* a = new IfcWriteArgument(0);
a->set(v);
this->entity = new IfcSelectHelperEntity(t,a);
}
bool IfcSelectHelper::is(Ifc2x3::Type::Enum t) const { return entity->is(t); }
Ifc2x3::Type::Enum IfcSelectHelper::type() const { return entity->type(); }
EntityBuffer* EntityBuffer::i = 0;
EntityBuffer* EntityBuffer::instance() {
if ( ! i ) {
i = new EntityBuffer();
i->buffer = IfcEntities(new IfcEntityList());
i->buffer = IfcEntityList::ptr(new IfcEntityList);
}
return i;
}
IfcEntities EntityBuffer::Get() {
IfcEntityList::ptr EntityBuffer::Get() {
return instance()->buffer;
}
void EntityBuffer::Clear() {
instance()->buffer = IfcEntities(new IfcEntityList());
instance()->buffer = IfcEntityList::ptr(new IfcEntityList);
}
void EntityBuffer::Add(IfcUtil::IfcSchemaEntity e) {
void EntityBuffer::Add(IfcUtil::IfcBaseClass* e) {
instance()->buffer->push(e);
}
+13 -62
View File
@@ -82,27 +82,15 @@ namespace IfcWrite {
// An entity instance argument. It will either serialize to
// e.g. #123 or datatype identifier for simple types, e.g.
// IFCREAL(12.3)
IfcUtil::IfcSchemaEntity,
IfcUtil::IfcBaseClass*,
// An entity list argument. It will either serialize to
// e.g. (#1,#2,#3) or datatype identifier for simple types,
// e.g. (IFCREAL(1.2),IFCINTEGER(3.))
IfcEntities
IfcEntityList::ptr,
// A list of list of entities. E.g. ((#1, #2), (#3))
IfcEntityListList::ptr
> container;
public:
enum argument_type {
argument_type_null,
argument_type_derived,
argument_type_int,
argument_type_bool,
argument_type_double,
argument_type_string,
argument_type_vector_int,
argument_type_vector_double,
argument_type_vector_string,
argument_type_enumeration,
argument_type_schema_entity,
argument_type_entities
};
IfcWriteArgument(IfcAbstractEntity* e) : entity(e) {}
template <typename T> const T& as() const {
if (const T* val = boost::get<T>(&container)) {
@@ -121,53 +109,16 @@ namespace IfcWrite {
operator std::vector<double>() const;
operator std::vector<int>() const;
operator std::vector<std::string>() const;
operator IfcUtil::IfcSchemaEntity() const;
operator IfcEntities() const;
operator IfcUtil::IfcBaseClass*() const;
operator IfcEntityList::ptr() const;
operator IfcEntityListList::ptr() const;
bool isNull() const;
ArgumentPtr operator [] (unsigned int i) const;
Argument* operator [] (unsigned int i) const;
std::string toString(bool upper=false) const;
unsigned int Size() const;
argument_type argumentType() const;
unsigned int size() const;
IfcUtil::ArgumentType type() const;
};
/// An entity to help with passing of SELECT arguments that
/// consist of simple types, for example useful to initialize
/// a new IfcProperty.
/// Proper memory management is difficult for now, so beware.
class IfcSelectHelperEntity : public IfcAbstractEntity {
private:
Ifc2x3::Type::Enum _type;
IfcWriteArgument* arg;
public:
// FIXME: Make this a non-pointer argument and implement a copy constructor
IfcSelectHelperEntity(Ifc2x3::Type::Enum t, IfcWriteArgument* a) : _type(t), arg(a) {}
IfcEntities getInverse(Ifc2x3::Type::Enum,int,const std::string &);
IfcEntities getInverse(Ifc2x3::Type::Enum);
std::string datatype();
ArgumentPtr getArgument(unsigned int i);
unsigned int getArgumentCount();
Ifc2x3::Type::Enum type() const;
bool is(Ifc2x3::Type::Enum t) const;
std::string toString(bool upper = false);
unsigned int id();
bool isWritable();
};
/// A helper class for passing of SELECT arguments that
/// consist of simple types, for example useful to initialize
/// a new IfcProperty.
/// Proper memory management is difficult for now, so beware.
class IfcSelectHelper : public IfcUtil::IfcBaseClass {
public:
IfcSelectHelper(const std::string& v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcText);
IfcSelectHelper(const char* const v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcText);
IfcSelectHelper(int v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcInteger);
IfcSelectHelper(double v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcReal);
IfcSelectHelper(bool v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcBoolean);
bool is(Ifc2x3::Type::Enum t) const;
Ifc2x3::Type::Enum type() const;
};
/// A helper class for the creation of IFC GlobalIds.
class IfcGuidHelper {
private:
@@ -183,13 +134,13 @@ namespace IfcWrite {
// This way they can be added in a single batch to the IfcFile
class EntityBuffer {
private:
IfcEntities buffer;
IfcEntityList::ptr buffer;
static EntityBuffer* i;
static EntityBuffer* instance();
public:
static IfcEntities Get();
static IfcEntityList::ptr Get();
static void Clear();
static void Add(IfcUtil::IfcSchemaEntity e);
static void Add(IfcUtil::IfcBaseClass* e);
};
}
-111
View File
@@ -1,111 +0,0 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* This examples exposes the IfcOpenShell API through a command-based stdin *
* interface *
* *
********************************************************************************/
#include <iostream>
#include "../ifcgeom/IfcGeomObjects.h"
#if defined(WIN32) && !defined(__CYGWIN__)
#include <io.h>
#include <fcntl.h>
#endif
#define PRODUCT ("IfcOpenShell-0.2.3")
#define ACK ("y")
#define NEG ("n")
#define CONFIRM ("ok")
#define CLOSED ("No opened file")
#define QUIT ("Bye :)")
#define UNKNOWN ("Unknown command")
void send_msg(const char* c) {
std::cout.write(c,strlen(c));
std::cout.flush();
}
void send_msg(const std::string& s) {
std::cout << s << std::flush;
}
int main ( int argc, char** argv ) {
#if defined(WIN32) && !defined(__CYGWIN__)
_setmode(_fileno(stdout), _O_BINARY);
std::cout.setf(std::ios_base::binary);
#endif
bool has_more = false;
send_msg(PRODUCT);
const IfcGeomObjects::IfcGeomObject* ifc_geom = 0;
while (1) {
std::string command;
std::cin >> command;
if ( command == "load" ) {
std::string fn;
std::getline(std::cin,fn);
fn = fn.erase(0,fn.find_first_not_of(" "));
has_more = IfcGeomObjects::Init(fn.c_str(),true,0,&std::cerr);
send_msg(has_more ? ACK : NEG);
} else if ( command == "loadstdin" ) {
send_msg(CONFIRM);
int len;
std::cin >> len;
send_msg(CONFIRM);
has_more = IfcGeomObjects::Init(std::cin,len,true,0,&std::cerr);
send_msg(has_more ? ACK : NEG);
} else if ( command == "get" ) {
if ( ! has_more ) send_msg(CLOSED);
else {
ifc_geom = IfcGeomObjects::Get();
const int vcount = ifc_geom->mesh->verts.size() / 3;
std::cout.write((char*)&vcount,sizeof(int));
std::cout.write((char*)&ifc_geom->mesh->verts[0],sizeof(float)*vcount*3);
const int fcount = ifc_geom->mesh->faces.size() / 3;
std::cout.write((char*)&fcount,sizeof(int));
std::cout.write((char*)&ifc_geom->mesh->faces[0],sizeof(int)*fcount*3);
std::cout.flush();
}
} else if ( command == "type" ) {
if ( ifc_geom ) send_msg(ifc_geom->type);
else send_msg(CLOSED);
} else if ( command == "guid" ) {
if ( ifc_geom ) send_msg(ifc_geom->guid);
else send_msg(CLOSED);
} else if ( command == "next" ) {
if ( !has_more ) send_msg(CLOSED);
else {
has_more = IfcGeomObjects::Next();
if ( ! has_more )
IfcGeomObjects::CleanUp();
send_msg(has_more ? ACK : NEG);
}
} else if ( command == "quit" || command == "exit" ) {
send_msg(QUIT);
break;
} else {
send_msg(UNKNOWN);
}
}
return 0;
}
+12 -11
View File
@@ -15,21 +15,22 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
SET(CMAKE_SWIG_FLAGS "")
SET_SOURCE_FILES_PROPERTIES(IfcPython.i PROPERTIES CPLUSPLUS ON)
SWIG_ADD_MODULE(IfcImport python IfcPython.i)
SWIG_LINK_LIBRARIES(IfcImport ${PYTHON_LIBRARIES} IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet)
SWIG_ADD_MODULE(ifcopenshell_wrapper python IfcPython.i)
SWIG_LINK_LIBRARIES(ifcopenshell_wrapper ${PYTHON_LIBRARIES} IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKOffset)
# To install IfcPython let's get the site-packackes dir from python
EXECUTE_PROCESS(COMMAND python -c "from distutils.sysconfig import get_python_lib as x; print (x())"
# To install IfcPython let's get the site-packages dir from python
EXECUTE_PROCESS(COMMAND python -c "import sys; from distutils.sysconfig import get_python_lib; sys.stdout.write(get_python_lib())"
OUTPUT_VARIABLE python_package_dir)
# Strip trailing whitespace from python print
STRING(REPLACE "\r" "" python_package_dir "${python_package_dir}")
STRING(REPLACE "\n" "" python_package_dir "${python_package_dir}")
INSTALL(FILES
"${CMAKE_BINARY_DIR}/ifcwrap/IfcImport.py"
DESTINATION "${python_package_dir}")
INSTALL(TARGETS _IfcImport DESTINATION "${python_package_dir}")
"${CMAKE_BINARY_DIR}/ifcwrap/ifcopenshell_wrapper.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/__init__.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/guid.py"
DESTINATION "${python_package_dir}/ifcopenshell")
INSTALL(FILES
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/geom/__init__.py"
DESTINATION "${python_package_dir}/ifcopenshell/geom")
INSTALL(TARGETS _ifcopenshell_wrapper DESTINATION "${python_package_dir}/ifcopenshell")
ENDIF(PYTHONLIBS_FOUND)
+328
View File
@@ -0,0 +1,328 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
%rename("settings") IteratorSettings;
// This is only used for RGB colours, hence the size of 3
%typemap(out) const double* {
$result = PyTuple_New(3);
for (int i = 0; i < 3; ++i) {
PyTuple_SetItem($result, i, PyFloat_FromDouble($1[i]));
}
}
// SWIG does not support bool references in a meaningful way, so the
// IfcGeom::IteratorSettings functions degrade to return a read only value
%typemap(out) double& {
$result = SWIG_From_double(*$1);
}
%typemap(out) bool& {
$result = PyBool_FromLong(static_cast<long>(*$1));
}
%include "../ifcgeom/IfcGeomIteratorSettings.h"
%include "../ifcgeom/IfcGeomElement.h"
%include "../ifcgeom/IfcGeomMaterial.h"
%include "../ifcgeom/IfcGeomRepresentation.h"
%include "../ifcgeom/IfcGeomIterator.h"
// Using RTTI return a more specialized type of Element
// Note that these elements are not to be owned by SWIG/Python as they will be freed automatically upon the next iteration
// except for the IfcGeom::Element instances which are returned by Iterator::getObject() calls
%typemap(out) IfcGeom::Element<float>* {
IfcGeom::SerializedElement<float>* serialized_elem = dynamic_cast<IfcGeom::SerializedElement<float>*>($1);
IfcGeom::TriangulationElement<float>* triangulation_elem = dynamic_cast<IfcGeom::TriangulationElement<float>*>($1);
if (triangulation_elem) {
$result = SWIG_NewPointerObj(SWIG_as_voidptr(triangulation_elem), SWIGTYPE_p_IfcGeom__TriangulationElementT_float_t, 0);
} else if (serialized_elem) {
$result = SWIG_NewPointerObj(SWIG_as_voidptr(serialized_elem), SWIGTYPE_p_IfcGeom__SerializedElementT_float_t, 0);
} else {
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1), SWIGTYPE_p_IfcGeom__ElementT_float_t, SWIG_POINTER_OWN);
}
}
// Using RTTI return a more specialized type of Element
// Note that these elements are not to be owned by SWIG/Python as they will be freed automatically upon the next iteration
// except for the IfcGeom::Element instances which are returned by Iterator::getObject() calls
%typemap(out) IfcGeom::Element<double>* {
IfcGeom::SerializedElement<double>* serialized_elem = dynamic_cast<IfcGeom::SerializedElement<double>*>($1);
IfcGeom::TriangulationElement<double>* triangulation_elem = dynamic_cast<IfcGeom::TriangulationElement<double>*>($1);
if (triangulation_elem) {
$result = SWIG_NewPointerObj(SWIG_as_voidptr(triangulation_elem), SWIGTYPE_p_IfcGeom__TriangulationElementT_double_t, 0);
} else if (serialized_elem) {
$result = SWIG_NewPointerObj(SWIG_as_voidptr(serialized_elem), SWIGTYPE_p_IfcGeom__SerializedElementT_double_t, 0);
} else {
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1), SWIGTYPE_p_IfcGeom__ElementT_double_t, SWIG_POINTER_OWN);
}
}
// Note that these elements ARE to be owned by SWIG/Python
%typemap(out) boost::variant<IfcGeom::Element<double>*, IfcGeom::Representation::Representation*> {
// See which type is set and return appropriate
IfcGeom::Element<double>* elem = boost::get<IfcGeom::Element<double>*>($1);
IfcGeom::SerializedElement<double>* serialized_elem = dynamic_cast<IfcGeom::SerializedElement<double>*>(elem);
IfcGeom::TriangulationElement<double>* triangulation_elem = dynamic_cast<IfcGeom::TriangulationElement<double>*>(elem);
if (triangulation_elem) {
$result = SWIG_NewPointerObj(SWIG_as_voidptr(triangulation_elem), SWIGTYPE_p_IfcGeom__TriangulationElementT_double_t, SWIG_POINTER_OWN);
} else if (serialized_elem) {
$result = SWIG_NewPointerObj(SWIG_as_voidptr(serialized_elem), SWIGTYPE_p_IfcGeom__SerializedElementT_double_t, SWIG_POINTER_OWN);
}
}
// This does not seem to work:
%ignore IfcGeom::Iterator<float>::Iterator(const IfcGeom::IteratorSettings&, IfcParse::IfcFile*);
%ignore IfcGeom::Iterator<float>::Iterator(const IfcGeom::IteratorSettings&, void*, int);
%ignore IfcGeom::Iterator<float>::Iterator(const IfcGeom::IteratorSettings&, std::istream&, int);
%ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, IfcParse::IfcFile*);
%ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, void*, int);
%ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, std::istream&, int);
%extend IfcGeom::IteratorSettings {
%pythoncode %{
attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "force_ccw_face_orientation", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices")
def __repr__(self):
return "%s(%s)"%(self.__class__.__name__, ",".join(tuple("%s=%r"%(a, getattr(self, a)()) for a in self.attrs)))
%}
}
%extend IfcGeom::Iterator<float> {
static int mantissa_size() {
return std::numeric_limits<float>::digits;
}
};
%extend IfcGeom::Iterator<double> {
static int mantissa_size() {
return std::numeric_limits<double>::digits;
}
};
%extend IfcGeom::Representation::Triangulation {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
id = property(id)
verts = property(verts)
faces = property(faces)
edges = property(edges)
normals = property(normals)
material_ids = property(material_ids)
materials = property(materials)
%}
};
%extend IfcGeom::Representation::Serialization {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
id = property(id)
brep_data = property(brep_data)
%}
};
%extend IfcGeom::Element {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
id = property(id)
parent_id = property(parent_id)
name = property(name)
type = property(type)
guid = property(guid)
transformation = property(transformation)
%}
};
%extend IfcGeom::TriangulationElement {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
geometry = property(geometry)
%}
};
%extend IfcGeom::SerializedElement {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
geometry = property(geometry)
%}
};
%extend IfcGeom::Material {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
has_diffuse = property(hasDiffuse)
has_specular = property(hasSpecular)
has_transparency = property(hasTransparency)
has_specularity = property(hasSpecularity)
diffuse = property(diffuse)
specular = property(specular)
transparency = property(transparency)
specularity = property(specularity)
name = property(name)
%}
};
%extend IfcGeom::Transformation {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
matrix = property(matrix)
%}
};
%extend IfcGeom::Matrix {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
data = property(data)
%}
};
%inline %{
boost::variant<IfcGeom::Element<double>*, IfcGeom::Representation::Representation*> create_shape(IfcGeom::IteratorSettings& settings, IfcParse::IfcLateBoundEntity* instance) {
if (instance->is(IfcSchema::Type::IfcProduct)) {
IfcParse::IfcFile* file = instance->entity->file;
IfcSchema::IfcProject::list::ptr projects = file->entitiesByType<IfcSchema::IfcProject>();
if (projects->size() != 1) {
throw IfcParse::IfcException("Not a single IfcProject instance");
}
IfcSchema::IfcProject* project = *projects->begin();
IfcGeom::Kernel kernel;
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1);
kernel.setValue(IfcGeom::Kernel::GV_FORCE_CCW_FACE_ORIENTATION, settings.force_ccw_face_orientation() ? 1 : -1);
IfcSchema::IfcProduct* product = (IfcSchema::IfcProduct*) instance;
if (!product->hasRepresentation()) {
throw IfcParse::IfcException("Representation is NULL");
}
IfcSchema::IfcProductRepresentation* prodrep = product->Representation();
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
IfcSchema::IfcRepresentation* representation = 0;
// First, try to find a representation with a 'Body' identifier
for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
IfcSchema::IfcRepresentation* rep = *it;
if (rep->RepresentationIdentifier() == "Body") {
representation = rep;
break;
}
}
// Otherwise, find a representation within the 'Model' context
if (!representation) {
for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
IfcSchema::IfcRepresentation* rep = *it;
IfcSchema::IfcRepresentationContext* context = rep->ContextOfItems();
// TODO: Remove redundancy with IfcGeomIterator.h
if (context->hasContextType()) {
std::set<std::string> context_types;
context_types.insert("model");
context_types.insert("design");
context_types.insert("model view");
std::string context_type_lc = context->ContextType();
for (std::string::iterator c = context_type_lc.begin(); c != context_type_lc.end(); ++c) {
*c = tolower(*c);
}
if (context_types.find(context_type_lc) != context_types.end()) {
representation = rep;
}
}
}
}
if (!representation) {
throw IfcParse::IfcException("No IfcRepresentations with a 'Body' RepresentationIdentifier found");
}
IfcSchema::IfcRepresentationContext* ctx = representation->ContextOfItems();
if (!ctx->is(IfcSchema::Type::IfcGeometricRepresentationContext)) {
throw IfcParse::IfcException("Context not of type IfcGeometricRepresentationContext");
}
IfcSchema::IfcGeometricRepresentationContext* context = (IfcSchema::IfcGeometricRepresentationContext*) ctx;
if (context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) {
IfcSchema::IfcGeometricRepresentationSubContext* subcontext = (IfcSchema::IfcGeometricRepresentationSubContext*) context;
context = subcontext->ParentContext();
}
double precision = 1.e-6;
if (context->hasPrecision()) {
precision = context->Precision();
}
std::pair<std::string, double> length_unit = kernel.initializeUnits(project->UnitsInContext());
precision *= length_unit.second;
// Some arbitrary factor that has proven to work better for the models in the set of test files.
precision *= 10.;
kernel.setValue(IfcGeom::Kernel::GV_PRECISION, precision);
IfcGeom::BRepElement<double>* brep = kernel.create_brep_for_representation_and_product<double>(settings, representation, product);
if (!brep) {
throw IfcParse::IfcException("Failed to process shape");
}
if (settings.use_brep_data()) {
IfcGeom::SerializedElement<double>* serialization = new IfcGeom::SerializedElement<double>(*brep);
delete brep;
return serialization;
} else if (!settings.disable_triangulation()) {
IfcGeom::TriangulationElement<double>* triangulation = new IfcGeom::TriangulationElement<double>(*brep);
delete brep;
return triangulation;
} else {
throw IfcParse::IfcException("No element to return based on provided settings");
}
} else {
throw IfcParse::IfcException("Only obtaining representations for IfcProduct instances is currently supported");
}
}
%}
namespace IfcGeom {
%template(iterator_single_precision) Iterator<float>;
%template(iterator_double_precision) Iterator<double>;
%template(element_single_precision) Element<float>;
%template(element_double_precision) Element<double>;
%template(triangulation_element_single_precision) TriangulationElement<float>;
%template(triangulation_element_double_precision) TriangulationElement<double>;
%template(serialized_element_single_precision) SerializedElement<float>;
%template(serialized_element_double_precision) SerializedElement<double>;
%template(transformation_single_precision) Transformation<float>;
%template(transformation_double_precision) Transformation<double>;
%template(matrix_single_precision) Matrix<float>;
%template(matrix_double_precision) Matrix<double>;
namespace Representation {
%template(triangulation_single_precision) Triangulation<float>;
%template(triangulation_double_precision) Triangulation<double>;
};
};
+298
View File
@@ -0,0 +1,298 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
// Two class declarations to silence SWIG warning about base classes being
// undefined, the constructors are private so that SWIG does not wrap them
class IfcAbstractEntity {
private:
IfcAbstractEntity();
};
namespace IfcUtil {
class IfcBaseEntity {
private:
IfcBaseEntity();
};
}
%ignore IfcParse::IfcLateBoundEntity::is;
%ignore IfcParse::IfcLateBoundEntity::type;
%ignore IfcParse::IfcLateBoundEntity::getArgument;
%ignore IfcParse::IfcLateBoundEntity::IfcLateBoundEntity(IfcAbstractEntity*);
%ignore IfcParse::IfcFile::Init;
%ignore IfcParse::IfcFile::entityById;
%ignore IfcParse::IfcFile::entityByGuid;
%ignore IfcParse::IfcFile::addEntity;
%ignore IfcParse::IfcFile::removeEntity;
%ignore IfcParse::IfcFile::traverse(IfcUtil::IfcBaseClass*, int);
%ignore IfcParse::IfcFile::traverse(IfcUtil::IfcBaseClass*);
%ignore operator<<;
%ignore IfcParse::FileDescription::FileDescription;
%ignore IfcParse::FileName::FileName;
%ignore IfcParse::FileSchema::FileSchema;
%ignore IfcParse::IfcFile::tokens;
%ignore IfcParse::IfcSpfHeader::IfcSpfHeader(IfcSpfLexer*);
%ignore IfcParse::IfcSpfHeader::lexer;
%ignore IfcParse::IfcSpfHeader::stream;
%ignore IfcParse::HeaderEntity::is;
%rename("by_type") entitiesByType;
%rename("__len__") getArgumentCount;
%rename("get_argument_type") getArgumentType;
%rename("get_argument_name") getArgumentName;
%rename("get_argument_index") getArgumentIndex;
%rename("get_argument_optionality") getArgumentOptionality;
%rename("get_attribute_names") getAttributeNames;
%rename("get_inverse_attribute_names") getInverseAttributeNames;
%rename("_set_argument") setArgument;
%rename("__repr__") toString;
%rename("entity_instance") IfcLateBoundEntity;
%rename("file") IfcFile;
%typemap(typecheck,precedence=SWIG_TYPECHECK_INTEGER) IfcEntityList::ptr {
$1 = (PySequence_Check($input) && !PyUnicode_Check($input) && !PyString_Check($input)) ? 1 : 0;
}
%typemap(in) IfcEntityList::ptr {
if (PySequence_Check($input)) {
$1 = IfcEntityList::ptr(new IfcEntityList());
for(Py_ssize_t i = 0; i < PySequence_Size($input); ++i) {
PyObject* obj = PySequence_GetItem($input, i);
if (obj) {
void *arg = 0;
int res = SWIG_ConvertPtr(obj, &arg, SWIGTYPE_p_IfcParse__IfcLateBoundEntity, 0);
if (!SWIG_IsOK(res)) {
SWIG_exception_fail(SWIG_ArgError(res), "Sequence element not of type IfcParse::IfcLateBoundEntity*");
} else {
$1->push(reinterpret_cast<IfcParse::IfcLateBoundEntity*>(arg));
}
}
}
} else {
SWIG_exception(SWIG_RuntimeError,"Unknown argument type");
}
}
%typemap(out) IfcEntityList::ptr {
const unsigned size = $1 ? $1->size() : 0;
$result = PyList_New(size);
for (unsigned i = 0; i < size; ++i) {
PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr((*$1)[i]), SWIGTYPE_p_IfcParse__IfcLateBoundEntity, 0);
PyList_SetItem($result,i,o);
}
}
%typemap(out) IfcUtil::ArgumentType {
$result = SWIG_Python_str_FromChar(IfcUtil::ArgumentTypeToString($1));
}
%typemap(out) std::pair<IfcUtil::ArgumentType, Argument*> {
// The SWIG %exception directive does not take care
// of our typemap. So the argument conversion block
// is wrapped in a try-catch block manually.
try {
const Argument& arg = *($1.second);
const IfcUtil::ArgumentType type = $1.first;
if (arg.isNull() || type == IfcUtil::Argument_DERIVED) {
Py_INCREF(Py_None);
$result = Py_None;
} else {
switch(type) {
case IfcUtil::Argument_INT:
$result = PyInt_FromLong((int)arg);
break;
case IfcUtil::Argument_BOOL:
$result = PyBool_FromLong((bool)arg);
break;
case IfcUtil::Argument_DOUBLE:
$result = PyFloat_FromDouble(arg);
break;
case IfcUtil::Argument_ENUMERATION:
case IfcUtil::Argument_STRING: {
const std::string s = arg;
$result = PyString_FromString(s.c_str());
break; }
case IfcUtil::Argument_VECTOR_INT: {
const std::vector<int> v = arg;
const unsigned size = v.size();
$result = PyList_New(size);
for (unsigned int i = 0; i < size; ++i) {
PyList_SetItem($result,i,PyInt_FromLong(v[i]));
}
break; }
case IfcUtil::Argument_VECTOR_DOUBLE: {
const std::vector<double> v = arg;
const unsigned size = v.size();
$result = PyList_New(size);
for (unsigned int i = 0; i < size; ++i) {
PyList_SetItem($result,i,PyFloat_FromDouble(v[i]));
}
break; }
case IfcUtil::Argument_VECTOR_STRING: {
const std::vector<std::string> v = arg;
const unsigned size = v.size();
$result = PyList_New(size);
for (unsigned int i = 0; i < size; ++i) {
PyList_SetItem($result,i,PyString_FromString(v[i].c_str()));
}
break; }
case IfcUtil::Argument_ENTITY: {
IfcUtil::IfcBaseClass* e = arg;
$result = SWIG_NewPointerObj(SWIG_as_voidptr(e), SWIGTYPE_p_IfcParse__IfcLateBoundEntity, 0);
break; }
case IfcUtil::Argument_ENTITY_LIST: {
IfcEntityList::ptr es = arg;
const unsigned size = es->size();
$result = PyList_New(size);
for (unsigned i = 0; i < size; ++i) {
PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr((*es)[i]), SWIGTYPE_p_IfcParse__IfcLateBoundEntity, 0);
PyList_SetItem($result,i,o);
}
break; }
case IfcUtil::Argument_UNKNOWN:
default:
SWIG_exception(SWIG_RuntimeError,"Unknown argument type");
break;
}
}
} catch(IfcParse::IfcException& e) {
SWIG_exception(SWIG_RuntimeError, e.what());
} catch(...) {
SWIG_exception(SWIG_RuntimeError, "An unknown error occurred");
}
}
%extend IfcParse::IfcFile {
IfcParse::IfcLateBoundEntity* by_id(unsigned id) {
return (IfcParse::IfcLateBoundEntity*) $self->entityById(id);
}
IfcParse::IfcLateBoundEntity* by_guid(const std::string& guid) {
return (IfcParse::IfcLateBoundEntity*) $self->entityByGuid(guid);
}
IfcParse::IfcLateBoundEntity* add(IfcParse::IfcLateBoundEntity* e) {
return (IfcParse::IfcLateBoundEntity*) $self->addEntity(e);
}
void remove(IfcParse::IfcLateBoundEntity* e) {
$self->removeEntity(e);
}
IfcEntityList::ptr traverse(IfcParse::IfcLateBoundEntity* e, int max_level=-1) {
return $self->traverse(e, max_level);
}
void write(const std::string& fn) {
std::ofstream f(fn.c_str());
f << (*$self);
}
std::vector<int> entity_names() const {
std::vector<int> keys;
keys.reserve(std::distance($self->begin(), $self->end()));
for (IfcParse::IfcFile::entity_by_id_t::const_iterator it = $self->begin(); it != $self->end(); ++ it) {
keys.push_back(it->first);
}
return keys;
}
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
header = property(header)
%}
}
%extend IfcParse::IfcLateBoundEntity {
%pythoncode %{
set_argument = lambda self,x,y: self._set_argument(x) if y is None else self._set_argument(x,y)
%}
}
%extend IfcParse::IfcSpfHeader {
%pythoncode %{
if _newclass:
# Hide the getters with read-only property implementations
file_description = property(file_description)
file_name = property(file_name)
file_schema = property(file_schema)
%}
};
%extend IfcParse::FileDescription {
%pythoncode %{
if _newclass:
# Hide the getters with read-write property implementations
__swig_getmethods__["description"] = description
__swig_setmethods__["description"] = description
description = property(description, description)
__swig_getmethods__["implementation_level"] = implementation_level
__swig_setmethods__["implementation_level"] = implementation_level
implementation_level = property(implementation_level, implementation_level)
%}
};
%extend IfcParse::FileName {
%pythoncode %{
if _newclass:
# Hide the getters with read-write property implementations
__swig_getmethods__["name"] = name
__swig_setmethods__["name"] = name
name = property(name, name)
__swig_getmethods__["time_stamp"] = time_stamp
__swig_setmethods__["time_stamp"] = time_stamp
time_stamp = property(time_stamp, time_stamp)
__swig_getmethods__["author"] = author
__swig_setmethods__["author"] = author
author = property(author, author)
__swig_getmethods__["organization"] = organization
__swig_setmethods__["organization"] = organization
organization = property(organization, organization)
__swig_getmethods__["preprocessor_version"] = preprocessor_version
__swig_setmethods__["preprocessor_version"] = preprocessor_version
preprocessor_version = property(preprocessor_version, preprocessor_version)
__swig_getmethods__["originating_system"] = originating_system
__swig_setmethods__["originating_system"] = originating_system
originating_system = property(originating_system, originating_system)
__swig_getmethods__["authorization"] = authorization
__swig_setmethods__["authorization"] = authorization
authorization = property(authorization, authorization)
%}
};
%extend IfcParse::FileSchema {
%pythoncode %{
if _newclass:
# Hide the getters with read-write property implementations
__swig_getmethods__["schema_identifiers"] = schema_identifiers
__swig_setmethods__["schema_identifiers"] = schema_identifiers
schema_identifiers = property(schema_identifiers, schema_identifiers)
%}
};
%include "../ifcparse/IfcSpfHeader.h"
%include "../ifcparse/IfcFile.h"
%include "../ifcparse/IfcLateBoundEntity.h"
// The IfcFile* returned by open() is to be freed by SWIG/Python
%newobject open;
%inline %{
IfcParse::IfcFile* open(const std::string& s) {
IfcParse::IfcFile* f = new IfcParse::IfcFile(true);
f->Init(s);
return f;
}
%}

Some files were not shown because too many files have changed in this diff Show More