mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-11 22:31:55 +00:00
Fix wall connectivity
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
#include "validation_utils.h"
|
#include "validation_utils.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
using namespace ifcopenshell::geometry;
|
||||||
|
|
||||||
void fix_wallconnectivity(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool stderr_progress) {
|
void fix_wallconnectivity(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool stderr_progress) {
|
||||||
intersection_validator v(f, { "IfcWall" }, no_progress, quiet, stderr_progress);
|
intersection_validator v(f, { "IfcWall" }, no_progress, quiet, stderr_progress);
|
||||||
|
|
||||||
@@ -17,61 +21,109 @@ void fix_wallconnectivity(IfcParse::IfcFile& f, bool no_progress, bool quiet, bo
|
|||||||
|
|
||||||
ifcopenshell::geometry::Converter c("cgal", &f, settings);
|
ifcopenshell::geometry::Converter c("cgal", &f, settings);
|
||||||
|
|
||||||
v([&c](const intersection_validator::Box& a, const intersection_validator::Box& b) {
|
auto rels = f.instances_by_type("IfcRelConnectsPathElements");
|
||||||
std::ostringstream ss;
|
std::map<std::set<const IfcUtil::IfcBaseClass*>, const IfcUtil::IfcBaseClass*> rel_by_elem;
|
||||||
|
std::for_each(rels->begin(), rels->end(), [&rel_by_elem](const IfcUtil::IfcBaseClass* rel) {
|
||||||
|
auto x = ((IfcUtil::IfcBaseEntity*)rel)->get_value<IfcUtil::IfcBaseClass*>("RelatingElement");
|
||||||
|
auto y = ((IfcUtil::IfcBaseEntity*)rel)->get_value<IfcUtil::IfcBaseClass*>("RelatedElement");
|
||||||
|
rel_by_elem.insert({{ x,y }, rel});
|
||||||
|
});
|
||||||
|
|
||||||
ss << a.handle()->first->data().toString() << "x" << a.handle()->first->data().toString() << std::endl;
|
v([&c, &rel_by_elem](const intersection_validator::Box& a, const intersection_validator::Box& b) {
|
||||||
|
auto A = a.handle()->first;
|
||||||
|
auto B = b.handle()->first;
|
||||||
|
|
||||||
|
auto rit = rel_by_elem.find({ A, B });
|
||||||
|
if (rit == rel_by_elem.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rel = rit->second;
|
||||||
|
const bool a_is_relating = A == ((IfcUtil::IfcBaseEntity*)rel)->get_value<IfcUtil::IfcBaseClass*>("RelatingElement");
|
||||||
|
auto a_type = ((IfcUtil::IfcBaseEntity*)rel)->get_value<std::string>("RelatingConnectionType");
|
||||||
|
auto b_type = ((IfcUtil::IfcBaseEntity*)rel)->get_value<std::string>("RelatedConnectionType");
|
||||||
|
if (!a_is_relating) {
|
||||||
|
std::swap(a_type, b_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
auto a_poly = ifcopenshell::geometry::utils::create_polyhedron(a.handle()->second);
|
||||||
|
auto b_poly = ifcopenshell::geometry::utils::create_polyhedron(b.handle()->second);
|
||||||
|
|
||||||
|
std::wcout << "a" << std::endl;
|
||||||
|
for (auto& v : vertices(a_poly)) {
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
std::wcout << CGAL::to_double(v->point().cartesian(i)) << " ";
|
||||||
|
}
|
||||||
|
std::wcout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wcout << "b" << std::endl;
|
||||||
|
for (auto& v : vertices(b_poly)) {
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
std::wcout << CGAL::to_double(v->point().cartesian(i)) << " ";
|
||||||
|
}
|
||||||
|
std::wcout << std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << A->data().toString() << "x" << B->data().toString() << std::endl;
|
||||||
auto x = a.handle()->second * b.handle()->second;
|
auto x = a.handle()->second * b.handle()->second;
|
||||||
if (x.is_empty()) {
|
if (x.is_empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
c.convert(a.handle()->first);
|
|
||||||
|
|
||||||
cgal_shape_t x_poly;
|
cgal_shape_t x_poly;
|
||||||
x.convert_to_polyhedron(x_poly);
|
x.convert_to_polyhedron(x_poly);
|
||||||
|
|
||||||
for (auto& v : vertices(x_poly)) {
|
auto get_axis_parameter_min_max = [&c, &x_poly](IfcUtil::IfcBaseEntity* inst) {
|
||||||
// project onto axes
|
auto item = c.mapping()->map(inst);
|
||||||
}
|
auto shaperep = ((taxonomy::collection*) item)->children[0];
|
||||||
|
auto loop = ((taxonomy::collection*) shaperep)->children[0];
|
||||||
|
|
||||||
CGAL::Polygon_mesh_processing::triangulate_faces(x_poly);
|
if (loop->kind() != taxonomy::LOOP) {
|
||||||
|
std::wcout << "no suitable axis" << std::endl;
|
||||||
|
} else {
|
||||||
|
auto first_vertex = ((taxonomy::edge*) ((taxonomy::loop*) loop)->children.front())->start;
|
||||||
|
auto last_vertex = ((taxonomy::edge*) ((taxonomy::loop*) loop)->children.back())->end;
|
||||||
|
|
||||||
auto s0 = a.handle()->first->declaration().name();
|
if (first_vertex.which() != 0 || last_vertex.which() != 0) {
|
||||||
auto s1 = b.handle()->first->declaration().name();
|
std::wcout << "trims not supported" << std::endl;
|
||||||
auto i0 = a.handle()->first->data().id();
|
} else {
|
||||||
auto i1 = b.handle()->first->data().id();
|
auto p0 = boost::get<taxonomy::point3>(first_vertex);
|
||||||
|
auto p1 = boost::get<taxonomy::point3>(last_vertex);
|
||||||
|
|
||||||
|
auto v0 = ((taxonomy::geom_item*)item)->matrix.components * p0.components.homogeneous();
|
||||||
|
auto v1 = ((taxonomy::geom_item*)item)->matrix.components * p1.components.homogeneous();
|
||||||
|
|
||||||
if (s0 < s1) {
|
auto P0 = Kernel_::Point_3(v0(0), v0(1), v0(2));
|
||||||
std::swap(s1, s0);
|
auto P1 = Kernel_::Point_3(v1(0), v1(1), v1(2));
|
||||||
std::swap(i0, i1);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
auto D = P1 - P0;
|
||||||
auto FN = s0 + "-" + s1 + "-" + std::to_string(i0) + "-" + std::to_string(i1) + "sb.off";
|
auto len = std::sqrt(CGAL::to_double(D.squared_length()));
|
||||||
|
D /= len;
|
||||||
|
|
||||||
std::ofstream os(FN.c_str());
|
std::wcout << "xx " << len << std::endl;
|
||||||
os.precision(17);
|
|
||||||
os << x_poly;
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_thickness r(x_poly);
|
std::vector<Kernel_::FT> parameters;
|
||||||
|
|
||||||
{
|
std::transform(vertices(x_poly).begin(), vertices(x_poly).end(), std::back_inserter(parameters), [&P0, D](auto& v) {
|
||||||
auto FN = s0 + "-" + s1 + "-" + std::to_string(i0) + "-" + std::to_string(i1) + "-sides-sb.off";
|
return (v->point() - P0) * D;
|
||||||
|
});
|
||||||
|
|
||||||
std::ofstream os(FN.c_str());
|
auto pit = std::minmax_element(parameters.begin(), parameters.end());
|
||||||
os.precision(17);
|
return std::make_pair(CGAL::to_double(*pit.first), CGAL::to_double(*pit.first));
|
||||||
os << r.polyhedron2;
|
}
|
||||||
}
|
}
|
||||||
|
return std::make_pair(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN());
|
||||||
|
};
|
||||||
|
|
||||||
{
|
auto u0u1 = get_axis_parameter_min_max(A);
|
||||||
auto FN = s0 + "-" + s1 + "-" + std::to_string(i0) + "-" + std::to_string(i1) + "-flat-sb.off";
|
std::wcout << a_type.c_str() << " " << u0u1.first << " " << u0u1.second << std::endl;
|
||||||
|
|
||||||
std::ofstream os(FN.c_str());
|
u0u1 = get_axis_parameter_min_max(B);
|
||||||
os.precision(17);
|
std::wcout << b_type.c_str() << " " << u0u1.first << " " << u0u1.second << std::endl;
|
||||||
os << r.flattened;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -379,6 +379,11 @@ struct remove_thickness {
|
|||||||
|
|
||||||
// @todo choose connected / connected_opposing based on largest combined area of facets?
|
// @todo choose connected / connected_opposing based on largest combined area of facets?
|
||||||
|
|
||||||
|
if (longitudonal.size() == 0) {
|
||||||
|
std::wcout << "no longitudonal faces detected :(" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto connected = connected_faces(*longitudonal.begin(), thin_sides_degenerate);
|
auto connected = connected_faces(*longitudonal.begin(), thin_sides_degenerate);
|
||||||
decltype(connected) connected_opposing;
|
decltype(connected) connected_opposing;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user