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 {