Brand new implementation of IfcFace(Surface)

This commit is contained in:
Thomas Krijnen
2015-05-20 08:55:02 +00:00
parent 9bf9f82b3b
commit 40a60386c8
12 changed files with 524 additions and 160 deletions
+176
View File
@@ -0,0 +1,176 @@
/********************************************************************************
* *
* 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 various forms of IfcFace *
* *
********************************************************************************/
#include "../ifcparse/Ifc2x3.h"
#include "../ifcparse/IfcUtil.h"
#include "../ifcparse/IfcHierarchyHelper.h"
typedef std::string S;
typedef IfcParse::IfcGlobalId guid;
boost::none_t const null = (static_cast<boost::none_t>(0));
static int x = 0;
void create_testcase(IfcHierarchyHelper& file, IfcSchema::IfcFace* face, const std::string& name) {
IfcSchema::IfcFace::list::ptr faces(new IfcSchema::IfcFace::list);
faces->push(face);
IfcSchema::IfcOpenShell* shell = new IfcSchema::IfcOpenShell(faces);
IfcSchema::IfcConnectedFaceSet::list::ptr shells(new IfcSchema::IfcConnectedFaceSet::list);
shells->push(shell);
IfcSchema::IfcFaceBasedSurfaceModel* model = new IfcSchema::IfcFaceBasedSurfaceModel(shells);
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
guid(), 0, name, null, null, 0, 0, null, null);
file.addBuildingProduct(product);
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
product->setObjectPlacement(file.addLocalPlacement(0, 1000 * x++, 0));
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);
items->push(model);
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
file.getRepresentationContext("Model"), S("Body"), S("SurfaceModel"), items);
reps->push(rep);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
file.addEntity(shape);
product->setRepresentation(shape);
}
int main(int argc, char** argv) {
IfcHierarchyHelper file;
{
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
bounds->push(bound);
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
create_testcase(file, face, "polyloop");
}
{
IfcSchema::IfcCartesianPoint* point1 = file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, 0., 0.);
IfcSchema::IfcCartesianPoint* point2 = file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, 0., 0.);
IfcSchema::IfcVertexPoint* vertex1 = new IfcSchema::IfcVertexPoint(point1);
IfcSchema::IfcVertexPoint* vertex2 = new IfcSchema::IfcVertexPoint(point2);
IfcSchema::IfcCircle* circle = new IfcSchema::IfcCircle(file.addPlacement2d(), 400.);
IfcSchema::IfcEdgeCurve* edge1 = new IfcSchema::IfcEdgeCurve(vertex1, vertex2, circle, true);
IfcSchema::IfcEdgeCurve* edge2 = new IfcSchema::IfcEdgeCurve(vertex2, vertex1, circle, true);
IfcSchema::IfcOrientedEdge* oriented_edge1 = new IfcSchema::IfcOrientedEdge(edge1, true);
IfcSchema::IfcOrientedEdge* oriented_edge2 = new IfcSchema::IfcOrientedEdge(edge2, true);
IfcSchema::IfcOrientedEdge::list::ptr edges(new IfcSchema::IfcOrientedEdge::list);
edges->push(oriented_edge1);
edges->push(oriented_edge2);
IfcSchema::IfcEdgeLoop* loop = new IfcSchema::IfcEdgeLoop(edges);
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
bounds->push(bound);
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
create_testcase(file, face, "circle");
}
{
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
IfcSchema::IfcFaceOuterBound* outer_bound = new IfcSchema::IfcFaceOuterBound(loop, true);
IfcSchema::IfcCartesianPoint::list::ptr points2 (new IfcSchema::IfcCartesianPoint::list);
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-300, -300, 0));
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, -300, 0));
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, +300, 0));
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-300, +300, 0));
IfcSchema::IfcPolyLoop* loop2 = new IfcSchema::IfcPolyLoop(points2);
IfcSchema::IfcFaceBound* inner_bound1 = new IfcSchema::IfcFaceBound(loop2, false);
IfcSchema::IfcCartesianPoint::list::ptr points3 (new IfcSchema::IfcCartesianPoint::list);
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, +300, 0));
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+300, +300, 0));
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+300, -300, 0));
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, -300, 0));
IfcSchema::IfcPolyLoop* loop3 = new IfcSchema::IfcPolyLoop(points3);
IfcSchema::IfcFaceBound* inner_bound2 = new IfcSchema::IfcFaceBound(loop3, true);
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
bounds->push(inner_bound1);
bounds->push(outer_bound);
bounds->push(inner_bound2);
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
create_testcase(file, face, "polyloop with holes");
}
{
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, -400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, +400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
IfcSchema::IfcFaceOuterBound* bound1 = new IfcSchema::IfcFaceOuterBound(loop, true);
IfcSchema::IfcCartesianPoint::list::ptr points2 (new IfcSchema::IfcCartesianPoint::list);
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, +400, 0));
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, -400, 0));
IfcSchema::IfcPolyLoop* loop2 = new IfcSchema::IfcPolyLoop(points2);
IfcSchema::IfcFaceOuterBound* bound2 = new IfcSchema::IfcFaceOuterBound(loop2, false);
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
bounds->push(bound1);
bounds->push(bound2);
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
create_testcase(file, face, "multiple outer boundaries (invalid)");
}
{
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 1e-6));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
bounds->push(bound);
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
create_testcase(file, face, "imprecise polyloop");
}
const std::string filename = "faces.ifc";
file.header().file_name().name(filename);
std::ofstream f(filename.c_str());
f << file;
}
-6
View File
@@ -120,10 +120,6 @@ int main(int argc, char** argv) {
"operand before applying the subtraction operation. This may "
"introduce a performance improvement at the risk of failing, in "
"which case the subtraction is applied one-by-one.")
("force-ccw-face-orientation",
"Recompute topological face normals using Newell's Method to "
"guarantee that face vertices are defined in a Counter Clock "
"Wise order, even if the faces are not part of a closed shell.")
("disable-opening-subtractions",
"Specifies whether to disable the boolean subtraction of "
"IfcOpeningElement Representations from their RelatingElements.")
@@ -173,7 +169,6 @@ int main(int argc, char** argv) {
const bool convert_back_units = vmap.count("convert-back-units") != 0;
const bool sew_shells = vmap.count("sew-shells") != 0;
const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0;
const bool force_ccw_face_orientation = vmap.count("force-ccw-face-orientation") != 0;
const bool disable_opening_subtractions = vmap.count("disable-opening-subtractions") != 0;
const bool include_entities = vmap.count("include") != 0;
const bool include_plan = vmap.count("plan") != 0;
@@ -240,7 +235,6 @@ int main(int argc, char** argv) {
settings.set(IfcGeom::IteratorSettings::SEW_SHELLS, sew_shells);
settings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, convert_back_units);
settings.set(IfcGeom::IteratorSettings::FASTER_BOOLEANS, merge_boolean_operands);
settings.set(IfcGeom::IteratorSettings::FORCE_CCW_FACE_ORIENTATION, force_ccw_face_orientation);
settings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions);
settings.set(IfcGeom::IteratorSettings::INCLUDE_CURVES, include_plan);
settings.set(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES, !include_model);
-3
View File
@@ -81,9 +81,6 @@ public:
// that consist of many faces is really detrimental for the performance.
// Default: 1000
GV_MAX_FACES_TO_SEW,
// By default singular faces have no explicitly defined orientation, to
// force faces to be defined CounterClockWise, set this value greater than zero.
GV_FORCE_CCW_FACE_ORIENTATION,
// The length unit used the creation of TopoDS_Shapes, primarily affects the
// interpretation of IfcCartesianPoints and IfcVector magnitudes
// DefaultL 1.0
+171 -105
View File
@@ -47,6 +47,7 @@
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_TrimmedCurve.hxx>
@@ -70,6 +71,7 @@
#include <TopoDS_Wire.hxx>
#include <TopoDS_Face.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Iterator.hxx>
#include <BRepAlgoAPI_Cut.hxx>
@@ -91,7 +93,6 @@
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Geom_Plane.hxx>
#include <BRepCheck_Face.hxx>
#endif
@@ -99,116 +100,181 @@
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) {
IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds();
IfcSchema::IfcFaceBound::list::it it = bounds->begin();
IfcSchema::IfcLoop* loop = (*it)->Bound();
// FIXME: The assumption that the first bound is
// the outer bound is not necessarily correct.
TopoDS_Wire outer_wire;
if ( ! convert_wire(loop,outer_wire) ) return false;
BRepBuilderAPI_MakeFace mf (outer_wire);
BRepBuilderAPI_FaceError er = mf.Error();
if ( er == BRepBuilderAPI_NotPlanar ) {
ShapeFix_ShapeTolerance FTol;
FTol.SetTolerance(outer_wire, 0.01, TopAbs_WIRE);
mf.~BRepBuilderAPI_MakeFace();
new (&mf) BRepBuilderAPI_MakeFace(outer_wire);
er = mf.Error();
}
if ( er != BRepBuilderAPI_FaceDone ) return false;
if ( bounds->size() == 1 ) {
face = mf.Face();
} else {
for( ++it; it != bounds->end(); ++ it) {
IfcSchema::IfcLoop* loop = (*it)->Bound();
TopoDS_Wire wire;
if ( ! convert_wire(loop,wire) ) return false;
mf.Add(wire);
}
if ( mf.IsDone() ) {
ShapeFix_Shape sfs(mf.Face());
sfs.Perform();
TopoDS_Shape sfs_shape = sfs.Shape();
bool is_face = sfs_shape.ShapeType() == TopAbs_FACE;
// This assertion is not strictly necessary. The schema
// does suggest there to be only one outer bound, but
// not all models comply with this.
if ( is_face ) {
face = TopoDS::Face(sfs_shape);
} else {
face = sfs_shape;
}
} else {
return false;
}
}
if ( getValue(GV_FORCE_CCW_FACE_ORIENTATION)>0 ) {
// Check the orientation of the face by comparing the
// normal of the topological surface to the Newell's Method's
// normal. Newell's Method is used for the normal calculation
// as a simple edge cross product can give opposite results
// for a concave face boundary.
// Reference: Graphics Gems III p. 231
BRepGProp_Face prop(TopoDS::Face(face));
gp_Vec normal_direction;
gp_Pnt center;
double u1,u2,v1,v2;
prop.Bounds(u1,u2,v1,v2);
prop.Normal((u1+u2)/2.0,(v1+v2)/2.0,center,normal_direction);
gp_Dir face_normal1 = gp_Dir(normal_direction.XYZ());
Handle(Geom_Surface) face_surface;
bool reversed_face_surface = false;
const bool is_face_surface = l->is(IfcSchema::Type::IfcFaceSurface);
double x = 0, y = 0, z = 0;
gp_Pnt current, previous, first;
int n = 0;
// Iterate over the vertices of the outer wire (discarding
// any potential holes)
for ( TopExp_Explorer exp(outer_wire,TopAbs_VERTEX);; exp.Next()) {
unsigned has_more = exp.More();
if ( has_more ) {
const TopoDS_Vertex& v = TopoDS::Vertex(exp.Current());
current = BRep_Tool::Pnt(v);
} else {
current = first;
}
if ( n ) {
const double& xn = previous.X();
const double& yn = previous.Y();
const double& zn = previous.Z();
const double& xn1 = current.X();
const double& yn1 = current.Y();
const double& zn1 = current.Z();
x += (yn-yn1)*(zn+zn1);
y += (xn+xn1)*(zn-zn1);
z += (xn-xn1)*(yn+yn1);
} else {
first = current;
}
if ( !has_more ) {
break;
}
previous = current;
++n;
}
if (is_face_surface) {
IfcSchema::IfcFaceSurface* fs = (IfcSchema::IfcFaceSurface*) l;
fs->FaceSurface();
// FIXME: Surfaces are interpreted as a TopoDS_Shape
TopoDS_Shape surface_shape;
if (!convert_shape(fs->FaceSurface(), surface_shape)) return false;
// If Newell's normal does not point in the same direction
// as the topological face normal the face orientation is
// reversed
gp_Vec face_normal2(x,y,z);
// FIXME: Assert this obtaines the only face
TopExp_Explorer exp(surface_shape, TopAbs_FACE);
if (!exp.More()) return false;
if (face_normal2.Magnitude() > ALMOST_ZERO) {
if ( face_normal1.Dot(face_normal2) < 0 ) {
TopAbs_Orientation o = face.Orientation();
face.Orientation(o == TopAbs_FORWARD ? TopAbs_REVERSED : TopAbs_FORWARD);
}
}
TopoDS_Face surface = TopoDS::Face(exp.Current());
face_surface = BRep_Tool::Surface(surface);
}
// It might be a good idea to globally discard faces
// smaller than a certain treshold value. But for now
// only when processing IfcConnectedFacesets the small
// faces are skipped.
// return face_area(face) > 0.0001;
return true;
const int num_bounds = bounds->size();
int num_outer_bounds = 0;
for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
IfcSchema::IfcFaceBound* bound = *it;
if (bound->is(IfcSchema::Type::IfcFaceOuterBound)) num_outer_bounds ++;
}
// The number of outer bounds should be one according to the schema. Also Open Cascade
// expects this, but it is not strictly checked. Regardless, if the number is greater,
// the face will still be processed as long as there are no holes. A compound of faces
// is returned in that case.
if (num_bounds > 1 && num_outer_bounds > 1 && num_bounds != num_outer_bounds) {
Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity);
return false;
}
TopoDS_Compound compound;
BRep_Builder builder;
if (num_outer_bounds > 1) {
builder.MakeCompound(compound);
}
// The builder is initialized on the heap because of the various different moments
// of initialization depending on the configuration of surfaces and boundaries.
BRepBuilderAPI_MakeFace* mf = 0;
bool success = false;
int processed = 0;
for (int process_interior = 0; process_interior <= 1; ++process_interior) {
for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
IfcSchema::IfcFaceBound* bound = *it;
IfcSchema::IfcLoop* loop = bound->Bound();
const bool same_sense = bound->Orientation();
const bool is_interior =
!bound->is(IfcSchema::Type::IfcFaceOuterBound) &&
(num_bounds > 1) &&
(num_outer_bounds < num_bounds);
// The exterior face boundary is processed first
if (is_interior == !process_interior) continue;
TopoDS_Wire wire;
if (!convert_wire(loop, wire)) break;
/*
The approach below does not result in a significant speed-up
if (loop->is(IfcSchema::Type::IfcPolyLoop) && processed == 0 && face_surface.IsNull()) {
IfcSchema::IfcPolyLoop* polyloop = (IfcSchema::IfcPolyLoop*) loop;
IfcSchema::IfcCartesianPoint::list::ptr points = polyloop->Polygon();
if (points->size() == 3) {
// Help Open Cascade by finding the plane more efficiently
IfcSchema::IfcCartesianPoint::list::it point_iterator = points->begin();
gp_Pnt a, b, c;
convert(*point_iterator++, a);
convert(*point_iterator++, b);
convert(*point_iterator++, c);
const gp_XYZ ab = (b.XYZ() - a.XYZ());
const gp_XYZ ac = (c.XYZ() - a.XYZ());
const gp_Vec cross = ab.Crossed(ac);
if (cross.SquareMagnitude() > ALMOST_ZERO) {
const gp_Dir n = cross;
face_surface = new Geom_Plane(a, n);
}
}
}
*/
if (!same_sense) {
wire.Reverse();
}
ShapeFix_ShapeTolerance FTol;
FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
if (!mf) {
if (face_surface.IsNull()) {
mf = new BRepBuilderAPI_MakeFace(wire);
} else {
mf = new BRepBuilderAPI_MakeFace(face_surface, wire);
}
/* BRepBuilderAPI_FaceError er = mf->Error();
if (er == BRepBuilderAPI_NotPlanar) {
ShapeFix_ShapeTolerance FTol;
FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
delete mf;
mf = new BRepBuilderAPI_MakeFace(wire);
} */
if (mf->IsDone()) {
TopoDS_Face outer_face_bound = mf->Face();
// If the wires are reversed the face needs to be reversed as well in order
// to maintain the counter-clock-wise ordering of the bounding wire's vertices.
bool all_reversed = true;
TopoDS_Iterator it(outer_face_bound, false);
for (; it.More(); it.Next()) {
const TopoDS_Wire& w = TopoDS::Wire(it.Value());
if ((w.Orientation() != TopAbs_REVERSED) == same_sense) {
all_reversed = false;
}
}
if (all_reversed) {
outer_face_bound.Reverse();
}
if (num_outer_bounds > 1) {
builder.Add(compound, outer_face_bound);
delete mf; mf = 0;
} else if (num_bounds > 1) {
// Reinitialize the builder to the outer face
// bound in order to add holes more robustly.
delete mf;
mf = new BRepBuilderAPI_MakeFace(outer_face_bound);
} else {
face = outer_face_bound;
success = true;
}
} else {
break;
}
} else {
mf->Add(wire);
}
processed ++;
}
}
if (!success) {
success = processed == num_bounds;
if (success) {
if (num_outer_bounds > 1) {
face = compound;
} else {
success = success && mf->IsDone();
if (success) {
face = mf->Face();
}
}
}
}
if (success) {
ShapeFix_ShapeTolerance FTol;
FTol.SetTolerance(face, getValue(GV_PRECISION), TopAbs_FACE);
}
delete mf;
return success;
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, TopoDS_Shape& face) {
-7
View File
@@ -503,7 +503,6 @@ static double point_equality_tolerance = 0.00001;
static double max_faces_to_sew = -1.0;
static double ifc_length_unit = 1.0;
static double ifc_planeangle_unit = -1.0;
static double force_ccw_face_orientation = -1.0;
static double modelling_precision = 0.00001;
static double dimensionality = 1;
@@ -530,9 +529,6 @@ void IfcGeom::Kernel::setValue(GeomValue var, double value) {
case GV_PLANEANGLE_UNIT:
ifc_planeangle_unit = value;
break;
case GV_FORCE_CCW_FACE_ORIENTATION:
force_ccw_face_orientation = value;
break;
case GV_PRECISION:
modelling_precision = value;
break;
@@ -562,9 +558,6 @@ double IfcGeom::Kernel::getValue(GeomValue var) {
case GV_PLANEANGLE_UNIT:
return ifc_planeangle_unit;
break;
case GV_FORCE_CCW_FACE_ORIENTATION:
return force_ccw_face_orientation;
break;
case GV_PRECISION:
return modelling_precision;
break;
-1
View File
@@ -450,7 +450,6 @@ namespace IfcGeom {
unit_magnitude = 1.f;
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1);
kernel.setValue(IfcGeom::Kernel::GV_FORCE_CCW_FACE_ORIENTATION, settings.force_ccw_face_orientation() ? 1 : -1);
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.include_curves() ? (settings.exclude_solids_and_surfaces() ? -1. : 0.) : +1.));
}
public:
+1 -10
View File
@@ -55,9 +55,6 @@ namespace IfcGeom {
// Specifies whether to compose IfcOpeningElements into a single compound
// in order to speed up the processing of opening subtractions.
static const int FASTER_BOOLEANS = 6;
// By default singular faces have no explicitly defined orientation, to
// force faces to be defined CounterClockWise set this to true.
static const int FORCE_CCW_FACE_ORIENTATION = 7;
// Disables the subtraction of IfcOpeningElement representations from
// the related building element representations.
static const int DISABLE_OPENING_SUBTRACTIONS = 8;
@@ -74,7 +71,7 @@ namespace IfcGeom {
// End of settings enumeration.
private:
bool _weld_vertices, _use_world_coords, _convert_back_units, _use_brep_data, _sew_shells, _faster_booleans, _force_ccw_face_orientation, _disable_opening_subtractions, _disable_triangulation, _apply_default_materials, _include_curves, _exclude_solids_and_surfaces;
bool _weld_vertices, _use_world_coords, _convert_back_units, _use_brep_data, _sew_shells, _faster_booleans, _disable_opening_subtractions, _disable_triangulation, _apply_default_materials, _include_curves, _exclude_solids_and_surfaces;
double _deflection_tolerance;
public:
IteratorSettings()
@@ -84,7 +81,6 @@ namespace IfcGeom {
, _use_brep_data(false)
, _sew_shells(false)
, _faster_booleans(false)
, _force_ccw_face_orientation(false)
, _disable_opening_subtractions(false)
, _disable_triangulation(false)
, _apply_default_materials(false)
@@ -107,8 +103,6 @@ namespace IfcGeom {
bool& sew_shells() { return _sew_shells; }
const bool& faster_booleans() const { return _faster_booleans; }
bool& faster_booleans() { return _faster_booleans; }
const bool& force_ccw_face_orientation() const { return _force_ccw_face_orientation; }
bool& force_ccw_face_orientation() { return _force_ccw_face_orientation; }
const bool& disable_opening_subtractions() const { return _disable_opening_subtractions; }
bool& disable_opening_subtractions() { return _disable_opening_subtractions; }
const bool& disable_triangulation() const { return _disable_triangulation; }
@@ -143,9 +137,6 @@ namespace IfcGeom {
case SEW_SHELLS:
_sew_shells = value;
break;
case FORCE_CCW_FACE_ORIENTATION:
_force_ccw_face_orientation = value;
break;
case DISABLE_OPENING_SUBTRACTIONS:
_disable_opening_subtractions = value;
break;
+10 -25
View File
@@ -408,30 +408,15 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& resu
IfcSchema::IfcOrientedEdge::list::ptr li = l->EdgeList();
BRepBuilderAPI_MakeWire mw;
for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) {
IfcSchema::IfcOrientedEdge* e = *it;
IfcSchema::IfcPoint* pnt1 = ((IfcSchema::IfcVertexPoint*) e->EdgeStart())->VertexGeometry();
IfcSchema::IfcPoint* pnt2 = ((IfcSchema::IfcVertexPoint*) e->EdgeEnd())->VertexGeometry();
if (!pnt1->is(IfcSchema::Type::IfcCartesianPoint) || !pnt2->is(IfcSchema::Type::IfcCartesianPoint)) {
Logger::Message(Logger::LOG_ERROR, "Only IfcCartesianPoints are supported for VertexGeometry", l->entity);
return false;
}
gp_Pnt p1, p2;
if (!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) ||
!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2))
{
return false;
}
mw.Add(BRepBuilderAPI_MakeEdge(p1, p2));
continue;
IfcSchema::IfcEdge* base = e->EdgeElement();
TopoDS_Wire w;
if (convert_wire(e->EdgeElement(), w)) {
if (!e->Orientation()) w.Reverse();
mw.Add(w);
if (convert_wire(*it, w)) {
if (!(*it)->Orientation()) w.Reverse();
TopoDS_Iterator it(w, false);
for (; it.More(); it.Next()) {
const TopoDS_Edge& e = TopoDS::Edge(it.Value());
mw.Add(e);
}
// mw.Add(w);
}
}
result = mw;
@@ -466,7 +451,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdge* l, TopoDS_Wire& result)
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcOrientedEdge* l, TopoDS_Wire& result) {
if (convert(l->EdgeElement(), result)) {
if (convert_wire(l->EdgeElement(), result)) {
if (!l->Orientation()) {
result.Reverse();
}
@@ -478,7 +463,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcOrientedEdge* l, TopoDS_Wire&
bool IfcGeom::Kernel::convert(const IfcSchema::IfcSubedge* l, TopoDS_Wire& result) {
TopoDS_Wire temp;
if (convert(l->ParentEdge(), result) && convert((IfcSchema::IfcEdge*) l, temp)) {
if (convert_wire(l->ParentEdge(), result) && convert((IfcSchema::IfcEdge*) l, temp)) {
TopExp_Explorer exp(result, TopAbs_EDGE);
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
Standard_Real u1, u2;
+1
View File
@@ -93,6 +93,7 @@ FACE(IfcEllipseProfileDef);
FACE(IfcCenterLineProfileDef);
FACE(IfcCompositeProfileDef);
FACE(IfcDerivedProfileDef);
// IfcFaceSurface included
FACE(IfcFace);
WIRE(IfcEdgeCurve);
-1
View File
@@ -321,7 +321,6 @@ int main (int argc, char** argv) {
settings.use_world_coords() = false;
settings.weld_vertices() = false;
settings.convert_back_units() = true;
settings.force_ccw_face_orientation() = true;
settings.include_curves() = true;
iterator = new IfcGeom::Iterator<float>(settings, data, len);
+1 -2
View File
@@ -95,7 +95,7 @@
%extend IfcGeom::IteratorSettings {
%pythoncode %{
attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "force_ccw_face_orientation", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices")
attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices")
def __repr__(self):
return "%s(%s)"%(self.__class__.__name__, ",".join(tuple("%s=%r"%(a, getattr(self, a)()) for a in self.attrs)))
%}
@@ -218,7 +218,6 @@
IfcGeom::Kernel kernel;
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1);
kernel.setValue(IfcGeom::Kernel::GV_FORCE_CCW_FACE_ORIENTATION, settings.force_ccw_face_orientation() ? 1 : -1);
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.include_curves() ? (settings.exclude_solids_and_surfaces() ? -1. : 0.) : +1.));
IfcSchema::IfcProduct* product = (IfcSchema::IfcProduct*) instance;
+164
View File
@@ -0,0 +1,164 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('faces.ifc','2015-05-20T10:50:06',(),(),'IfcOpenShell 0.5.0-dev','IfcOpenShell 0.5.0-dev','');
FILE_SCHEMA(('IFC2X3'));
ENDSEC;
DATA;
#1=IFCCARTESIANPOINT((-400.,-400.,0.));
#2=IFCCARTESIANPOINT((400.,-400.,0.));
#3=IFCCARTESIANPOINT((400.,400.,0.));
#4=IFCCARTESIANPOINT((-400.,400.,0.));
#5=IFCPERSON($,$,'',$,$,$,$,$);
#6=IFCORGANIZATION($,'IfcOpenShell',$,$,$);
#7=IFCPERSONANDORGANIZATION(#5,#6,$);
#8=IFCAPPLICATION(#6,'0.5.0-dev','IfcOpenShell','IfcOpenShell');
#9=IFCOWNERHISTORY(#7,#8,$,.ADDED.,1432111806,#7,#8,1432111806);
#10=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
#11=IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.);
#12=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
#14=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453293),#12);
#15=IFCCONVERSIONBASEDUNIT(#10,.PLANEANGLEUNIT.,'Degrees',#14);
#16=IFCUNITASSIGNMENT((#11,#15));
#17=IFCPROJECT('1HQX190X58kvRECR6voyfc',#9,$,$,$,$,$,(#51),#16);
#18=IFCDIRECTION((1.,0.,0.));
#19=IFCDIRECTION((0.,0.,1.));
#20=IFCCARTESIANPOINT((0.,0.,0.));
#21=IFCAXIS2PLACEMENT3D(#20,#19,#18);
#22=IFCLOCALPLACEMENT($,#21);
#23=IFCSITE('0eyqmWf4z3dANo5Kaef3tu',#9,$,$,$,#22,$,$,.ELEMENT.,$,$,$,$,$);
#24=IFCRELAGGREGATES('18QNJy24z3FB9H1omtBuo_',#9,$,$,#17,(#23));
#25=IFCDIRECTION((1.,0.,0.));
#26=IFCDIRECTION((0.,0.,1.));
#27=IFCCARTESIANPOINT((0.,0.,0.));
#28=IFCAXIS2PLACEMENT3D(#27,#26,#25);
#29=IFCLOCALPLACEMENT(#22,#28);
#30=IFCBUILDING('3jWWZTz7n64v5lXI7dcOG2',#9,$,$,$,#29,$,$,.ELEMENT.,$,$,$);
#31=IFCRELAGGREGATES('3I_AMlVAjD7AJyIfSH193g',#9,$,$,#23,(#30));
#32=IFCDIRECTION((1.,0.,0.));
#33=IFCDIRECTION((0.,0.,1.));
#34=IFCCARTESIANPOINT((0.,0.,0.));
#35=IFCAXIS2PLACEMENT3D(#34,#33,#32);
#36=IFCLOCALPLACEMENT(#29,#35);
#37=IFCBUILDINGSTOREY('1_ImA5b7HELAI8raWFYphY',#9,$,$,$,#36,$,$,.ELEMENT.,$);
#38=IFCRELAGGREGATES('29hL9yBXj6lvk6BXb$wnMF',#9,$,$,#30,(#37));
#39=IFCBUILDINGELEMENTPROXY('344_rTMFT6RuKWcRH19W6g',#9,'polyloop',$,$,#45,#58,$,$);
#40=IFCRELCONTAINEDINSPATIALSTRUCTURE('2RQ$SfpKfBYuSRATxRwC0V',#9,$,$,(#39),#37);
#41=IFCDIRECTION((1.,0.,0.));
#42=IFCDIRECTION((0.,0.,1.));
#43=IFCCARTESIANPOINT((0.,0.,0.));
#44=IFCAXIS2PLACEMENT3D(#43,#42,#41);
#45=IFCLOCALPLACEMENT($,#44);
#46=IFCDIRECTION((0.,1.));
#47=IFCDIRECTION((1.,0.,0.));
#48=IFCDIRECTION((0.,0.,1.));
#49=IFCCARTESIANPOINT((0.,0.,0.));
#50=IFCAXIS2PLACEMENT3D(#49,#48,#47);
#51=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-005,#50,#46);
#52=IFCPOLYLOOP((#1,#2,#3,#4));
#53=IFCFACEOUTERBOUND(#52,.T.);
#54=IFCFACE((#53));
#55=IFCOPENSHELL((#54));
#56=IFCFACEBASEDSURFACEMODEL((#55));
#57=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#56));
#58=IFCPRODUCTDEFINITIONSHAPE($,$,(#57));
#59=IFCCARTESIANPOINT((400.,0.,0.));
#60=IFCCARTESIANPOINT((-400.,0.,0.));
#61=IFCDIRECTION((1.,0.));
#62=IFCCARTESIANPOINT((0.,0.));
#63=IFCAXIS2PLACEMENT2D(#62,#61);
#64=IFCBUILDINGELEMENTPROXY('35crzRJnnE9Akf8211DDa3',#9,'circle',$,$,#70,#84,$,$);
#65=IFCRELCONTAINEDINSPATIALSTRUCTURE('3gBsuCqwb3me5EkC8o3Mpn',#9,$,$,(#64),#37);
#66=IFCDIRECTION((1.,0.,0.));
#67=IFCDIRECTION((0.,0.,1.));
#68=IFCCARTESIANPOINT((1000.,0.,0.));
#69=IFCAXIS2PLACEMENT3D(#68,#67,#66);
#70=IFCLOCALPLACEMENT($,#69);
#71=IFCVERTEXPOINT(#59);
#72=IFCVERTEXPOINT(#60);
#73=IFCCIRCLE(#63,400.);
#74=IFCEDGECURVE(#71,#72,#73,.T.);
#75=IFCORIENTEDEDGE(*,*,#74,.T.);
#76=IFCEDGECURVE(#72,#71,#73,.T.);
#77=IFCORIENTEDEDGE(*,*,#76,.T.);
#78=IFCEDGELOOP((#75,#77));
#79=IFCFACEOUTERBOUND(#78,.T.);
#80=IFCFACE((#79));
#81=IFCOPENSHELL((#80));
#82=IFCFACEBASEDSURFACEMODEL((#81));
#83=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#82));
#84=IFCPRODUCTDEFINITIONSHAPE($,$,(#83));
#85=IFCCARTESIANPOINT((-400.,-400.,0.));
#86=IFCCARTESIANPOINT((400.,-400.,0.));
#87=IFCCARTESIANPOINT((400.,400.,0.));
#88=IFCCARTESIANPOINT((-400.,400.,0.));
#89=IFCCARTESIANPOINT((-300.,-300.,0.));
#90=IFCCARTESIANPOINT((-100.,-300.,0.));
#91=IFCCARTESIANPOINT((-100.,300.,0.));
#92=IFCCARTESIANPOINT((-300.,300.,0.));
#93=IFCCARTESIANPOINT((100.,300.,0.));
#94=IFCCARTESIANPOINT((300.,300.,0.));
#95=IFCCARTESIANPOINT((300.,-300.,0.));
#96=IFCCARTESIANPOINT((100.,-300.,0.));
#97=IFCBUILDINGELEMENTPROXY('3w09rKcILCYAnKVxlLSjOP',#9,'polyloop with holes',$,$,#103,#114,$,$);
#98=IFCRELCONTAINEDINSPATIALSTRUCTURE('2QRyhTXwH8WPAUUlchhb7x',#9,$,$,(#97),#37);
#99=IFCDIRECTION((1.,0.,0.));
#100=IFCDIRECTION((0.,0.,1.));
#101=IFCCARTESIANPOINT((2000.,0.,0.));
#102=IFCAXIS2PLACEMENT3D(#101,#100,#99);
#103=IFCLOCALPLACEMENT($,#102);
#104=IFCPOLYLOOP((#89,#90,#91,#92));
#105=IFCFACEBOUND(#104,.F.);
#106=IFCPOLYLOOP((#85,#86,#87,#88));
#107=IFCFACEOUTERBOUND(#106,.T.);
#108=IFCPOLYLOOP((#93,#94,#95,#96));
#109=IFCFACEBOUND(#108,.T.);
#110=IFCFACE((#105,#107,#109));
#111=IFCOPENSHELL((#110));
#112=IFCFACEBASEDSURFACEMODEL((#111));
#113=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#112));
#114=IFCPRODUCTDEFINITIONSHAPE($,$,(#113));
#115=IFCCARTESIANPOINT((-400.,-400.,0.));
#116=IFCCARTESIANPOINT((-100.,-400.,0.));
#117=IFCCARTESIANPOINT((-100.,400.,0.));
#118=IFCCARTESIANPOINT((-400.,400.,0.));
#119=IFCCARTESIANPOINT((100.,400.,0.));
#120=IFCCARTESIANPOINT((400.,400.,0.));
#121=IFCCARTESIANPOINT((400.,-400.,0.));
#122=IFCCARTESIANPOINT((100.,-400.,0.));
#123=IFCBUILDINGELEMENTPROXY('0cxEkTWf97T8imCiw2hTqD',#9,'multiple outer boundaries (invalid)',$,$,#129,#138,$,$);
#124=IFCRELCONTAINEDINSPATIALSTRUCTURE('0$orfSvG18vfnhm9zOB5l5',#9,$,$,(#123),#37);
#125=IFCDIRECTION((1.,0.,0.));
#126=IFCDIRECTION((0.,0.,1.));
#127=IFCCARTESIANPOINT((3000.,0.,0.));
#128=IFCAXIS2PLACEMENT3D(#127,#126,#125);
#129=IFCLOCALPLACEMENT($,#128);
#130=IFCPOLYLOOP((#115,#116,#117,#118));
#131=IFCFACEOUTERBOUND(#130,.T.);
#132=IFCPOLYLOOP((#119,#120,#121,#122));
#133=IFCFACEOUTERBOUND(#132,.F.);
#134=IFCFACE((#131,#133));
#135=IFCOPENSHELL((#134));
#136=IFCFACEBASEDSURFACEMODEL((#135));
#137=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#136));
#138=IFCPRODUCTDEFINITIONSHAPE($,$,(#137));
#139=IFCCARTESIANPOINT((-400.,-400.,1.E-006));
#140=IFCCARTESIANPOINT((400.,-400.,0.));
#141=IFCCARTESIANPOINT((400.,400.,0.));
#142=IFCCARTESIANPOINT((-400.,400.,0.));
#143=IFCBUILDINGELEMENTPROXY('1u73lgHiH3IesmFCYzbd$l',#9,'imprecise polyloop',$,$,#149,#156,$,$);
#144=IFCRELCONTAINEDINSPATIALSTRUCTURE('0AV1k6Kl19x9ot0jkkQV8h',#9,$,$,(#143),#37);
#145=IFCDIRECTION((1.,0.,0.));
#146=IFCDIRECTION((0.,0.,1.));
#147=IFCCARTESIANPOINT((4000.,0.,0.));
#148=IFCAXIS2PLACEMENT3D(#147,#146,#145);
#149=IFCLOCALPLACEMENT($,#148);
#150=IFCPOLYLOOP((#139,#140,#141,#142));
#151=IFCFACEOUTERBOUND(#150,.T.);
#152=IFCFACE((#151));
#153=IFCOPENSHELL((#152));
#154=IFCFACEBASEDSURFACEMODEL((#153));
#155=IFCSHAPEREPRESENTATION(#51,'Body','SurfaceModel',(#154));
#156=IFCPRODUCTDEFINITIONSHAPE($,$,(#155));
ENDSEC;
END-ISO-10303-21;