Unexpected result when merging several meshes into one using corefine_and_compute_union() #8128
-
IssueHello, I have numerous different meshes that I would like to merge to create a single unified mesh. However, the issue is that once all the meshes are assembled, the result doesn't form a single cohesive mesh but rather a mesh with separations between each "child mesh" (see image below). Is there a way to avoid that ? Picture of the resulting meshMy code
Additional informations
|
Beta Was this translation helpful? Give feedback.
Replies: 9 comments 11 replies
-
iteration variable is mesh and it is not used in the function call within the loop. Could it be the issue? |
Beta Was this translation helpful? Give feedback.
-
It seems like all the child meshes are not fully merged but just fitted together like bricks. Is there a way to avoid that @sloriot ? |
Beta Was this translation helpful? Give feedback.
-
My guess is that you have cubic cells that you are trying to union. But at some intermediate step you have two cubic cells sharing a vertex and it becomes non-manifold. While it could be only "temporary" as more cell will be added, I guess you could also have that in the output, right? |
Beta Was this translation helpful? Give feedback.
-
Yes it is what I think too. Here is the code if you want to try it yourself:
|
Beta Was this translation helpful? Give feedback.
-
Update !!I found that doing this: Mesh final_mesh, tmp;
for (Mesh mesh : meshes){
PMP::corefine_and_compute_union(tmp, mesh, final_mesh);
} creates a mesh that has self-intersections without throwing any error. So, to solve this I tried to do it like this: Surface_mesh result;
for (auto mesh : meshes)
{
Surface_mesh output;
PMP::corefine_and_compute_union(result, mesh, output);
result = output;
}
CGAL::IO::write_STL("./result.stl", result) This threw a What I foundBy trying new things I found that it doesn't throw any error if the vector that contains all the meshes is sorted. For example I made an algorithm that creates a 3D stairs-like mesh: vector<Surface_mesh> meshes;
double offset = 2;
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < i + 1; j++)
{
for (int k = 0; k < j + 1; k++)
{
meshes.push_back(makeHexahedron(Point(offset * i, offset * j, offset * k), Point(offset * (i + 1), offset * (j + 1), offset * (k + 1))));
}
}
} If I shuffle the vector before merging all the mesh, it throws a BUT, if the vector isn't shuffled before merging all the mesh, the final mesh is well created and without any self-intersections. This was used to merge all the meshes:
ConclusionSo, to conclude, I think the issue happened in the code I gave because the meshes that I merge are not in a right order... So how could I solve that ? Full code#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
#include <CGAL/boost/graph/properties.h>
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
#include <algorithm>
#include <random>
namespace PMP = CGAL::Polygon_mesh_processing;
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_3 Point;
typedef CGAL::Surface_mesh<Point> Surface_mesh;
typedef boost::graph_traits<Surface_mesh>::face_descriptor face_descriptor;
using namespace std;
Surface_mesh makeHexahedron(Point min_coord, Point max_coord)
{
// Declaring hexahedron to return
Surface_mesh hexahedron;
// Declaring x, y, and z tmp coordinates
auto x = min_coord.x(), y = min_coord.y(), z = min_coord.z();
array<Point, 8> points;
// Construct the hexhedron
for (int i = 0; i < 8; i++)
{
// Change x coordinate
if (i != 0 && (i + 1) % 2 == 0)
x = x == min_coord.x() ? max_coord.x() : min_coord.x();
// Change y coordinate
if (i != 0 && i % 2 == 0)
y = y == min_coord.y() ? max_coord.y() : min_coord.y();
// Change z coordinate
if (i != 0 && i % 4 == 0)
z = max_coord.z();
points[i] = Point(x, y, z);
}
// Create hexahedron and triangulate its faces
CGAL::make_hexahedron(points[0], points[1], points[2], points[3], points[4], points[5], points[6], points[7], hexahedron);
PMP::triangulate_faces(hexahedron);
return hexahedron;
}
int main()
{
vector<Surface_mesh> meshes;
double offset = 2;
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < i + 1; j++)
{
for (int k = 0; k < j + 1; k++)
{
meshes.push_back(makeHexahedron(Point(offset * i, offset * j, offset * k), Point(offset * (i + 1), offset * (j + 1), offset * (k + 1))));
}
}
}
// IF ENABLED --> Self intersections error will be thrown
// auto rng = std::default_random_engine{};
// std::shuffle(std::begin(meshes), std::end(meshes), rng);
Surface_mesh result, tmp;
int i = 0;
for (auto mesh : meshes)
{
Surface_mesh output;
PMP::corefine_and_compute_union(tmp, mesh, output);
tmp = output;
cout << "Does self intersect [ " << i << "]" << PMP::does_self_intersect(output) << endl;
i++;
}
cout << CGAL::IO::write_STL("./result1.stl", tmp);
return 0;
} |
Beta Was this translation helpful? Give feedback.
-
The order change prevent non-manifold features to appear, which is why you could compute the whole union. Unfortunately I don't see an easy solution for scheduling operations. What I'm not sure is if you really need to use that function. To me it seems that you are only doing union of iso-cuboids with intersection being of volume 0. There might be a most efficient way to handle that. From the top of my head, I'd use |
Beta Was this translation helpful? Give feedback.
-
Thanks for your answer @sloriot ! My questionIs there a way to fill these holes ? What I already tried
unsigned int nb_holes = 0;
vector<halfedge_descriptor> border_cycles;
PMP::extract_boundary_cycles(mesh, back_inserter(border_cycles));
for (halfedge_descriptor h : border_cycles)
{
vector<face_descriptor> patch_facets;
vector<vertex_descriptor> patch_vertices;
bool success = std::get<0>(PMP::triangulate_refine_and_fair_hole(mesh,
h,
CGAL::parameters::face_output_iterator(back_inserter(patch_facets))
.vertex_output_iterator(back_inserter(patch_vertices))));
++nb_holes;
} It didn't do anything.
Image |
Beta Was this translation helpful? Give feedback.
-
If you provide a (small) self-contained example I can compile and run it and have a look at the output. No need to give the code for the first step, you can dump meshes using maximum stream precision (using |
Beta Was this translation helpful? Give feedback.
-
As I said you don't need corefinement_and_compute_union(). https://gist.github.com/sloriot/50f6c9b1ae9f1d2e0b0a45900703e45a However, the output contains non-manifold edges so the output, if oriented to be put in a triangle mesh will end up being self-intersecting. |
Beta Was this translation helpful? Give feedback.
As I said you don't need corefinement_and_compute_union().
I modified a bit your example and got what I think you expected.
https://gist.github.com/sloriot/50f6c9b1ae9f1d2e0b0a45900703e45a
However, the output contains non-manifold edges so the output, if oriented to be put in a triangle mesh will end up being self-intersecting.