diff --git a/src/ifcparse/IfcGeom.cpp b/src/ifcparse/IfcGeom.cpp index fec6e8f053..2302af8677 100644 --- a/src/ifcparse/IfcGeom.cpp +++ b/src/ifcparse/IfcGeom.cpp @@ -71,6 +71,8 @@ #include #include +#include + #include bool IfcGeom::convert(IfcSchema::ExtrudedAreaSolid* IfcExtrudedAreaSolid, TopoDS_Shape& shape) { @@ -273,7 +275,7 @@ bool IfcGeom::convert(IfcSchema::ArbitraryProfileDefWithVoids* IfcArbitraryProfi face = TopoDS::Face(sfs.Shape()); return true; } -bool IfcGeom::convert(IfcSchema::RectangleProfileDef* IfcRectangleProfileDef,class TopoDS_Wire& wire) { +bool IfcGeom::convert(IfcSchema::RectangleProfileDef* IfcRectangleProfileDef,class TopoDS_Face& face) { const float x = IfcRectangleProfileDef->Width() / 2.0f * Ifc::LengthUnit; const float y = IfcRectangleProfileDef->Height() / 2.0f * Ifc::LengthUnit; @@ -282,21 +284,90 @@ bool IfcGeom::convert(IfcSchema::RectangleProfileDef* IfcRectangleProfileDef,cla return false; } - gp_Trsf2d trsf; - IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcRectangleProfileDef->Placement().get(),trsf); - - gp_XY p1 (-x,-y);trsf.Transforms(p1);gp_Pnt P1(p1.X(),p1.Y(),0.0f); - gp_XY p2 ( x,-y);trsf.Transforms(p2);gp_Pnt P2(p2.X(),p2.Y(),0.0f); - gp_XY p3 ( x, y);trsf.Transforms(p3);gp_Pnt P3(p3.X(),p3.Y(),0.0f); - gp_XY p4 (-x, y);trsf.Transforms(p4);gp_Pnt P4(p4.X(),p4.Y(),0.0f); - - BRepBuilderAPI_MakeWire w; - w.Add(BRepBuilderAPI_MakeEdge(P1,P2)); - w.Add(BRepBuilderAPI_MakeEdge(P2,P3)); - w.Add(BRepBuilderAPI_MakeEdge(P3,P4)); - w.Add(BRepBuilderAPI_MakeEdge(P4,P1)); - wire = w.Wire(); - return true; + gp_Trsf2d trsf2d; + IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcRectangleProfileDef->Placement().get(),trsf2d); + float coords[8] = {-x,-y,x,-y,x,y,-x,y}; + return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face); +} +bool IfcGeom::convert(IfcSchema::IShapeProfileDef* IfcIShapeProfileDef,class TopoDS_Face& face) { + const float x = IfcIShapeProfileDef->Width() / 2.0f * Ifc::LengthUnit; + const float y = IfcIShapeProfileDef->Depth() / 2.0f * Ifc::LengthUnit; + const float d1 = IfcIShapeProfileDef->WebThickness() / 2.0f * Ifc::LengthUnit; + const float d2 = IfcIShapeProfileDef->FlangeThickness() * Ifc::LengthUnit; + bool doFillet = false; + float f; + try { + f = IfcIShapeProfileDef->FilletRadius() * Ifc::LengthUnit; + doFillet = true; + } catch ( IfcParse::IfcException& ) {} + + if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) { + std::cout << "[Notice] Skipping zero sized profile:" << std::endl << IfcIShapeProfileDef->toString() << std::endl; + return false; + } + + gp_Trsf2d trsf2d; + IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcIShapeProfileDef->Placement().get(),trsf2d); + + float coords[24] = {-x,-y,x,-y,x,-y+d2,d1,-y+d2,d1,y-d2,x,y-d2,x,y,-x,y,-x,y-d2,-d1,y-d2,-d1,-y+d2,-x,-y+d2}; + int fillets[4] = {3,4,9,10}; + float radii[4] = {f,f,f,f}; + return IfcGeom::profile_helper(12,coords,doFillet ? 4 : 0,fillets,radii,trsf2d,face); +} +bool IfcGeom::convert(IfcSchema::CShapeProfileDef* IfcCShapeProfileDef,class TopoDS_Face& face) { + const float x = IfcCShapeProfileDef->Depth() / 2.0f * Ifc::LengthUnit; + const float y = IfcCShapeProfileDef->Width() / 2.0f * Ifc::LengthUnit; + const float d1 = IfcCShapeProfileDef->WallThickness() * Ifc::LengthUnit; + const float d2 = IfcCShapeProfileDef->Girth() * Ifc::LengthUnit; + bool doFillet = false; + float f1,f2; + try { + f1 = IfcCShapeProfileDef->InternalFilletRadius() * Ifc::LengthUnit; + f2 = f1 + d1; + doFillet = true; + } catch ( IfcParse::IfcException& ) {} + + if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) { + std::cout << "[Notice] Skipping zero sized profile:" << std::endl << IfcCShapeProfileDef->toString() << std::endl; + return false; + } + + gp_Trsf2d trsf2d; + IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcCShapeProfileDef->Placement().get(),trsf2d); + + float coords[24] = {-x,-y,x,-y,x,-y+d2,x-d1,-y+d2,x-d1,-y+d1,-x+d1,-y+d1,-x+d1,y-d1,x-d1,y-d1,x-d1,y-d2,x,y-d2,x,y,-x,y}; + int fillets[8] = {0,1,4,5,6,7,10,11}; + float radii[8] = {f2,f2,f1,f1,f1,f1,f2,f2}; + return IfcGeom::profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face); +} +bool IfcGeom::convert(IfcSchema::LShapeProfileDef* IfcLShapeProfileDef,class TopoDS_Face& face) { + const float y = IfcLShapeProfileDef->Depth() / 2.0f * Ifc::LengthUnit; + const float x = IfcLShapeProfileDef->Width() / 2.0f * Ifc::LengthUnit; + const float d = IfcLShapeProfileDef->Thickness() * Ifc::LengthUnit; + bool doFillet = false; + float f1 = 0.0f; + float f2 = 0.0f; + try { + f1 = IfcLShapeProfileDef->FilletRadius() * Ifc::LengthUnit; + doFillet = true; + } catch ( IfcParse::IfcException& ) {} + try { + f2 = IfcLShapeProfileDef->EdgeRadius() * Ifc::LengthUnit; + doFillet = true; + } catch ( IfcParse::IfcException& ) {} + + if ( x == 0.0f || y == 0.0f || d == 0.0f ) { + std::cout << "[Notice] Skipping zero sized profile:" << std::endl << IfcLShapeProfileDef->toString() << std::endl; + return false; + } + + gp_Trsf2d trsf2d; + IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcLShapeProfileDef->Placement().get(),trsf2d); + + float coords[12] = {-x,-y,x,-y,x,-y+d,-x+d,-y+d,-x+d,y,-x,y}; + int fillets[3] = {2,3,4}; + float radii[3] = {f2,f1,f2}; + return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face); } bool IfcGeom::convert(IfcSchema::CircleProfileDef* IfcCircleProfileDef,class TopoDS_Wire& wire) { const float r = IfcCircleProfileDef->Radius() * Ifc::LengthUnit; @@ -505,4 +576,33 @@ bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) { if ( er != BRepBuilderAPI_FaceDone ) return false; face = mf.Face(); return true; +} +bool IfcGeom::profile_helper(int numVerts, float* verts, int numFillets, int* filletIndices, float* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face) { + 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])); + + IfcGeom::convert_wire_to_face(w.Wire(),face); + + if ( numFillets ) { + BRepFilletAPI_MakeFillet2d fillet (face); + for ( int i = 0; i < numFillets; i ++ ) { + const float radius = filletRadii[i]; + if ( radius < 1e-7 ) continue; + fillet.AddFillet(vertices[filletIndices[i]],radius); + } + fillet.Build(); + face = TopoDS::Face(fillet.Shape()); + } + + delete[] vertices; + return true; } \ No newline at end of file diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index bbebc6b7eb..5c61081bc7 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -179,7 +179,9 @@ Entity::Entity(std::istream* ss, std::vector& refs, bool sub) { std::string curvar; curvar.reserve(64); bool inStr = false; + bool inComment = false; char c[1] = ""; + char p[1] = ""; int state = -1; int previousPos = -1; args = 0; @@ -187,8 +189,8 @@ Entity::Entity(std::istream* ss, std::vector& refs, bool sub) { id = -1; do { ss->read(c,1); - if ( !inStr && ((*c) == ' ' || (*c) == '\r' || (*c) == '\n' || (*c) == '\t') ) continue; - if ( curvar.size() && !inStr && ( term(*c) || term(*curvar.rbegin())) ) { + if ( !inComment && !inStr && ((*c) == ' ' || (*c) == '\r' || (*c) == '\n' || (*c) == '\t') ) continue; + if ( curvar.size() && !inComment && !inStr && ( term(*c) || term(*curvar.rbegin())) ) { Argument* v = new Argument(curvar); curvar.clear(); curvar.push_back(*c); @@ -234,8 +236,12 @@ Entity::Entity(std::istream* ss, std::vector& refs, bool sub) { } previousPos = ss->tellg(); delete v; - } else curvar.push_back(*c); - if ( *c == '\'' ) inStr = !inStr; + } + else if ( ! inComment ) curvar.push_back(*c); + if ( !inComment && *c == '\'' ) inStr = !inStr; + else if ( !inStr && *p == '/' && *c == '*' ) { inComment = true; curvar.clear(); } + else if ( !inStr && *p == '*' && *c == '/' ) inComment = false; + p[0] = c[0]; } while ( !ss->eof() && (*c != ';' || inStr) ); } Entity::~Entity() { @@ -316,8 +322,7 @@ EntityPtr Entities::operator[] (int i) { Entities::Entities() { size = 0; } - -File::File(std::string fn, bool debug) { +File::File(const std::string& fn, bool debug) { valid = false; std::ifstream f(fn.c_str()); if ( ! f.is_open() ) return; @@ -392,7 +397,7 @@ EntitiesPtr Ifc::EntitiesByReference(int t) { EntityPtr Ifc::EntityById(int id) { return f->EntityById(id); } -bool Ifc::Init(std::string fn) { +bool Ifc::Init(const std::string& fn) { f = new File(fn, false); IfcEntity IfcUnitAssigment = *EntitiesByType(IfcSchema::Enum::IfcUnitAssignment)->begin(); IfcEntities units = ((IfcSchema::UnitAssignment*)IfcUnitAssigment.get())->Units(); diff --git a/src/ifcparse/IfcParse.h b/src/ifcparse/IfcParse.h index 372aede8fa..d7b8b22276 100644 --- a/src/ifcparse/IfcParse.h +++ b/src/ifcparse/IfcParse.h @@ -156,7 +156,7 @@ namespace IfcParse { std::map byref; bool valid; - File(std::string fn, bool debug = false); + File(const std::string& fn, bool debug = false); EntitiesPtr EntitiesByType(IfcSchema::Enum::IfcTypes t); EntitiesPtr EntitiesByReference(int id); EntityPtr EntityById(int id); @@ -186,7 +186,7 @@ public: static IfcEntities EntitiesByType(IfcSchema::Enum::IfcTypes t); static IfcEntities EntitiesByReference(int id); static IfcEntity EntityById(int id); - static bool Init(std::string fn); + static bool Init(const std::string& fn); static void Dispose(); static float LengthUnit; static float PlaneAngleUnit; diff --git a/src/ifcparse/IfcSchema.h b/src/ifcparse/IfcSchema.h index c627ee619e..ad90603332 100644 --- a/src/ifcparse/IfcSchema.h +++ b/src/ifcparse/IfcSchema.h @@ -114,7 +114,7 @@ IFC_REF(ArbitraryProfileDefWithVoids,Polyline,2) IFC_REFS(ArbitraryProfileDefWithVoids,Voids,3) IFC_END_CLASS -IFC_WIRE_CLASS(RectangleProfileDef) +IFC_FACE_CLASS(RectangleProfileDef) IFC_REF(RectangleProfileDef,Placement,2) IFC_FLT(RectangleProfileDef,Width,3) IFC_FLT(RectangleProfileDef,Height,4) @@ -131,6 +131,34 @@ IFC_FLT(CircleHollowProfileDef,Radius,3) IFC_FLT(CircleHollowProfileDef,WallThickness,4) IFC_END_CLASS +IFC_FACE_CLASS(IShapeProfileDef) +IFC_REF(IShapeProfileDef,Placement,2) +IFC_FLT(IShapeProfileDef,Width,3) +IFC_FLT(IShapeProfileDef,Depth,4) +IFC_FLT(IShapeProfileDef,WebThickness,5) +IFC_FLT(IShapeProfileDef,FlangeThickness,6) +IFC_FLT(IShapeProfileDef,FilletRadius,7) +IFC_END_CLASS + +IFC_FACE_CLASS(CShapeProfileDef) +IFC_REF(CShapeProfileDef,Placement,2) +IFC_FLT(CShapeProfileDef,Width,3) +IFC_FLT(CShapeProfileDef,Depth,4) +IFC_FLT(CShapeProfileDef,WallThickness,5) +IFC_FLT(CShapeProfileDef,Girth,6) +IFC_FLT(CShapeProfileDef,InternalFilletRadius,7) +IFC_END_CLASS + +IFC_FACE_CLASS(LShapeProfileDef) +IFC_REF(LShapeProfileDef,Placement,2) +IFC_FLT(LShapeProfileDef,Depth,3) +IFC_FLT(LShapeProfileDef,Width,4) +IFC_FLT(LShapeProfileDef,Thickness,5) +IFC_FLT(LShapeProfileDef,FilletRadius,6) +IFC_FLT(LShapeProfileDef,EdgeRadius,7) +IFC_FLT(LShapeProfileDef,LegSlope,8) +IFC_END_CLASS + IFC_CURVE_CLASS(Circle) IFC_REF(Circle,Placement,0) IFC_FLT(Circle,Radius,1) diff --git a/src/ifcparse/IfcTypes.h b/src/ifcparse/IfcTypes.h index 2d6da0ab69..29d3436ece 100644 --- a/src/ifcparse/IfcTypes.h +++ b/src/ifcparse/IfcTypes.h @@ -46,6 +46,7 @@ namespace IfcGeom { bool convert_curve(const IfcEntity L, Handle(Geom_Curve)& result); bool convert_face(const IfcEntity L, TopoDS_Face& result); bool convert_openings(const IfcSchema::BuildingElement* IfcBuildingElement, const IfcEntities openings, TopoDS_Shape& result, const gp_Trsf& trsf); + bool profile_helper(int numVerts, float* verts, int numFillets, int* filletIndices, float* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face); } #endif