xyz; xyz.push_back(pnt.X()); xyz.push_back(pnt.Y()); xyz.push_back(pnt.Z());
- IfcSchema::IfcCartesianPoint* cpnt = new IfcSchema::IfcCartesianPoint(xyz);
- vertices.push_back(cpnt);
- es->push(cpnt);
- }
- const Poly_Array1OfTriangle& triangles = tri->Triangles();
- for (int i = 1; i <= triangles.Length(); ++ i) {
- int n1, n2, n3;
- triangles(i).Get(n1, n2, n3);
- IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
- points->push(vertices[n1-1]);
- points->push(vertices[n2-1]);
- points->push(vertices[n3-1]);
- IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
- IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, face.Orientation() != TopAbs_REVERSED);
- IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
- bounds->push(bound);
- IfcSchema::IfcFace* face2 = new IfcSchema::IfcFace(bounds);
- es->push(loop);
- es->push(bound);
- es->push(face2);
- faces->push(face2);
- }
- }
- }
- IfcSchema::IfcOpenShell* shell = new IfcSchema::IfcOpenShell(faces);
- IfcSchema::IfcConnectedFaceSet::list::ptr shells (new IfcSchema::IfcConnectedFaceSet::list);
- shells->push(shell);
- IfcSchema::IfcFaceBasedSurfaceModel* surface_model = new IfcSchema::IfcFaceBasedSurfaceModel(shells);
-
- IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
- IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);
-
- items->push(surface_model);
-
- IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
- 0, std::string("Facetation"), std::string("SurfaceModel"), items);
-
- reps->push(rep);
- IfcSchema::IfcProductDefinitionShape* shapedef = new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, reps);
-
- es->push(shell);
- es->push(surface_model);
- es->push(rep);
- es->push(shapedef);
-
- return shapedef;
-}
-
// Returns the vertex part of an TopoDS_Edge edge that is not TopoDS_Vertex vertex
TopoDS_Vertex find_other(const TopoDS_Edge& edge, const TopoDS_Vertex& vertex) {
TopExp_Explorer exp(edge, TopAbs_VERTEX);
diff --git a/src/ifcgeom/IfcGeomRepresentation.h b/src/ifcgeom/IfcGeomRepresentation.h
index 4c7d3a0578..472b049813 100644
--- a/src/ifcgeom/IfcGeomRepresentation.h
+++ b/src/ifcgeom/IfcGeomRepresentation.h
@@ -259,7 +259,8 @@ namespace IfcGeom {
if (num_faces == 0) {
// Edges are only emitted if there are no faces. A mixed representation of faces
// and loose edges is discouraged by the standard. An alternative would be to use
- // TopExp::MapShapesAndAncestors() to find edges that do not belong to any face.
+ // TopExp_Explorer texp(s, TopAbs_EDGE, TopAbs_FACE) to find edges that do not
+ // belong to any face.
for (TopExp_Explorer texp(s, TopAbs_EDGE); texp.More(); texp.Next()) {
BRepAdaptor_Curve crv(TopoDS::Edge(texp.Current()));
GCPnts_QuasiUniformDeflection tessellater(crv, settings().deflection_tolerance());
@@ -267,6 +268,40 @@ namespace IfcGeom {
int start = (int)_verts.size() / 3;
for (int i = 1; i <= n; ++i) {
gp_XYZ p = tessellater.Value(i).XYZ();
+
+ /*
+ // In case you want direction arrows on your edges
+ double u = tessellater.Parameter(i);
+ gp_XYZ p2, p3;
+ gp_Pnt tmp;
+ gp_Vec tmp2;
+ crv.D1(u, tmp, tmp2);
+ gp_Dir d1, d2, d3, d4;
+ d1 = tmp2;
+ if (texp.Current().Orientation() == TopAbs_REVERSED) {
+ d1 = -d1;
+ }
+ if (fabs(d1.Z()) < 0.5) {
+ d2 = d1.Crossed(gp::DZ());
+ } else {
+ d2 = d1.Crossed(gp::DY());
+ }
+ d3 = d1.XYZ() + d2.XYZ();
+ d4 = d1.XYZ() - d2.XYZ();
+ p2 = p - d3.XYZ() / 10.;
+ p3 = p - d4.XYZ() / 10.;
+ trsf.Transforms(p2);
+ trsf.Transforms(p3);
+ _material_ids.push_back(surface_style_id);
+ _material_ids.push_back(surface_style_id);
+ _verts.push_back(static_cast(p2.X()));
+ _verts.push_back(static_cast
(p2.Y()));
+ _verts.push_back(static_cast
(p2.Z()));
+ _verts.push_back(static_cast
(p3.X()));
+ _verts.push_back(static_cast
(p3.Y()));
+ _verts.push_back(static_cast
(p3.Z()));
+ */
+
trsf.Transforms(p);
_material_ids.push_back(surface_style_id);
@@ -278,7 +313,14 @@ namespace IfcGeom {
if (i > 1) {
_edges.push_back(start + i - 2);
_edges.push_back(start + i - 1);
+ // _edges.push_back(start + 3 * (i - 2) + 2);
+ // _edges.push_back(start + 3 * (i - 1) + 2);
}
+
+ // _edges.push_back(start + 3 * (i - 1) + 0);
+ // _edges.push_back(start + 3 * (i - 1) + 2);
+ // _edges.push_back(start + 3 * (i - 1) + 1);
+ // _edges.push_back(start + 3 * (i - 1) + 2);
}
}
}
diff --git a/src/ifcgeom/IfcGeomSerialisation.cpp b/src/ifcgeom/IfcGeomSerialisation.cpp
new file mode 100644
index 0000000000..e473480455
--- /dev/null
+++ b/src/ifcgeom/IfcGeomSerialisation.cpp
@@ -0,0 +1,648 @@
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include "IfcGeom.h"
+
+template
+int convert_to_ifc(const T& t, U*& u, bool /*advanced*/) {
+ std::vector coords(3);
+ coords[0] = t.X(); coords[1] = t.Y(); coords[2] = t.Z();
+ u = new U(coords);
+ return 1;
+}
+
+template <>
+int convert_to_ifc(const TopoDS_Vertex& v, IfcSchema::IfcCartesianPoint*& p, bool advanced) {
+ gp_Pnt pnt = BRep_Tool::Pnt(v);
+ return convert_to_ifc(pnt, p, advanced);
+}
+
+template <>
+int convert_to_ifc(const TopoDS_Vertex& v, IfcSchema::IfcVertex*& vertex, bool advanced) {
+ IfcSchema::IfcCartesianPoint* p;
+ convert_to_ifc(v, p, advanced);
+ vertex = new IfcSchema::IfcVertexPoint(p);
+ return 1;
+}
+
+template <>
+int convert_to_ifc(const gp_Ax2& a, IfcSchema::IfcAxis2Placement3D*& ax, bool advanced) {
+ IfcSchema::IfcCartesianPoint* p;
+ IfcSchema::IfcDirection *x, *z;
+ if (!(convert_to_ifc(a.Location(), p, advanced) && convert_to_ifc(a.Direction(), z, advanced) && convert_to_ifc(a.XDirection(), x, advanced))) {
+ return 0;
+ }
+ ax = new IfcSchema::IfcAxis2Placement3D(p, z, x);
+ return 1;
+}
+
+template
+void opencascade_array_to_vector(T& t, std::vector& u) {
+ u.reserve(t.Length());
+ for (int i = t.Lower(); i <= t.Upper(); ++i) {
+ u.push_back(t.Value(i));
+ }
+}
+
+template
+void opencascade_array_to_vector2(T& t, std::vector< std::vector >& u) {
+ u.reserve(t.RowLength());
+ for (int j = t.LowerRow(); j <= t.UpperRow(); ++j) {
+ std::vector v;
+ v.reserve(t.ColLength());
+ for (int i = t.LowerCol(); i <= t.UpperCol(); ++i) {
+ v.push_back(t.Value(j, i));
+ }
+ u.push_back(v);
+ }
+}
+
+#ifdef USE_IFC4
+IfcSchema::IfcKnotType::IfcKnotType opencascade_knotspec_to_ifc(GeomAbs_BSplKnotDistribution bspline_knot_spec) {
+ IfcSchema::IfcKnotType::IfcKnotType knot_spec = IfcSchema::IfcKnotType::IfcKnotType_UNSPECIFIED;
+ if (bspline_knot_spec == GeomAbs_Uniform) {
+ knot_spec = IfcSchema::IfcKnotType::IfcKnotType_UNIFORM_KNOTS;
+ } else if (bspline_knot_spec == GeomAbs_QuasiUniform) {
+ knot_spec = IfcSchema::IfcKnotType::IfcKnotType_QUASI_UNIFORM_KNOTS;
+ } else if (bspline_knot_spec == GeomAbs_PiecewiseBezier) {
+ knot_spec = IfcSchema::IfcKnotType::IfcKnotType_PIECEWISE_BEZIER_KNOTS;
+ }
+ return knot_spec;
+}
+#endif
+
+template <>
+int convert_to_ifc(const Handle_Geom_Curve& c, IfcSchema::IfcCurve*& curve, bool advanced) {
+ if (c->DynamicType() == STANDARD_TYPE(Geom_Line)) {
+ IfcSchema::IfcDirection* d;
+ IfcSchema::IfcCartesianPoint* p;
+
+ Handle_Geom_Line line = Handle_Geom_Line::DownCast(c);
+
+ if (!convert_to_ifc(line->Position().Location(), p, advanced)) {
+ return 0;
+ }
+ if (!convert_to_ifc(line->Position().Direction(), d, advanced)) {
+ return 0;
+ }
+
+ IfcSchema::IfcVector* v = new IfcSchema::IfcVector(d, 1.);
+ curve = new IfcSchema::IfcLine(p, v);
+
+ return 1;
+ } else if (c->DynamicType() == STANDARD_TYPE(Geom_Circle)) {
+ IfcSchema::IfcAxis2Placement3D* ax;
+
+ Handle_Geom_Circle circle = Handle_Geom_Circle::DownCast(c);
+
+ convert_to_ifc(circle->Position(), ax, advanced);
+ curve = new IfcSchema::IfcCircle(ax, circle->Radius());
+
+ return 1;
+ } else if (c->DynamicType() == STANDARD_TYPE(Geom_Ellipse)) {
+ IfcSchema::IfcAxis2Placement3D* ax;
+
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(c);
+
+ convert_to_ifc(ellipse->Position(), ax, advanced);
+ curve = new IfcSchema::IfcEllipse(ax, ellipse->MajorRadius(), ellipse->MinorRadius());
+
+ return 1;
+ }
+#ifdef USE_IFC4
+ else if (c->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve)) {
+ Handle_Geom_BSplineCurve bspline = Handle_Geom_BSplineCurve::DownCast(c);
+
+ IfcSchema::IfcCartesianPoint::list::ptr points(new IfcSchema::IfcCartesianPoint::list);
+ TColgp_Array1OfPnt poles(1, bspline->NbPoles());
+ bspline->Poles(poles);
+ for (int i = 1; i <= bspline->NbPoles(); ++i) {
+ IfcSchema::IfcCartesianPoint* p;
+ if (!convert_to_ifc(poles.Value(i), p, advanced)) {
+ return 0;
+ }
+ points->push(p);
+ }
+ IfcSchema::IfcKnotType::IfcKnotType knot_spec = opencascade_knotspec_to_ifc(bspline->KnotDistribution());
+
+ std::vector mults;
+ std::vector knots;
+ std::vector weights;
+
+ TColStd_Array1OfInteger bspline_mults(1, bspline->NbKnots());
+ TColStd_Array1OfReal bspline_knots(1, bspline->NbKnots());
+ TColStd_Array1OfReal bspline_weights(1, bspline->NbPoles());
+
+ bspline->Multiplicities(bspline_mults);
+ bspline->Knots(bspline_knots);
+ bspline->Weights(bspline_weights);
+
+ opencascade_array_to_vector(bspline_mults, mults);
+ opencascade_array_to_vector(bspline_knots, knots);
+ opencascade_array_to_vector(bspline_weights, weights);
+
+ bool rational = false;
+ for (std::vector::const_iterator it = weights.begin(); it != weights.end(); ++it) {
+ if ((*it) != 1.) {
+ rational = true;
+ break;
+ }
+ }
+
+ if (rational) {
+ curve = new IfcSchema::IfcRationalBSplineCurveWithKnots(
+ bspline->Degree(),
+ points,
+ IfcSchema::IfcBSplineCurveForm::IfcBSplineCurveForm_UNSPECIFIED,
+ bspline->IsClosed(),
+ false,
+ mults,
+ knots,
+ knot_spec,
+ weights
+ );
+ } else {
+ curve = new IfcSchema::IfcBSplineCurveWithKnots(
+ bspline->Degree(),
+ points,
+ IfcSchema::IfcBSplineCurveForm::IfcBSplineCurveForm_UNSPECIFIED,
+ bspline->IsClosed(),
+ false,
+ mults,
+ knots,
+ knot_spec
+ );
+ }
+
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+template <>
+int convert_to_ifc(const Handle_Geom_Surface& s, IfcSchema::IfcSurface*& surface, bool advanced) {
+ if (s->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
+ Handle_Geom_Plane plane = Handle_Geom_Plane::DownCast(s);
+ IfcSchema::IfcAxis2Placement3D* place;
+ /// @todo: Note that the Ax3 is converted to an Ax2 here
+ if (!convert_to_ifc(plane->Position().Ax2(), place, advanced)) {
+ return 0;
+ }
+ surface = new IfcSchema::IfcPlane(place);
+ return 1;
+ }
+#ifdef USE_IFC4
+ else if (s->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
+ Handle_Geom_CylindricalSurface cyl = Handle_Geom_CylindricalSurface::DownCast(s);
+ IfcSchema::IfcAxis2Placement3D* place;
+ /// @todo: Note that the Ax3 is converted to an Ax2 here
+ if (!convert_to_ifc(cyl->Position().Ax2(), place, advanced)) {
+ return 0;
+ }
+ surface = new IfcSchema::IfcCylindricalSurface(place, cyl->Radius());
+ return 1;
+ } else if (s->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface)) {
+ typedef IfcTemplatedEntityListList points_t;
+
+ Handle_Geom_BSplineSurface bspline = Handle_Geom_BSplineSurface::DownCast(s);
+ points_t::ptr points(new points_t);
+
+ TColgp_Array2OfPnt poles(1, bspline->NbUPoles(), 1, bspline->NbVPoles());
+ bspline->Poles(poles);
+ for (int i = 1; i <= bspline->NbUPoles(); ++i) {
+ std::vector ps;
+ ps.reserve(bspline->NbVPoles());
+ for (int j = 1; j <= bspline->NbVPoles(); ++j) {
+ IfcSchema::IfcCartesianPoint* p;
+ if (!convert_to_ifc(poles.Value(i, j), p, advanced)) {
+ return 0;
+ }
+ ps.push_back(p);
+ }
+ points->push(ps);
+ }
+
+ IfcSchema::IfcKnotType::IfcKnotType knot_spec_u = opencascade_knotspec_to_ifc(bspline->UKnotDistribution());
+ IfcSchema::IfcKnotType::IfcKnotType knot_spec_v = opencascade_knotspec_to_ifc(bspline->VKnotDistribution());
+
+ if (knot_spec_u != knot_spec_v) {
+ knot_spec_u = IfcSchema::IfcKnotType::IfcKnotType_UNSPECIFIED;
+ }
+
+ std::vector umults;
+ std::vector vmults;
+ std::vector uknots;
+ std::vector vknots;
+ std::vector< std::vector > weights;
+
+ TColStd_Array1OfInteger bspline_umults(1, bspline->NbUKnots());
+ TColStd_Array1OfInteger bspline_vmults(1, bspline->NbVKnots());
+ TColStd_Array1OfReal bspline_uknots(1, bspline->NbUKnots());
+ TColStd_Array1OfReal bspline_vknots(1, bspline->NbVKnots());
+ TColStd_Array2OfReal bspline_weights(1, bspline->NbUPoles(), 1, bspline->NbVPoles());
+
+ bspline->UMultiplicities(bspline_umults);
+ bspline->VMultiplicities(bspline_vmults);
+ bspline->UKnots(bspline_uknots);
+ bspline->VKnots(bspline_vknots);
+ bspline->Weights(bspline_weights);
+
+ opencascade_array_to_vector(bspline_umults, umults);
+ opencascade_array_to_vector(bspline_vmults, vmults);
+ opencascade_array_to_vector(bspline_uknots, uknots);
+ opencascade_array_to_vector(bspline_vknots, vknots);
+ opencascade_array_to_vector2(bspline_weights, weights);
+
+ bool rational = false;
+ for (std::vector< std::vector >::const_iterator it = weights.begin(); it != weights.end(); ++it) {
+ for (std::vector::const_iterator jt = it->begin(); jt != it->end(); ++jt) {
+ if ((*jt) != 1.) {
+ rational = true;
+ break;
+ }
+ }
+ }
+
+ if (rational) {
+ surface = new IfcSchema::IfcRationalBSplineSurfaceWithKnots(
+ bspline->UDegree(),
+ bspline->VDegree(),
+ points,
+ IfcSchema::IfcBSplineSurfaceForm::IfcBSplineSurfaceForm_UNSPECIFIED,
+ bspline->IsUClosed(),
+ bspline->IsVClosed(),
+ false,
+ umults,
+ vmults,
+ uknots,
+ vknots,
+ knot_spec_u,
+ weights
+ );
+ } else {
+ surface = new IfcSchema::IfcBSplineSurfaceWithKnots(
+ bspline->UDegree(),
+ bspline->VDegree(),
+ points,
+ IfcSchema::IfcBSplineSurfaceForm::IfcBSplineSurfaceForm_UNSPECIFIED,
+ bspline->IsUClosed(),
+ bspline->IsVClosed(),
+ false,
+ umults,
+ vmults,
+ uknots,
+ vknots,
+ knot_spec_u
+ );
+ }
+
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+template <>
+int convert_to_ifc(const TopoDS_Edge& e, IfcSchema::IfcCurve*& c, bool advanced) {
+ double a, b;
+ IfcSchema::IfcCurve* base;
+
+ Handle_Geom_Curve crv = BRep_Tool::Curve(e, a, b);
+ if (!convert_to_ifc(crv, base, advanced)) {
+ return 0;
+ }
+
+ IfcEntityList::ptr trim1(new IfcEntityList);
+ IfcEntityList::ptr trim2(new IfcEntityList);
+ trim1->push(new IfcSchema::IfcParameterValue(a));
+ trim2->push(new IfcSchema::IfcParameterValue(b));
+
+ c = new IfcSchema::IfcTrimmedCurve(base, trim1, trim2, true, IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
+
+ return 1;
+}
+
+template <>
+int convert_to_ifc(const TopoDS_Edge& e, IfcSchema::IfcEdge*& edge, bool advanced) {
+ double a, b;
+
+ TopExp_Explorer exp(e, TopAbs_VERTEX);
+ if (!exp.More()) return 0;
+ TopoDS_Vertex v1 = TopoDS::Vertex(exp.Current());
+ exp.Next();
+ if (!exp.More()) return 0;
+ TopoDS_Vertex v2 = TopoDS::Vertex(exp.Current());
+
+ IfcSchema::IfcVertex *vertex1, *vertex2;
+ if (!(convert_to_ifc(v1, vertex1, advanced) && convert_to_ifc(v2, vertex2, advanced))) {
+ return 0;
+ }
+
+ Handle_Geom_Curve crv = BRep_Tool::Curve(e, a, b);
+
+ if (crv.IsNull()) {
+ return 0;
+ }
+
+ if (crv->DynamicType() == STANDARD_TYPE(Geom_Line) && !advanced) {
+ IfcSchema::IfcEdge* edge2 = new IfcSchema::IfcEdge(vertex1, vertex2);
+ edge = new IfcSchema::IfcOrientedEdge(edge2, true);
+ return 1;
+ } else {
+ IfcSchema::IfcCurve* curve;
+ if (!convert_to_ifc(crv, curve, advanced)) {
+ return 0;
+ }
+ /// @todo probably not correct
+ const bool sense = e.Orientation() == TopAbs_FORWARD;
+ IfcSchema::IfcEdge* edge2 = new IfcSchema::IfcEdgeCurve(vertex1, vertex2, curve, true);
+ edge = new IfcSchema::IfcOrientedEdge(edge2, sense);
+ return 1;
+ }
+}
+
+template <>
+int convert_to_ifc(const TopoDS_Wire& wire, IfcSchema::IfcLoop*& loop, bool advanced) {
+ bool polygonal = true;
+ for (TopExp_Explorer exp(wire, TopAbs_EDGE); exp.More(); exp.Next()) {
+ double a, b;
+ Handle_Geom_Curve crv = BRep_Tool::Curve(TopoDS::Edge(exp.Current()), a, b);
+ if (crv.IsNull()) {
+ continue;
+ }
+ if (crv->DynamicType() != STANDARD_TYPE(Geom_Line)) {
+ polygonal = false;
+ break;
+ }
+ }
+ if (!polygonal && !advanced) {
+ return 0;
+ } else if (polygonal && !advanced) {
+ IfcSchema::IfcCartesianPoint::list::ptr points(new IfcSchema::IfcCartesianPoint::list);
+ BRepTools_WireExplorer exp(wire);
+ IfcSchema::IfcCartesianPoint* p;
+ for (; exp.More(); exp.Next()) {
+ if (convert_to_ifc(exp.CurrentVertex(), p, advanced)) {
+ points->push(p);
+ } else {
+ return 0;
+ }
+ }
+ loop = new IfcSchema::IfcPolyLoop(points);
+ return 1;
+ } else {
+ IfcSchema::IfcOrientedEdge::list::ptr edges(new IfcSchema::IfcOrientedEdge::list);
+ BRepTools_WireExplorer exp(wire);
+ for (; exp.More(); exp.Next()) {
+ IfcSchema::IfcEdge* edge;
+ // With advanced set to true convert_to_ifc(TopoDS_Edge&) will always create an IfcOrientedEdge
+ if (!convert_to_ifc(exp.Current(), edge, true)) {
+ double a, b;
+ if (BRep_Tool::Curve(TopoDS::Edge(exp.Current()), a, b).IsNull()) {
+ continue;
+ } else {
+ return 0;
+ }
+ }
+ edges->push(edge->as());
+ }
+ loop = new IfcSchema::IfcEdgeLoop(edges);
+ return 1;
+ }
+}
+
+template <>
+int convert_to_ifc(const TopoDS_Face& f, IfcSchema::IfcFace*& face, bool advanced) {
+ Handle_Geom_Surface surf = BRep_Tool::Surface(f);
+ TopExp_Explorer exp(f, TopAbs_WIRE);
+ IfcSchema::IfcFaceBound::list::ptr bounds(new IfcSchema::IfcFaceBound::list);
+ int index = 0;
+ for (; exp.More(); exp.Next(), ++index) {
+ IfcSchema::IfcLoop* loop;
+ if (!convert_to_ifc(TopoDS::Wire(exp.Current()), loop, advanced)) {
+ return 0;
+ }
+ IfcSchema::IfcFaceBound* bnd;
+ if (index == 0) {
+ bnd = new IfcSchema::IfcFaceOuterBound(loop, true);
+ } else {
+ bnd = new IfcSchema::IfcFaceBound(loop, true);
+ }
+ bounds->push(bnd);
+ }
+
+ const bool is_planar = surf->DynamicType() == STANDARD_TYPE(Geom_Plane);
+
+ if (!is_planar && !advanced) {
+ return 0;
+ }
+ if (is_planar && !advanced) {
+ face = new IfcSchema::IfcFace(bounds);
+ return 1;
+ } else {
+#ifdef USE_IFC4
+ IfcSchema::IfcSurface* surface;
+ if (!convert_to_ifc(surf, surface, advanced)) {
+ return 0;
+ }
+ face = new IfcSchema::IfcAdvancedFace(bounds, surface, f.Orientation() == TopAbs_FORWARD);
+ return 1;
+#else
+ // No IfcAdvancedFace in Ifc2x3
+ return 0;
+#endif
+ }
+}
+
+template
+int convert_to_ifc(const TopoDS_Shape& s, U*& item, bool advanced) {
+ IfcSchema::IfcFace::list::ptr faces(new IfcSchema::IfcFace::list);
+ IfcSchema::IfcFace* f;
+ for (TopExp_Explorer exp(s, TopAbs_FACE); exp.More(); exp.Next()) {
+ if (convert_to_ifc(TopoDS::Face(exp.Current()), f, advanced)) {
+ faces->push(f);
+ }
+ }
+ item = new U(faces);
+ return faces->size();
+}
+
+IfcSchema::IfcProductDefinitionShape* IfcGeom::serialise(const TopoDS_Shape& shape, bool advanced) {
+#ifndef USE_IFC4
+ advanced = false;
+#endif
+
+ for (TopExp_Explorer exp(shape, TopAbs_COMPSOLID); exp.More();) {
+ /// @todo CompSolids are not supported
+ return 0;
+ }
+
+ IfcSchema::IfcRepresentation* rep = 0;
+ IfcSchema::IfcRepresentationItem::list::ptr items(new IfcSchema::IfcRepresentationItem::list);
+
+ // First check if there is a solid with one or more shells
+ for (TopExp_Explorer exp(shape, TopAbs_SOLID); exp.More(); exp.Next()) {
+ IfcSchema::IfcClosedShell* outer = 0;
+ IfcSchema::IfcClosedShell::list::ptr inner(new IfcSchema::IfcClosedShell::list);
+ for (TopExp_Explorer exp2(exp.Current(), TopAbs_SHELL); exp2.More(); exp2.Next()) {
+ IfcSchema::IfcClosedShell* shell;
+ if (!convert_to_ifc(exp2.Current(), shell, advanced)) {
+ return 0;
+ }
+ /// @todo Are shells always in this order or does Orientation() needs to be checked?
+ if (outer) {
+ inner->push(shell);
+ } else {
+ outer = shell;
+ }
+ }
+
+#ifdef USE_IFC4
+ if (advanced) {
+ if (inner->size()) {
+ items->push(new IfcSchema::IfcAdvancedBrepWithVoids(outer, inner));
+ } else {
+ items->push(new IfcSchema::IfcAdvancedBrep(outer));
+ }
+ } else
+#endif
+
+ /// @todo this is not necessarily correct as the shell is not necessarily facetted.
+ if (inner->size()) {
+ items->push(new IfcSchema::IfcFacetedBrepWithVoids(outer, inner));
+ } else {
+ items->push(new IfcSchema::IfcFacetedBrep(outer));
+ }
+
+ }
+
+ if (items->size() > 0) {
+ rep = new IfcSchema::IfcShapeRepresentation(0, std::string("Body"), std::string("Brep"), items);
+ } else {
+
+ // If not, see if there is a shell
+ IfcSchema::IfcOpenShell::list::ptr shells(new IfcSchema::IfcOpenShell::list);
+ for (TopExp_Explorer exp(shape, TopAbs_SHELL); exp.More(); exp.Next()) {
+ IfcSchema::IfcOpenShell* shell;
+ if (!convert_to_ifc(exp.Current(), shell, advanced)) {
+ return 0;
+ }
+ shells->push(shell);
+ }
+
+ if (shells->size() > 0) {
+ items->push(new IfcSchema::IfcShellBasedSurfaceModel(shells->generalize()));
+ rep = new IfcSchema::IfcShapeRepresentation(0, std::string("Body"), std::string("Brep"), items);
+ } else {
+
+ // If not, see if there is are one of more faces. Note that they will be grouped into a shell.
+ IfcSchema::IfcOpenShell* shell;
+ int face_count = convert_to_ifc(shape, shell, advanced);
+
+ if (face_count > 0) {
+ items->push(shell);
+ rep = new IfcSchema::IfcShapeRepresentation(0, std::string("Body"), std::string("Brep"), items);
+ } else {
+
+ // If not, see if there are any edges. Note that wires are skipped as
+ // they are not commonly top-level geometrical descriptions in IFC.
+ // Also note that edges are written as trimmed curves rather than edges.
+
+ IfcEntityList::ptr edges(new IfcEntityList);
+
+ for (TopExp_Explorer exp(shape, TopAbs_EDGE); exp.More(); exp.Next()) {
+ IfcSchema::IfcCurve* c;
+ if (!convert_to_ifc(TopoDS::Edge(exp.Current()), c, advanced)) {
+ return 0;
+ }
+ edges->push(c);
+ }
+
+ if (edges->size() == 0) {
+ return 0;
+ } else if (edges->size() == 1) {
+ rep = new IfcSchema::IfcShapeRepresentation(0, std::string("Axis"), std::string("Curve2D"), edges->as());
+ } else {
+ // A geometric set is created as that probably (?) makes more sense in IFC
+ IfcSchema::IfcGeometricCurveSet* curves = new IfcSchema::IfcGeometricCurveSet(edges);
+ items->push(curves);
+ rep = new IfcSchema::IfcShapeRepresentation(0, std::string("Axis"), std::string("GeometricCurveSet"), items->as());
+ }
+
+ }
+ }
+ }
+
+ IfcSchema::IfcRepresentation::list::ptr reps(new IfcSchema::IfcRepresentation::list);
+ reps->push(rep);
+ return new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, reps);
+}
+
+IfcSchema::IfcProductDefinitionShape* IfcGeom::tesselate(const TopoDS_Shape& shape, double deflection) {
+ BRepMesh_IncrementalMesh(shape, deflection);
+
+ IfcSchema::IfcFace::list::ptr faces(new IfcSchema::IfcFace::list);
+
+ for (TopExp_Explorer exp(shape, TopAbs_FACE); exp.More(); exp.Next()) {
+ const TopoDS_Face& face = TopoDS::Face(exp.Current());
+ TopLoc_Location loc;
+ Handle(Poly_Triangulation) tri = BRep_Tool::Triangulation(face, loc);
+
+ if (!tri.IsNull()) {
+ const TColgp_Array1OfPnt& nodes = tri->Nodes();
+ std::vector vertices;
+ for (int i = 1; i <= nodes.Length(); ++i) {
+ gp_Pnt pnt = nodes(i).Transformed(loc);
+ std::vector xyz; xyz.push_back(pnt.X()); xyz.push_back(pnt.Y()); xyz.push_back(pnt.Z());
+ IfcSchema::IfcCartesianPoint* cpnt = new IfcSchema::IfcCartesianPoint(xyz);
+ vertices.push_back(cpnt);
+ }
+ const Poly_Array1OfTriangle& triangles = tri->Triangles();
+ for (int i = 1; i <= triangles.Length(); ++i) {
+ int n1, n2, n3;
+ triangles(i).Get(n1, n2, n3);
+ IfcSchema::IfcCartesianPoint::list::ptr points(new IfcSchema::IfcCartesianPoint::list);
+ points->push(vertices[n1 - 1]);
+ points->push(vertices[n2 - 1]);
+ points->push(vertices[n3 - 1]);
+ IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
+ IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, face.Orientation() != TopAbs_REVERSED);
+ IfcSchema::IfcFaceBound::list::ptr bounds(new IfcSchema::IfcFaceBound::list);
+ bounds->push(bound);
+ IfcSchema::IfcFace* face2 = new IfcSchema::IfcFace(bounds);
+ faces->push(face2);
+ }
+ }
+ }
+ IfcSchema::IfcOpenShell* shell = new IfcSchema::IfcOpenShell(faces);
+ IfcSchema::IfcConnectedFaceSet::list::ptr shells(new IfcSchema::IfcConnectedFaceSet::list);
+ shells->push(shell);
+ IfcSchema::IfcFaceBasedSurfaceModel* surface_model = new IfcSchema::IfcFaceBasedSurfaceModel(shells);
+
+ IfcSchema::IfcRepresentation::list::ptr reps(new IfcSchema::IfcRepresentation::list);
+ IfcSchema::IfcRepresentationItem::list::ptr items(new IfcSchema::IfcRepresentationItem::list);
+
+ items->push(surface_model);
+
+ IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
+ 0, std::string("Facetation"), std::string("SurfaceModel"), items);
+
+ reps->push(rep);
+ IfcSchema::IfcProductDefinitionShape* shapedef = new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, reps);
+
+ return shapedef;
+}
diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp
index d6e32ecbf0..714244ae96 100644
--- a/src/ifcgeom/IfcGeomWires.cpp
+++ b/src/ifcgeom/IfcGeomWires.cpp
@@ -83,6 +83,9 @@
#include
#include
+#include
+#include
+
#include "../ifcgeom/IfcGeom.h"
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) {
@@ -390,29 +393,46 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& res
result = mw;
return true;
} else if (is_bounded && convert_wire(l->EdgeGeometry(), result)) {
- if (!l->SameSense()) std::swap(pnt1, pnt2);
- TopExp_Explorer exp(result, TopAbs_EDGE);
+ if (!l->SameSense()) {
+ result.Reverse();
+ }
+
bool first = true;
+ TopExp_Explorer exp(result, TopAbs_EDGE);
+
while (exp.More()) {
const TopoDS_Edge& ed = TopoDS::Edge(exp.Current());
Standard_Real u1, u2;
Handle(Geom_Curve) ecrv = BRep_Tool::Curve(ed, u1, u2);
exp.Next();
const bool last = !exp.More();
- first = false;
+
+ gp_Pnt a, b;
+
if (first && last) {
- mw.Add(BRepBuilderAPI_MakeEdge(ecrv, p1, p2));
+ a = p1;
+ b = p2;
} else if (first) {
- gp_Pnt pu;
- ecrv->D0(u2, pu);
- mw.Add(BRepBuilderAPI_MakeEdge(ecrv, p1, pu));
+ a = p1;
+ ecrv->D0(u2, b);
} else if (last) {
- gp_Pnt pu;
- ecrv->D0(u1, pu);
- mw.Add(BRepBuilderAPI_MakeEdge(ecrv, pu, p2));
+ ecrv->D0(u1, a);
+ b = p2;
} else {
mw.Add(BRepBuilderAPI_MakeEdge(ecrv, u1, u2));
+ first = false;
+ continue;
}
+
+ BRep_Builder builder;
+ TopoDS_Vertex v1, v2;
+ /// @todo project first and emit warnings accordingly
+ builder.MakeVertex(v1, a, getValue(GV_PRECISION));
+ builder.MakeVertex(v2, b, getValue(GV_PRECISION));
+
+ mw.Add(BRepBuilderAPI_MakeEdge(ecrv, v1, v2));
+
+ first = false;
}
result = mw;
return true;
@@ -427,13 +447,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& resu
for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) {
TopoDS_Wire w;
if (convert_wire(*it, w)) {
- if (!(*it)->Orientation()) w.Reverse();
- TopoDS_Iterator topoit(w, false);
- for (; topoit.More(); topoit.Next()) {
- const TopoDS_Edge& e = TopoDS::Edge(topoit.Value());
- mw.Add(e);
- }
- // mw.Add(w);
+ mw.Add(TopoDS::Edge(TopoDS_Iterator(w).Value()));
}
}
result = mw;
diff --git a/src/ifcgeom/IfcRegister.h b/src/ifcgeom/IfcRegister.h
index c566333a9c..2e6f20297d 100644
--- a/src/ifcgeom/IfcRegister.h
+++ b/src/ifcgeom/IfcRegister.h
@@ -119,6 +119,7 @@ CURVE(IfcCircle);
CURVE(IfcEllipse);
CURVE(IfcLine);
#ifdef USE_IFC4
+// IfcRationalBSplineCurveWithKnots included
CURVE(IfcBSplineCurveWithKnots);
#endif
diff --git a/src/ifcopenshell-python/ifcopenshell/__init__.py b/src/ifcopenshell-python/ifcopenshell/__init__.py
index 1fe59e2b03..bf4b6f43f9 100644
--- a/src/ifcopenshell-python/ifcopenshell/__init__.py
+++ b/src/ifcopenshell-python/ifcopenshell/__init__.py
@@ -17,16 +17,11 @@
# #
###############################################################################
+from __future__ import print_function
+
import os
import sys
-import numbers
import platform
-import functools
-import itertools
-
-from functools import reduce
-
-from . import guid
python_distribution = os.path.join(platform.system().lower(),
platform.architecture()[0],
@@ -37,106 +32,16 @@ sys.path.append(os.path.abspath(os.path.join(
try:
from . import ifcopenshell_wrapper
-except:
+except Exception as e:
+ if int(platform.python_version_tuple()[0]) == 2:
+ import traceback
+ traceback.print_exc()
+ print('-' * 64)
raise ImportError("IfcOpenShell not built for '%s'" % python_distribution)
-
-class entity_instance(object):
- def __init__(self, e):
- super(entity_instance, self).__setattr__('wrapped_data', e)
- def __getattr__(self, name):
- INVALID, FORWARD, INVERSE = range(3)
- attr_cat = self.wrapped_data.get_attribute_category(name)
- if attr_cat == FORWARD:
- return entity_instance.wrap_value(self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name)))
- elif attr_cat == INVERSE:
- return entity_instance.wrap_value(self.wrapped_data.get_inverse(name))
- else: raise AttributeError("entity instance of type '%s' has no attribute '%s'"%(self.wrapped_data.is_a(), name))
- @staticmethod
- def walk(f, g, value):
- if isinstance(value, (tuple, list)): return tuple(map(functools.partial(entity_instance.walk, f, g), value))
- elif f(value): return g(value)
- else: return value
- @staticmethod
- def wrap_value(v):
- wrap = lambda e: entity_instance(e)
- is_instance = lambda e: isinstance(e, ifcopenshell_wrapper.entity_instance)
- return entity_instance.walk(is_instance, wrap, v)
- @staticmethod
- def unwrap_value(v):
- unwrap = lambda e: e.wrapped_data
- is_instance = lambda e: isinstance(e, entity_instance)
- return entity_instance.walk(is_instance, unwrap, v)
- def attribute_type(self, attr):
- attr_idx = attr if isinstance(attr, numbers.Integral) else self.wrapped_data.get_argument_index(attr)
- return self.wrapped_data.get_argument_type(attr_idx)
- def attribute_name(self, attr_idx):
- return self.wrapped_data.get_argument_name(attr_idx)
- def __setattr__(self, key, value):
- self[self.wrapped_data.get_argument_index(key)] = value
- def __getitem__(self, key):
- return entity_instance.wrap_value(self.wrapped_data.get_argument(key))
- def __setitem__(self, idx, value):
- if value is None:
- self.wrapped_data.setArgumentAsNull(idx)
- else:
- attr_type = self.attribute_type(idx).title().replace(' ', '')
- attr_type = attr_type.replace('Binary', 'String')
- attr_type = attr_type.replace('Enumeration', 'String')
- try:
- if isinstance(value, unicode): value = value.encode("utf-8")
- except: pass
- getattr(self.wrapped_data, "setArgumentAs%s" % attr_type)(idx, entity_instance.unwrap_value(value))
- return value
- def __len__(self): return len(self.wrapped_data)
- def __repr__(self): return repr(self.wrapped_data)
- def is_a(self, *args): return self.wrapped_data.is_a(*args)
- def id(self): return self.wrapped_data.id()
- def __eq__(self, other):
- if type(self) != type(other): return False
- return self.wrapped_data == other.wrapped_data
- def __hash__(self):
- return hash((self.id(), self.wrapped_data.file_pointer()))
- def __dir__(self):
- return sorted(set(itertools.chain(
- dir(type(self)),
- self.wrapped_data.get_attribute_names(),
- self.wrapped_data.get_inverse_attribute_names()
- )))
-
-
-class file(object):
- def __init__(self, f=None):
- self.wrapped_data = f or ifcopenshell_wrapper.file(True)
- def create_entity(self,type,*args,**kwargs):
- e = entity_instance(ifcopenshell_wrapper.entity_instance(type))
- attrs = list(enumerate(args)) + \
- [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
- for idx, arg in attrs: e[idx] = arg
- self.wrapped_data.add(e.wrapped_data)
- e.wrapped_data.this.disown()
- return e
- def __getattr__(self, attr):
- if attr[0:6] == 'create': return functools.partial(self.create_entity,attr[6:])
- else: return getattr(self.wrapped_data, attr)
- def __getitem__(self, key):
- if isinstance(key, numbers.Integral):
- return entity_instance(self.wrapped_data.by_id(key))
- elif isinstance(key, str):
- return entity_instance(self.wrapped_data.by_guid(key))
- def by_id(self, id): return self[id]
- def by_guid(self, guid): return self[guid]
- def add(self, inst):
- inst.wrapped_data.this.disown()
- return entity_instance(self.wrapped_data.add(inst.wrapped_data))
- def by_type(self, type):
- return [entity_instance(e) for e in self.wrapped_data.by_type(type)]
- def traverse(self, inst):
- return [entity_instance(e) for e in self.wrapped_data.traverse(inst.wrapped_data)]
- def remove(self, inst):
- return self.wrapped_data.remove(inst.wrapped_data)
- def __iter__(self):
- return iter(self[id] for id in self.wrapped_data.entity_names())
-
+
+from . import guid
+from .file import file
+from .entity_instance import entity_instance
def open(fn=None):
return file(ifcopenshell_wrapper.open(os.path.abspath(fn))) if fn else file()
diff --git a/src/ifcopenshell-python/ifcopenshell/entity_instance.py b/src/ifcopenshell-python/ifcopenshell/entity_instance.py
new file mode 100644
index 0000000000..4bb25f026f
--- /dev/null
+++ b/src/ifcopenshell-python/ifcopenshell/entity_instance.py
@@ -0,0 +1,87 @@
+###############################################################################
+# #
+# 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 . #
+# #
+###############################################################################
+
+import numbers
+import functools
+import itertools
+
+from . import ifcopenshell_wrapper
+
+class entity_instance(object):
+ def __init__(self, e):
+ super(entity_instance, self).__setattr__('wrapped_data', e)
+ def __getattr__(self, name):
+ INVALID, FORWARD, INVERSE = range(3)
+ attr_cat = self.wrapped_data.get_attribute_category(name)
+ if attr_cat == FORWARD:
+ return entity_instance.wrap_value(self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name)))
+ elif attr_cat == INVERSE:
+ return entity_instance.wrap_value(self.wrapped_data.get_inverse(name))
+ else: raise AttributeError("entity instance of type '%s' has no attribute '%s'"%(self.wrapped_data.is_a(), name))
+ @staticmethod
+ def walk(f, g, value):
+ if isinstance(value, (tuple, list)): return tuple(map(functools.partial(entity_instance.walk, f, g), value))
+ elif f(value): return g(value)
+ else: return value
+ @staticmethod
+ def wrap_value(v):
+ wrap = lambda e: entity_instance(e)
+ is_instance = lambda e: isinstance(e, ifcopenshell_wrapper.entity_instance)
+ return entity_instance.walk(is_instance, wrap, v)
+ @staticmethod
+ def unwrap_value(v):
+ unwrap = lambda e: e.wrapped_data
+ is_instance = lambda e: isinstance(e, entity_instance)
+ return entity_instance.walk(is_instance, unwrap, v)
+ def attribute_type(self, attr):
+ attr_idx = attr if isinstance(attr, numbers.Integral) else self.wrapped_data.get_argument_index(attr)
+ return self.wrapped_data.get_argument_type(attr_idx)
+ def attribute_name(self, attr_idx):
+ return self.wrapped_data.get_argument_name(attr_idx)
+ def __setattr__(self, key, value):
+ self[self.wrapped_data.get_argument_index(key)] = value
+ def __getitem__(self, key):
+ return entity_instance.wrap_value(self.wrapped_data.get_argument(key))
+ def __setitem__(self, idx, value):
+ if value is None:
+ self.wrapped_data.setArgumentAsNull(idx)
+ else:
+ attr_type = self.attribute_type(idx).title().replace(' ', '')
+ attr_type = attr_type.replace('Binary', 'String')
+ attr_type = attr_type.replace('Enumeration', 'String')
+ try:
+ if isinstance(value, unicode): value = value.encode("utf-8")
+ except: pass
+ getattr(self.wrapped_data, "setArgumentAs%s" % attr_type)(idx, entity_instance.unwrap_value(value))
+ return value
+ def __len__(self): return len(self.wrapped_data)
+ def __repr__(self): return repr(self.wrapped_data)
+ def is_a(self, *args): return self.wrapped_data.is_a(*args)
+ def id(self): return self.wrapped_data.id()
+ def __eq__(self, other):
+ if type(self) != type(other): return False
+ return self.wrapped_data == other.wrapped_data
+ def __hash__(self):
+ return hash((self.id(), self.wrapped_data.file_pointer()))
+ def __dir__(self):
+ return sorted(set(itertools.chain(
+ dir(type(self)),
+ self.wrapped_data.get_attribute_names(),
+ self.wrapped_data.get_inverse_attribute_names()
+ )))
diff --git a/src/ifcopenshell-python/ifcopenshell/file.py b/src/ifcopenshell-python/ifcopenshell/file.py
new file mode 100644
index 0000000000..421e8bf34b
--- /dev/null
+++ b/src/ifcopenshell-python/ifcopenshell/file.py
@@ -0,0 +1,57 @@
+###############################################################################
+# #
+# 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 . #
+# #
+###############################################################################
+
+import numbers
+import functools
+
+from . import ifcopenshell_wrapper
+from .entity_instance import entity_instance
+
+class file(object):
+ def __init__(self, f=None):
+ self.wrapped_data = f or ifcopenshell_wrapper.file(True)
+ def create_entity(self,type,*args,**kwargs):
+ e = entity_instance(ifcopenshell_wrapper.entity_instance(type))
+ attrs = list(enumerate(args)) + \
+ [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
+ for idx, arg in attrs: e[idx] = arg
+ self.wrapped_data.add(e.wrapped_data)
+ e.wrapped_data.this.disown()
+ return e
+ def __getattr__(self, attr):
+ if attr[0:6] == 'create': return functools.partial(self.create_entity,attr[6:])
+ else: return getattr(self.wrapped_data, attr)
+ def __getitem__(self, key):
+ if isinstance(key, numbers.Integral):
+ return entity_instance(self.wrapped_data.by_id(key))
+ elif isinstance(key, str):
+ return entity_instance(self.wrapped_data.by_guid(key))
+ def by_id(self, id): return self[id]
+ def by_guid(self, guid): return self[guid]
+ def add(self, inst):
+ inst.wrapped_data.this.disown()
+ return entity_instance(self.wrapped_data.add(inst.wrapped_data))
+ def by_type(self, type):
+ return [entity_instance(e) for e in self.wrapped_data.by_type(type)]
+ def traverse(self, inst):
+ return [entity_instance(e) for e in self.wrapped_data.traverse(inst.wrapped_data)]
+ def remove(self, inst):
+ return self.wrapped_data.remove(inst.wrapped_data)
+ def __iter__(self):
+ return iter(self[id] for id in self.wrapped_data.entity_names())
diff --git a/src/ifcopenshell-python/ifcopenshell/geom/main.py b/src/ifcopenshell-python/ifcopenshell/geom/main.py
index b325793df2..28a148a3a5 100644
--- a/src/ifcopenshell-python/ifcopenshell/geom/main.py
+++ b/src/ifcopenshell-python/ifcopenshell/geom/main.py
@@ -21,6 +21,7 @@ import os
import sys
from .. import ifcopenshell_wrapper
+from ..entity_instance import entity_instance
def has_occ():
try: import OCC.BRepTools
@@ -82,5 +83,19 @@ def iterate(settings, filename):
while True:
yield it.get()
if not it.next(): break
-
-
+
+def make_shape_function(fn):
+ entity_instance_or_none = lambda e: None if e is None else entity_instance(e)
+ if has_occ:
+ import OCC.TopoDS
+ def _(string_or_shape, *args):
+ if isinstance(string_or_shape, OCC.TopoDS.TopoDS_Shape):
+ string_or_shape = utils.serialize_shape(string_or_shape)
+ return entity_instance_or_none(fn(string_or_shape, *args))
+ else:
+ def _(string, *args):
+ return entity_instance_or_none(fn(string, *args))
+ return _
+
+serialise = make_shape_function(ifcopenshell_wrapper.serialise)
+tesselate = make_shape_function(ifcopenshell_wrapper.tesselate)
diff --git a/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py b/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py
index 97186735a7..2e2fd35015 100644
--- a/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py
+++ b/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py
@@ -180,7 +180,12 @@ def get_bounding_box_center(bbox):
bbmin[0], bbmin[1], bbmin[2], bbmax[0], bbmax[1], bbmax[2] = bbox.Get()
return OCC.gp.gp_Pnt(*map(lambda xy: (xy[0]+xy[1])/2., zip(bbmin, bbmax)))
-
+
+def serialize_shape(shape):
+ shapes = OCC.BRepTools.BRepTools_ShapeSet()
+ shapes.Add(shape)
+ return shapes.WriteToString()
+
def create_shape_from_serialization(brep_object):
import OCC.BRepTools
diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i
index 07222a743a..1f66eab9fd 100644
--- a/src/ifcwrap/IfcGeomWrapper.i
+++ b/src/ifcwrap/IfcGeomWrapper.i
@@ -389,6 +389,34 @@ struct ShapeRTTI : public boost::static_visitor
}
return boost::variant*, IfcGeom::Representation::Representation*>();
}
+
+ IfcParse::IfcLateBoundEntity* serialise(const std::string& s, bool advanced=true) {
+ std::stringstream stream(s);
+ BRepTools_ShapeSet shapes;
+ shapes.Read(stream);
+ const TopoDS_Shape& shp = shapes.Shape(shapes.NbShapes());
+
+ const IfcUtil::IfcBaseClass* e = IfcGeom::serialise(shp, advanced);
+ if (e) {
+ return new IfcParse::IfcLateBoundEntity(e->entity);
+ } else {
+ return 0;
+ }
+ }
+
+ IfcParse::IfcLateBoundEntity* tesselate(const std::string& s, double d) {
+ std::stringstream stream(s);
+ BRepTools_ShapeSet shapes;
+ shapes.Read(stream);
+ const TopoDS_Shape& shp = shapes.Shape(shapes.NbShapes());
+
+ const IfcUtil::IfcBaseClass* e = IfcGeom::tesselate(shp, d);
+ if (e) {
+ return new IfcParse::IfcLateBoundEntity(e->entity);
+ } else {
+ return 0;
+ }
+ }
%}
namespace IfcGeom {
diff --git a/src/ifcwrap/IfcPython.i b/src/ifcwrap/IfcPython.i
index ef42830a14..419de7e2fd 100644
--- a/src/ifcwrap/IfcPython.i
+++ b/src/ifcwrap/IfcPython.i
@@ -76,6 +76,8 @@
#else
#include "../ifcparse/Ifc2x3-latebound.h"
#endif
+
+ #include
%}
%include "utils/type_conversion.i"