mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Add support for IfcBooleanResult, IfcBlock, IfcRectangularPyramid, IfcRightCircularCylinder, IfcRightCircularCone, IfcSphere, IfcCsgSolid, IfcCurveBoundedPlane, IfcRectangularTrimmedSurface, IfcSurfaceCurveSweptAreaSolid, IfcCylindricalSurface.
Add CSG example.
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example that generates a Constructive Solid Geometry example *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#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<boost::none_t>(0));
|
||||
|
||||
class Node {
|
||||
private:
|
||||
typedef enum {
|
||||
OP_ADD, OP_SUBTRACT, OP_INTERSECT, OP_TERMINAL
|
||||
} Op;
|
||||
typedef enum {
|
||||
PRIM_BOX, PRIM_CONE, PRIM_CYLINDER, PRIM_PYRAMID, PRIM_SPHERE
|
||||
} Prim;
|
||||
|
||||
double x,y,z, zx,zy,zz, xx,xy,xz, a,b,c;
|
||||
const Node *left, *right;
|
||||
|
||||
Op op;
|
||||
Prim prim;
|
||||
|
||||
Node& operate(Op op, const Node& p) {
|
||||
left = new Node(*this);
|
||||
right = new Node(p);
|
||||
this->op = op;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Node(Prim p, double la, double lb=0., double lc=0.)
|
||||
: prim(p), op(OP_TERMINAL),
|
||||
x(0.), y(0.), z(0.),
|
||||
zx(0.), zy(0.), zz(1.),
|
||||
xx(1.), xy(0.), xz(0.),
|
||||
a(la), b(lb), c(lc) {}
|
||||
public:
|
||||
static Node Sphere(double r) {
|
||||
return Node(PRIM_SPHERE, r);
|
||||
}
|
||||
static Node Box(double dx, double dy, double dz) {
|
||||
return Node(PRIM_BOX, dx, dy, dz);
|
||||
}
|
||||
static Node Pyramid(double dx, double dy, double dz) {
|
||||
return Node(PRIM_PYRAMID, dx, dy, dz);
|
||||
}
|
||||
static Node Cylinder(double r, double h) {
|
||||
return Node(PRIM_CYLINDER, r, h);
|
||||
}
|
||||
static Node Cone(double r, double h) {
|
||||
return Node(PRIM_CONE, r, h);
|
||||
}
|
||||
|
||||
Node& move(
|
||||
double px = 0., double py = 0., double pz = 0.,
|
||||
double zx = 0., double zy = 0., double zz = 1.,
|
||||
double xx = 1., double xy = 0., double xz = 0.)
|
||||
{
|
||||
this->x = px; this->y = py; this->z = pz;
|
||||
this->zx = zx; this->zy = zy; this->zz = zz;
|
||||
this->xx = xx; this->xy = xy; this->xz = xz;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Node& add(const Node& p) {
|
||||
return operate(OP_ADD, p);
|
||||
}
|
||||
Node& subtract(const Node& p) {
|
||||
return operate(OP_SUBTRACT, p);
|
||||
}
|
||||
Node& intersect(const Node& p) {
|
||||
return operate(OP_INTERSECT, p);
|
||||
}
|
||||
|
||||
IfcSchema::IfcRepresentationItem* serialize(IfcHierarchyHelper& file) const {
|
||||
IfcSchema::IfcRepresentationItem* my;
|
||||
if (op == OP_TERMINAL) {
|
||||
IfcSchema::IfcAxis2Placement3D* place = file.addPlacement3d(x,y,z,zx,zy,zz,xx,xy,xz);
|
||||
if (prim == PRIM_SPHERE) {
|
||||
my = new IfcSchema::IfcSphere(place, a);
|
||||
} else if (prim == PRIM_BOX) {
|
||||
my = new IfcSchema::IfcBlock(place, a, b, c);
|
||||
} else if (prim == PRIM_PYRAMID) {
|
||||
my = new IfcSchema::IfcRectangularPyramid(place, a, b, c);
|
||||
} else if (prim == PRIM_CYLINDER) {
|
||||
my = new IfcSchema::IfcRightCircularCylinder(place, b, a);
|
||||
} else if (prim == PRIM_CONE) {
|
||||
my = new IfcSchema::IfcRightCircularCone(place, b, a);
|
||||
}
|
||||
} else {
|
||||
IfcSchema::IfcBooleanOperator::IfcBooleanOperator o;
|
||||
if (op == OP_ADD) {
|
||||
o = IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION;
|
||||
} else if (op == OP_SUBTRACT) {
|
||||
o = IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE;
|
||||
} else if (op == OP_INTERSECT) {
|
||||
o = IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION;
|
||||
}
|
||||
my = new IfcSchema::IfcBooleanResult(o, left->serialize(file), right->serialize(file));
|
||||
}
|
||||
file.AddEntity(my);
|
||||
return my;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char filename[] = "IfcCsgPrimitive.ifc";
|
||||
IfcHierarchyHelper file;
|
||||
file.filename(filename);
|
||||
|
||||
IfcSchema::IfcRepresentationItem* csg1 = Node::Box(8000.,6000.,3000.).subtract(
|
||||
Node::Box(7600.,5600.,2800.).move(200.,200.,200.)
|
||||
).add(
|
||||
Node::Pyramid(8000.,6000.,3000.).move(0,0,3000.).add(
|
||||
Node::Cylinder(1000.,4000.).move(4000.,1000.,4000., 0.,1.,0.)
|
||||
).subtract(
|
||||
Node::Pyramid(7600.,5600.,2800.).move(200.,200.,3000.)
|
||||
).subtract(
|
||||
Node::Cylinder(900.,4000.).move(4000.,1000.,4000., 0.,1.,0.).intersect(
|
||||
Node::Box(2000.,4000.,1000.).move(3000.,1000.,4000.)
|
||||
)
|
||||
)
|
||||
).serialize(file);
|
||||
|
||||
const double x = 1000.; const double y = -4000.;
|
||||
|
||||
IfcSchema::IfcRepresentationItem* csg2 = Node::Sphere(5000.).move(x,y,-4500.).intersect(
|
||||
Node::Box(6000., 6000., 6000.).move(x-3000., y-3000., 0.)
|
||||
).add(
|
||||
Node::Cone(500., 3000.).move(x,y).add(
|
||||
Node::Cone(1500., 1000.).move(x,y, 900.).add(
|
||||
Node::Cone(1100., 1000.).move(x,y, 1800.).add(
|
||||
Node::Cone(750., 600.).move(x,y, 2700.)
|
||||
)))).serialize(file);
|
||||
|
||||
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
|
||||
guid(), 0, S("IfcCsgPrimitive"), null, null, 0, 0, null, null);
|
||||
|
||||
file.addBuildingProduct(product);
|
||||
|
||||
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
product->setObjectPlacement(file.addLocalPlacement());
|
||||
|
||||
IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
|
||||
IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
|
||||
|
||||
items->push(csg1);
|
||||
items->push(csg2);
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("CSG"), items);
|
||||
reps->push(rep);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
|
||||
file.AddEntity(rep);
|
||||
file.AddEntity(shape);
|
||||
|
||||
product->setRepresentation(shape);
|
||||
|
||||
file.getSingle<IfcSchema::IfcProject>()->setName("IfcCompositeProfileDef");
|
||||
|
||||
std::ofstream f(filename);
|
||||
f << file;
|
||||
}
|
||||
@@ -103,6 +103,7 @@ namespace IfcGeom {
|
||||
void apply_tolerance(TopoDS_Shape& s, double t);
|
||||
void SetValue(GeomValue var, double value);
|
||||
double GetValue(GeomValue var);
|
||||
bool fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape);
|
||||
IfcSchema::IfcProductDefinitionShape* tesselate(TopoDS_Shape& shape, double deflection, IfcEntities es);
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include <gp_Pnt.hxx>
|
||||
@@ -92,6 +93,11 @@
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <Poly_Array1OfTriangle.hxx>
|
||||
|
||||
#include <TopExp.hxx>
|
||||
#include <TopTools_IndexedMapOfShape.hxx>
|
||||
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
||||
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
|
||||
@@ -572,4 +578,100 @@ IfcSchema::IfcProductDefinitionShape* IfcGeom::tesselate(TopoDS_Shape& shape, do
|
||||
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);
|
||||
while (exp.More()) {
|
||||
if (!exp.Current().IsSame(vertex)) {
|
||||
return TopoDS::Vertex(exp.Current());
|
||||
}
|
||||
exp.Next();
|
||||
}
|
||||
}
|
||||
|
||||
TopoDS_Edge find_next(const TopTools_IndexedMapOfShape& edge_set, const TopTools_IndexedDataMapOfShapeListOfShape& vertex_to_edges, const TopoDS_Vertex& current, const TopoDS_Edge& previous_edge) {
|
||||
const TopTools_ListOfShape& edges = vertex_to_edges.FindFromKey(current);
|
||||
TopTools_ListIteratorOfListOfShape eit;
|
||||
for (eit.Initialize(edges); eit.More(); eit.Next()) {
|
||||
const TopoDS_Edge& edge = TopoDS::Edge(eit.Value());
|
||||
if (edge.IsSame(previous_edge)) continue;
|
||||
if (edge_set.Contains(edge)) {
|
||||
return edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IfcGeom::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) {
|
||||
BRepOffsetAPI_Sewing sew;
|
||||
sew.Add(shape);
|
||||
|
||||
TopTools_IndexedDataMapOfShapeListOfShape edge_to_faces;
|
||||
TopTools_IndexedDataMapOfShapeListOfShape vertex_to_edges;
|
||||
std::set<int> visited;
|
||||
TopTools_IndexedMapOfShape edge_set;
|
||||
|
||||
TopExp::MapShapesAndAncestors (shape, TopAbs_EDGE, TopAbs_FACE, edge_to_faces);
|
||||
|
||||
const int num_edges = edge_to_faces.Extent();
|
||||
for (int i = 1; i <= num_edges; ++i) {
|
||||
const TopTools_ListOfShape& faces = edge_to_faces.FindFromIndex(i);
|
||||
const int count = faces.Extent();
|
||||
// Find only the non-manifold edges: Edges that are only part of a
|
||||
// single face and therefore part of the wire(s) we want to fill.
|
||||
if (count == 1) {
|
||||
const TopoDS_Shape& edge = edge_to_faces.FindKey(i);
|
||||
TopExp::MapShapesAndAncestors (edge, TopAbs_VERTEX, TopAbs_EDGE, vertex_to_edges);
|
||||
edge_set.Add(edge);
|
||||
}
|
||||
}
|
||||
|
||||
const int num_verts = vertex_to_edges.Extent();
|
||||
TopoDS_Vertex first, current;
|
||||
TopoDS_Edge previous_edge;
|
||||
|
||||
// Now loop over all the vertices that are part of the wire(s) to be filled
|
||||
for (int i = 1; i <= num_verts; ++i) {
|
||||
first = current = TopoDS::Vertex(vertex_to_edges.FindKey(i));
|
||||
const bool isSame = first.IsSame(current);
|
||||
// We keep track of the vertices we already used
|
||||
if (visited.find(vertex_to_edges.FindIndex(current)) != visited.end()) {
|
||||
continue;
|
||||
}
|
||||
// Given these vertices, try to find closed loops and create new
|
||||
// wires out of them.
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
while (true) {
|
||||
visited.insert(vertex_to_edges.FindIndex(current));
|
||||
// Find the edge that the current vertex is part of and points
|
||||
// away from the previous vertex (null for the first vertex).
|
||||
TopoDS_Edge edge = find_next(edge_set, vertex_to_edges, current, previous_edge);
|
||||
if (edge.IsNull()) {
|
||||
return false;
|
||||
}
|
||||
TopoDS_Vertex other = find_other(edge, current);
|
||||
w.Add(edge);
|
||||
// See if the starting point of this loop has been reached. Note that
|
||||
// additional wires after this one potentially will be created.
|
||||
if (other.IsSame(first)) {
|
||||
break;
|
||||
}
|
||||
previous_edge = edge;
|
||||
current = other;
|
||||
}
|
||||
sew.Add(BRepBuilderAPI_MakeFace(w));
|
||||
previous_edge.Nullify();
|
||||
}
|
||||
|
||||
sew.Perform();
|
||||
shape = sew.SewedShape();
|
||||
|
||||
try {
|
||||
ShapeFix_Solid solid;
|
||||
solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
shape = solid.SolidFromShell(TopoDS::Shell(shape));
|
||||
} catch(...) {}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -175,8 +175,11 @@ IfcGeomObjects::IfcRepresentationTriangulation::IfcRepresentationTriangulation(c
|
||||
const gp_Pnt2d& uv = uvs(i);
|
||||
gp_Pnt p;
|
||||
gp_Vec normal_direction;
|
||||
prop.Normal(uv.X(),uv.Y(),p,normal_direction);
|
||||
gp_Dir normal = gp_Dir(normal_direction.XYZ() * rotation_matrix);
|
||||
prop.Normal(uv.X(),uv.Y(),p,normal_direction);
|
||||
gp_Vec normal(0., 0., 0.);
|
||||
if (normal_direction.Magnitude() > ALMOST_ZERO) {
|
||||
normal = gp_Dir(normal_direction.XYZ() * rotation_matrix);
|
||||
}
|
||||
_normals.push_back((float)normal.X());
|
||||
_normals.push_back((float)normal.Y());
|
||||
_normals.push_back((float)normal.Z());
|
||||
|
||||
+260
-24
@@ -45,12 +45,17 @@
|
||||
#include <TColgp_Array1OfPnt2d.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <Geom_CylindricalSurface.hxx>
|
||||
|
||||
#include <BRepOffsetAPI_Sewing.hxx>
|
||||
#include <BRepOffsetAPI_MakePipe.hxx>
|
||||
#include <BRepOffsetAPI_MakePipeShell.hxx>
|
||||
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
@@ -64,10 +69,20 @@
|
||||
|
||||
#include <BRepPrimAPI_MakePrism.hxx>
|
||||
#include <BRepPrimAPI_MakeRevol.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <BRepPrimAPI_MakeCone.hxx>
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <BRepPrimAPI_MakeSphere.hxx>
|
||||
#include <BRepPrimAPI_MakeWedge.hxx>
|
||||
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepBuilderAPI_MakeShell.hxx>
|
||||
#include <BRepBuilderAPI_MakeSolid.hxx>
|
||||
#include <BRepPrimAPI_MakeHalfSpace.hxx>
|
||||
|
||||
#include <BRepAlgoAPI_Cut.hxx>
|
||||
#include <BRepAlgoAPI_Fuse.hxx>
|
||||
#include <BRepAlgoAPI_Common.hxx>
|
||||
|
||||
#include <ShapeFix_Shape.hxx>
|
||||
#include <ShapeFix_ShapeTolerance.hxx>
|
||||
@@ -76,7 +91,6 @@
|
||||
#include <TopLoc_Location.hxx>
|
||||
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepAlgoAPI_Common.hxx>
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
@@ -223,7 +237,7 @@ bool IfcGeom::convert(const IfcSchema::IfcShellBasedSurfaceModel::ptr l, IfcRepr
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcBooleanClippingResult::ptr l, TopoDS_Shape& shape) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcBooleanResult::ptr l, TopoDS_Shape& shape) {
|
||||
TopoDS_Shape s1, s2;
|
||||
TopoDS_Wire boundary_wire;
|
||||
IfcSchema::IfcBooleanOperand operand1 = l->FirstOperand();
|
||||
@@ -249,32 +263,76 @@ bool IfcGeom::convert(const IfcSchema::IfcBooleanClippingResult::ptr l, TopoDS_S
|
||||
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",operand2->entity);
|
||||
}
|
||||
|
||||
bool valid_cut = false;
|
||||
BRepAlgoAPI_Cut brep_cut(s1,s2);
|
||||
if ( brep_cut.IsDone() ) {
|
||||
TopoDS_Shape result = brep_cut;
|
||||
const IfcSchema::IfcBooleanOperator::IfcBooleanOperator op = l->Operator();
|
||||
|
||||
ShapeFix_Shape fix(result);
|
||||
fix.Perform();
|
||||
result = fix.Shape();
|
||||
if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) {
|
||||
|
||||
bool valid_cut = false;
|
||||
BRepAlgoAPI_Cut brep_cut(s1,s2);
|
||||
if ( brep_cut.IsDone() ) {
|
||||
TopoDS_Shape result = brep_cut;
|
||||
|
||||
ShapeFix_Shape fix(result);
|
||||
fix.Perform();
|
||||
result = fix.Shape();
|
||||
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
}
|
||||
}
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( valid_cut ) {
|
||||
const double volume_after_subtraction = shape_volume(shape);
|
||||
if ( ALMOST_THE_SAME(first_operand_volume,volume_after_subtraction) )
|
||||
Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",l->entity);
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",l->entity);
|
||||
shape = s1;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) {
|
||||
|
||||
BRepAlgoAPI_Fuse brep_fuse(s1,s2);
|
||||
if ( brep_fuse.IsDone() ) {
|
||||
TopoDS_Shape result = brep_fuse;
|
||||
|
||||
ShapeFix_Shape fix(result);
|
||||
fix.Perform();
|
||||
result = fix.Shape();
|
||||
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) {
|
||||
|
||||
BRepAlgoAPI_Common brep_common(s1,s2);
|
||||
if ( brep_common.IsDone() ) {
|
||||
TopoDS_Shape result = brep_common;
|
||||
|
||||
ShapeFix_Shape fix(result);
|
||||
fix.Perform();
|
||||
result = fix.Shape();
|
||||
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
if ( valid_cut ) {
|
||||
const double volume_after_subtraction = shape_volume(shape);
|
||||
if ( ALMOST_THE_SAME(first_operand_volume,volume_after_subtraction) )
|
||||
Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",l->entity);
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",l->entity);
|
||||
shape = s1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet::ptr l, TopoDS_Shape& shape) {
|
||||
@@ -392,4 +450,182 @@ bool IfcGeom::convert(const IfcSchema::IfcGeometricSet::ptr l, IfcRepresentation
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcBlock::ptr l, TopoDS_Shape& shape) {
|
||||
const double dx = l->XLength() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double dy = l->YLength() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double dz = l->ZLength() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
|
||||
BRepPrimAPI_MakeBox builder(dx, dy, dz);
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert(l->Position(),trsf);
|
||||
shape = builder.Solid().Moved(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcRectangularPyramid::ptr l, TopoDS_Shape& shape) {
|
||||
const double dx = l->XLength() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double dy = l->YLength() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double dz = l->Height() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
|
||||
BRepPrimAPI_MakeWedge builder(dx, dz, dy, dx / 2., dy / 2., dx / 2., dy / 2.);
|
||||
|
||||
gp_Trsf trsf1, trsf2;
|
||||
trsf2.SetValues(1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 1, 0, 0, Precision::Confusion(), Precision::Confusion());
|
||||
|
||||
IfcGeom::convert(l->Position(), trsf1);
|
||||
shape = BRepBuilderAPI_Transform(builder.Solid(), trsf1 * trsf2);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcRightCircularCylinder::ptr l, TopoDS_Shape& shape) {
|
||||
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double h = l->Height() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
|
||||
BRepPrimAPI_MakeCylinder builder(r, h);
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert(l->Position(),trsf);
|
||||
shape = builder.Solid().Moved(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcRightCircularCone::ptr l, TopoDS_Shape& shape) {
|
||||
const double r = l->BottomRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double h = l->Height() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
|
||||
BRepPrimAPI_MakeCone builder(r, 0., h);
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert(l->Position(),trsf);
|
||||
shape = builder.Solid().Moved(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcSphere::ptr l, TopoDS_Shape& shape) {
|
||||
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
|
||||
BRepPrimAPI_MakeSphere builder(r);
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert(l->Position(),trsf);
|
||||
shape = builder.Solid().Moved(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCsgSolid::ptr l, TopoDS_Shape& shape) {
|
||||
return IfcGeom::convert_shape(l->TreeRootExpression(), shape);
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCurveBoundedPlane::ptr l, TopoDS_Shape& face) {
|
||||
gp_Pln pln;
|
||||
IfcGeom::convert(l->BasisSurface(), pln);
|
||||
|
||||
gp_Trsf trsf;
|
||||
trsf.SetTransformation(pln.Position());
|
||||
|
||||
TopoDS_Wire outer;
|
||||
IfcGeom::convert_wire(l->OuterBoundary(), outer);
|
||||
|
||||
BRepBuilderAPI_MakeFace mf (outer);
|
||||
mf.Add(outer);
|
||||
|
||||
IfcSchema::IfcCurve::list inner = l->InnerBoundaries();
|
||||
|
||||
for (IfcSchema::IfcCurve::it it = inner->begin(); it != inner->end(); ++it) {
|
||||
TopoDS_Wire inner;
|
||||
IfcGeom::convert_wire(*it, inner);
|
||||
|
||||
mf.Add(inner);
|
||||
}
|
||||
|
||||
ShapeFix_Shape sfs(mf.Face());
|
||||
sfs.Perform();
|
||||
face = TopoDS::Face(sfs.Shape()).Moved(trsf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcRectangularTrimmedSurface::ptr l, TopoDS_Shape& face) {
|
||||
if (!l->BasisSurface()->is(IfcSchema::Type::IfcPlane)) {
|
||||
// Not implemented
|
||||
return false;
|
||||
}
|
||||
gp_Pln pln;
|
||||
IfcGeom::convert((IfcSchema::IfcPlane*) l->BasisSurface(), pln);
|
||||
|
||||
BRepBuilderAPI_MakeFace mf(pln, l->U1(), l->U2(), l->V1(), l->V2());
|
||||
|
||||
face = mf.Face();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid::ptr l, TopoDS_Shape& shape) {
|
||||
gp_Trsf trsf, axis, position;
|
||||
TopoDS_Shape face;
|
||||
TopoDS_Wire wire, section;
|
||||
|
||||
if (!IfcGeom::convert_face(l->SweptArea(), face)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IfcGeom::convert_wire(l->Directrix(), wire)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
axis.SetTransformation(gp_Ax3(gp::Origin(), gp::DX(), -gp::DZ()));
|
||||
IfcGeom::convert(l->Position(), position);
|
||||
|
||||
if (!l->ReferenceSurface()->is(IfcSchema::Type::IfcPlane)) {
|
||||
// Not implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
gp_Pln pln;
|
||||
IfcGeom::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln);
|
||||
|
||||
trsf.SetTransformation(pln.Position());
|
||||
trsf.Invert();
|
||||
trsf.Multiply(axis);
|
||||
|
||||
// NB: Note that StartParam and EndParam param are ignored and the assumption is
|
||||
// made that the parametric range over which to be swept matches the IfcCurve in
|
||||
// its entirety.
|
||||
BRepOffsetAPI_MakePipeShell builder(wire);
|
||||
|
||||
face = BRepBuilderAPI_Transform(face, trsf);
|
||||
|
||||
TopExp_Explorer exp(face, TopAbs_WIRE);
|
||||
section = TopoDS::Wire(exp.Current());
|
||||
|
||||
builder.Add(section);
|
||||
builder.SetTransitionMode(BRepBuilderAPI_RightCorner);
|
||||
builder.Build();
|
||||
|
||||
shape = builder.Shape();
|
||||
|
||||
bool succeeded = false;
|
||||
try {
|
||||
succeeded = IfcGeom::fill_nonmanifold_wires_with_planar_faces(shape);
|
||||
} catch(...) {}
|
||||
if (!succeeded) {
|
||||
Logger::Message(Logger::LOG_WARNING, "Failed to cap solid for:", l->entity);
|
||||
}
|
||||
|
||||
shape.Move(position);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_IFC4
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCylindricalSurface::ptr l, TopoDS_Shape& face) {
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert(l->Position(),trsf);
|
||||
|
||||
face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius()), GetValue(GV_PRECISION)).Face().Moved(trsf);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -53,11 +53,23 @@ SHAPES(IfcGeometricSet);
|
||||
SHAPE(IfcExtrudedAreaSolid);
|
||||
SHAPE(IfcRevolvedAreaSolid);
|
||||
SHAPE(IfcConnectedFaceSet);
|
||||
SHAPE(IfcBooleanClippingResult);
|
||||
SHAPE(IfcBooleanResult);
|
||||
SHAPE(IfcPolygonalBoundedHalfSpace);
|
||||
SHAPE(IfcHalfSpaceSolid);
|
||||
SHAPE(IfcSurfaceOfLinearExtrusion);
|
||||
SHAPE(IfcSurfaceOfRevolution);
|
||||
SHAPE(IfcBlock);
|
||||
SHAPE(IfcRectangularPyramid);
|
||||
SHAPE(IfcRightCircularCylinder);
|
||||
SHAPE(IfcRightCircularCone);
|
||||
SHAPE(IfcSphere);
|
||||
SHAPE(IfcCsgSolid);
|
||||
SHAPE(IfcCurveBoundedPlane);
|
||||
SHAPE(IfcRectangularTrimmedSurface);
|
||||
SHAPE(IfcSurfaceCurveSweptAreaSolid);
|
||||
#ifdef USE_IFC4
|
||||
SHAPE(IfcCylindricalSurface);
|
||||
#endif
|
||||
|
||||
FACE(IfcArbitraryProfileDefWithVoids);
|
||||
FACE(IfcArbitraryClosedProfileDef);
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
|
||||
FILE_NAME('IfcCsgPrimitive.ifc','2014-03-17T18:28:00',(''),('',''),'IfcOpenShell 0.5.0-dev','IfcOpenShell 0.5.0-dev','');
|
||||
FILE_SCHEMA(('IFC2X3'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCDIRECTION((1.,0.,0.));
|
||||
#2=IFCDIRECTION((0.,0.,1.));
|
||||
#3=IFCCARTESIANPOINT((3000.,1000.,4000.));
|
||||
#4=IFCAXIS2PLACEMENT3D(#3,#2,#1);
|
||||
#5=IFCBLOCK(#4,2000.,4000.,1000.);
|
||||
#6=IFCDIRECTION((1.,0.,0.));
|
||||
#7=IFCDIRECTION((0.,1.,0.));
|
||||
#8=IFCCARTESIANPOINT((4000.,1000.,4000.));
|
||||
#9=IFCAXIS2PLACEMENT3D(#8,#7,#6);
|
||||
#10=IFCRIGHTCIRCULARCYLINDER(#9,4000.,900.);
|
||||
#11=IFCBOOLEANRESULT(.INTERSECTION.,#10,#5);
|
||||
#12=IFCDIRECTION((1.,0.,0.));
|
||||
#13=IFCDIRECTION((0.,0.,1.));
|
||||
#14=IFCCARTESIANPOINT((200.,200.,3000.));
|
||||
#15=IFCAXIS2PLACEMENT3D(#14,#13,#12);
|
||||
#16=IFCRECTANGULARPYRAMID(#15,7600.,5600.,2800.);
|
||||
#17=IFCDIRECTION((1.,0.,0.));
|
||||
#18=IFCDIRECTION((0.,1.,0.));
|
||||
#19=IFCCARTESIANPOINT((4000.,1000.,4000.));
|
||||
#20=IFCAXIS2PLACEMENT3D(#19,#18,#17);
|
||||
#21=IFCRIGHTCIRCULARCYLINDER(#20,4000.,1000.);
|
||||
#22=IFCDIRECTION((1.,0.,0.));
|
||||
#23=IFCDIRECTION((0.,0.,1.));
|
||||
#24=IFCCARTESIANPOINT((0.,0.,3000.));
|
||||
#25=IFCAXIS2PLACEMENT3D(#24,#23,#22);
|
||||
#26=IFCRECTANGULARPYRAMID(#25,8000.,6000.,3000.);
|
||||
#27=IFCBOOLEANRESULT(.UNION.,#26,#21);
|
||||
#28=IFCBOOLEANRESULT(.DIFFERENCE.,#27,#16);
|
||||
#29=IFCBOOLEANRESULT(.DIFFERENCE.,#28,#11);
|
||||
#30=IFCDIRECTION((1.,0.,0.));
|
||||
#31=IFCDIRECTION((0.,0.,1.));
|
||||
#32=IFCCARTESIANPOINT((200.,200.,200.));
|
||||
#33=IFCAXIS2PLACEMENT3D(#32,#31,#30);
|
||||
#34=IFCBLOCK(#33,7600.,5600.,2800.);
|
||||
#35=IFCDIRECTION((1.,0.,0.));
|
||||
#36=IFCDIRECTION((0.,0.,1.));
|
||||
#37=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#38=IFCAXIS2PLACEMENT3D(#37,#36,#35);
|
||||
#39=IFCBLOCK(#38,8000.,6000.,3000.);
|
||||
#40=IFCBOOLEANRESULT(.DIFFERENCE.,#39,#34);
|
||||
#41=IFCBOOLEANRESULT(.UNION.,#40,#29);
|
||||
#42=IFCDIRECTION((1.,0.,0.));
|
||||
#43=IFCDIRECTION((0.,0.,1.));
|
||||
#44=IFCCARTESIANPOINT((1000.,-4000.,2700.));
|
||||
#45=IFCAXIS2PLACEMENT3D(#44,#43,#42);
|
||||
#46=IFCRIGHTCIRCULARCONE(#45,600.,750.);
|
||||
#47=IFCDIRECTION((1.,0.,0.));
|
||||
#48=IFCDIRECTION((0.,0.,1.));
|
||||
#49=IFCCARTESIANPOINT((1000.,-4000.,1800.));
|
||||
#50=IFCAXIS2PLACEMENT3D(#49,#48,#47);
|
||||
#51=IFCRIGHTCIRCULARCONE(#50,1000.,1100.);
|
||||
#52=IFCBOOLEANRESULT(.UNION.,#51,#46);
|
||||
#53=IFCDIRECTION((1.,0.,0.));
|
||||
#54=IFCDIRECTION((0.,0.,1.));
|
||||
#55=IFCCARTESIANPOINT((1000.,-4000.,900.));
|
||||
#56=IFCAXIS2PLACEMENT3D(#55,#54,#53);
|
||||
#57=IFCRIGHTCIRCULARCONE(#56,1000.,1500.);
|
||||
#58=IFCBOOLEANRESULT(.UNION.,#57,#52);
|
||||
#59=IFCDIRECTION((1.,0.,0.));
|
||||
#60=IFCDIRECTION((0.,0.,1.));
|
||||
#61=IFCCARTESIANPOINT((1000.,-4000.,0.));
|
||||
#62=IFCAXIS2PLACEMENT3D(#61,#60,#59);
|
||||
#63=IFCRIGHTCIRCULARCONE(#62,3000.,500.);
|
||||
#64=IFCBOOLEANRESULT(.UNION.,#63,#58);
|
||||
#65=IFCDIRECTION((1.,0.,0.));
|
||||
#66=IFCDIRECTION((0.,0.,1.));
|
||||
#67=IFCCARTESIANPOINT((-2000.,-7000.,0.));
|
||||
#68=IFCAXIS2PLACEMENT3D(#67,#66,#65);
|
||||
#69=IFCBLOCK(#68,6000.,6000.,6000.);
|
||||
#70=IFCDIRECTION((1.,0.,0.));
|
||||
#71=IFCDIRECTION((0.,0.,1.));
|
||||
#72=IFCCARTESIANPOINT((1000.,-4000.,-4500.));
|
||||
#73=IFCAXIS2PLACEMENT3D(#72,#71,#70);
|
||||
#74=IFCSPHERE(#73,5000.);
|
||||
#75=IFCBOOLEANRESULT(.INTERSECTION.,#74,#69);
|
||||
#76=IFCBOOLEANRESULT(.UNION.,#75,#64);
|
||||
#77=IFCPERSON($,$,'',$,$,$,$,$);
|
||||
#78=IFCORGANIZATION($,'IfcOpenShell',$,$,$);
|
||||
#79=IFCPERSONANDORGANIZATION(#77,#78,$);
|
||||
#80=IFCAPPLICATION(#78,'0.5.0-dev','IfcOpenShell','IfcOpenShell');
|
||||
#81=IFCOWNERHISTORY(#79,#80,$,.ADDED.,$,#79,#80,1395077280);
|
||||
#82=IFCDIRECTION((0.,1.,0.));
|
||||
#83=IFCDIRECTION((1.,0.,0.));
|
||||
#84=IFCDIRECTION((0.,0.,1.));
|
||||
#85=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#86=IFCAXIS2PLACEMENT3D(#85,#84,#83);
|
||||
#87=IFCGEOMETRICREPRESENTATIONCONTEXT('Plan','Model',3,1.E-005,#86,#82);
|
||||
#88=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
|
||||
#89=IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.);
|
||||
#90=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
|
||||
#91=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.0174533),#90);
|
||||
#92=IFCCONVERSIONBASEDUNIT(#88,.PLANEANGLEUNIT.,'Degrees',#91);
|
||||
#93=IFCUNITASSIGNMENT((#89,#92));
|
||||
#94=IFCPROJECT('0DMnBGAAP0egv6AtzWaDtb',#81,'IfcCompositeProfileDef',$,$,$,$,(#87),#93);
|
||||
#95=IFCDIRECTION((1.,0.,0.));
|
||||
#96=IFCDIRECTION((0.,0.,1.));
|
||||
#97=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#98=IFCAXIS2PLACEMENT3D(#97,#96,#95);
|
||||
#99=IFCLOCALPLACEMENT($,#98);
|
||||
#100=IFCSITE('1zP1fQSXb4cxuwjjpQU6bU',#81,$,$,$,#99,$,$,.ELEMENT.,$,$,$,$,$);
|
||||
#101=IFCRELAGGREGATES('0ZzcG2ut9F2BG7u28TPexy',#81,$,$,#94,(#100));
|
||||
#102=IFCDIRECTION((1.,0.,0.));
|
||||
#103=IFCDIRECTION((0.,0.,1.));
|
||||
#104=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#105=IFCAXIS2PLACEMENT3D(#104,#103,#102);
|
||||
#106=IFCLOCALPLACEMENT(#99,#105);
|
||||
#107=IFCBUILDING('0cM$4pWjvEFe6tscjMbee8',#81,$,$,$,#106,$,$,.ELEMENT.,$,$,$);
|
||||
#108=IFCRELAGGREGATES('0zaDy4$156SBV4NFDY$SC5',#81,$,$,#100,(#107));
|
||||
#109=IFCDIRECTION((1.,0.,0.));
|
||||
#110=IFCDIRECTION((0.,0.,1.));
|
||||
#111=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#112=IFCAXIS2PLACEMENT3D(#111,#110,#109);
|
||||
#113=IFCLOCALPLACEMENT(#106,#112);
|
||||
#114=IFCBUILDINGSTOREY('0WbxDykS94XukFPy9QwxyX',#81,$,$,$,#113,$,$,.ELEMENT.,$);
|
||||
#115=IFCRELAGGREGATES('2LJSUZqR53NhOup_TIPm5y',#81,$,$,#107,(#114));
|
||||
#116=IFCBUILDINGELEMENTPROXY('1qAWhlc9bBc9v_UZeT6Xd3',#81,'IfcCsgPrimitive',$,$,#122,#124,$,$);
|
||||
#117=IFCRELCONTAINEDINSPATIALSTRUCTURE('1SveiYYOXAmPiFhsZbsl1q',#81,$,$,(#116),#114);
|
||||
#118=IFCDIRECTION((1.,0.,0.));
|
||||
#119=IFCDIRECTION((0.,0.,1.));
|
||||
#120=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#121=IFCAXIS2PLACEMENT3D(#120,#119,#118);
|
||||
#122=IFCLOCALPLACEMENT($,#121);
|
||||
#123=IFCSHAPEREPRESENTATION(#87,'Body','CSG',(#41,#76));
|
||||
#124=IFCPRODUCTDEFINITIONSHAPE($,$,(#123));
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
Reference in New Issue
Block a user