Merge branch 'master' into performance_improvements

# Conflicts:
#	src/ifcexpressparser/implementation.py
#	src/ifcgeom/IfcGeomFunctions.cpp
#	src/ifcparse/Ifc4.cpp
This commit is contained in:
Thomas Krijnen
2016-04-24 15:22:10 +02:00
32 changed files with 1271 additions and 371 deletions
+2
View File
@@ -141,6 +141,8 @@ public:
void remove_collinear_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.);
bool wire_to_sequence_of_point(const TopoDS_Wire&, TColgp_SequenceOfPnt&);
void sequence_of_point_to_wire(const TColgp_SequenceOfPnt&, TopoDS_Wire&, bool closed);
bool approximate_plane_through_wire(const TopoDS_Wire&, gp_Pln&);
bool flatten_wire(TopoDS_Wire&);
bool is_identity_transform(IfcUtil::IfcBaseClass*);
+13 -2
View File
@@ -202,7 +202,11 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) {
ShapeFix_ShapeTolerance FTol;
FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
bool flattened_wire = false;
if (!mf) {
process_wire:
if (face_surface.IsNull()) {
mf = new BRepBuilderAPI_MakeFace(wire);
} else {
@@ -264,9 +268,16 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) {
success = true;
}
} else {
Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary", bound->entity);
const bool non_planar = mf->Error() == BRepBuilderAPI_NotPlanar;
delete mf;
return false;
if (!non_planar || flattened_wire || !flatten_wire(wire)) {
Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary", bound->entity);
return false;
} else {
Logger::Message(Logger::LOG_ERROR, "Flattening face boundary", bound->entity);
flattened_wire = true;
goto process_wire;
}
}
} else {
+73
View File
@@ -75,6 +75,8 @@
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepAlgo_NormalProjection.hxx>
#include <ShapeFix_Shape.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeFix_Solid.hxx>
@@ -94,6 +96,7 @@
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepTools.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_Array1OfTriangle.hxx>
@@ -1396,3 +1399,73 @@ bool IfcGeom::Kernel::is_identity_transform(IfcUtil::IfcBaseClass* l) {
}
}
bool IfcGeom::Kernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp_Pln& plane) {
// 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
double x = 0, y = 0, z = 0;
gp_Pnt current, previous, first;
gp_XYZ center;
int n = 0;
BRepTools_WireExplorer exp(wire);
for (;; exp.Next()) {
const bool has_more = exp.More();
if (has_more) {
const TopoDS_Vertex& v = exp.CurrentVertex();
current = BRep_Tool::Pnt(v);
center += current.XYZ();
} 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 (n < 3) {
return false;
}
plane = gp_Pln(center / n, gp_Dir(x, y, z));
return true;
}
bool IfcGeom::Kernel::flatten_wire(TopoDS_Wire& wire) {
gp_Pln pln;
if (!approximate_plane_through_wire(wire, pln)) {
return false;
}
TopoDS_Face face = BRepBuilderAPI_MakeFace(pln).Face();
BRepAlgo_NormalProjection proj(face);
proj.Add(wire);
proj.Build();
if (!proj.IsDone()) {
return false;
}
TopTools_ListOfShape list;
proj.BuildWire(list);
if (list.Extent() != 1) {
return false;
}
wire = TopoDS::Wire(list.First());
return true;
}
+17
View File
@@ -38,6 +38,23 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
const TopoDS_Shape& s = it->Shape();
gp_GTrsf trsf = it->Placement();
if (it->hasStyle() && it->Style().Diffuse()) {
const IfcGeom::SurfaceStyle::ColorComponent& clr = *it->Style().Diffuse();
_surface_styles.push_back(clr.R());
_surface_styles.push_back(clr.G());
_surface_styles.push_back(clr.B());
} else {
_surface_styles.push_back(-1.);
_surface_styles.push_back(-1.);
_surface_styles.push_back(-1.);
}
if (it->hasStyle() && it->Style().Transparency()) {
_surface_styles.push_back(1. - *it->Style().Transparency());
} else {
_surface_styles.push_back(1.);
}
if (settings().get(IteratorSettings::CONVERT_BACK_UNITS)) {
gp_Trsf scale;
scale.SetScaleFactor(1.0 / settings().unit_magnitude());
+2
View File
@@ -77,9 +77,11 @@ namespace IfcGeom {
private:
int _id;
std::string _brep_data;
std::vector<double> _surface_styles;
public:
int id() const { return _id; }
const std::string& brep_data() const { return _brep_data; }
const std::vector<double>& surface_styles() const { return _surface_styles; }
Serialization(const BRep& brep);
virtual ~Serialization() {}
private:
+30 -29
View File
@@ -98,6 +98,8 @@
#include <Standard_Version.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include "../ifcgeom/IfcGeom.h"
bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& shape) {
@@ -442,28 +444,38 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape
bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& shape) {
IfcSchema::IfcFace::list::ptr faces = l->CfsFaces();
bool facesAdded = false;
const unsigned int num_faces = (unsigned)faces->size();
TopTools_ListOfShape face_list;
for (IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++it) {
TopoDS_Face face;
try {
convert_face(*it, face);
} catch (...) {
continue;
}
if (face_area(face) > getValue(GV_MINIMAL_FACE_AREA)) {
face_list.Append(face);
} else {
Logger::Message(Logger::LOG_WARNING, "Invalid face:", (*it)->entity);
}
}
if (face_list.Extent() == 0) {
return false;
}
bool valid_shell = false;
if ( num_faces < getValue(GV_MAX_FACES_TO_SEW) ) {
TopTools_ListIteratorOfListOfShape face_iterator;
if ( face_list.Extent() < getValue(GV_MAX_FACES_TO_SEW) ) {
BRepOffsetAPI_Sewing builder;
builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMaxTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
builder.SetMinTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) {
TopoDS_Face face;
bool converted_face = false;
try {
converted_face = convert_face(*it,face);
} catch (...) {}
if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) {
builder.Add(face);
facesAdded = true;
} else {
Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity);
}
for (face_iterator.Initialize(face_list); face_iterator.More(); face_iterator.Next()) {
builder.Add(face_iterator.Value());
}
if ( ! facesAdded ) return false;
try {
builder.Perform();
shape = builder.SewedShape();
@@ -489,20 +501,9 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Sh
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) {
TopoDS_Face face;
bool converted_face = false;
try {
converted_face = convert_face(*it,face);
} catch (...) {}
if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) {
builder.Add(compound,face);
facesAdded = true;
} else {
Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity);
}
for (face_iterator.Initialize(face_list); face_iterator.More(); face_iterator.Next()) {
builder.Add(compound, face_iterator.Value());
}
if ( ! facesAdded ) return false;
shape = compound;
}
return true;