diff --git a/src/examples/ellipse_pies.cpp b/src/examples/ellipse_pies.cpp new file mode 100644 index 0000000000..967eb2cd12 --- /dev/null +++ b/src/examples/ellipse_pies.cpp @@ -0,0 +1,148 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +/******************************************************************************** + * * + * Example that generates profiles of trimmed ellipses. * + * * + ********************************************************************************/ + +#include +#include +#include + +#include "../ifcparse/Ifc2x3.h" +#include "../ifcparse/IfcUtil.h" +#include "../ifcparse/IfcHierarchyHelper.h" + +typedef std::string S; +typedef IfcWrite::IfcGuidHelper guid; +boost::none_t const null = (static_cast(0)); + +typedef struct { + double r1; + double r2; + double t1; + double t2; +} EllipsePie; + +static int i = 0; + +void create_testcase_for(IfcHierarchyHelper& file, const EllipsePie& pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference pref) { + const double deg = 1. / 180. * 3.141592653; + double flt1[] = {0. , 0. }; + double flt2[] = {pie.r1 * cos(pie.t1*deg), pie.r2 * sin(pie.t1*deg)}; + double flt3[] = {pie.r1 * cos(pie.t2*deg), pie.r2 * sin(pie.t2*deg)}; + + std::vector coords1(flt1, flt1 + 2); + std::vector coords2(flt2, flt2 + 2); + std::vector coords3(flt3, flt3 + 2); + + Ifc2x3::IfcCartesianPoint* p1 = new Ifc2x3::IfcCartesianPoint(coords1); + Ifc2x3::IfcCartesianPoint* p2 = new Ifc2x3::IfcCartesianPoint(coords2); + Ifc2x3::IfcCartesianPoint* p3 = new Ifc2x3::IfcCartesianPoint(coords3); + + Ifc2x3::IfcCartesianPoint::list points(new IfcTemplatedEntityList()); + points->push(p3); + points->push(p1); + points->push(p2); + file.AddEntities(points->generalize()); + + + Ifc2x3::IfcEllipse* ellipse = new Ifc2x3::IfcEllipse(file.addPlacement2d(), pie.r1, pie.r2); + file.AddEntity(ellipse); + IfcEntities trim1(new IfcEntityList()); + IfcEntities trim2(new IfcEntityList()); + if (pref == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER) { + trim1->push(new IfcWrite::IfcSelectHelper(pie.t1, Ifc2x3::Type::IfcParameterValue)); + trim2->push(new IfcWrite::IfcSelectHelper(pie.t2, Ifc2x3::Type::IfcParameterValue)); + } else { + trim1->push(p2); + trim2->push(p3); + } + Ifc2x3::IfcTrimmedCurve* trim = new Ifc2x3::IfcTrimmedCurve(ellipse, trim1, trim2, true, pref); + file.AddEntity(trim); + + Ifc2x3::IfcCompositeCurveSegment::list segments(new IfcTemplatedEntityList()); + Ifc2x3::IfcCompositeCurveSegment* s2 = new Ifc2x3::IfcCompositeCurveSegment(Ifc2x3::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, trim); + + Ifc2x3::IfcPolyline* poly = new Ifc2x3::IfcPolyline(points); + file.AddEntity(poly); + Ifc2x3::IfcCompositeCurveSegment* s1 = new Ifc2x3::IfcCompositeCurveSegment(Ifc2x3::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly); + segments->push(s1); + + segments->push(s2); + file.AddEntities(segments->generalize()); + + Ifc2x3::IfcCompositeCurve* ccurve = new Ifc2x3::IfcCompositeCurve(segments, false); + Ifc2x3::IfcArbitraryClosedProfileDef* profile = new Ifc2x3::IfcArbitraryClosedProfileDef(Ifc2x3::IfcProfileTypeEnum::IfcProfileType_AREA, null, ccurve); + file.AddEntity(ccurve); + file.AddEntity(profile); + + IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy( + guid(), 0, S("profile"), null, null, 0, 0, null, null); + file.addBuildingProduct(product); + product->setOwnerHistory(file.getSingle()); + + product->setObjectPlacement(file.addLocalPlacement(200 * i++)); + + IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(profile, + file.addPlacement3d(), file.addTriplet(0, 0, 1), 20.0); + + file.AddEntity(solid); + + IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList()); + IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList()); + + items->push(solid); + IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation( + file.getSingle(), S("Body"), S("SweptSolid"), items); + reps->push(rep); + + IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps); + file.AddEntity(rep); + file.AddEntity(shape); + + product->setRepresentation(shape); +} + +int main(int argc, char** argv) { + const std::string filename = "ellipse_pies.ifc"; + IfcHierarchyHelper file; + { EllipsePie pie = {80., 50., 0., 150.}; + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER); + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);} + { EllipsePie pie = {80, 50., 30., 300.}; + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER); + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);} + { EllipsePie pie = {80, 50., 300., 30.}; + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER); + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);} + { EllipsePie pie = {50., 80., 0., 150.}; + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER); + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);} + { EllipsePie pie = {50, 80., 30., 300.}; + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER); + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);} + { EllipsePie pie = {50, 80., 300., 30.}; + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER); + create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);} + std::ofstream f(filename.c_str()); + f << file; +} diff --git a/src/ifcgeom/IfcGeomCurves.cpp b/src/ifcgeom/IfcGeomCurves.cpp index 1a89b74da3..0c5580be06 100644 --- a/src/ifcgeom/IfcGeomCurves.cpp +++ b/src/ifcgeom/IfcGeomCurves.cpp @@ -23,6 +23,8 @@ * * ********************************************************************************/ +#include + #include #include #include @@ -96,7 +98,12 @@ bool IfcGeom::convert(const IfcSchema::IfcCircle::ptr l, Handle(Geom_Curve)& cur bool IfcGeom::convert(const IfcSchema::IfcEllipse::ptr l, Handle(Geom_Curve)& curve) { double x = l->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT); double y = l->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT); - if ( x == 0.0f || y == 0.0f || y > x ) { return false; } + if (x < ALMOST_ZERO || y < ALMOST_ZERO) { return false; } + // Open Cascade does not allow ellipses of which the minor radius + // is greater than the major radius. Hence, in this case, the + // ellipse is rotated. Note that special care needs to be taken + // when creating a trimmed curve off of an ellipse like this. + const bool rotated = y > x; gp_Trsf trsf; IfcSchema::IfcAxis2Placement placement = l->Position(); if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { @@ -106,7 +113,12 @@ bool IfcGeom::convert(const IfcSchema::IfcEllipse::ptr l, Handle(Geom_Curve)& cu IfcGeom::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d); trsf = trsf2d; } - gp_Ax2 ax = gp_Ax2().Transformed(trsf); + gp_Ax2 ax = gp_Ax2(); + if (rotated) { + ax.Rotate(ax.Axis(), M_PI / 2.); + std::swap(x, y); + } + ax.Transform(trsf); curve = new Geom_Ellipse(ax, x, y); return true; } diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index 5b7c87df8b..b86bb6308a 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -243,6 +243,16 @@ bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire const double magnitude = line->Dir()->Magnitude(); flts[0] *= magnitude; flts[1] *= magnitude; } + if ( basis_curve->is(IfcSchema::Type::IfcEllipse) ) { + IfcSchema::IfcEllipse* ellipse = static_cast(basis_curve); + double x = ellipse->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT); + double y = ellipse->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const bool rotated = y > x; + if (rotated) { + flts[0] -= M_PI / 2.; + flts[1] -= M_PI / 2.; + } + } if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],(double)(M_PI*2.0)),0.0f) ) { w.Add(BRepBuilderAPI_MakeEdge(curve)); } else {