Mesh refining run forever
sonukiller opened this issue · 6 comments
When I am trying to implement 6_delaunay_refinement/
, the step of refining before coarsening takes a lot of time (also refining after coarsening) and runs for forever. I am getting results quickly for the sample mesh boxpart.obj
but for some big meshes (>30K), this problem is coming. Any solution?
Also, I am getting this error for dragon_fat.obj
malloc(): invalid next size (unsorted)
Aborted (core dumped)
I tried mesh simplification for dragon_fat.obj
using Blender and reduced the vertices to 5.5K and it was working with --refinement_time=BEFORE
and I got same error as above with --refinement_time=AFTER
! Can you please help with this?
The infinite loop is due to the or condition. What do you think?
It might help to decrease the angle_threshold
argument to the delaunay_refine
function, which controls how much Delaunay refinement tries to improve triangle quality. The default value of 25 degrees has usually worked pretty well for me, but can cause problems on meshes with very pointy vertices
I tried to reduce the default value of 25 degrees to 5 degrees and it was working but not as expected.
I implemented Dealuney refinement using this repo and it is working for 25 degrees also.
What is the difference between the Delaunay refinement using this repo and here? And one more thing I want to ask, does your coarsening algorithm have implementation using geometry central library?
Ah, interesting! No, this code uses a reimplementation of Delaunay refinement, and in this implementation, I left out some code to handle complicated edge cases (specifically this part about parent faces) which I thought were pretty rare. But these edge cases could well come up more often than I thought. I'm a bit busy at the moment, but I can probably take a closer look at the code in a week or two.
In the meantime, here's some code we used to do Delaunay refinement using geometry-central while working on this project. It sounds like switching to using geometry-central's implementation will hopefully solve the problems you're having
Code
#include <Eigen/Core>
#include <Eigen/Dense>
#include "geometrycentral/surface/manifold_surface_mesh.h"
#include "geometrycentral/surface/vertex_position_geometry.h"
#include "geometrycentral/surface/signpost_intrinsic_triangulation.h"
#include "global_variables.h"
#include "glue_face_sides.h"
/*
doing delaunay refinement and transfer barycentric coordinates to the refined mesh
Inputs:
VO: input vertex list
FO: input face list
bary_coords: |BC|x3 barycentric coordinates
bary_faces: |BC|x1 index to FO
Outputs:
F: delaunay refined face list
l: delaunay refined edge lengths
bary_coords: |BC|x3 barycentric coordinates
bary_faces: |BC|x1 index to F
*/
void delaunay_refine(
const Eigen::MatrixXd & VO,
const Eigen::MatrixXi & FO,
Eigen::MatrixXi & F,
Eigen::MatrixXi & G,
Eigen::MatrixXd & l)
{
using namespace std;
using namespace Eigen;
using namespace geometrycentral;
using namespace surface;
using namespace global_variables;
ManifoldSurfaceMesh mesh(FO);
VertexPositionGeometry geometry(mesh, VO);
SignpostIntrinsicTriangulation tri(mesh, geometry);
tri.delaunayRefine();
tri.intrinsicMesh->validateConnectivity();
int nF = tri.intrinsicMesh->nFaces();
F.resize(nF,3);
l.resize(nF,3);
F = tri.intrinsicMesh->getFaceVertexMatrix<int>();
tri.requireEdgeLengths();
for(Face f : tri.intrinsicMesh->faces()) {
size_t iHe = 0;
for(Halfedge he : f.adjacentHalfedges()) {
if (f.getIndex() >= nF)
throw std::runtime_error("[Error] delaunayRefine deleted vertices");
l(f.getIndex(),iHe) = tri.edgeLengths[he.edge()];
iHe++;
}
}
// build glue map
G.resize(nF, 3*2);
G.fill(0);
for(Face f : tri.intrinsicMesh->faces()) {
size_t s = 0; // side
for(Halfedge he : f.adjacentHalfedges()) {
// the face side of "he"
Vector2i fs = {he.face().getIndex(), s};
// get the face side of "he.twin()"
Vector2i fs_twin;
if (he.twin().isInterior())
{
// if he.twin() is an inteior half-edge, then find its face-side
int s_twin = 0; // side of he_tmp
for (Halfedge he_tmp : he.twin().face().adjacentHalfedges())
{
if (he_tmp == he.twin()) // if found it, then break
break;
s_twin++;
}
fs_twin << he.twin().face().getIndex(), s_twin;
}
else
{
// if he.twin() is an exterior half-edge, then set it to ghost
fs_twin << GHOST_INDEX, GHOST_INDEX;
}
glue_face_sides(fs, fs_twin, G);
s++;
}
}
}
void delaunay_refine(
const Eigen::MatrixXd & VO,
const Eigen::MatrixXi & FO,
Eigen::MatrixXi & F,
Eigen::MatrixXi & G,
Eigen::MatrixXd & l,
Eigen::MatrixXd & bary_coords,
Eigen::VectorXi & bary_faces)
{
using namespace std;
using namespace Eigen;
using namespace geometrycentral;
using namespace surface;
using namespace global_variables;
ManifoldSurfaceMesh mesh(FO);
VertexPositionGeometry geometry(mesh, VO);
SignpostIntrinsicTriangulation tri(mesh, geometry);
tri.delaunayRefine();
tri.intrinsicMesh->validateConnectivity();
for (int ii=0; ii<bary_coords.rows(); ii++)
{
if (bary_faces(ii) != GHOST_INDEX) // if this bary is valid
{
int f = bary_faces(ii);
geometrycentral::Vector3 bc{bary_coords(ii,0), bary_coords(ii,1), bary_coords(ii,2)};
SurfacePoint bary_point(tri.inputMesh.face(f), bc);
SurfacePoint bary_point_intrinsic = tri.equivalentPointOnIntrinsic(bary_point);
bary_faces(ii) = bary_point_intrinsic.face.getIndex();
bary_coords.row(ii) << bary_point_intrinsic.faceCoords[0], bary_point_intrinsic.faceCoords[1], bary_point_intrinsic.faceCoords[2];
}
}
int nF = tri.intrinsicMesh->nFaces();
F.resize(nF,3);
F = tri.intrinsicMesh->getFaceVertexMatrix<int>();
l.resize(nF, 3);
tri.requireEdgeLengths();
for(Face f : tri.intrinsicMesh->faces()) {
size_t iHe = 0;
for(Halfedge he : f.adjacentHalfedges()) {
l(f.getIndex(),iHe) = tri.edgeLengths[he.edge()];
iHe++;
}
}
// build glue map
G.resize(nF, 3*2);
G.fill(0);
for(Face f : tri.intrinsicMesh->faces()) {
size_t s = 0; // side
for(Halfedge he : f.adjacentHalfedges()) {
// the face side of "he"
Vector2i fs = {he.face().getIndex(), s};
// get the face side of "he.twin()"
Vector2i fs_twin;
if (he.twin().isInterior())
{
// if he.twin() is an inteior half-edge, then find its face-side
int s_twin = 0; // side of he_tmp
for (Halfedge he_tmp : he.twin().face().adjacentHalfedges())
{
if (he_tmp == he.twin()) // if found it, then break
break;
s_twin++;
}
fs_twin << he.twin().face().getIndex(), s_twin;
}
else
{
// if he.twin() is an exterior half-edge, then set it to ghost
fs_twin << GHOST_INDEX, GHOST_INDEX;
}
glue_face_sides(fs, fs_twin, G);
s++;
}
}
}
void delaunay_refine(
const Eigen::MatrixXi & FO,
const Eigen::MatrixXd & lO,
Eigen::MatrixXi & F,
Eigen::MatrixXi & G,
Eigen::MatrixXd & l)
{
using namespace std;
using namespace Eigen;
using namespace geometrycentral;
using namespace surface;
using namespace global_variables;
ManifoldSurfaceMesh mesh(FO);
EdgeData<double> edgeLengths(mesh);
for(Face f : mesh.faces()) {
size_t iHe = 0;
for(Halfedge he : f.adjacentHalfedges()) {
edgeLengths[he.edge()] = lO(f.getIndex(),iHe);
iHe++;
}
}
EdgeLengthGeometry geometry(mesh, edgeLengths);
SignpostIntrinsicTriangulation tri(mesh, geometry);
tri.delaunayRefine();
tri.intrinsicMesh->validateConnectivity();
int nF = tri.intrinsicMesh->nFaces();
F.resize(nF,3);
l.resize(nF,3);
F = tri.intrinsicMesh->getFaceVertexMatrix<int>();
tri.requireEdgeLengths();
for(Face f : tri.intrinsicMesh->faces()) {
size_t iHe = 0;
for(Halfedge he : f.adjacentHalfedges()) {
if (f.getIndex() >= nF)
throw std::runtime_error("[Error] delaunayRefine deleted vertices");
l(f.getIndex(),iHe) = tri.edgeLengths[he.edge()];
iHe++;
}
}
// build glue map
G.resize(nF, 3*2);
G.fill(0);
for(Face f : tri.intrinsicMesh->faces()) {
size_t s = 0; // side
for(Halfedge he : f.adjacentHalfedges()) {
// the face side of "he"
Vector2i fs = {he.face().getIndex(), s};
// get the face side of "he.twin()"
Vector2i fs_twin;
if (he.twin().isInterior())
{
// if he.twin() is an inteior half-edge, then find its face-side
int s_twin = 0; // side of he_tmp
for (Halfedge he_tmp : he.twin().face().adjacentHalfedges())
{
if (he_tmp == he.twin()) // if found it, then break
break;
s_twin++;
}
fs_twin << he.twin().face().getIndex(), s_twin;
}
else
{
// if he.twin() is an exterior half-edge, then set it to ghost
fs_twin << GHOST_INDEX, GHOST_INDEX;
}
glue_face_sides(fs, fs_twin, G);
s++;
}
}
}
Thanks for the code!
The coarsening algorithm is implemented before and after Delaunay refinement and it requires F, G, l, A, v2fs, BC, F2V. The above three delaunay_refine
functions not fully output these values.
Can you please provide a delaunay_refine
function using geometry-central which will output all these values required for the coarsening algorithm or if possible can you provide the implementation of the coarsening algorithm using geometry-central.
A possibility is to use the delaunay refinement from geometry central to obtain an intrinsic mesh, and you can then compute the information using these two functions
build_glue_map(F,G);
build_angular_coordinates(F,G,l,A,v2fs);