From bd79df2be7fa686aaee66b929c10ba7bb7c4261c Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 23 Oct 2011 17:11:06 +0000 Subject: [PATCH] - Make distinction between single shape and list of shapes - Store shapes in std::vectors rather than TopoDS_Compounds - Apply transformation only on triangulated meshes or when processing openings - Store transformations in a gp_GTrsf to allow arbitrary transformations - Support IfcCartesianTransformationOperator3DnonUniform - TODO: Create proper class for ShapeList - TODO: Carefully check for null pointers returned from IfcGeom::convert_shape() --- src/ifcgeom/IfcGeom.h | 13 +- src/ifcgeom/IfcGeomCurves.cpp | 5 +- src/ifcgeom/IfcGeomFaces.cpp | 5 +- src/ifcgeom/IfcGeomFunctions.cpp | 96 ++++++++--- src/ifcgeom/IfcGeomHelpers.cpp | 51 +++++- src/ifcgeom/IfcGeomObjects.cpp | 183 ++++++++++++--------- src/ifcgeom/IfcGeomObjects.h | 13 +- src/ifcgeom/IfcGeomShapes.cpp | 100 +++++------ src/ifcgeom/IfcGeomWires.cpp | 7 +- src/ifcgeom/IfcRegister.cpp | 19 ++- src/ifcgeom/IfcRegister.h | 17 +- src/ifcgeom/IfcRegisterConvertShape.h | 4 +- src/ifcgeom/IfcRegisterConvertShapes.h | 8 + src/ifcgeom/IfcRegisterDef.h | 3 + src/ifcgeom/IfcRegisterGeomHeader.h | 1 + src/ifcgeom/IfcRegisterIsShapeCollection.h | 6 + src/ifcgeom/IfcRegisterUndef.h | 3 + 17 files changed, 360 insertions(+), 174 deletions(-) create mode 100644 src/ifcgeom/IfcRegisterConvertShapes.h create mode 100644 src/ifcgeom/IfcRegisterIsShapeCollection.h diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index 540c9fd2ae..322d0c2bfd 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -25,6 +25,10 @@ #include #include +#include +#include +#include +#include #include #include #include @@ -37,12 +41,17 @@ #include "../ifcparse/IfcUtil.h" namespace IfcGeom { + typedef std::pair LocationShape; + typedef std::vector ShapeList; + bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face); - bool convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result); + bool convert_shapes(const IfcUtil::IfcBaseClass* L, ShapeList& result); + bool is_shape_collection(const IfcUtil::IfcBaseClass* L); + const TopoDS_Shape* convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result); 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 L, const Ifc2x3::IfcRelVoidsElement::list& openings, TopoDS_Shape& result, const gp_Trsf& trsf); + bool convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings, const ShapeList& entity_shapes, const gp_Trsf& entity_trsf, ShapeList& cut_shapes); bool profile_helper(int numVerts, float* verts, int numFillets, int* filletIndices, float* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face); float shape_volume(const TopoDS_Shape& s); namespace Cache { diff --git a/src/ifcgeom/IfcGeomCurves.cpp b/src/ifcgeom/IfcGeomCurves.cpp index dc1da4dd80..1cf182cd21 100644 --- a/src/ifcgeom/IfcGeomCurves.cpp +++ b/src/ifcgeom/IfcGeomCurves.cpp @@ -29,9 +29,12 @@ #include #include #include +#include +#include +#include +#include #include #include -#include #include #include #include diff --git a/src/ifcgeom/IfcGeomFaces.cpp b/src/ifcgeom/IfcGeomFaces.cpp index eb0b803942..fe3037e2d2 100644 --- a/src/ifcgeom/IfcGeomFaces.cpp +++ b/src/ifcgeom/IfcGeomFaces.cpp @@ -31,9 +31,12 @@ #include #include #include +#include +#include +#include +#include #include #include -#include #include #include #include diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 4497e9e327..8f56bda120 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -29,9 +29,12 @@ #include #include #include +#include +#include +#include +#include #include #include -#include #include #include #include @@ -75,37 +78,86 @@ #include #include +#include + #include "../ifcgeom/IfcGeom.h" -bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, - const Ifc2x3::IfcRelVoidsElement::list& openings, TopoDS_Shape& result, const gp_Trsf& trsf2) { +bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings, + const ShapeList& entity_shapes, const gp_Trsf& entity_trsf, ShapeList& cut_shapes) { + // Iterate over IfcOpeningElements + IfcGeom::ShapeList 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) ) { - gp_Trsf trsf; - IfcGeom::convert(fes->ObjectPlacement(),trsf); - trsf.PreMultiply(trsf2.Inverted()); + + // Convert the IfcRepresentation of the IfcOpeningElement + gp_Trsf opening_trsf; + IfcGeom::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(); - if ( prodrep->is(Ifc2x3::Type::IfcProductDefinitionShape) ) { - Ifc2x3::IfcProductDefinitionShape::ptr pds = reinterpret_pointer_cast(prodrep); - Ifc2x3::IfcRepresentation::list reps = pds->Representations(); - for ( Ifc2x3::IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) { - TopoDS_Shape s; - IfcGeom::convert_shape(*it2,s); - s.Move(trsf); - const float opening_volume = shape_volume(s); - if ( opening_volume <= ALMOST_ZERO ) - Ifc::LogMessage("warning","Empty solid for:",fes->entity); - const float original_shape_volume = shape_volume(result); - result = BRepAlgoAPI_Cut(result,s); - const float volume_after_subtraction = shape_volume(result); - if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) ) - Ifc::LogMessage("warning","Warning subtraction yields unchanged volume:",entity->entity); - } + Ifc2x3::IfcRepresentation::list reps = prodrep->Representations(); + + for ( Ifc2x3::IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) { + IfcGeom::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].first->PreMultiply(opening_trsf); + } + last_size = current_size; } } + + // Iterate over the shapes of the IfcProduct + for ( IfcGeom::ShapeList::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { + const TopoDS_Shape& entity_shape_unlocated = *(it3->second); + const gp_GTrsf& entity_shape_gtrsf = *(it3->first); + TopoDS_Shape entity_shape; + if ( entity_shape_gtrsf.Form() == gp_Other ) { + Ifc::LogMessage("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()); + } + + // Iterate over the shapes of the IfcOpeningElements + for ( IfcGeom::ShapeList::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) { + const TopoDS_Shape& opening_shape_unlocated = *(it4->second); + const gp_GTrsf& opening_shape_gtrsf = *(it4->first); + if ( opening_shape_gtrsf.Form() == gp_Other ) { + Ifc::LogMessage("warning","Applying non uniform transformation to opening of:",entity->entity); + } + 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()); + + const float opening_volume = shape_volume(opening_shape); + if ( opening_volume <= ALMOST_ZERO ) + Ifc::LogMessage("warning","Empty opening for:",entity->entity); + + const float original_shape_volume = shape_volume(entity_shape); + + entity_shape = BRepAlgoAPI_Cut(entity_shape,opening_shape); + + const float volume_after_subtraction = shape_volume(entity_shape); + + if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) ) + Ifc::LogMessage("warning","Warning subtraction yields unchanged volume:",entity->entity); + } + cut_shapes.push_back(IfcGeom::LocationShape(new gp_GTrsf(),new TopoDS_Shape(entity_shape))); + } + + // Delete references to opening transformations, but keep shapes in the cache + for ( IfcGeom::ShapeList::const_iterator it5 = opening_shapes.begin(); it5 != opening_shapes.end(); ++ it5 ) { + delete it5->first; + } + return true; } bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) { diff --git a/src/ifcgeom/IfcGeomHelpers.cpp b/src/ifcgeom/IfcGeomHelpers.cpp index 483dd26c63..13e119d975 100644 --- a/src/ifcgeom/IfcGeomHelpers.cpp +++ b/src/ifcgeom/IfcGeomHelpers.cpp @@ -29,9 +29,12 @@ #include #include #include +#include +#include +#include +#include #include #include -#include #include #include #include @@ -160,6 +163,52 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2D::ptr l, CACHE(IfcCartesianTransformationOperator2D,l,trsf) return true; } +bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3DnonUniform::ptr l, gp_GTrsf& gtrsf) { + IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf) + gp_Trsf trsf; + gp_Pnt origin; + IfcGeom::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_Ax3 ax3 (origin,axis3,axis1); + if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse(); + trsf.SetTransformation(ax3); + trsf.Invert(); + const float scale1 = l->hasScale() ? l->Scale() : 1.0f; + const float scale2 = l->hasScale2() ? l->Scale2() : scale1; + const float scale3 = l->hasScale3() ? l->Scale3() : scale1; + gtrsf = gp_GTrsf(); + gtrsf.SetValue(1,1,scale1); + gtrsf.SetValue(2,2,scale2); + gtrsf.SetValue(3,3,scale3); + gtrsf.Multiply(trsf); + CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gtrsf) + return true; +} +bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2DnonUniform::ptr 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())); + trsf.SetTransformation(ax2d); + trsf.Invert(); + const float scale1 = l->hasScale() ? l->Scale() : 1.0f; + const float scale2 = l->hasScale2() ? l->Scale2() : scale1; + gtrsf = gp_GTrsf2d(); + gtrsf.SetValue(1,1,scale1); + gtrsf.SetValue(2,2,scale2); + gtrsf.Multiply(trsf); + CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gtrsf) + return true; +} bool IfcGeom::convert(const Ifc2x3::IfcPlane::ptr pln, gp_Pln& plane) { IN_CACHE(IfcPlane,pln,gp_Pln,plane) Ifc2x3::IfcAxis2Placement3D::ptr l = pln->Position(); diff --git a/src/ifcgeom/IfcGeomObjects.cpp b/src/ifcgeom/IfcGeomObjects.cpp index ec77eb313c..f2ac3029af 100644 --- a/src/ifcgeom/IfcGeomObjects.cpp +++ b/src/ifcgeom/IfcGeomObjects.cpp @@ -19,7 +19,12 @@ #include +#include +#include +#include +#include #include +#include #include #include #include @@ -38,7 +43,7 @@ #include "../ifcgeom/IfcGeom.h" // Welds vertices that belong to different faces -int IfcGeomObjects::IfcMesh::addvert(gp_Pnt p) { +int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) { const float X = (float)p.X();const float Y = (float)p.Y();const float Z = (float)p.Z(); const VertKey key = VertKey(X,std::pair(Y,Z)); VertKeyMap::const_iterator it = welds.find(key); @@ -51,54 +56,62 @@ int IfcGeomObjects::IfcMesh::addvert(gp_Pnt p) { return i; } -IfcGeomObjects::IfcMesh::IfcMesh(int i, TopoDS_Shape s) { +IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) { id = i; - // Triangulate the shape - try { - BRepTools::Clean(s); - BRepMesh::Mesh(s,0.001f); - } catch(...) { - Ifc::LogMessage("Error","Failed to triangulate mesh:",Ifc::EntityById(i)->entity); - return; - } - TopExp_Explorer exp; + for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) { - // 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); + const TopoDS_Shape& s = *(*it).second; + const gp_GTrsf& trsf = *(*it).first; - if ( ! tri.IsNull() ) { + // Triangulate the shape + try { + //BRepTools::Clean(s); + BRepMesh::Mesh(s,0.001f); + } catch(...) { + Ifc::LogMessage("Error","Failed to triangulate mesh:",Ifc::EntityById(i)->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() ) { - // Keep track of the number of times an edge is used - // Manifold edges (i.e. edges used twice) are deemed invisible - std::map,int> edgecount; - std::vector > edges_temp; + // Keep track of the number of times an edge is used + // Manifold edges (i.e. edges used twice) are deemed invisible + std::map,int> edgecount; + std::vector > edges_temp; - const TColgp_Array1OfPnt& nodes = tri->Nodes(); - std::map dict; - for( int i = 1; i <= nodes.Length(); ++ i ) { - dict[i] = addvert(nodes(i).Transformed(loc)); - } + const TColgp_Array1OfPnt& nodes = tri->Nodes(); + std::map dict; + for( int i = 1; i <= nodes.Length(); ++ i ) { + gp_XYZ xyz = nodes(i).Transformed(loc).XYZ(); + trsf.Transforms(xyz); + dict[i] = addvert(xyz); + } - 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); - faces.push_back(dict[n1]); - faces.push_back(dict[n2]); - faces.push_back(dict[n3]); + 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); + faces.push_back(dict[n1]); + faces.push_back(dict[n2]); + faces.push_back(dict[n3]); - addedge(n1,n2,edgecount,edges_temp); - addedge(n2,n3,edgecount,edges_temp); - addedge(n3,n1,edgecount,edges_temp); - } - for ( std::vector >::const_iterator it = edges_temp.begin(); it != edges_temp.end(); ++it ) { - edges.push_back(edgecount[*it]==1); + addedge(n1,n2,edgecount,edges_temp); + addedge(n2,n3,edgecount,edges_temp); + addedge(n3,n1,edgecount,edges_temp); + } + for ( std::vector >::const_iterator it = edges_temp.begin(); it != edges_temp.end(); ++it ) { + edges.push_back(edgecount[*it]==1); + } } } } @@ -138,14 +151,8 @@ IfcGeomObjects::IfcGeomObject::IfcGeomObject(int my_id, Ifc2x3::IfcShapeRepresentation::list shapereps; Ifc2x3::IfcShapeRepresentation::it outer; -// The triangulated shape is stored globally because it can be used by multiple IfcBuildingElements -IfcGeomObjects::IfcMesh* shape; -// The compound shape is stored globally because multiple IfcShapeRepresentations -// can have IfcBuildingElements with different IfcOpeningElements -TopoDS_Shape shapes; - // The object is fetched beforehand to be positive an entity actually exists -IfcGeomObjects::IfcGeomObject* currentGeomObj; +IfcGeomObjects::IfcGeomObject* current_geom_obj; // A container and iterator for IfcBuildingElements for the current IfcShapeRepresentation referenced by *outer Ifc2x3::IfcProduct::list entities; @@ -157,9 +164,6 @@ int total; // Move the the next IfcShapeRepresentation void _nextShape() { - if ( shape ) delete shape; - shapes.Nullify(); - shape = 0; entities.reset(); ++ outer; ++ done; @@ -215,13 +219,15 @@ IfcGeomObjects::IfcGeomObject* _get() { _nextShape(); continue; } - // Has the TopoDS_Shape been created for this representation? - if ( shapes.IsNull() ) { - if ( !IfcGeom::convert_shape(shaperep,shapes) ) { - _nextShape(); - continue; - } + + IfcGeomObjects::IfcMesh* shape; + IfcGeom::ShapeList shapes; + + if ( !IfcGeom::convert_shapes(shaperep,shapes) ) { + _nextShape(); + continue; } + Ifc2x3::IfcProduct::ptr ifc_product = *inner; int parent_id = -1; const std::string name = ifc_product->hasName() ? ifc_product->Name() : ""; @@ -270,42 +276,55 @@ IfcGeomObjects::IfcGeomObject* _get() { } } - if ( (openings && openings->Size()) || use_world_coords ) { - if ( shape ) delete shape; - TopoDS_Shape temp_shape = shapes.Moved(gp_Trsf()); + if ( openings && openings->Size() ) { + IfcGeom::ShapeList opened_shapes; try { - if (openings && openings->Size()) { - IfcGeom::convert_openings(ifc_product,openings,temp_shape,trsf); - } - } catch( IfcParse::IfcException& e ) { - Ifc::LogMessage("Error",e.what(),ifc_product->entity); + IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes); } catch(...) { Ifc::LogMessage("Error","Error processing openings for:",ifc_product->entity); } if ( use_world_coords ) { - shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),temp_shape.Moved(trsf)); + for ( IfcGeom::ShapeList::const_iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) { + it->first->PreMultiply(trsf); + } trsf = gp_Trsf(); - } else { - shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),temp_shape); } - } else if ( ! shape ) { + shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),opened_shapes); + for ( IfcGeom::ShapeList::const_iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) { + delete it->first; + delete it->second; + } + } else if ( use_world_coords ) { + for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) { + it->first->PreMultiply(trsf); + } + trsf = gp_Trsf(); + shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),shapes); + } else { shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),shapes); } - return new IfcGeomObjects::IfcGeomObject(ifc_product->entity->id(), parent_id, name, - Ifc2x3::Type::ToString(ifc_product->type()), guid, trsf, shape); - } - + IfcGeomObjects::IfcGeomObject* geom_obj = new IfcGeomObjects::IfcGeomObject(ifc_product->entity->id(), parent_id, name, + Ifc2x3::Type::ToString(ifc_product->type()), guid, trsf, shape); + + for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) { + delete it->first; + } + + return geom_obj; + } } bool IfcGeomObjects::Next() { + if ( current_geom_obj ) { + delete current_geom_obj->mesh; + delete current_geom_obj; + } if ( entities ) { ++inner; } - delete currentGeomObj; - currentGeomObj = _get(); - if ( ! currentGeomObj ) { - delete shape; + current_geom_obj = _get(); + if ( ! current_geom_obj ) { return false; } else { return true; @@ -362,7 +381,7 @@ const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) { return ifc_object; } const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() { - return currentGeomObj; + return current_geom_obj; } bool IfcGeomObjects::Init(const char* fn, bool world_coords) { return IfcGeomObjects::Init(fn, world_coords, 0, 0); @@ -377,9 +396,9 @@ bool IfcGeomObjects::Init(const char* fn, bool world_coords, std::ostream* log1, outer = shapereps->begin(); entities.reset(); - currentGeomObj = _get(); + current_geom_obj = _get(); - if ( ! currentGeomObj ) return false; + if ( ! current_geom_obj ) return false; done = 0; total = shapereps->Size(); @@ -395,9 +414,9 @@ bool IfcGeomObjects::Init(std::istream& f, int len, bool world_coords, std::ostr outer = shapereps->begin(); entities.reset(); - currentGeomObj = _get(); + current_geom_obj = _get(); - if ( ! currentGeomObj ) return false; + if ( ! current_geom_obj ) return false; done = 0; total = shapereps->Size(); diff --git a/src/ifcgeom/IfcGeomObjects.h b/src/ifcgeom/IfcGeomObjects.h index da60d3f8f6..e327c9d244 100644 --- a/src/ifcgeom/IfcGeomObjects.h +++ b/src/ifcgeom/IfcGeomObjects.h @@ -57,9 +57,14 @@ #include #include +#include +#include +#include +#include #include -#include -#include +#include + +#include "../ifcgeom/IfcGeom.h" namespace IfcGeomObjects { @@ -77,9 +82,9 @@ namespace IfcGeomObjects { std::vector edges; VertKeyMap welds; - IfcMesh(int i, TopoDS_Shape s); + IfcMesh(int i, const IfcGeom::ShapeList& s); private: - int addvert(gp_Pnt p); + int addvert(const gp_XYZ& p); inline void addedge(int n1, int n2, std::map,int>& edgecount, std::vector >& edges_temp) { const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) ); if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1; diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index 61691d497d..67c76ab9b2 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -29,9 +29,12 @@ #include #include #include +#include +#include +#include +#include #include #include -#include #include #include #include @@ -88,21 +91,22 @@ bool IfcGeom::convert(const Ifc2x3::IfcExtrudedAreaSolid::ptr l, TopoDS_Shape& s shape.Move(trsf); return ! shape.IsNull(); } -bool IfcGeom::convert(const Ifc2x3::IfcFacetedBrep::ptr l, TopoDS_Shape& shape) { - return IfcGeom::convert_shape(l->Outer(),shape); +bool IfcGeom::convert(const Ifc2x3::IfcFacetedBrep::ptr l, ShapeList& shape) { + TopoDS_Shape s; + if ( const TopoDS_Shape* shape_id = IfcGeom::convert_shape(l->Outer(),s) ) { + shape.push_back(LocationShape(new gp_GTrsf(),shape_id)); + return true; + } + return false; } -bool IfcGeom::convert(const Ifc2x3::IfcFaceBasedSurfaceModel::ptr l, TopoDS_Shape& shape) { +bool IfcGeom::convert(const Ifc2x3::IfcFaceBasedSurfaceModel::ptr l, ShapeList& shapes) { Ifc2x3::IfcConnectedFaceSet::list facesets = l->FbsmFaces(); - BRep_Builder builder; - TopoDS_Compound c; - builder.MakeCompound(c); for( Ifc2x3::IfcConnectedFaceSet::it it = facesets->begin(); it != facesets->end(); ++ it ) { TopoDS_Shape s; - if ( IfcGeom::convert_shape(*it,s) ) { - builder.Add(c,s); + if ( const TopoDS_Shape* shape_id = IfcGeom::convert_shape(*it,s) ) { + shapes.push_back(LocationShape(new gp_GTrsf(),shape_id)); } } - shape = c; return true; } bool IfcGeom::convert(const Ifc2x3::IfcHalfSpaceSolid::ptr l, TopoDS_Shape& shape) { @@ -128,24 +132,20 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr l, TopoDS_ if ( ! IfcGeom::convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false; gp_Trsf trsf; convert(l->Position(),trsf); - TopoDS_Shape extrusion = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,20000.0)); - gp_Trsf down; down.SetTranslation(gp_Vec(0,0,-10000.0)); + TopoDS_Shape extrusion = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,200.0)); + gp_Trsf down; down.SetTranslation(gp_Vec(0,0,-100.0)); extrusion.Move(down*trsf); shape = BRepAlgoAPI_Cut(extrusion,halfspace); return true; } -bool IfcGeom::convert(const Ifc2x3::IfcShellBasedSurfaceModel::ptr l, TopoDS_Shape& shape) { +bool IfcGeom::convert(const Ifc2x3::IfcShellBasedSurfaceModel::ptr l, ShapeList& shapes) { IfcUtil::IfcAbstractSelect::list shells = l->SbsmBoundary(); - BRep_Builder builder; - TopoDS_Compound c; - builder.MakeCompound(c); for( IfcUtil::IfcAbstractSelect::it it = shells->begin(); it != shells->end(); ++ it ) { TopoDS_Shape s; - if ( IfcGeom::convert_shape(*it,s) ) { - builder.Add(c,s); + if ( const TopoDS_Shape* shape_id = IfcGeom::convert_shape(*it,s) ) { + shapes.push_back(LocationShape(new gp_GTrsf(),shape_id)); } } - shape = c; return true; } bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shape& shape) { @@ -200,47 +200,53 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh } catch(...) {} return true; } -bool IfcGeom::convert(const Ifc2x3::IfcMappedItem::ptr l, TopoDS_Shape& shape) { - gp_Trsf trsf1; +bool IfcGeom::convert(const Ifc2x3::IfcMappedItem::ptr l, ShapeList& shapes) { + gp_GTrsf gtrsf; Ifc2x3::IfcCartesianTransformationOperator::ptr transform = l->MappingTarget(); - if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator2DnonUniform) || - transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3DnonUniform) ) { - // Not implemented - return false; - } else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3D) ) { + if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3DnonUniform) ) { IfcGeom::convert(reinterpret_pointer_cast(transform),trsf1); + Ifc2x3::IfcCartesianTransformationOperator3DnonUniform>(transform),gtrsf); + } else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator2DnonUniform) ) { + return false; + } else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3D) ) { + gp_Trsf trsf; + IfcGeom::convert(reinterpret_pointer_cast(transform),trsf); + gtrsf = trsf; } else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator2D) ) { - gp_Trsf2d trsf1_2d; + gp_Trsf2d trsf_2d; IfcGeom::convert(reinterpret_pointer_cast(transform),trsf1_2d); - trsf1 = trsf1_2d; + Ifc2x3::IfcCartesianTransformationOperator2D>(transform),trsf_2d); + gtrsf = (gp_Trsf) trsf_2d; } Ifc2x3::IfcRepresentationMap::ptr map = l->MappingSource(); Ifc2x3::IfcAxis2Placement placement = map->MappingOrigin(); - gp_Trsf trsf2; + gp_Trsf trsf; if (placement->is(Ifc2x3::Type::IfcAxis2Placement3D)) { - IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)placement,trsf2); + IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)placement,trsf); } else { - gp_Trsf2d trsf2_2d; - IfcGeom::convert((Ifc2x3::IfcAxis2Placement2D*)placement,trsf2_2d); - trsf2 = trsf2_2d; + gp_Trsf2d trsf_2d; + IfcGeom::convert((Ifc2x3::IfcAxis2Placement2D*)placement,trsf_2d); + trsf = trsf_2d; } - if ( ! IfcGeom::convert_shape(map->MappedRepresentation(),shape) ) return false; - shape = shape.Moved(trsf2 * trsf1); - return !shape.IsNull(); + gtrsf.Multiply(trsf); + const unsigned int previous_size = (const unsigned int) shapes.size(); + bool b = IfcGeom::convert_shapes(map->MappedRepresentation(),shapes); + for ( unsigned int i = previous_size; i < shapes.size(); ++ i ) { + shapes[i].first->Multiply(gtrsf); + } + return b; } -bool IfcGeom::convert(const Ifc2x3::IfcShapeRepresentation::ptr l, TopoDS_Shape& shape) { +bool IfcGeom::convert(const Ifc2x3::IfcShapeRepresentation::ptr l, ShapeList& shapes) { Ifc2x3::IfcRepresentationItem::list items = l->Items(); if ( ! items->Size() ) return false; - BRep_Builder builder; - TopoDS_Compound c; - builder.MakeCompound(c); for ( Ifc2x3::IfcRepresentationItem::it it = items->begin(); it != items->end(); ++ it ) { - TopoDS_Shape s; - if ( ! IfcGeom::convert_shape(*it,s)) continue; - builder.Add(c,s); + if ( IfcGeom::is_shape_collection(*it) ) IfcGeom::convert_shapes(*it,shapes); + else { + TopoDS_Shape s; + if ( const TopoDS_Shape* shape_id = IfcGeom::convert_shape(*it,s)) + shapes.push_back(LocationShape(new gp_GTrsf(),shape_id)); + } } - shape = c; - return !shape.IsNull(); + return true; } \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index e447bfce2b..dfa359645e 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -29,9 +29,12 @@ #include #include #include +#include +#include +#include +#include #include #include -#include #include #include #include @@ -89,7 +92,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire) } if ( ! (*it)->SameSense() ) wire2.Reverse(); ShapeFix_ShapeTolerance FTol; - FTol.SetTolerance(wire2, 0.001, TopAbs_WIRE); + FTol.SetTolerance(wire2, 0.0001, TopAbs_WIRE); /*if ( it != segments->begin() ) { TopExp_Explorer exp (wire2,TopAbs_VERTEX); const TopoDS_Vertex& first_vertex = TopoDS::Vertex(exp.Current()); diff --git a/src/ifcgeom/IfcRegister.cpp b/src/ifcgeom/IfcRegister.cpp index 0de29fe298..00e3e1ae24 100644 --- a/src/ifcgeom/IfcRegister.cpp +++ b/src/ifcgeom/IfcRegister.cpp @@ -31,14 +31,23 @@ namespace IfcGeom { using namespace Ifc2x3; using namespace IfcUtil; -bool IfcGeom::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) { - const unsigned int id = l->entity->id(); - std::map::const_iterator it = Cache::Shape.find(id); - if ( it != Cache::Shape.end() ) { r = it->second; return true; } -#include "IfcRegisterConvertShape.h" +bool IfcGeom::convert_shapes(const IfcBaseClass* l, ShapeList& r) { +#include "IfcRegisterConvertShapes.h" Ifc::LogMessage("Error","No operation defined for:",l->entity); return false; } +bool IfcGeom::is_shape_collection(const IfcBaseClass* l) { +#include "IfcRegisterIsShapeCollection.h" + return false; +} +const TopoDS_Shape* IfcGeom::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) { + const unsigned int id = l->entity->id(); + std::map::const_iterator it = Cache::Shape.find(id); + if ( it != Cache::Shape.end() ) { r = it->second; return &(it->second); } +#include "IfcRegisterConvertShape.h" + Ifc::LogMessage("Error","No operation defined for:",l->entity); + return 0; +} bool IfcGeom::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) { #include "IfcRegisterConvertWire.h" Ifc::LogMessage("Error","No operation defined for:",l->entity); diff --git a/src/ifcgeom/IfcRegister.h b/src/ifcgeom/IfcRegister.h index b17fc1a583..7ab46a78e7 100644 --- a/src/ifcgeom/IfcRegister.h +++ b/src/ifcgeom/IfcRegister.h @@ -31,6 +31,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -38,14 +42,15 @@ using namespace Ifc2x3; +SHAPES(IfcShellBasedSurfaceModel); +SHAPES(IfcFaceBasedSurfaceModel); +SHAPES(IfcShapeRepresentation); +SHAPES(IfcMappedItem); +SHAPES(IfcFacetedBrep); + SHAPE(IfcExtrudedAreaSolid); SHAPE(IfcConnectedFaceSet); -SHAPE(IfcFacetedBrep); -SHAPE(IfcShellBasedSurfaceModel); -SHAPE(IfcFaceBasedSurfaceModel); SHAPE(IfcBooleanClippingResult); -SHAPE(IfcShapeRepresentation); -SHAPE(IfcMappedItem); SHAPE(IfcPolygonalBoundedHalfSpace); SHAPE(IfcHalfSpaceSolid); @@ -72,6 +77,8 @@ CLASS(IfcCartesianPoint,gp_Pnt); CLASS(IfcDirection,gp_Dir); CLASS(IfcAxis2Placement2D,gp_Trsf2d); CLASS(IfcAxis2Placement3D,gp_Trsf); +CLASS(IfcCartesianTransformationOperator2DnonUniform,gp_GTrsf2d); +CLASS(IfcCartesianTransformationOperator3DnonUniform,gp_GTrsf); CLASS(IfcCartesianTransformationOperator2D,gp_Trsf2d); CLASS(IfcCartesianTransformationOperator3D,gp_Trsf); CLASS(IfcObjectPlacement,gp_Trsf); diff --git a/src/ifcgeom/IfcRegisterConvertShape.h b/src/ifcgeom/IfcRegisterConvertShape.h index 9655755d6b..9f1067dda8 100644 --- a/src/ifcgeom/IfcRegisterConvertShape.h +++ b/src/ifcgeom/IfcRegisterConvertShape.h @@ -3,8 +3,8 @@ if ( l->is(T::Class()) ) { \ try { \ if ( convert((T*)l,r) ) { \ - Cache::Shape[l->entity->id()] = r; \ - return true; \ + Cache::Shape[id] = r; \ + return &(Cache::Shape[id]); \ } \ } catch(...) { } \ Ifc::LogMessage("Error","Failed to convert:",l->entity); \ diff --git a/src/ifcgeom/IfcRegisterConvertShapes.h b/src/ifcgeom/IfcRegisterConvertShapes.h new file mode 100644 index 0000000000..54a2dc0139 --- /dev/null +++ b/src/ifcgeom/IfcRegisterConvertShapes.h @@ -0,0 +1,8 @@ +#include "IfcRegisterUndef.h" +#define SHAPES(T) \ + if ( l->is(T::Class()) ) { \ + return IfcGeom::convert((T*)l,r); \ + } +#include "IfcRegisterDef.h" + +#include "IfcRegister.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterDef.h b/src/ifcgeom/IfcRegisterDef.h index d1d9f1c000..a1d5af0f47 100644 --- a/src/ifcgeom/IfcRegisterDef.h +++ b/src/ifcgeom/IfcRegisterDef.h @@ -1,3 +1,6 @@ +#ifndef SHAPES +#define SHAPES(T) +#endif #ifndef SHAPE #define SHAPE(T) #endif diff --git a/src/ifcgeom/IfcRegisterGeomHeader.h b/src/ifcgeom/IfcRegisterGeomHeader.h index e0990b9a96..bf31b2aa9a 100644 --- a/src/ifcgeom/IfcRegisterGeomHeader.h +++ b/src/ifcgeom/IfcRegisterGeomHeader.h @@ -1,5 +1,6 @@ #include "IfcRegisterUndef.h" #define CLASS(T,V) bool convert(const T::ptr L, V& r); +#define SHAPES(T) CLASS(T,ShapeList) #define SHAPE(T) CLASS(T,TopoDS_Shape) #define WIRE(T) CLASS(T,TopoDS_Wire) #define FACE(T) CLASS(T,TopoDS_Face) diff --git a/src/ifcgeom/IfcRegisterIsShapeCollection.h b/src/ifcgeom/IfcRegisterIsShapeCollection.h new file mode 100644 index 0000000000..810dc654d1 --- /dev/null +++ b/src/ifcgeom/IfcRegisterIsShapeCollection.h @@ -0,0 +1,6 @@ +#include "IfcRegisterUndef.h" +#define SHAPES(T) \ + if ( l->is(T::Class()) ) return true; +#include "IfcRegisterDef.h" + +#include "IfcRegister.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterUndef.h b/src/ifcgeom/IfcRegisterUndef.h index d39fa4ab15..97fab37319 100644 --- a/src/ifcgeom/IfcRegisterUndef.h +++ b/src/ifcgeom/IfcRegisterUndef.h @@ -1,3 +1,6 @@ +#ifdef SHAPES +#undef SHAPES +#endif #ifdef SHAPE #undef SHAPE #endif