mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-19 03:33:48 +00:00
Merge branch 'master' into performance_improvements
# Conflicts: # src/ifcexpressparser/implementation.py # src/ifcgeom/IfcGeomFunctions.cpp # src/ifcparse/Ifc4.cpp
This commit is contained in:
@@ -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*);
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user