From 2fb4be2edcd307033af3586894116a819b813606 Mon Sep 17 00:00:00 2001 From: aothms Date: Sat, 8 Mar 2014 17:21:39 +0000 Subject: [PATCH] Implementations for more parameterized profile definitions --- src/examples/profiles.cpp | 16 +- src/ifcgeom/IfcGeomFaces.cpp | 332 +++++++++++++++++++++++++++++-- src/ifcgeom/IfcGeomFunctions.cpp | 2 +- src/ifcgeom/IfcRegister.h | 9 +- 4 files changed, 334 insertions(+), 25 deletions(-) diff --git a/src/examples/profiles.cpp b/src/examples/profiles.cpp index e0c2a992d5..3092648a49 100644 --- a/src/examples/profiles.cpp +++ b/src/examples/profiles.cpp @@ -93,10 +93,10 @@ int main(int argc, char** argv) { null, 0, 50.0, 25.0, 5.0, 5.0, 2.0, 2.0, null, null)); profiles->push(new Ifc2x3::IfcUShapeProfileDef( IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, - null, 0, 50.0, 25.0, 5.0, 5.0, null, null, 0.1, null)); + null, 0, 50.0, 25.0, 5.0, 5.0, null, null, 4.0, null)); profiles->push(new Ifc2x3::IfcUShapeProfileDef( IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, - null, 0, 50.0, 25.0, 5.0, 5.0, 1.0, 3.0, 0.1, null)); + null, 0, 50.0, 25.0, 5.0, 5.0, 1.0, 3.0, 6.0, null)); create_testcase_for(profiles); } { IfcSchema::IfcProfileDef::list profiles (new IfcTemplatedEntityList()); @@ -108,10 +108,10 @@ int main(int argc, char** argv) { null, 0, 50.0, 25.0, 5.0, 5.0, 2.0, 2.0, 2.0, null, null, null)); profiles->push(new Ifc2x3::IfcTShapeProfileDef( IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, - null, 0, 50.0, 25.0, 5.0, 5.0, null, null, null, 0.1, 0.1, null)); + null, 0, 50.0, 25.0, 5.0, 5.0, null, null, null, 2.0, 2.0, null)); profiles->push(new Ifc2x3::IfcTShapeProfileDef( IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, - null, 0, 50.0, 25.0, 5.0, 5.0, 1.0, 2.0, 3.0, 0.1, 0.2, null)); + null, 0, 50.0, 25.0, 5.0, 5.0, 3.0, 2.0, 1.0, 2.0, 2.0, null)); create_testcase_for(profiles); } { IfcSchema::IfcProfileDef::list profiles (new IfcTemplatedEntityList()); @@ -126,10 +126,10 @@ int main(int argc, char** argv) { { IfcSchema::IfcProfileDef::list profiles (new IfcTemplatedEntityList()); profiles->push(new Ifc2x3::IfcEllipseProfileDef( IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, - null, 0, 50.0, 25.0)); + null, 0, 25.0, 15.0)); profiles->push(new Ifc2x3::IfcEllipseProfileDef( IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, - null, 0, 25.0, 50.0)); + null, 0, 15.0, 25.0)); create_testcase_for(profiles); } { IfcSchema::IfcProfileDef::list profiles (new IfcTemplatedEntityList()); @@ -150,10 +150,10 @@ int main(int argc, char** argv) { null, 0, 50.0, 25.0, 5.0, 2.0, 2.0, null, null, null)); profiles->push(new Ifc2x3::IfcLShapeProfileDef( IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, - null, 0, 50.0, 25.0, 5.0, null, null, 0.1, null, null)); + null, 0, 50.0, 25.0, 5.0, null, null, 2.0, null, null)); profiles->push(new Ifc2x3::IfcLShapeProfileDef( IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, - null, 0, 50.0, 25.0, 5.0, 1.0, 2.0, 0.3, null, null)); + null, 0, 50.0, 25.0, 5.0, 1.0, 2.0, 2.0, null, null)); create_testcase_for(profiles); } { IfcSchema::IfcProfileDef::list profiles (new IfcTemplatedEntityList()); diff --git a/src/ifcgeom/IfcGeomFaces.cpp b/src/ifcgeom/IfcGeomFaces.cpp index d75a052dd8..9532a53151 100644 --- a/src/ifcgeom/IfcGeomFaces.cpp +++ b/src/ifcgeom/IfcGeomFaces.cpp @@ -208,7 +208,7 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangleProfileDef::ptr l, TopoDS_Fac const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - if ( x == 0.0f || y == 0.0f ) { + if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); return false; } @@ -218,13 +218,92 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangleProfileDef::ptr l, TopoDS_Fac double coords[8] = {-x,-y,x,-y,x,y,-x,y}; return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face); } +bool IfcGeom::convert(const IfcSchema::IfcRoundedRectangleProfileDef::ptr l, TopoDS_Face& face) { + const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double r = l->RoundingRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || r < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + gp_Trsf2d trsf2d; + IfcGeom::convert(l->Position(),trsf2d); + double coords[8] = {-x,-y, x,-y, x,y, -x,y}; + int fillets[4] = {0,1,2,3}; + double radii[4] = {r,r,r,r}; + return IfcGeom::profile_helper(4,coords,4,fillets,radii,trsf2d,face); +} +bool IfcGeom::convert(const IfcSchema::IfcRectangleHollowProfileDef::ptr l, TopoDS_Face& face) { + const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double d = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); + + const bool fr1 = l->hasInnerFilletRadius(); + const bool fr2 = l->hasInnerFilletRadius(); + + const double r1 = fr2 ? l->OuterFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT) : 0.; + const double r2 = fr1 ? l->InnerFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT) : 0.; + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + TopoDS_Face f1; + TopoDS_Face f2; + + gp_Trsf2d trsf2d; + IfcGeom::convert(l->Position(),trsf2d); + double coords1[8] = {-x ,-y, x ,-y, x, y, -x, y }; + double coords2[8] = {-x+d,-y+d, x-d,-y+d, x-d,y-d, -x+d,y-d}; + double radii1[4] = {r1,r1,r1,r1}; + double radii2[4] = {r2,r2,r2,r2}; + int fillets[4] = {0,1,2,3}; + + bool s1 = IfcGeom::profile_helper(4,coords1,fr1 ? 4 : 0,fillets,radii1,trsf2d,f1); + bool s2 = IfcGeom::profile_helper(4,coords2,fr2 ? 4 : 0,fillets,radii2,trsf2d,f2); + + if (!s1 || !s2) return false; + + TopExp_Explorer exp1(f1, TopAbs_WIRE); + TopExp_Explorer exp2(f2, TopAbs_WIRE); + + TopoDS_Wire w1 = TopoDS::Wire(exp1.Current()); + TopoDS_Wire w2 = TopoDS::Wire(exp2.Current()); + + BRepBuilderAPI_MakeFace mf(w1, false); + mf.Add(w2); + + ShapeFix_Shape sfs(mf.Face()); + sfs.Perform(); + face = TopoDS::Face(sfs.Shape()); + return true; +} +bool IfcGeom::convert(const IfcSchema::IfcTrapeziumProfileDef::ptr l, TopoDS_Face& face) { + const double x1 = l->BottomXDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double w = l->TopXDim() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double dx = l->TopXOffset() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + + if ( x1 < ALMOST_ZERO || w < ALMOST_ZERO || y < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + gp_Trsf2d trsf2d; + IfcGeom::convert(l->Position(),trsf2d); + double coords[8] = {-x1,-y, x1,-y, dx+w-x1,y, dx-x1,y}; + return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face); +} bool IfcGeom::convert(const IfcSchema::IfcIShapeProfileDef::ptr l, TopoDS_Face& face) { const double x = l->OverallWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); const double y = l->OverallDepth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); const double d1 = l->WebThickness() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); const double d2 = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); bool doFillet = l->hasFilletRadius(); - double f; + double f = 0.; if ( doFillet ) { f = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); } @@ -242,19 +321,52 @@ bool IfcGeom::convert(const IfcSchema::IfcIShapeProfileDef::ptr l, TopoDS_Face& double radii[4] = {f,f,f,f}; return IfcGeom::profile_helper(12,coords,doFillet ? 4 : 0,fillets,radii,trsf2d,face); } +bool IfcGeom::convert(const IfcSchema::IfcZShapeProfileDef::ptr l, TopoDS_Face& face) { + const double x = l->FlangeWidth() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double dx = l->WebThickness() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double dy = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); + + bool doFillet = l->hasFilletRadius(); + bool doEdgeFillet = l->hasEdgeRadius(); + + double f1 = 0.; + double f2 = 0.; + + if ( doFillet ) { + f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + } + if ( doEdgeFillet ) { + f2 = l->EdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + } + + if ( x == 0.0f || y == 0.0f || dx == 0.0f || dy == 0.0f ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + gp_Trsf2d trsf2d; + IfcGeom::convert(l->Position(),trsf2d); + + double coords[16] = {-dx,-y, x,-y, x,-y+dy, dx,-y+dy, dx,y, -x,y, -x,y-dy, -dx,y-dy}; + int fillets[4] = {2,3,6,7}; + double radii[4] = {f2,f1,f2,f1}; + return IfcGeom::profile_helper(8,coords,(doFillet || doEdgeFillet) ? 4 : 0,fillets,radii,trsf2d,face); +} bool IfcGeom::convert(const IfcSchema::IfcCShapeProfileDef::ptr l, TopoDS_Face& face) { - const double x = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double y = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double x = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); const double d1 = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); const double d2 = l->Girth() * IfcGeom::GetValue(GV_LENGTH_UNIT); bool doFillet = l->hasInternalFilletRadius(); - double f1,f2; + double f1 = 0; + double f2 = 0; if ( doFillet ) { f1 = l->InternalFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); f2 = f1 + d1; } - if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) { + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); return false; } @@ -268,11 +380,15 @@ bool IfcGeom::convert(const IfcSchema::IfcCShapeProfileDef::ptr l, TopoDS_Face& return IfcGeom::profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face); } bool IfcGeom::convert(const IfcSchema::IfcLShapeProfileDef::ptr l, TopoDS_Face& face) { + const bool hasSlope = l->hasLegSlope(); + const bool doEdgeFillet = l->hasEdgeRadius(); + const bool doFillet = l->hasFilletRadius(); + const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double x = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double x = (l->hasWidth() ? l->Width() : l->Depth()) / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); const double d = l->Thickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); - bool doEdgeFillet = l->hasEdgeRadius(); - bool doFillet = l->hasFilletRadius(); + const double slope = hasSlope ? (l->LegSlope() * IfcGeom::GetValue(GV_PLANEANGLE_UNIT)) : 0.; + double f1 = 0.0f; double f2 = 0.0f; if (doFillet) { @@ -281,7 +397,85 @@ bool IfcGeom::convert(const IfcSchema::IfcLShapeProfileDef::ptr l, TopoDS_Face& if ( doEdgeFillet) { f2 = l->EdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); } - if ( x == 0.0f || y == 0.0f || d == 0.0f ) { + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + double xx = -x+d; + double xy = -y+d; + double dy1 = 0.; + double dy2 = 0.; + double dx1 = 0.; + double dx2 = 0.; + if (hasSlope) { + dy1 = tan(slope) * x; + dy2 = tan(slope) * (x - d); + dx1 = tan(slope) * y; + dx2 = tan(slope) * (y - d); + + const double x1s = x; const double y1s = -y + d - dy1; + const double x1e = -x + d; const double y1e = -y + d + dy2; + const double x2s = -x + d - dx1; const double y2s = y; + const double x2e = -x + d + dx2; const double y2e = -y + d; + + const double a1 = y1e - y1s; + const double b1 = x1s - x1e; + const double c1 = a1*x1s + b1*y1s; + + const double a2 = y2e - y2s; + const double b2 = x2s - x2e; + const double c2 = a2*x2s + b2*y2s; + + const double det = a1*b2 - a2*b1; + + if (ALMOST_THE_SAME(det, 0.)) { + Logger::Message(Logger::LOG_NOTICE, "Legs do not intersect for:",l->entity); + return false; + } + + xx = (b2*c1 - b1*c2) / det; + xy = (a1*c2 - a2*c1) / det; + } + + gp_Trsf2d trsf2d; + IfcGeom::convert(l->Position(),trsf2d); + + double coords[12] = {-x,-y, x,-y, x,-y+d-dy1, xx, xy, -x+d-dx1,y, -x,y}; + int fillets[3] = {2,3,4}; + double radii[3] = {f2,f1,f2}; + return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face); +} +bool IfcGeom::convert(const IfcSchema::IfcUShapeProfileDef::ptr l, TopoDS_Face& face) { + const bool doEdgeFillet = l->hasEdgeRadius(); + const bool doFillet = l->hasFilletRadius(); + const bool hasSlope = l->hasFlangeSlope(); + + const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double x = l->FlangeWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double d1 = l->WebThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double d2 = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double slope = hasSlope ? (l->FlangeSlope() * IfcGeom::GetValue(GV_PLANEANGLE_UNIT)) : 0.; + + double dy1 = 0.0f; + double dy2 = 0.0f; + double f1 = 0.0f; + double f2 = 0.0f; + + if (doFillet) { + f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + } + if (doEdgeFillet) { + f2 = l->EdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + } + + if (hasSlope) { + dy1 = (x - d1) * tan(slope); + dy2 = x * tan(slope); + } + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); return false; } @@ -289,10 +483,92 @@ bool IfcGeom::convert(const IfcSchema::IfcLShapeProfileDef::ptr l, TopoDS_Face& gp_Trsf2d trsf2d; IfcGeom::convert(l->Position(),trsf2d); - double coords[12] = {-x,-y,x,-y,x,-y+d,-x+d,-y+d,-x+d,y,-x,y}; - int fillets[3] = {2,3,4}; - double radii[3] = {f2,f1,f2}; - return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face); + double coords[16] = {-x,-y, x,-y, x,-y+d2-dy2, -x+d1,-y+d2+dy1, -x+d1,y-d2-dy1, x,y-d2+dy2, x,y, -x,y}; + int fillets[4] = {2,3,4,5}; + double radii[4] = {f2,f1,f1,f2}; + return IfcGeom::profile_helper(8, coords, (doFillet || doEdgeFillet) ? 4 : 0, fillets, radii, trsf2d, face); +} +bool IfcGeom::convert(const IfcSchema::IfcTShapeProfileDef::ptr l, TopoDS_Face& face) { + const bool doFlangeEdgeFillet = l->hasFlangeEdgeRadius(); + const bool doWebEdgeFillet = l->hasWebEdgeRadius(); + const bool doFillet = l->hasFilletRadius(); + const bool hasFlangeSlope = l->hasFlangeSlope(); + const bool hasWebSlope = l->hasWebSlope(); + + const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double x = l->FlangeWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double d1 = l->WebThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double d2 = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double flangeSlope = hasFlangeSlope ? (l->FlangeSlope() * IfcGeom::GetValue(GV_PLANEANGLE_UNIT)) : 0.; + const double webSlope = hasWebSlope ? (l->WebSlope() * IfcGeom::GetValue(GV_PLANEANGLE_UNIT)) : 0.; + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + double dy1 = 0.0f; + double dy2 = 0.0f; + double dx1 = 0.0f; + double dx2 = 0.0f; + double f1 = 0.0f; + double f2 = 0.0f; + double f3 = 0.0f; + + if (doFillet) { + f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + } + if (doWebEdgeFillet) { + f2 = l->WebEdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + } + if (doFlangeEdgeFillet) { + f3 = l->FlangeEdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + } + + double xx, xy; + if (hasFlangeSlope) { + dy1 = (x / 2. - d1) * tan(flangeSlope); + dy2 = x / 2. * tan(flangeSlope); + } + if (hasWebSlope) { + dx1 = (y - d2) * tan(webSlope); + dx2 = y * tan(webSlope); + } + if (hasWebSlope || hasFlangeSlope) { + const double x1s = d1/2. - dx2; const double y1s = -y; + const double x1e = d1/2. + dx1; const double y1e = y - d2; + const double x2s = x; const double y2s = y - d2 + dy2; + const double x2e = d1/2.; const double y2e = y - d2 - dy1; + + const double a1 = y1e - y1s; + const double b1 = x1s - x1e; + const double c1 = a1*x1s + b1*y1s; + + const double a2 = y2e - y2s; + const double b2 = x2s - x2e; + const double c2 = a2*x2s + b2*y2s; + + const double det = a1*b2 - a2*b1; + + if (ALMOST_THE_SAME(det, 0.)) { + Logger::Message(Logger::LOG_NOTICE, "Web and flange do not intersect for:",l->entity); + return false; + } + + xx = (b2*c1 - b1*c2) / det; + xy = (a1*c2 - a2*c1) / det; + } else { + xx = d1 / 2; + xy = y - d2; + } + + gp_Trsf2d trsf2d; + IfcGeom::convert(l->Position(),trsf2d); + + double coords[16] = {d1/2.-dx2,-y, xx,xy, x,y-d2+dy2, x,y, -x,y, -x,y-d2+dy2, -xx,xy, -d1/2.+dx2,-y}; + int fillets[6] = {0,1,2,5,6,7}; + double radii[6] = {f2,f1,f3,f3,f1,f2}; + return IfcGeom::profile_helper(8, coords, (doFillet || doWebEdgeFillet || doFlangeEdgeFillet) ? 6 : 0, fillets, radii, trsf2d, face); } bool IfcGeom::convert(const IfcSchema::IfcCircleProfileDef::ptr l, TopoDS_Face& face) { const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT); @@ -338,4 +614,30 @@ bool IfcGeom::convert(const IfcSchema::IfcCircleHollowProfileDef::ptr l, TopoDS_ sfs.Perform(); face = TopoDS::Face(sfs.Shape()); return true; -} \ No newline at end of file +} +bool IfcGeom::convert(const IfcSchema::IfcEllipseProfileDef::ptr l, TopoDS_Face& face) { + double rx = l->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT); + double ry = l->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT); + + if ( rx < ALMOST_ZERO || ry < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + const bool rotated = ry > rx; + gp_Trsf2d trsf; + IfcGeom::convert(l->Position(),trsf); + + gp_Ax2 ax = gp_Ax2(); + if (rotated) { + ax.Rotate(ax.Axis(), M_PI / 2.); + std::swap(rx, ry); + } + ax.Transform(trsf); + + BRepBuilderAPI_MakeWire w; + Handle(Geom_Ellipse) ellipse = new Geom_Ellipse(ax, rx, ry); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(ellipse); + w.Add(edge); + return IfcGeom::convert_wire_to_face(w, face); +} \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 555d584673..7739cd3897 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -336,7 +336,7 @@ bool IfcGeom::profile_helper(int numVerts, double* verts, int numFillets, int* f BRepFilletAPI_MakeFillet2d fillet (face); for ( int i = 0; i < numFillets; i ++ ) { const double radius = filletRadii[i]; - if ( radius < 1e-7 ) continue; + if ( radius < ALMOST_ZERO ) continue; fillet.AddFillet(vertices[filletIndices[i]],radius); } fillet.Build(); diff --git a/src/ifcgeom/IfcRegister.h b/src/ifcgeom/IfcRegister.h index 7bb265827c..0055947b14 100644 --- a/src/ifcgeom/IfcRegister.h +++ b/src/ifcgeom/IfcRegister.h @@ -57,12 +57,19 @@ SHAPE(IfcHalfSpaceSolid); FACE(IfcArbitraryProfileDefWithVoids); FACE(IfcArbitraryClosedProfileDef); +FACE(IfcRoundedRectangleProfileDef); +FACE(IfcRectangleHollowProfileDef); FACE(IfcRectangleProfileDef); -FACE(IfcIShapeProfileDef); +FACE(IfcTrapeziumProfileDef) FACE(IfcCShapeProfileDef); +FACE(IfcIShapeProfileDef); FACE(IfcLShapeProfileDef); +FACE(IfcTShapeProfileDef); +FACE(IfcUShapeProfileDef); +FACE(IfcZShapeProfileDef); FACE(IfcCircleHollowProfileDef); FACE(IfcCircleProfileDef); +FACE(IfcEllipseProfileDef); FACE(IfcFace); WIRE(IfcPolyline);