2012-07-19 18:26:47 +00:00
/********************************************************************************
2011-07-25 14:56:40 +00:00
* *
* 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/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Implementations of the various conversion functions defined in IfcGeom.h *
* *
********************************************************************************/
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
2014-03-22 10:31:51 +00:00
# include <set>
2012-06-25 15:08:58 +00:00
# include <cassert>
2014-07-24 11:14:54 +00:00
# include <algorithm>
2012-06-25 15:08:58 +00:00
2011-07-25 14:56:40 +00:00
# include <gp_Pnt.hxx>
# include <gp_Vec.hxx>
# include <gp_Dir.hxx>
# include <gp_Pnt2d.hxx>
# include <gp_Vec2d.hxx>
# include <gp_Dir2d.hxx>
2011-10-23 17:11:06 +00:00
# include <gp_Mat.hxx>
# include <gp_Mat2d.hxx>
# include <gp_GTrsf.hxx>
# include <gp_GTrsf2d.hxx>
2011-07-25 14:56:40 +00:00
# include <gp_Trsf.hxx>
# include <gp_Trsf2d.hxx>
# include <gp_Ax3.hxx>
# include <gp_Ax2d.hxx>
# include <gp_Pln.hxx>
# include <gp_Circ.hxx>
# include <TColgp_Array1OfPnt.hxx>
# 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_MakeFace.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepBuilderAPI_MakeWire.hxx>
# include <BRepBuilderAPI_MakePolygon.hxx>
# include <BRepBuilderAPI_MakeVertex.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Wire.hxx>
# include <TopoDS_Face.hxx>
2016-02-18 13:17:15 +01:00
# include <TopoDS_CompSolid.hxx>
# include <TopExp.hxx>
2011-07-25 14:56:40 +00:00
# include <TopExp_Explorer.hxx>
# include <BRepPrimAPI_MakePrism.hxx>
# include <BRepBuilderAPI_MakeShell.hxx>
# include <BRepBuilderAPI_MakeSolid.hxx>
# include <BRepPrimAPI_MakeHalfSpace.hxx>
# include <BRepAlgoAPI_Cut.hxx>
2014-07-06 14:21:56 +00:00
# include <BRepAlgoAPI_Fuse.hxx>
2011-07-25 14:56:40 +00:00
# include <ShapeFix_Shape.hxx>
# include <ShapeFix_ShapeTolerance.hxx>
# include <ShapeFix_Solid.hxx>
# include <BRepFilletAPI_MakeFillet2d.hxx>
# include <TopLoc_Location.hxx>
2011-10-12 16:43:29 +00:00
# include <GProp_GProps.hxx>
# include <BRepGProp.hxx>
2011-10-23 17:11:06 +00:00
# include <BRepBuilderAPI_GTransform.hxx>
2012-03-13 11:56:52 +00:00
# include <BRepCheck_Analyzer.hxx>
# include <BRepGProp_Face.hxx>
2015-01-19 16:02:34 +00:00
# include <BRepMesh_IncrementalMesh.hxx>
2012-11-04 16:26:33 +00:00
# include <BRepTools.hxx>
# include <Poly_Triangulation.hxx>
# include <Poly_Array1OfTriangle.hxx>
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
2014-03-22 10:31:51 +00:00
# include <TopTools_IndexedMapOfShape.hxx>
# include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
# include <TopTools_ListIteratorOfListOfShape.hxx>
2016-01-22 17:27:28 +01:00
# include <Standard_Version.hxx>
2015-02-17 19:48:41 +00:00
# include "../ifcparse/IfcSIPrefix.h"
2011-08-24 12:21:07 +00:00
# include "../ifcgeom/IfcGeom.h"
2011-07-25 14:56:40 +00:00
2016-01-25 13:30:33 +01:00
# if OCC_VERSION_HEX < 0x60900
2016-02-18 13:17:15 +01:00
# ifdef _MSC_VER
2016-01-25 13:30:33 +01:00
# pragma message("warning: You are linking against Open CASCADE version " OCC_VERSION_COMPLETE ". Version 6.9.0 introduces various improvements with relation to boolean operations. You are advised to upgrade.")
2016-02-18 13:17:15 +01:00
# else
# warning "You are linking against linking against an older version of Open CASCADE. Version 6.9.0 introduces various improvements with relation to boolean operations. You are advised to upgrade."
# endif
2016-01-25 13:30:33 +01:00
# endif
2014-12-19 12:14:36 +00:00
bool IfcGeom : : Kernel : : create_solid_from_compound ( const TopoDS_Shape & compound , TopoDS_Shape & shape ) {
2012-03-01 21:17:06 +00:00
BRepOffsetAPI_Sewing builder ;
2014-12-19 12:14:36 +00:00
builder . SetTolerance ( getValue ( GV_POINT_EQUALITY_TOLERANCE ) ) ;
builder . SetMaxTolerance ( getValue ( GV_POINT_EQUALITY_TOLERANCE ) ) ;
builder . SetMinTolerance ( getValue ( GV_POINT_EQUALITY_TOLERANCE ) ) ;
2012-03-01 21:17:06 +00:00
TopExp_Explorer exp ( compound , TopAbs_FACE ) ;
if ( ! exp . More ( ) ) return false ;
for ( ; exp . More ( ) ; exp . Next ( ) ) {
TopoDS_Face face = TopoDS : : Face ( exp . Current ( ) ) ;
builder . Add ( face ) ;
}
builder . Perform ( ) ;
shape = builder . SewedShape ( ) ;
try {
ShapeFix_Solid sf_solid ;
2014-12-19 12:14:36 +00:00
sf_solid . LimitTolerance ( getValue ( GV_POINT_EQUALITY_TOLERANCE ) ) ;
2012-03-01 21:17:06 +00:00
shape = sf_solid . SolidFromShell ( TopoDS : : Shell ( shape ) ) ;
} catch ( . . . ) { }
return true ;
}
2014-12-19 12:14:36 +00:00
bool IfcGeom : : Kernel : : is_compound ( const TopoDS_Shape & shape ) {
2012-03-13 11:56:52 +00:00
bool has_solids = TopExp_Explorer ( shape , TopAbs_SOLID ) . More ( ) ! = 0 ;
2012-03-01 21:17:06 +00:00
bool has_shells = TopExp_Explorer ( shape , TopAbs_SHELL ) . More ( ) ! = 0 ;
bool has_compounds = TopExp_Explorer ( shape , TopAbs_COMPOUND ) . More ( ) ! = 0 ;
bool has_faces = TopExp_Explorer ( shape , TopAbs_FACE ) . More ( ) ! = 0 ;
return has_compounds & & has_faces & & ! has_solids & & ! has_shells ;
}
2014-12-19 12:14:36 +00:00
const TopoDS_Shape & IfcGeom : : Kernel : : ensure_fit_for_subtraction ( const TopoDS_Shape & shape , TopoDS_Shape & solid ) {
const bool is_comp = is_compound ( shape ) ;
2015-06-21 16:14:37 +00:00
if ( ! is_comp ) {
return solid = shape ;
}
2014-12-19 12:14:36 +00:00
create_solid_from_compound ( shape , solid ) ;
2014-06-09 12:56:47 +00:00
// If the SEW_SHELLS option had been set this precision had been applied
2014-12-19 12:14:36 +00:00
// at the end of the generic convert_shape() call.
const double precision = getValue ( GV_PRECISION ) ;
apply_tolerance ( solid , precision ) ;
2014-06-09 12:56:47 +00:00
2012-03-01 21:17:06 +00:00
return solid ;
}
2014-12-19 12:14:36 +00:00
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 ) {
2015-05-22 15:41:56 +00:00
// TODO: Refactor convert_openings() convert_openings_fast() and convert(IfcBooleanResult) to use
// the same code base and conform to the same checks and logging messages.
2011-10-23 17:11:06 +00:00
// Iterate over IfcOpeningElements
2013-05-05 08:49:25 +00:00
IfcGeom : : IfcRepresentationShapeItems opening_shapes ;
2011-10-23 17:11:06 +00:00
unsigned int last_size = 0 ;
2014-05-04 14:42:55 +00:00
for ( IfcSchema : : IfcRelVoidsElement : : list : : it it = openings - > begin ( ) ; it ! = openings - > end ( ) ; + + it ) {
IfcSchema : : IfcRelVoidsElement * v = * it ;
IfcSchema : : IfcFeatureElementSubtraction * fes = v - > RelatedOpeningElement ( ) ;
2014-02-17 22:13:55 +00:00
if ( fes - > is ( IfcSchema : : Type : : IfcOpeningElement ) ) {
2015-12-05 17:14:10 +01:00
if ( ! fes - > hasRepresentation ( ) ) continue ;
2011-10-23 17:11:06 +00:00
// Convert the IfcRepresentation of the IfcOpeningElement
gp_Trsf opening_trsf ;
2015-12-05 17:14:10 +01:00
if ( fes - > hasObjectPlacement ( ) ) {
try {
convert ( fes - > ObjectPlacement ( ) , opening_trsf ) ;
} catch ( . . . ) { }
}
2011-10-23 17:11:06 +00:00
// Move the opening into the coordinate system of the IfcProduct
opening_trsf . PreMultiply ( entity_trsf . Inverted ( ) ) ;
2014-05-04 14:42:55 +00:00
IfcSchema : : IfcProductRepresentation * prodrep = fes - > Representation ( ) ;
IfcSchema : : IfcRepresentation : : list : : ptr reps = prodrep - > Representations ( ) ;
2011-10-23 17:11:06 +00:00
2014-05-04 14:42:55 +00:00
for ( IfcSchema : : IfcRepresentation : : list : : it it2 = reps - > begin ( ) ; it2 ! = reps - > end ( ) ; + + it2 ) {
2014-12-19 12:14:36 +00:00
convert_shapes ( * it2 , opening_shapes ) ;
2011-10-23 17:11:06 +00:00
}
const unsigned int current_size = ( const unsigned int ) opening_shapes . size ( ) ;
for ( unsigned int i = last_size ; i < current_size ; + + i ) {
2013-07-20 22:12:40 +00:00
opening_shapes [ i ] . prepend ( opening_trsf ) ;
2011-07-25 14:56:40 +00:00
}
2011-10-23 17:11:06 +00:00
last_size = current_size ;
2011-07-25 14:56:40 +00:00
}
}
2011-10-23 17:11:06 +00:00
// Iterate over the shapes of the IfcProduct
2013-05-05 08:49:25 +00:00
for ( IfcGeom : : IfcRepresentationShapeItems : : const_iterator it3 = entity_shapes . begin ( ) ; it3 ! = entity_shapes . end ( ) ; + + it3 ) {
2012-03-01 21:17:06 +00:00
TopoDS_Shape entity_shape_solid ;
2014-12-19 12:14:36 +00:00
const TopoDS_Shape & entity_shape_unlocated = ensure_fit_for_subtraction ( it3 - > Shape ( ) , entity_shape_solid ) ;
2013-05-05 08:49:25 +00:00
const gp_GTrsf & entity_shape_gtrsf = it3 - > Placement ( ) ;
2011-10-23 17:11:06 +00:00
TopoDS_Shape entity_shape ;
if ( entity_shape_gtrsf . Form ( ) = = gp_Other ) {
2012-08-11 13:24:08 +00:00
Logger : : Message ( Logger : : LOG_WARNING , " Applying non uniform transformation to: " , entity - > entity ) ;
2011-10-23 17:11:06 +00:00
entity_shape = BRepBuilderAPI_GTransform ( entity_shape_unlocated , entity_shape_gtrsf , true ) . Shape ( ) ;
} else {
entity_shape = entity_shape_unlocated . Moved ( entity_shape_gtrsf . Trsf ( ) ) ;
}
// Iterate over the shapes of the IfcOpeningElements
2013-05-05 08:49:25 +00:00
for ( IfcGeom : : IfcRepresentationShapeItems : : const_iterator it4 = opening_shapes . begin ( ) ; it4 ! = opening_shapes . end ( ) ; + + it4 ) {
2012-03-01 21:17:06 +00:00
TopoDS_Shape opening_shape_solid ;
2014-12-19 12:14:36 +00:00
const TopoDS_Shape & opening_shape_unlocated = ensure_fit_for_subtraction ( it4 - > Shape ( ) , opening_shape_solid ) ;
2013-05-05 08:49:25 +00:00
const gp_GTrsf & opening_shape_gtrsf = it4 - > Placement ( ) ;
2011-10-23 17:11:06 +00:00
if ( opening_shape_gtrsf . Form ( ) = = gp_Other ) {
2012-08-11 13:24:08 +00:00
Logger : : Message ( Logger : : LOG_WARNING , " Applying non uniform transformation to opening of: " , entity - > entity ) ;
2011-10-23 17:11:06 +00:00
}
const TopoDS_Shape & opening_shape = opening_shape_gtrsf . Form ( ) = = gp_Other
? BRepBuilderAPI_GTransform ( opening_shape_unlocated , opening_shape_gtrsf , true ) . Shape ( )
: opening_shape_unlocated . Moved ( opening_shape_gtrsf . Trsf ( ) ) ;
2015-11-21 23:05:28 +02:00
double opening_volume ;
2012-08-11 13:24:08 +00:00
if ( Logger : : Verbosity ( ) > = Logger : : LOG_WARNING ) {
2012-06-07 14:38:21 +00:00
opening_volume = shape_volume ( opening_shape ) ;
if ( opening_volume < = ALMOST_ZERO )
2012-08-11 13:24:08 +00:00
Logger : : Message ( Logger : : LOG_WARNING , " Empty opening for: " , entity - > entity ) ;
2012-06-07 14:38:21 +00:00
}
2012-03-01 21:17:06 +00:00
2014-07-24 11:22:31 +00:00
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 ( ) ) {
2016-01-22 17:27:28 +01:00
# if OCC_VERSION_HEX < 0x60900
2014-07-24 11:22:31 +00:00
BRepAlgoAPI_Cut brep_cut ( exp . Current ( ) , opening_shape ) ;
2016-01-22 17:27:28 +01:00
# else
BRepAlgoAPI_Cut brep_cut ;
TopTools_ListOfShape s1s ;
s1s . Append ( exp . Current ( ) ) ;
TopTools_ListOfShape s2s ;
s2s . Append ( opening_shape ) ;
brep_cut . SetFuzzyValue ( getValue ( GV_PRECISION ) ) ;
brep_cut . SetArguments ( s1s ) ;
brep_cut . SetTools ( s2s ) ;
brep_cut . Build ( ) ;
# endif
2014-07-24 11:22:31 +00:00
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 ) {
2015-11-21 23:05:28 +02:00
TopExp_Explorer exp2 ( brep_cut_result , TopAbs_SOLID ) ;
for ( ; exp2 . More ( ) ; exp2 . Next ( ) ) {
builder . Add ( compound , exp2 . Current ( ) ) ;
2014-07-24 11:22:31 +00:00
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 {
2016-01-22 17:27:28 +01:00
# if OCC_VERSION_HEX < 0x60900
2014-07-24 11:22:31 +00:00
BRepAlgoAPI_Cut brep_cut ( entity_shape , opening_shape ) ;
2016-01-22 17:27:28 +01:00
# else
BRepAlgoAPI_Cut brep_cut ;
TopTools_ListOfShape s1s ;
s1s . Append ( entity_shape ) ;
TopTools_ListOfShape s2s ;
s2s . Append ( opening_shape ) ;
brep_cut . SetFuzzyValue ( getValue ( GV_PRECISION ) ) ;
brep_cut . SetArguments ( s1s ) ;
brep_cut . SetTools ( s2s ) ;
brep_cut . Build ( ) ;
# endif
2014-07-24 11:22:31 +00:00
if ( brep_cut . IsDone ( ) ) {
TopoDS_Shape brep_cut_result = brep_cut ;
2015-05-22 15:41:56 +00:00
ShapeFix_Shape fix ( brep_cut_result ) ;
try {
fix . Perform ( ) ;
brep_cut_result = fix . Shape ( ) ;
} catch ( . . . ) {
Logger : : Message ( Logger : : LOG_WARNING , " Shape healing failed on opening subtraction result " , entity - > entity ) ;
}
2014-07-24 11:22:31 +00:00
BRepCheck_Analyzer analyser ( brep_cut_result ) ;
bool is_valid = analyser . IsValid ( ) ! = 0 ;
if ( is_valid ) {
2015-05-22 15:41:56 +00:00
entity_shape = brep_cut_result ;
2014-07-24 11:22:31 +00:00
if ( Logger : : Verbosity ( ) > = Logger : : LOG_WARNING ) {
const double volume_after_subtraction = shape_volume ( entity_shape ) ;
2015-11-21 23:05:28 +02:00
double original_shape_volume = shape_volume ( entity_shape ) ;
2014-07-24 11:22:31 +00:00
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 ) ;
2012-06-07 14:38:21 +00:00
}
2012-03-13 11:56:52 +00:00
} else {
2014-07-24 11:22:31 +00:00
Logger : : Message ( Logger : : LOG_ERROR , " Failed to process subtraction: " , entity - > entity ) ;
2012-03-13 11:56:52 +00:00
}
2012-03-01 21:17:06 +00:00
}
2012-03-13 11:56:52 +00:00
2011-10-23 17:11:06 +00:00
}
2013-05-05 08:49:25 +00:00
cut_shapes . push_back ( IfcGeom : : IfcRepresentationShapeItem ( entity_shape , & it3 - > Style ( ) ) ) ;
2011-10-23 17:11:06 +00:00
}
2011-07-25 14:56:40 +00:00
return true ;
}
2012-06-07 14:38:21 +00:00
2016-01-25 13:30:33 +01:00
# if OCC_VERSION_HEX < 0x60900
2014-12-19 12:14:36 +00:00
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 ) {
2012-06-07 14:38:21 +00:00
// 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 ) ;
2014-05-04 14:42:55 +00:00
for ( IfcSchema : : IfcRelVoidsElement : : list : : it it = openings - > begin ( ) ; it ! = openings - > end ( ) ; + + it ) {
IfcSchema : : IfcRelVoidsElement * v = * it ;
IfcSchema : : IfcFeatureElementSubtraction * fes = v - > RelatedOpeningElement ( ) ;
2014-02-17 22:13:55 +00:00
if ( fes - > is ( IfcSchema : : Type : : IfcOpeningElement ) ) {
2015-12-05 17:14:10 +01:00
if ( ! fes - > hasRepresentation ( ) ) continue ;
2012-06-07 14:38:21 +00:00
// Convert the IfcRepresentation of the IfcOpeningElement
gp_Trsf opening_trsf ;
2015-12-05 17:14:10 +01:00
if ( fes - > hasObjectPlacement ( ) ) {
try {
convert ( fes - > ObjectPlacement ( ) , opening_trsf ) ;
} catch ( . . . ) { }
}
2012-06-07 14:38:21 +00:00
// Move the opening into the coordinate system of the IfcProduct
opening_trsf . PreMultiply ( entity_trsf . Inverted ( ) ) ;
2014-05-04 14:42:55 +00:00
IfcSchema : : IfcProductRepresentation * prodrep = fes - > Representation ( ) ;
IfcSchema : : IfcRepresentation : : list : : ptr reps = prodrep - > Representations ( ) ;
2012-06-07 14:38:21 +00:00
2013-05-05 08:49:25 +00:00
IfcGeom : : IfcRepresentationShapeItems opening_shapes ;
2012-06-07 14:38:21 +00:00
2014-05-04 14:42:55 +00:00
for ( IfcSchema : : IfcRepresentation : : list : : it it2 = reps - > begin ( ) ; it2 ! = reps - > end ( ) ; + + it2 ) {
2014-12-19 12:14:36 +00:00
convert_shapes ( * it2 , opening_shapes ) ;
2012-06-07 14:38:21 +00:00
}
for ( unsigned int i = 0 ; i < opening_shapes . size ( ) ; + + i ) {
2013-05-05 08:49:25 +00:00
gp_GTrsf gtrsf = opening_shapes [ i ] . Placement ( ) ;
2012-06-07 14:38:21 +00:00
gtrsf . PreMultiply ( opening_trsf ) ;
const TopoDS_Shape & opening_shape = gtrsf . Form ( ) = = gp_Other
2013-05-05 08:49:25 +00:00
? BRepBuilderAPI_GTransform ( opening_shapes [ i ] . Shape ( ) , gtrsf , true ) . Shape ( )
: ( opening_shapes [ i ] . Shape ( ) ) . Moved ( gtrsf . Trsf ( ) ) ;
2012-06-07 14:38:21 +00:00
builder . Add ( opening_compound , opening_shape ) ;
}
}
}
// Iterate over the shapes of the IfcProduct
2013-05-05 08:49:25 +00:00
for ( IfcGeom : : IfcRepresentationShapeItems : : const_iterator it3 = entity_shapes . begin ( ) ; it3 ! = entity_shapes . end ( ) ; + + it3 ) {
2012-06-07 14:38:21 +00:00
TopoDS_Shape entity_shape_solid ;
2014-12-19 12:14:36 +00:00
const TopoDS_Shape & entity_shape_unlocated = ensure_fit_for_subtraction ( it3 - > Shape ( ) , entity_shape_solid ) ;
2013-05-05 08:49:25 +00:00
const gp_GTrsf & entity_shape_gtrsf = it3 - > Placement ( ) ;
2012-06-07 14:38:21 +00:00
TopoDS_Shape entity_shape ;
if ( entity_shape_gtrsf . Form ( ) = = gp_Other ) {
2012-08-11 13:24:08 +00:00
Logger : : Message ( Logger : : LOG_WARNING , " Applying non uniform transformation to: " , entity - > entity ) ;
2012-06-07 14:38:21 +00:00
entity_shape = BRepBuilderAPI_GTransform ( entity_shape_unlocated , entity_shape_gtrsf , true ) . Shape ( ) ;
} else {
entity_shape = entity_shape_unlocated . Moved ( entity_shape_gtrsf . Trsf ( ) ) ;
}
BRepAlgoAPI_Cut brep_cut ( entity_shape , opening_compound ) ;
2016-01-25 13:30:33 +01:00
bool is_valid = false ;
if ( brep_cut . IsDone ( ) ) {
TopoDS_Shape brep_cut_result = brep_cut ;
BRepCheck_Analyzer analyser ( brep_cut_result ) ;
is_valid = analyser . IsValid ( ) ! = 0 ;
if ( is_valid ) {
cut_shapes . push_back ( IfcGeom : : IfcRepresentationShapeItem ( brep_cut_result , & it3 - > Style ( ) ) ) ;
}
}
if ( ! is_valid ) {
// Apparently processing the boolean operation failed or resulted in an invalid result
// in which case the original shape without the subtractions is returned instead
// we try convert the openings in the original way, one by one.
Logger : : Message ( Logger : : LOG_WARNING , " Subtracting combined openings compound failed: " , entity - > entity ) ;
return false ;
}
}
return true ;
}
2016-01-22 17:27:28 +01:00
# else
2016-01-25 13:30:33 +01:00
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 ) {
TopTools_ListOfShape opening_shapelist ;
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 ) ) {
if ( ! fes - > hasRepresentation ( ) ) continue ;
// Convert the IfcRepresentation of the IfcOpeningElement
gp_Trsf opening_trsf ;
if ( fes - > hasObjectPlacement ( ) ) {
try {
convert ( fes - > ObjectPlacement ( ) , opening_trsf ) ;
} catch ( . . . ) { }
}
// Move the opening into the coordinate system of the IfcProduct
opening_trsf . PreMultiply ( entity_trsf . Inverted ( ) ) ;
IfcSchema : : IfcProductRepresentation * prodrep = fes - > Representation ( ) ;
IfcSchema : : IfcRepresentation : : list : : ptr reps = prodrep - > Representations ( ) ;
IfcGeom : : IfcRepresentationShapeItems 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 ( ) ) ;
opening_shapelist . Append ( opening_shape ) ;
}
}
}
// 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 = 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 ) {
Logger : : Message ( Logger : : LOG_WARNING , " Applying non uniform transformation to: " , entity - > entity ) ;
entity_shape = BRepBuilderAPI_GTransform ( entity_shape_unlocated , entity_shape_gtrsf , true ) . Shape ( ) ;
} else {
entity_shape = entity_shape_unlocated . Moved ( entity_shape_gtrsf . Trsf ( ) ) ;
}
2016-01-22 17:27:28 +01:00
BRepAlgoAPI_Cut brep_cut ;
TopTools_ListOfShape s1s ;
s1s . Append ( entity_shape ) ;
brep_cut . SetFuzzyValue ( getValue ( GV_PRECISION ) ) ;
brep_cut . SetArguments ( s1s ) ;
2016-01-25 13:30:33 +01:00
brep_cut . SetTools ( opening_shapelist ) ;
2016-01-22 17:27:28 +01:00
brep_cut . Build ( ) ;
2012-06-07 14:38:21 +00:00
bool is_valid = false ;
if ( brep_cut . IsDone ( ) ) {
TopoDS_Shape brep_cut_result = brep_cut ;
BRepCheck_Analyzer analyser ( brep_cut_result ) ;
is_valid = analyser . IsValid ( ) ! = 0 ;
if ( is_valid ) {
2013-05-05 08:49:25 +00:00
cut_shapes . push_back ( IfcGeom : : IfcRepresentationShapeItem ( brep_cut_result , & it3 - > Style ( ) ) ) ;
2012-06-07 14:38:21 +00:00
}
}
if ( ! is_valid ) {
// Apparently processing the boolean operation failed or resulted in an invalid result
// in which case the original shape without the subtractions is returned instead
// we try convert the openings in the original way, one by one.
2016-01-25 13:30:33 +01:00
Logger : : Message ( Logger : : LOG_WARNING , " Subtracting combined openings compound failed: " , entity - > entity ) ;
2012-06-07 14:38:21 +00:00
return false ;
}
}
return true ;
}
2016-01-25 13:30:33 +01:00
# endif
2012-06-07 14:38:21 +00:00
2014-12-19 12:14:36 +00:00
bool IfcGeom : : Kernel : : convert_wire_to_face ( const TopoDS_Wire & wire , TopoDS_Face & face ) {
2011-07-25 14:56:40 +00:00
BRepBuilderAPI_MakeFace mf ( wire , false ) ;
BRepBuilderAPI_FaceError er = mf . Error ( ) ;
if ( er = = BRepBuilderAPI_NotPlanar ) {
ShapeFix_ShapeTolerance FTol ;
FTol . SetTolerance ( wire , 0.01 , TopAbs_WIRE ) ;
2011-08-30 15:49:08 +00:00
mf . ~ BRepBuilderAPI_MakeFace ( ) ;
new ( & mf ) BRepBuilderAPI_MakeFace ( wire ) ;
2011-07-25 14:56:40 +00:00
er = mf . Error ( ) ;
}
if ( er ! = BRepBuilderAPI_FaceDone ) return false ;
face = mf . Face ( ) ;
return true ;
}
2014-03-15 11:51:23 +00:00
2014-12-19 12:14:36 +00:00
bool IfcGeom : : Kernel : : convert_curve_to_wire ( const Handle ( Geom_Curve ) & curve , TopoDS_Wire & wire ) {
2015-04-22 09:15:48 +00:00
try {
wire = BRepBuilderAPI_MakeWire ( BRepBuilderAPI_MakeEdge ( curve ) ) ;
} catch ( . . . ) { return false ; }
2014-03-15 11:51:23 +00:00
return true ;
}
2014-12-19 12:14:36 +00:00
bool IfcGeom : : Kernel : : profile_helper ( int numVerts , double * verts , int numFillets , int * filletIndices , double * filletRadii , gp_Trsf2d trsf , TopoDS_Shape & face_shape ) {
2011-07-25 14:56:40 +00:00
TopoDS_Vertex * vertices = new TopoDS_Vertex [ numVerts ] ;
for ( int i = 0 ; i < numVerts ; i + + ) {
gp_XY xy ( verts [ 2 * i ] , verts [ 2 * i + 1 ] ) ;
trsf . Transforms ( xy ) ;
vertices [ i ] = BRepBuilderAPI_MakeVertex ( gp_Pnt ( xy . X ( ) , xy . Y ( ) , 0.0f ) ) ;
}
BRepBuilderAPI_MakeWire w ;
for ( int i = 0 ; i < numVerts ; i + + )
w . Add ( BRepBuilderAPI_MakeEdge ( vertices [ i ] , vertices [ ( i + 1 ) % numVerts ] ) ) ;
2014-03-16 13:34:01 +00:00
TopoDS_Face face ;
2014-12-19 12:14:36 +00:00
convert_wire_to_face ( w . Wire ( ) , face ) ;
2011-07-25 14:56:40 +00:00
2014-07-24 11:14:54 +00:00
if ( numFillets & & * std : : max_element ( filletRadii , filletRadii + numFillets ) > ALMOST_ZERO ) {
2011-07-25 14:56:40 +00:00
BRepFilletAPI_MakeFillet2d fillet ( face ) ;
for ( int i = 0 ; i < numFillets ; i + + ) {
2012-03-13 11:56:52 +00:00
const double radius = filletRadii [ i ] ;
2014-07-24 11:14:54 +00:00
if ( radius < = ALMOST_ZERO ) continue ;
2011-07-25 14:56:40 +00:00
fillet . AddFillet ( vertices [ filletIndices [ i ] ] , radius ) ;
}
fillet . Build ( ) ;
2014-07-24 11:14:54 +00:00
if ( fillet . IsDone ( ) ) {
face = TopoDS : : Face ( fillet . Shape ( ) ) ;
} else {
Logger : : Message ( Logger : : LOG_WARNING , " Failed to process profile fillets " ) ;
}
2011-07-25 14:56:40 +00:00
}
2014-03-16 13:34:01 +00:00
face_shape = face ;
2011-07-25 14:56:40 +00:00
delete [ ] vertices ;
return true ;
2011-10-12 16:43:29 +00:00
}
2014-12-19 12:14:36 +00:00
double IfcGeom : : Kernel : : shape_volume ( const TopoDS_Shape & s ) {
2012-04-07 14:34:44 +00:00
GProp_GProps prop ;
BRepGProp : : VolumeProperties ( s , prop ) ;
return prop . Mass ( ) ;
}
2014-12-19 12:14:36 +00:00
double IfcGeom : : Kernel : : face_area ( const TopoDS_Face & f ) {
2012-04-07 14:34:44 +00:00
GProp_GProps prop ;
BRepGProp : : SurfaceProperties ( f , prop ) ;
return prop . Mass ( ) ;
2012-03-13 11:56:52 +00:00
}
2014-12-19 12:14:36 +00:00
bool IfcGeom : : Kernel : : is_convex ( const TopoDS_Wire & wire ) {
2012-03-13 11:56:52 +00:00
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 ) ;
// Store the neighboring points
std : : vector < gp_Pnt > neighbors ;
for ( TopExp_Explorer exp3 ( wire , TopAbs_EDGE ) ; exp3 . More ( ) ; exp3 . Next ( ) ) {
TopoDS_Edge edge = TopoDS : : Edge ( exp3 . Current ( ) ) ;
std : : vector < gp_Pnt > edge_points ;
for ( TopExp_Explorer exp2 ( edge , TopAbs_VERTEX ) ; exp2 . More ( ) ; exp2 . Next ( ) ) {
TopoDS_Vertex V2 = TopoDS : : Vertex ( exp2 . Current ( ) ) ;
gp_Pnt P2 = BRep_Tool : : Pnt ( V2 ) ;
edge_points . push_back ( P2 ) ;
}
if ( edge_points . size ( ) ! = 2 ) continue ;
2014-12-19 12:14:36 +00:00
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 ] ) ;
2012-03-13 11:56:52 +00:00
}
// There should be two of these
if ( neighbors . size ( ) ! = 2 ) return false ;
// Now find the non neighboring points
std : : vector < gp_Pnt > non_neighbors ;
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 ) ;
2014-12-19 12:14:36 +00:00
if ( P1 . IsEqual ( P2 , getValue ( GV_POINT_EQUALITY_TOLERANCE ) ) ) continue ;
2012-03-13 11:56:52 +00:00
bool found = false ;
for ( std : : vector < gp_Pnt > : : const_iterator it = neighbors . begin ( ) ; it ! = neighbors . end ( ) ; + + it ) {
2014-12-19 12:14:36 +00:00
if ( ( * it ) . IsEqual ( P2 , getValue ( GV_POINT_EQUALITY_TOLERANCE ) ) ) { found = true ; break ; }
2012-03-13 11:56:52 +00:00
}
if ( ! found ) non_neighbors . push_back ( P2 ) ;
}
// Calculate the angle between the two edges of the vertex
gp_Dir dir1 ( neighbors [ 0 ] . XYZ ( ) - P1 . XYZ ( ) ) ;
gp_Dir dir2 ( neighbors [ 1 ] . XYZ ( ) - P1 . XYZ ( ) ) ;
const double angle = acos ( dir1 . Dot ( dir2 ) ) + 0.0001 ;
// Now for the non-neighbors see whether a greater angle can be found with one of the edges
for ( std : : vector < gp_Pnt > : : const_iterator it = non_neighbors . begin ( ) ; it ! = non_neighbors . end ( ) ; + + it ) {
gp_Dir dir3 ( ( * it ) . XYZ ( ) - P1 . XYZ ( ) ) ;
const double angle2 = acos ( dir3 . Dot ( dir1 ) ) ;
const double angle3 = acos ( dir3 . Dot ( dir2 ) ) ;
if ( angle2 > angle | | angle3 > angle ) return false ;
}
}
return true ;
}
2014-12-19 12:14:36 +00:00
TopoDS_Shape IfcGeom : : Kernel : : halfspace_from_plane ( const gp_Pln & pln , const gp_Pnt & cent ) {
2012-03-13 11:56:52 +00:00
TopoDS_Face face = BRepBuilderAPI_MakeFace ( pln ) . Face ( ) ;
return BRepPrimAPI_MakeHalfSpace ( face , cent ) . Solid ( ) ;
}
2014-12-19 12:14:36 +00:00
gp_Pln IfcGeom : : Kernel : : plane_from_face ( const TopoDS_Face & face ) {
2012-03-13 11:56:52 +00:00
BRepGProp_Face prop ( face ) ;
Standard_Real u1 , u2 , v1 , v2 ;
prop . Bounds ( u1 , u2 , v1 , v2 ) ;
Standard_Real u = ( u1 + u2 ) / 2.0 ;
Standard_Real v = ( v1 + v2 ) / 2.0 ;
gp_Pnt p ;
gp_Vec n ;
prop . Normal ( u , v , p , n ) ;
return gp_Pln ( p , n ) ;
}
2014-12-19 12:14:36 +00:00
gp_Pnt IfcGeom : : Kernel : : point_above_plane ( const gp_Pln & pln , bool agree ) {
2012-03-13 11:56:52 +00:00
if ( agree ) {
return pln . Location ( ) . Translated ( pln . Axis ( ) . Direction ( ) ) ;
} else {
return pln . Location ( ) . Translated ( - pln . Axis ( ) . Direction ( ) ) ;
}
2012-06-25 15:08:58 +00:00
}
2014-12-19 12:14:36 +00:00
void IfcGeom : : Kernel : : apply_tolerance ( TopoDS_Shape & s , double t ) {
2013-11-24 15:44:27 +00:00
ShapeFix_ShapeTolerance tol ;
tol . SetTolerance ( s , t ) ;
}
2012-06-25 15:08:58 +00:00
static double deflection_tolerance = 0.001 ;
static double wire_creation_tolerance = 0.0001 ;
static double minimal_face_area = 0.000001 ;
static double point_equality_tolerance = 0.00001 ;
2012-08-11 13:24:08 +00:00
static double max_faces_to_sew = - 1.0 ;
static double ifc_length_unit = 1.0 ;
static double ifc_planeangle_unit = - 1.0 ;
2013-11-24 15:44:27 +00:00
static double modelling_precision = 0.00001 ;
2015-04-22 09:15:48 +00:00
static double dimensionality = 1 ;
2012-06-25 15:08:58 +00:00
2014-12-19 12:14:36 +00:00
void IfcGeom : : Kernel : : setValue ( GeomValue var , double value ) {
2012-06-25 15:08:58 +00:00
switch ( var ) {
case GV_DEFLECTION_TOLERANCE :
deflection_tolerance = value ;
2012-06-27 15:59:09 +00:00
break ;
2012-06-25 15:08:58 +00:00
case GV_WIRE_CREATION_TOLERANCE :
wire_creation_tolerance = value ;
2012-06-27 15:59:09 +00:00
break ;
2012-06-25 15:08:58 +00:00
case GV_MINIMAL_FACE_AREA :
minimal_face_area = value ;
2012-06-27 15:59:09 +00:00
break ;
2012-06-25 15:08:58 +00:00
case GV_POINT_EQUALITY_TOLERANCE :
point_equality_tolerance = value ;
2012-06-27 15:59:09 +00:00
break ;
2012-06-25 15:08:58 +00:00
case GV_MAX_FACES_TO_SEW :
max_faces_to_sew = value ;
2012-06-27 15:59:09 +00:00
break ;
2012-08-11 13:24:08 +00:00
case GV_LENGTH_UNIT :
ifc_length_unit = value ;
break ;
case GV_PLANEANGLE_UNIT :
ifc_planeangle_unit = value ;
break ;
2013-11-24 15:44:27 +00:00
case GV_PRECISION :
modelling_precision = value ;
break ;
2015-04-22 09:15:48 +00:00
case GV_DIMENSIONALITY :
dimensionality = value ;
break ;
2012-06-27 15:59:09 +00:00
default :
assert ( ! " never reach here " ) ;
2012-06-25 15:08:58 +00:00
}
}
2015-10-07 16:13:25 +02:00
double IfcGeom : : Kernel : : getValue ( GeomValue var ) const {
2012-06-25 15:08:58 +00:00
switch ( var ) {
case GV_DEFLECTION_TOLERANCE :
return deflection_tolerance ;
case GV_WIRE_CREATION_TOLERANCE :
return wire_creation_tolerance ;
case GV_MINIMAL_FACE_AREA :
return minimal_face_area ;
case GV_POINT_EQUALITY_TOLERANCE :
return point_equality_tolerance ;
case GV_MAX_FACES_TO_SEW :
return max_faces_to_sew ;
2012-08-11 13:24:08 +00:00
case GV_LENGTH_UNIT :
return ifc_length_unit ;
break ;
case GV_PLANEANGLE_UNIT :
return ifc_planeangle_unit ;
break ;
2013-11-24 15:44:27 +00:00
case GV_PRECISION :
return modelling_precision ;
break ;
2015-04-22 09:15:48 +00:00
case GV_DIMENSIONALITY :
return dimensionality ;
break ;
2012-06-25 15:08:58 +00:00
}
assert ( ! " never reach here " ) ;
return 0 ;
2012-11-04 16:26:33 +00:00
}
2015-01-06 10:19:24 +00:00
IfcSchema : : IfcProductDefinitionShape * IfcGeom : : tesselate ( TopoDS_Shape & shape , double deflection , IfcEntityList : : ptr es ) {
2015-01-19 16:02:34 +00:00
BRepMesh_IncrementalMesh ( shape , deflection ) ;
2012-11-04 16:26:33 +00:00
2014-05-04 14:42:55 +00:00
IfcSchema : : IfcFace : : list : : ptr faces ( new IfcSchema : : IfcFace : : list ) ;
2012-11-04 16:26:33 +00:00
for ( TopExp_Explorer exp ( shape , TopAbs_FACE ) ; exp . More ( ) ; exp . Next ( ) ) {
const TopoDS_Face & face = TopoDS : : Face ( exp . Current ( ) ) ;
TopLoc_Location loc ;
Handle ( Poly_Triangulation ) tri = BRep_Tool : : Triangulation ( face , loc ) ;
if ( ! tri . IsNull ( ) ) {
const TColgp_Array1OfPnt & nodes = tri - > Nodes ( ) ;
2014-02-17 22:13:55 +00:00
std : : vector < IfcSchema : : IfcCartesianPoint * > vertices ;
2012-11-04 16:26:33 +00:00
for ( int i = 1 ; i < = nodes . Length ( ) ; + + i ) {
2014-03-22 21:13:02 +00:00
gp_Pnt pnt = nodes ( i ) . Transformed ( loc ) ;
2012-11-04 16:26:33 +00:00
std : : vector < double > xyz ; xyz . push_back ( pnt . X ( ) ) ; xyz . push_back ( pnt . Y ( ) ) ; xyz . push_back ( pnt . Z ( ) ) ;
2014-02-17 22:13:55 +00:00
IfcSchema : : IfcCartesianPoint * cpnt = new IfcSchema : : IfcCartesianPoint ( xyz ) ;
2012-11-04 16:26:33 +00:00
vertices . push_back ( cpnt ) ;
es - > push ( cpnt ) ;
}
const Poly_Array1OfTriangle & triangles = tri - > Triangles ( ) ;
for ( int i = 1 ; i < = triangles . Length ( ) ; + + i ) {
int n1 , n2 , n3 ;
triangles ( i ) . Get ( n1 , n2 , n3 ) ;
2014-05-04 14:42:55 +00:00
IfcSchema : : IfcCartesianPoint : : list : : ptr points ( new IfcSchema : : IfcCartesianPoint : : list ) ;
2012-11-04 16:26:33 +00:00
points - > push ( vertices [ n1 - 1 ] ) ;
points - > push ( vertices [ n2 - 1 ] ) ;
points - > push ( vertices [ n3 - 1 ] ) ;
2014-02-17 22:13:55 +00:00
IfcSchema : : IfcPolyLoop * loop = new IfcSchema : : IfcPolyLoop ( points ) ;
IfcSchema : : IfcFaceOuterBound * bound = new IfcSchema : : IfcFaceOuterBound ( loop , face . Orientation ( ) ! = TopAbs_REVERSED ) ;
2014-05-04 14:42:55 +00:00
IfcSchema : : IfcFaceBound : : list : : ptr bounds ( new IfcSchema : : IfcFaceBound : : list ) ;
2012-11-04 16:26:33 +00:00
bounds - > push ( bound ) ;
2015-11-21 23:05:28 +02:00
IfcSchema : : IfcFace * face2 = new IfcSchema : : IfcFace ( bounds ) ;
2012-11-04 16:26:33 +00:00
es - > push ( loop ) ;
es - > push ( bound ) ;
2015-11-21 23:05:28 +02:00
es - > push ( face2 ) ;
faces - > push ( face2 ) ;
2012-11-04 16:26:33 +00:00
}
}
}
2014-02-17 22:13:55 +00:00
IfcSchema : : IfcOpenShell * shell = new IfcSchema : : IfcOpenShell ( faces ) ;
2014-05-04 14:42:55 +00:00
IfcSchema : : IfcConnectedFaceSet : : list : : ptr shells ( new IfcSchema : : IfcConnectedFaceSet : : list ) ;
2012-11-04 16:26:33 +00:00
shells - > push ( shell ) ;
2014-02-17 22:13:55 +00:00
IfcSchema : : IfcFaceBasedSurfaceModel * surface_model = new IfcSchema : : IfcFaceBasedSurfaceModel ( shells ) ;
2012-11-04 16:26:33 +00:00
2014-05-04 14:42:55 +00:00
IfcSchema : : IfcRepresentation : : list : : ptr reps ( new IfcSchema : : IfcRepresentation : : list ) ;
IfcSchema : : IfcRepresentationItem : : list : : ptr items ( new IfcSchema : : IfcRepresentationItem : : list ) ;
2012-11-04 16:26:33 +00:00
items - > push ( surface_model ) ;
2014-02-17 22:13:55 +00:00
IfcSchema : : IfcShapeRepresentation * rep = new IfcSchema : : IfcShapeRepresentation (
2012-11-04 16:26:33 +00:00
0 , std : : string ( " Facetation " ) , std : : string ( " SurfaceModel " ) , items ) ;
reps - > push ( rep ) ;
2015-07-09 13:23:40 +00:00
IfcSchema : : IfcProductDefinitionShape * shapedef = new IfcSchema : : IfcProductDefinitionShape ( boost : : none , boost : : none , reps ) ;
2012-11-04 16:26:33 +00:00
es - > push ( shell ) ;
es - > push ( surface_model ) ;
es - > push ( rep ) ;
es - > push ( shapedef ) ;
return shapedef ;
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
2014-03-22 10:31:51 +00:00
}
// 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 ( ) ;
}
2014-03-31 14:00:02 +00:00
return TopoDS_Vertex ( ) ;
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
2014-03-22 10:31:51 +00:00
}
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 ;
}
}
2014-03-31 14:00:02 +00:00
return TopoDS_Edge ( ) ;
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
2014-03-22 10:31:51 +00:00
}
2014-12-19 12:14:36 +00:00
bool IfcGeom : : Kernel : : fill_nonmanifold_wires_with_planar_faces ( TopoDS_Shape & shape ) {
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
2014-03-22 10:31:51 +00:00
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 ) ) ;
// 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 ;
2015-11-21 23:05:28 +02:00
for ( ; ; ) {
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
2014-03-22 10:31:51 +00:00
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 ) ;
2014-03-31 14:00:02 +00:00
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 ) ;
}
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
2014-03-22 10:31:51 +00:00
// 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 ;
2014-12-19 12:14:36 +00:00
solid . LimitTolerance ( getValue ( GV_POINT_EQUALITY_TOLERANCE ) ) ;
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
2014-03-22 10:31:51 +00:00
shape = solid . SolidFromShell ( TopoDS : : Shell ( shape ) ) ;
} catch ( . . . ) { }
return true ;
2014-07-06 14:21:56 +00:00
}
2014-12-19 12:14:36 +00:00
bool IfcGeom : : Kernel : : flatten_shape_list ( const IfcGeom : : IfcRepresentationShapeItems & shapes , TopoDS_Shape & result , bool fuse ) {
2014-07-06 14:21:56 +00:00
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 ) {
2014-12-19 12:14:36 +00:00
ensure_fit_for_subtraction ( s , merged ) ;
2014-07-06 14:21:56 +00:00
} else {
merged = s ;
}
const gp_GTrsf & trsf = it - > Placement ( ) ;
bool trsf_valid = false ;
gp_Trsf _trsf ;
try {
_trsf = trsf . Trsf ( ) ;
trsf_valid = true ;
} catch ( . . . ) { }
2015-10-07 16:14:34 +02:00
const TopoDS_Shape moved_shape = trsf . Form ( ) = = gp_Identity
? merged
: (
trsf_valid
? merged . Moved ( _trsf )
: BRepBuilderAPI_GTransform ( merged , trsf , true ) . Shape ( )
) ;
2014-07-06 14:21:56 +00:00
if ( shapes . size ( ) = = 1 ) {
result = moved_shape ;
2015-02-06 17:14:05 +00:00
const double precision = getValue ( GV_PRECISION ) ;
apply_tolerance ( result , precision ) ;
2014-07-06 14:21:56 +00:00
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 ) ;
}
}
2015-10-07 16:14:34 +02:00
if ( ! fuse ) {
result = compound ;
}
2015-02-06 17:14:05 +00:00
const bool success = ! result . IsNull ( ) ;
if ( success ) {
const double precision = getValue ( GV_PRECISION ) ;
apply_tolerance ( result , precision ) ;
}
return success ;
2014-07-06 14:21:56 +00:00
}
2014-07-28 20:03:53 +00:00
2016-01-22 17:27:28 +01:00
void IfcGeom : : Kernel : : remove_duplicate_points_from_loop ( TColgp_SequenceOfPnt & polygon , bool closed , double tol ) {
2014-12-19 12:14:36 +00:00
if ( tol < = 0. ) tol = getValue ( GV_POINT_EQUALITY_TOLERANCE ) ;
2014-07-28 20:03:53 +00:00
tol * = tol ;
2015-11-21 23:05:28 +02:00
for ( ; ; ) {
2014-07-28 20:03:53 +00:00
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 ;
}
2015-01-05 14:11:42 +00:00
}
2016-01-22 17:27:28 +01:00
void IfcGeom : : Kernel : : remove_collinear_points_from_loop ( TColgp_SequenceOfPnt & polygon , bool closed , double tol ) {
if ( tol < = 0. ) tol = getValue ( GV_POINT_EQUALITY_TOLERANCE ) ;
const int start = closed ? 1 : 2 ;
const int end = polygon . Length ( ) - ( closed ? 0 : 1 ) ;
std : : vector < bool > to_remove ( polygon . Length ( ) , false ) ;
for ( int i = start ; i < = end ; + + i ) {
const gp_Pnt & a = polygon . Value ( ( ( i - 2 + polygon . Length ( ) ) % polygon . Length ( ) ) + 1 ) ;
const gp_Pnt & b = polygon . Value ( i ) ;
const gp_Pnt & c = polygon . Value ( ( i % polygon . Length ( ) ) + 1 ) ;
const gp_Vec d1 = c . XYZ ( ) - a . XYZ ( ) ;
const gp_Vec d2 = b . XYZ ( ) - a . XYZ ( ) ;
const double dt = d2 . Dot ( d1 ) / d1 . Dot ( d1 ) ;
const gp_Vec d3 = d1 . Scaled ( dt ) ;
const gp_Pnt b2 = a . XYZ ( ) + d3 . XYZ ( ) ;
if ( b . Distance ( b2 ) < tol ) {
to_remove [ i - 1 ] = true ;
}
}
2016-01-25 13:30:33 +01:00
for ( int i = ( int ) to_remove . size ( ) - 1 ; i > = 0 ; - - i ) {
2016-01-22 17:27:28 +01:00
if ( to_remove [ i ] ) {
polygon . Remove ( i + 1 ) ;
}
}
}
bool IfcGeom : : Kernel : : wire_to_sequence_of_point ( const TopoDS_Wire & w , TColgp_SequenceOfPnt & p ) {
TopExp_Explorer exp ( w , TopAbs_EDGE ) ;
for ( ; exp . More ( ) ; exp . Next ( ) ) {
double a , b ;
Handle_Geom_Curve crv = BRep_Tool : : Curve ( TopoDS : : Edge ( exp . Current ( ) ) , a , b ) ;
if ( crv - > DynamicType ( ) ! = STANDARD_TYPE ( Geom_Line ) ) {
return false ;
}
}
exp . ReInit ( ) ;
int i = 0 ;
for ( ; exp . More ( ) ; exp . Next ( ) , + + i ) {
TopoDS_Vertex v1 , v2 ;
TopExp : : Vertices ( TopoDS : : Edge ( exp . Current ( ) ) , v1 , v2 , true ) ;
if ( exp . More ( ) ) {
if ( i = = 0 ) {
p . Append ( BRep_Tool : : Pnt ( v1 ) ) ;
}
p . Append ( BRep_Tool : : Pnt ( v2 ) ) ;
}
}
return true ;
}
void IfcGeom : : Kernel : : sequence_of_point_to_wire ( const TColgp_SequenceOfPnt & p , TopoDS_Wire & w , bool close ) {
BRepBuilderAPI_MakePolygon builder ;
for ( int i = 1 ; i < = p . Length ( ) ; + + i ) {
builder . Add ( p . Value ( i ) ) ;
}
if ( close ) {
builder . Close ( ) ;
}
w = builder . Wire ( ) ;
}
2015-01-05 14:11:42 +00:00
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 - > hasName ( ) ? product - > Name ( ) : " " ;
const std : : string guid = product - > GlobalId ( ) ;
gp_Trsf trsf ;
try {
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 ) ;
2015-01-10 22:13:52 +00:00
if ( ! settings . disable_opening_subtractions ( ) & & openings & & openings - > size ( ) ) {
2015-01-05 14:11:42 +00:00
IfcGeom : : IfcRepresentationShapeItems opened_shapes ;
try {
2016-01-25 13:30:33 +01:00
# if OCC_VERSION_HEX < 0x60900
const bool faster_booleans = settings . faster_booleans ( ) ;
# else
const bool faster_booleans = true ;
# endif
if ( faster_booleans ) {
2015-01-05 14:11:42 +00:00
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 ) ;
}
2015-04-22 09:15:48 +00:00
std : : string context_string = " " ;
if ( representation - > hasRepresentationIdentifier ( ) ) {
context_string = representation - > RepresentationIdentifier ( ) ;
} else if ( representation - > ContextOfItems ( ) - > hasContextType ( ) ) {
context_string = representation - > ContextOfItems ( ) - > ContextType ( ) ;
}
2015-01-05 14:11:42 +00:00
return new BRepElement < P > (
product - > entity - > id ( ) ,
parent_id ,
name ,
product_type ,
guid ,
2015-04-22 09:15:48 +00:00
context_string ,
2015-01-05 14:11:42 +00:00
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 ( ) ;
2015-01-10 22:13:52 +00:00
if ( voids - > size ( ) ) {
2015-01-05 14:11:42 +00:00
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
2015-01-10 22:13:52 +00:00
if ( fills - > size ( ) ) {
2015-01-05 14:11:42 +00:00
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 ( ) ;
2015-01-10 22:13:52 +00:00
if ( parents - > size ( ) ) {
2015-01-05 14:11:42 +00:00
IfcSchema : : IfcRelContainedInSpatialStructure * container = * parents - > begin ( ) ;
parent = container - > RelatingStructure ( ) ;
}
}
}
// Parent decompositions to the RelatingObject
if ( ! parent ) {
2015-01-10 22:13:52 +00:00
IfcEntityList : : ptr parents = product - > entity - > getInverse ( IfcSchema : : Type : : IfcRelAggregates , - 1 ) ;
parents - > push ( product - > entity - > getInverse ( IfcSchema : : Type : : IfcRelNests , - 1 ) ) ;
2015-01-05 14:11:42 +00:00
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 ( ) ;
2015-01-10 22:13:52 +00:00
if ( ! units | | ! units - > size ( ) ) {
2015-01-05 14:11:42 +00:00
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 - > hasPrefix ( ) ) {
2015-02-17 19:48:41 +00:00
value * = IfcParse : : IfcSIPrefixToValue ( unit - > Prefix ( ) ) ;
2015-01-05 14:11:42 +00:00
}
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 - > hasPrefix ( ) ) {
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 ) ;
2016-01-22 17:27:28 +01:00
}
const IfcSchema : : IfcRepresentationItem * IfcGeom : : Kernel : : find_item_carrying_style ( const IfcSchema : : IfcRepresentationItem * item ) {
2016-02-03 22:34:50 +02:00
if ( item - > StyledByItem ( ) - > size ( ) ) {
2016-01-22 17:27:28 +01:00
return item ;
}
while ( item - > is ( IfcSchema : : Type : : IfcBooleanClippingResult ) ) {
// All instantiations of IfcBooleanOperand (type of FirstOperand) are subtypes of
// IfcGeometricRepresentationItem
item = ( IfcSchema : : IfcGeometricRepresentationItem * ) ( ( IfcSchema : : IfcBooleanClippingResult * ) item ) - > FirstOperand ( ) ;
2016-02-03 22:34:50 +02:00
if ( item - > StyledByItem ( ) - > size ( ) ) {
2016-01-22 17:27:28 +01:00
return item ;
}
}
// TODO: Ideally this would be done for other entities (such as IfcCsgSolid) as well.
// But neither are these very prevalent, nor does the current IfcOpenShell style
// mechanism enable to conveniently style subshapes, which would be necessary for
// distinctly styled union operands.
return item ;
2016-02-03 22:34:50 +02:00
}