diff --git a/src/ifcgeom_schema_agnostic/IfcGeomTree.h b/src/ifcgeom_schema_agnostic/IfcGeomTree.h index a64f105a7d..ed4f4ff821 100644 --- a/src/ifcgeom_schema_agnostic/IfcGeomTree.h +++ b/src/ifcgeom_schema_agnostic/IfcGeomTree.h @@ -53,6 +53,8 @@ #include #include #include +#include +#include #include #include #include @@ -695,10 +697,12 @@ namespace IfcGeom { const std::vector& bvh_b_is = pair.second; for (int i=bvh_a->BegPrimitive(bvh_a_i); i<=bvh_a->EndPrimitive(bvh_a_i); ++i) { + // Uncomment this to get old behaviour + /* if ( ! valid_tris_a[i]) { continue; } - + */ const std::array& tri = tris_a[i]; const gp_Pnt& v1_a_pnt = verts_a[tri[0]]; const gp_Pnt& v2_a_pnt = verts_a[tri[1]]; @@ -711,10 +715,12 @@ namespace IfcGeom { for (const auto& bvh_b_i : bvh_b_is) { for (int j=bvh_b->BegPrimitive(bvh_b_i); j<=bvh_b->EndPrimitive(bvh_b_i); ++j) { + // Uncomment this to get old behaviour + /* if ( ! valid_tris_b[j]) { continue; } - + */ const std::array& tri = tris_b[j]; const gp_Pnt& v1_b_pnt = verts_b[tri[0]]; const gp_Pnt& v2_b_pnt = verts_b[tri[1]]; @@ -956,79 +962,176 @@ namespace IfcGeom { max_protrusions_[t] = std::min(std::min(obb.XHSize(), obb.YHSize()), obb.ZHSize()) * 2; - BRepExtrema_ShapeList shape_list; + std::vector> tris; + std::vector verts; + std::vector normals; - std::vector is_reversed; + // DM: changed initialisation to get it to compile and actually have a BVH + const auto builder = new BVH_LinearBuilder (BVH_Constants_LeafNodeSizeDefault, BVH_Constants_MaxTreeDepth); + BVH_Triangulation triangulation(builder); - TopExp_Explorer exp_f; - for (exp_f.Init(s, TopAbs_FACE); exp_f.More(); exp_f.Next()) { - shape_list.Append(exp_f.Current()); - - TopoDS_Face f = TopoDS::Face(exp_f.Current()); - is_reversed.push_back(f.Orientation() == TopAbs_REVERSED); - } - - BRepExtrema_TriangleSet triangle_set(shape_list); - const opencascade::handle>& bvh = triangle_set.BVH(); - - std::vector valid_tris(triangle_set.Size(), true); - std::vector> tris(triangle_set.Size()); - std::vector normals(triangle_set.Size()); - - const BVH_Array3d& vertices = triangle_set.GetVertices(); - std::vector verts(vertices.size()); - int i = 0; - for (const auto& v : vertices) { - verts[i] = gp_Pnt(v[0], v[1], v[2]); - i++; - } - - for (int i=0; i indices; - triangle_set.GetVtxIndices(i, indices); - if (is_reversed[triangle_set.GetFaceID(i)]) { - std::swap(indices[0], indices[2]); - } - - gp_Pnt& v1_pnt = verts[indices[0]]; - gp_Pnt& v2_pnt = verts[indices[1]]; - gp_Pnt& v3_pnt = verts[indices[2]]; - gp_Vec dir1(v1_pnt, v2_pnt); - gp_Vec dir2(v1_pnt, v3_pnt); - gp_Vec cross_product = dir1.Crossed(dir2); - if (cross_product.Magnitude() > Precision::Confusion()) { - normals[i] = cross_product.Normalized(); - tris[i] = {indices[0], indices[1], indices[2]}; - } else { - valid_tris[i] = false; - } - } - - // Debug + // std::list shapes; /* - std::cout << "DEBUGG:" << std::endl; - for (int i=0; iMapNodeArray()->ChangeArray1(); + auto theTrsf = loc.Transformation(); + for (Standard_Integer aVertIdx = 1; aVertIdx <= theNodes.Size(); ++aVertIdx) + { + gp_Pnt n_pnt = theNodes.Value (aVertIdx); + n_pnt.Transform (theTrsf); + triangulation.Vertices.push_back (BVH_Vec3d (n_pnt.X(), n_pnt.Y(), n_pnt.Z())); + verts.push_back(n_pnt); + } + + /* + for (int i = 1; i <= tri->NbNodes(); ++i) { + // DM: modified to pass in NCollection_Vec3 not gp_XYZ + gp_Pnt n_pnt(tri->Node(i).Transformed(loc).XYZ()); + NCollection_Vec3 vec(n_pnt.X(), n_pnt.Y(), n_pnt.Z()); + triangulation.Vertices.push_back(vec); + verts.push_back(n_pnt); + } + */ + + const Poly_Array1OfTriangle& triangles = tri->Triangles(); + for (int i = 1; i <= triangles.Length(); ++i) { + int n1, n2, n3; // These indices start from 1 + if (is_reversed) { + triangles(i).Get(n3, n2, n1); + } else { + triangles(i).Get(n1, n2, n3); + } + + // DM: calculate per-triangle normal here and only push back valid triangles + n1 += vertex_offset; + n2 += vertex_offset; + n3 += vertex_offset; + + const auto& v1_pnt = verts[n1]; + const auto& v2_pnt = verts[n2]; + const auto& v3_pnt = verts[n3]; + + gp_Vec dir1(v1_pnt, v2_pnt); + gp_Vec dir2(v1_pnt, v3_pnt); + gp_Vec cross_product = dir1.Crossed(dir2); + if (cross_product.Magnitude() > Precision::Confusion()) { + // The 0 at the end is an arbitrary reference to anything we want. + NCollection_Vec4 element(n1, n2, n3, 0); + triangulation.Elements.push_back(element); + tris.push_back({n1, n2, n3}); + normals.push_back(cross_product.Normalized()); + } + } + } + //} + + // DM: moved out of the shape loop. + triangulation.MarkDirty(); + + const auto bvh = triangulation.BVH(); bvhs_[t] = bvh; is_manifold_[t] = is_shape_manifold(s); tris_[t] = std::move(tris); verts_[t] = std::move(verts); normals_[t] = std::move(normals); - valid_tris_[t] = std::move(valid_tris); + + + +// This is the old method of bvh generation +BRepExtrema_ShapeList shape_list; +std::vector is_reversed2; +TopExp_Explorer exp_f2; +for (exp_f2.Init(s, TopAbs_FACE); exp_f2.More(); exp_f2.Next()) { + shape_list.Append(exp_f2.Current()); + + TopoDS_Face f = TopoDS::Face(exp_f2.Current()); + is_reversed2.push_back(f.Orientation() == TopAbs_REVERSED); +} +BRepExtrema_TriangleSet triangle_set(shape_list); +const opencascade::handle>& bvh2 = triangle_set.BVH(); +std::vector valid_tris(triangle_set.Size(), true); +std::vector> tris2(triangle_set.Size()); +std::vector normals2(triangle_set.Size()); +const BVH_Array3d& vertices = triangle_set.GetVertices(); +std::vector verts2(vertices.size()); +int i = 0; +for (const auto& v : vertices) { + verts2[i] = gp_Pnt(v[0], v[1], v[2]); + i++; +} +for (int i=0; i indices; + triangle_set.GetVtxIndices(i, indices); + if (is_reversed2[triangle_set.GetFaceID(i)]) { + std::swap(indices[0], indices[2]); + } + gp_Pnt& v1_pnt = verts2[indices[0]]; + gp_Pnt& v2_pnt = verts2[indices[1]]; + gp_Pnt& v3_pnt = verts2[indices[2]]; + gp_Vec dir1(v1_pnt, v2_pnt); + gp_Vec dir2(v1_pnt, v3_pnt); + gp_Vec cross_product = dir1.Crossed(dir2); + if (cross_product.Magnitude() > Precision::Confusion()) { + normals2[i] = cross_product.Normalized(); + tris2[i] = {indices[0], indices[1], indices[2]}; + } else { + valid_tris[i] = false; + } +} + +// Uncomment this to get old behaviour +// bvhs_[t] = bvh2; +// tris_[t] = std::move(tris2); +// verts_[t] = std::move(verts2); +// normals_[t] = std::move(normals2); +// valid_tris_[t] = std::move(valid_tris); + + /* + std::cout << "DEBUGG:" << std::endl; + for (int i=0; i select_box(const T& t, bool completely_within = false, double extend=-1.e-5) const {