closed shell; placements; faceset_helper

This commit is contained in:
Thomas Krijnen
2019-08-28 09:54:20 +02:00
parent 3bfe3b9ab5
commit 64ee3e9af3
6 changed files with 66 additions and 43 deletions
@@ -841,7 +841,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::shell *shell, ifcopenshell:
bool OpenCascadeKernel::convert(const taxonomy::matrix4* matrix, gp_GTrsf& trsf) {
// @todo check
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++i) {
for (int j = 0; j < 4; ++j) {
trsf.SetValue(i + 1, j + 1, matrix->components(i, j));
}
}
@@ -1415,14 +1415,42 @@ OpenCascadeKernel::faceset_helper::~faceset_helper() {
kernel_->faceset_helper_ = nullptr;
}
#include "IfcGeomTree.h"
namespace {
void find_neighbours(ifcopenshell::geometry::impl::tree<int>& tree, std::vector<std::unique_ptr<gp_Pnt>>& pnts, std::set<int>& visited, int p, double eps) {
visited.insert(p);
Bnd_Box b;
b.Set(*pnts[p].get());
b.Enlarge(eps);
std::vector<int> js = tree.select_box(b, false);
for (int j : js) {
visited.insert(j);
#ifdef FACESET_HELPER_RECURSIVE
if (visited.find(j) == visited.end()) {
// @todo, making this recursive removes the dependence on the initial ordering, but will
// likely result in empty results when all vertices are within 1 eps from another point.
find_neighbours(tree, pnts, visited, j, eps);
}
#endif
}
}
}
OpenCascadeKernel::faceset_helper::faceset_helper(OpenCascadeKernel* kernel, const taxonomy::shell* shell)
: kernel_(kernel)
, non_manifold_(false) {
kernel->faceset_helper_ = this;
// @todo use pointers?
std::vector<taxonomy::point3> points;
std::vector<taxonomy::loop*> loops;
for (auto& f : shell->children_as<taxonomy::face>()) {
for (auto& l : f->children_as<taxonomy::loop>()) {
loops.push_back(l);
for (auto& e : l->children_as<taxonomy::edge>()) {
// @todo make sure only cartesian points are provided here
points.push_back(boost::get<taxonomy::point3>(e->start));
@@ -1434,22 +1462,17 @@ OpenCascadeKernel::faceset_helper::faceset_helper(OpenCascadeKernel* kernel, con
std::vector<TopoDS_Vertex> vertices(pnts.size());
// @todo
/*
IfcGeom::impl::tree<int> tree;
impl::tree<int> tree;
BRep_Builder B;
Bnd_Box box;
for (size_t i = 0; i < points->size(); ++i) {
gp_Pnt* p = new gp_Pnt();
if (kernel->convert(*(points->begin() + i), *p)) {
pnts[i].reset(p);
B.MakeVertex(vertices[i], *p, Precision::Confusion());
tree.add(i, vertices[i]);
box.Add(*p);
} else {
delete p;
}
for (size_t i = 0; i < points.size(); ++i) {
gp_Pnt* p = new gp_Pnt(convert_xyz<gp_Pnt>(points[i]));
pnts[i].reset(p);
B.MakeVertex(vertices[i], *p, Precision::Confusion());
tree.add(i, vertices[i]);
box.Add(*p);
}
// Use the bbox diagonal to influence local epsilon
@@ -1469,19 +1492,18 @@ OpenCascadeKernel::faceset_helper::faceset_helper(OpenCascadeKernel* kernel, con
double bdiff = std::numeric_limits<double>::infinity();
for (size_t i = 0; i < 3; ++i) {
const double d = bmax[i] - bmin[i];
if (d > kernel->getValue(GV_PRECISION) * 10. && d < bdiff) {
if (d > kernel->precision_ * 10. && d < bdiff) {
bdiff = d;
}
}
eps_ = kernel->getValue(GV_PRECISION) * 10. * (std::min)(1.0, bdiff);
eps_ = kernel->precision_ * 10. * (std::min)(1.0, bdiff);
// @todo, there a tiny possibility that the duplicate faces are triggered
// for an internal boundary, that is also present as an external boundary.
// This will result in non-manifold configuration then, but this is deemed
// such as corner-case that it is not considered.
IfcSchema::IfcPolyLoop::list::ptr loops = IfcParse::traverse((IfcUtil::IfcBaseClass*)l)->as<IfcSchema::IfcPolyLoop>();
size_t loops_removed, non_manifold, duplicate_faces;
std::map<std::pair<int, int>, int> edge_use;
@@ -1512,9 +1534,9 @@ OpenCascadeKernel::faceset_helper::faceset_helper(OpenCascadeKernel* kernel, con
find_neighbours(tree, pnts, vs, i, eps_);
for (int v : vs) {
auto pt = *(points->begin() + v);
auto& pt = points[v];
// NB: insert() ignores duplicate keys
vertex_mapping_.insert({ pt->data().id() , i });
vertex_mapping_.insert({ pt.instance->data().id() , i });
}
}
}
@@ -1523,20 +1545,18 @@ OpenCascadeKernel::faceset_helper::faceset_helper(OpenCascadeKernel* kernel, con
typedef std::set<edge_t> edge_set_t;
std::set<edge_set_t> edge_sets;
for (auto& loop : *loops) {
auto ps = loop->Polygon();
for (auto& loop : loops) {
std::vector<std::pair<int, int> > segments;
edge_set_t segment_set;
loop_(ps, [&segments, &segment_set](int C, int D, bool) {
loop_(loop, [&segments, &segment_set](int C, int D, bool) {
segment_set.insert({ { C, D } });
segments.push_back({ C, D });
});
if (edge_sets.find(segment_set) != edge_sets.end()) {
duplicate_faces++;
duplicates_.insert(loop);
duplicates_.insert(loop->instance->data().id());
continue;
}
edge_sets.insert(segment_set);
@@ -1567,8 +1587,7 @@ OpenCascadeKernel::faceset_helper::faceset_helper(OpenCascadeKernel* kernel, con
}
}
if (loops_removed || (non_manifold && l->declaration().is(IfcSchema::IfcClosedShell::Class()))) {
Logger::Warning(boost::lexical_cast<std::string>(duplicate_faces) + " duplicate faces removed, " + boost::lexical_cast<std::string>(loops_removed) + " loops removed and " + boost::lexical_cast<std::string>(non_manifold) + " non-manifold edges for:", l);
if (loops_removed || (non_manifold && shell->closed.get_value_or(false))) {
Logger::Warning(boost::lexical_cast<std::string>(duplicate_faces) + " duplicate faces removed, " + boost::lexical_cast<std::string>(loops_removed) + " loops removed and " + boost::lexical_cast<std::string>(non_manifold) + " non-manifold edges for:", shell->instance);
}
*/
}
+12 -12
View File
@@ -23,7 +23,7 @@
#include "../../../ifcparse/IfcFile.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomIterator.h"
#include "../../../ifcgeom/schema_agnostic/Kernel.h"
#include "../../../ifcgeom/schema_agnostic/Converter.h"
#include "../../../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h"
#include <NCollection_UBTree.hxx>
@@ -33,7 +33,7 @@
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
namespace IfcGeom {
namespace ifcopenshell { namespace geometry {
namespace impl {
template <typename T>
@@ -259,30 +259,30 @@ namespace IfcGeom {
tree() {};
tree(IfcParse::IfcFile& f) {
add_file(f, IfcGeom::IteratorSettings());
add_file(f, ifcopenshell::geometry::settings());
}
tree(IfcParse::IfcFile& f, const IfcGeom::IteratorSettings& settings) {
tree(IfcParse::IfcFile& f, const ifcopenshell::geometry::settings& settings) {
add_file(f, settings);
}
void add_file(IfcParse::IfcFile& f, const IfcGeom::IteratorSettings& settings) {
IfcGeom::IteratorSettings settings_ = settings;
settings_.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true);
settings_.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true);
settings_.set(IfcGeom::IteratorSettings::SEW_SHELLS, true);
void add_file(IfcParse::IfcFile& f, const ifcopenshell::geometry::settings& settings) {
ifcopenshell::geometry::settings settings_ = settings;
settings_.set(ifcopenshell::geometry::settings::DISABLE_TRIANGULATION, true);
settings_.set(ifcopenshell::geometry::settings::USE_WORLD_COORDS, true);
settings_.set(ifcopenshell::geometry::settings::SEW_SHELLS, true);
IfcGeom::Iterator<double> it(settings_, &f);
Iterator it(settings_, &f);
if (it.initialize()) {
do {
IfcGeom::NativeElement<double>* elem = (IfcGeom::NativeElement<double>*)it.get();
NativeElement* elem = (NativeElement*)it.get();
add((IfcUtil::IfcBaseEntity*)f.instance_by_id(elem->id()), ((OpenCascadeShape*)elem->geometry().as_compound())->shape());
} while (it.next());
}
}
};
}
}}
#endif
@@ -12,7 +12,7 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(const settings& setti
// @todo check
gp_GTrsf trsf;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++i) {
for (int j = 0; j < 4; ++j) {
trsf.SetValue(i + 1, j + 1, place.components(i, j));
}
}
+3 -1
View File
@@ -163,7 +163,9 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcFaceBasedSurfaceModel* ins
}
taxonomy::item* mapping::map_impl(const IfcSchema::IfcConnectedFaceSet* inst) {
return map_to_collection<taxonomy::shell>(this, inst->CfsFaces());
auto shell = map_to_collection<taxonomy::shell>(this, inst->CfsFaces());
shell->closed = inst->declaration().is(IfcSchema::IfcClosedShell::Class());
return shell;
}
taxonomy::item* mapping::map_impl(const IfcSchema::IfcFace* inst) {
@@ -96,7 +96,7 @@ ifcopenshell::geometry::ConversionResultShape* ifcopenshell::geometry::Represent
// @todo, check
gp_GTrsf trsf;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++i) {
for (int j = 0; j < 4; ++j) {
trsf.SetValue(i + 1, j + 1, it->Placement().components(i, j));
}
}
@@ -241,7 +241,7 @@ bool ifcopenshell::geometry::Representation::BRep::calculate_projected_surface_a
// @todo check
gp_GTrsf trsf;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++i) {
for (int j = 0; j < 4; ++j) {
trsf.SetValue(i + 1, j + 1, place.components(i, j));
}
}
+2
View File
@@ -193,6 +193,8 @@ struct collection : public geom_item {
};
struct shell : public collection {
boost::optional<bool> closed;
virtual item* clone() const { return new shell(*this); }
virtual kinds kind() const { return SHELL; }
};