From 1d6f20c48daabec989ff52a6820ddcd0b5cfb7db Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 26 Jan 2020 17:11:14 +0100 Subject: [PATCH] Fix wall connectivity --- src/ifcconvert/validate_wall_connectivity.cpp | 124 +++++++++++++----- src/ifcconvert/validation_utils.h | 5 + 2 files changed, 93 insertions(+), 36 deletions(-) diff --git a/src/ifcconvert/validate_wall_connectivity.cpp b/src/ifcconvert/validate_wall_connectivity.cpp index fbfb9aca66..95a9c9d274 100644 --- a/src/ifcconvert/validate_wall_connectivity.cpp +++ b/src/ifcconvert/validate_wall_connectivity.cpp @@ -1,5 +1,9 @@ #include "validation_utils.h" +#include + +using namespace ifcopenshell::geometry; + void fix_wallconnectivity(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool 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); - v([&c](const intersection_validator::Box& a, const intersection_validator::Box& b) { - std::ostringstream ss; + auto rels = f.instances_by_type("IfcRelConnectsPathElements"); + std::map, 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("RelatingElement"); + auto y = ((IfcUtil::IfcBaseEntity*)rel)->get_value("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("RelatingElement"); + auto a_type = ((IfcUtil::IfcBaseEntity*)rel)->get_value("RelatingConnectionType"); + auto b_type = ((IfcUtil::IfcBaseEntity*)rel)->get_value("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; if (x.is_empty()) { return; } - c.convert(a.handle()->first); - cgal_shape_t x_poly; x.convert_to_polyhedron(x_poly); - for (auto& v : vertices(x_poly)) { - // project onto axes - } + auto get_axis_parameter_min_max = [&c, &x_poly](IfcUtil::IfcBaseEntity* inst) { + 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(); - auto s1 = b.handle()->first->declaration().name(); - auto i0 = a.handle()->first->data().id(); - auto i1 = b.handle()->first->data().id(); + if (first_vertex.which() != 0 || last_vertex.which() != 0) { + std::wcout << "trims not supported" << std::endl; + } else { + auto p0 = boost::get(first_vertex); + auto p1 = boost::get(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) { - std::swap(s1, s0); - std::swap(i0, i1); - } + auto P0 = Kernel_::Point_3(v0(0), v0(1), v0(2)); + auto P1 = Kernel_::Point_3(v1(0), v1(1), v1(2)); - { - auto FN = s0 + "-" + s1 + "-" + std::to_string(i0) + "-" + std::to_string(i1) + "sb.off"; + auto D = P1 - P0; + auto len = std::sqrt(CGAL::to_double(D.squared_length())); + D /= len; - std::ofstream os(FN.c_str()); - os.precision(17); - os << x_poly; - } + std::wcout << "xx " << len << std::endl; - remove_thickness r(x_poly); + std::vector parameters; - { - auto FN = s0 + "-" + s1 + "-" + std::to_string(i0) + "-" + std::to_string(i1) + "-sides-sb.off"; + std::transform(vertices(x_poly).begin(), vertices(x_poly).end(), std::back_inserter(parameters), [&P0, D](auto& v) { + return (v->point() - P0) * D; + }); - std::ofstream os(FN.c_str()); - os.precision(17); - os << r.polyhedron2; - } + auto pit = std::minmax_element(parameters.begin(), parameters.end()); + return std::make_pair(CGAL::to_double(*pit.first), CGAL::to_double(*pit.first)); + } + } + return std::make_pair(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); + }; - { - auto FN = s0 + "-" + s1 + "-" + std::to_string(i0) + "-" + std::to_string(i1) + "-flat-sb.off"; + auto u0u1 = get_axis_parameter_min_max(A); + std::wcout << a_type.c_str() << " " << u0u1.first << " " << u0u1.second << std::endl; - std::ofstream os(FN.c_str()); - os.precision(17); - os << r.flattened; - } + u0u1 = get_axis_parameter_min_max(B); + std::wcout << b_type.c_str() << " " << u0u1.first << " " << u0u1.second << std::endl; }); } diff --git a/src/ifcconvert/validation_utils.h b/src/ifcconvert/validation_utils.h index 382603371f..e3c12e140f 100644 --- a/src/ifcconvert/validation_utils.h +++ b/src/ifcconvert/validation_utils.h @@ -379,6 +379,11 @@ struct remove_thickness { // @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); decltype(connected) connected_opposing;