Skip to content

Commit 868bd6e

Browse files
author
aothms
committed
Add support for ellipses with SemiAxis2 > SemiAxis1
1 parent 27e1838 commit 868bd6e

3 files changed

Lines changed: 172 additions & 2 deletions

File tree

src/examples/ellipse_pies.cpp

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/********************************************************************************
2+
* *
3+
* This file is part of IfcOpenShell. *
4+
* *
5+
* IfcOpenShell is free software: you can redistribute it and/or modify *
6+
* it under the terms of the Lesser GNU General Public License as published by *
7+
* the Free Software Foundation, either version 3.0 of the License, or *
8+
* (at your option) any later version. *
9+
* *
10+
* IfcOpenShell is distributed in the hope that it will be useful, *
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13+
* Lesser GNU General Public License for more details. *
14+
* *
15+
* You should have received a copy of the Lesser GNU General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
* *
18+
********************************************************************************/
19+
20+
/********************************************************************************
21+
* *
22+
* Example that generates profiles of trimmed ellipses. *
23+
* *
24+
********************************************************************************/
25+
26+
#include <string>
27+
#include <iostream>
28+
#include <fstream>
29+
30+
#include "../ifcparse/Ifc2x3.h"
31+
#include "../ifcparse/IfcUtil.h"
32+
#include "../ifcparse/IfcHierarchyHelper.h"
33+
34+
typedef std::string S;
35+
typedef IfcWrite::IfcGuidHelper guid;
36+
boost::none_t const null = (static_cast<boost::none_t>(0));
37+
38+
typedef struct {
39+
double r1;
40+
double r2;
41+
double t1;
42+
double t2;
43+
} EllipsePie;
44+
45+
static int i = 0;
46+
47+
void create_testcase_for(IfcHierarchyHelper& file, const EllipsePie& pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference pref) {
48+
const double deg = 1. / 180. * 3.141592653;
49+
double flt1[] = {0. , 0. };
50+
double flt2[] = {pie.r1 * cos(pie.t1*deg), pie.r2 * sin(pie.t1*deg)};
51+
double flt3[] = {pie.r1 * cos(pie.t2*deg), pie.r2 * sin(pie.t2*deg)};
52+
53+
std::vector<double> coords1(flt1, flt1 + 2);
54+
std::vector<double> coords2(flt2, flt2 + 2);
55+
std::vector<double> coords3(flt3, flt3 + 2);
56+
57+
Ifc2x3::IfcCartesianPoint* p1 = new Ifc2x3::IfcCartesianPoint(coords1);
58+
Ifc2x3::IfcCartesianPoint* p2 = new Ifc2x3::IfcCartesianPoint(coords2);
59+
Ifc2x3::IfcCartesianPoint* p3 = new Ifc2x3::IfcCartesianPoint(coords3);
60+
61+
Ifc2x3::IfcCartesianPoint::list points(new IfcTemplatedEntityList<Ifc2x3::IfcCartesianPoint>());
62+
points->push(p3);
63+
points->push(p1);
64+
points->push(p2);
65+
file.AddEntities(points->generalize());
66+
67+
68+
Ifc2x3::IfcEllipse* ellipse = new Ifc2x3::IfcEllipse(file.addPlacement2d(), pie.r1, pie.r2);
69+
file.AddEntity(ellipse);
70+
IfcEntities trim1(new IfcEntityList());
71+
IfcEntities trim2(new IfcEntityList());
72+
if (pref == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER) {
73+
trim1->push(new IfcWrite::IfcSelectHelper(pie.t1, Ifc2x3::Type::IfcParameterValue));
74+
trim2->push(new IfcWrite::IfcSelectHelper(pie.t2, Ifc2x3::Type::IfcParameterValue));
75+
} else {
76+
trim1->push(p2);
77+
trim2->push(p3);
78+
}
79+
Ifc2x3::IfcTrimmedCurve* trim = new Ifc2x3::IfcTrimmedCurve(ellipse, trim1, trim2, true, pref);
80+
file.AddEntity(trim);
81+
82+
Ifc2x3::IfcCompositeCurveSegment::list segments(new IfcTemplatedEntityList<Ifc2x3::IfcCompositeCurveSegment>());
83+
Ifc2x3::IfcCompositeCurveSegment* s2 = new Ifc2x3::IfcCompositeCurveSegment(Ifc2x3::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, trim);
84+
85+
Ifc2x3::IfcPolyline* poly = new Ifc2x3::IfcPolyline(points);
86+
file.AddEntity(poly);
87+
Ifc2x3::IfcCompositeCurveSegment* s1 = new Ifc2x3::IfcCompositeCurveSegment(Ifc2x3::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly);
88+
segments->push(s1);
89+
90+
segments->push(s2);
91+
file.AddEntities(segments->generalize());
92+
93+
Ifc2x3::IfcCompositeCurve* ccurve = new Ifc2x3::IfcCompositeCurve(segments, false);
94+
Ifc2x3::IfcArbitraryClosedProfileDef* profile = new Ifc2x3::IfcArbitraryClosedProfileDef(Ifc2x3::IfcProfileTypeEnum::IfcProfileType_AREA, null, ccurve);
95+
file.AddEntity(ccurve);
96+
file.AddEntity(profile);
97+
98+
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
99+
guid(), 0, S("profile"), null, null, 0, 0, null, null);
100+
file.addBuildingProduct(product);
101+
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
102+
103+
product->setObjectPlacement(file.addLocalPlacement(200 * i++));
104+
105+
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(profile,
106+
file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 20.0);
107+
108+
file.AddEntity(solid);
109+
110+
IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
111+
IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
112+
113+
items->push(solid);
114+
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
115+
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("SweptSolid"), items);
116+
reps->push(rep);
117+
118+
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
119+
file.AddEntity(rep);
120+
file.AddEntity(shape);
121+
122+
product->setRepresentation(shape);
123+
}
124+
125+
int main(int argc, char** argv) {
126+
const std::string filename = "ellipse_pies.ifc";
127+
IfcHierarchyHelper file;
128+
{ EllipsePie pie = {80., 50., 0., 150.};
129+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
130+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
131+
{ EllipsePie pie = {80, 50., 30., 300.};
132+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
133+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
134+
{ EllipsePie pie = {80, 50., 300., 30.};
135+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
136+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
137+
{ EllipsePie pie = {50., 80., 0., 150.};
138+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
139+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
140+
{ EllipsePie pie = {50, 80., 30., 300.};
141+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
142+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
143+
{ EllipsePie pie = {50, 80., 300., 30.};
144+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
145+
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
146+
std::ofstream f(filename.c_str());
147+
f << file;
148+
}

src/ifcgeom/IfcGeomCurves.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
* *
2424
********************************************************************************/
2525

26+
#include <algorithm>
27+
2628
#include <gp_Pnt.hxx>
2729
#include <gp_Vec.hxx>
2830
#include <gp_Dir.hxx>
@@ -96,7 +98,12 @@ bool IfcGeom::convert(const IfcSchema::IfcCircle::ptr l, Handle(Geom_Curve)& cur
9698
bool IfcGeom::convert(const IfcSchema::IfcEllipse::ptr l, Handle(Geom_Curve)& curve) {
9799
double x = l->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT);
98100
double y = l->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT);
99-
if ( x == 0.0f || y == 0.0f || y > x ) { return false; }
101+
if (x < ALMOST_ZERO || y < ALMOST_ZERO) { return false; }
102+
// Open Cascade does not allow ellipses of which the minor radius
103+
// is greater than the major radius. Hence, in this case, the
104+
// ellipse is rotated. Note that special care needs to be taken
105+
// when creating a trimmed curve off of an ellipse like this.
106+
const bool rotated = y > x;
100107
gp_Trsf trsf;
101108
IfcSchema::IfcAxis2Placement placement = l->Position();
102109
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
@@ -106,7 +113,12 @@ bool IfcGeom::convert(const IfcSchema::IfcEllipse::ptr l, Handle(Geom_Curve)& cu
106113
IfcGeom::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d);
107114
trsf = trsf2d;
108115
}
109-
gp_Ax2 ax = gp_Ax2().Transformed(trsf);
116+
gp_Ax2 ax = gp_Ax2();
117+
if (rotated) {
118+
ax.Rotate(ax.Axis(), M_PI / 2.);
119+
std::swap(x, y);
120+
}
121+
ax.Transform(trsf);
110122
curve = new Geom_Ellipse(ax, x, y);
111123
return true;
112124
}

src/ifcgeom/IfcGeomWires.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,16 @@ bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire
243243
const double magnitude = line->Dir()->Magnitude();
244244
flts[0] *= magnitude; flts[1] *= magnitude;
245245
}
246+
if ( basis_curve->is(IfcSchema::Type::IfcEllipse) ) {
247+
IfcSchema::IfcEllipse* ellipse = static_cast<IfcSchema::IfcEllipse*>(basis_curve);
248+
double x = ellipse->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT);
249+
double y = ellipse->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT);
250+
const bool rotated = y > x;
251+
if (rotated) {
252+
flts[0] -= M_PI / 2.;
253+
flts[1] -= M_PI / 2.;
254+
}
255+
}
246256
if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],(double)(M_PI*2.0)),0.0f) ) {
247257
w.Add(BRepBuilderAPI_MakeEdge(curve));
248258
} else {

0 commit comments

Comments
 (0)