Replies: 1 comment
-
I found a work around by inserting new points at the centroids of unique cells instead of the mid points of unique edges. Now it seems to be working. I guess inserting new points in the middle of edges makes it a bad Delaunay mesh. #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Periodic_3_Delaunay_triangulation_traits_3.h>
#include <CGAL/Periodic_3_triangulation_ds_vertex_base_3.h>
#include <CGAL/Periodic_3_triangulation_ds_cell_base_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
#include <CGAL/Triangulation_cell_base_with_info_3.h>
#include <CGAL/Periodic_3_Delaunay_triangulation_3.h>
#include <CGAL/Triangulation_data_structure_3.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/number_type_config.h> // CGAL_PI
#include <random>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Periodic_3_Delaunay_triangulation_traits_3<K> P3_Traits;
typedef CGAL::Periodic_3_triangulation_ds_vertex_base_3<> P3_VbDS;
typedef CGAL::Triangulation_vertex_base_3<P3_Traits, P3_VbDS > P3_Vb;
typedef CGAL::Periodic_3_triangulation_ds_cell_base_3<> P3_CbDS;
typedef CGAL::Triangulation_cell_base_3<P3_Traits, P3_CbDS > P3_Cb;
typedef CGAL::Triangulation_vertex_base_with_info_3<double, P3_Traits, P3_Vb > VbInfo; // Test to attach data to vertices.
typedef CGAL::Triangulation_cell_base_with_info_3<double, P3_Traits, P3_Cb > CbInfo; // Test to attach data to cells.
typedef CGAL::Triangulation_data_structure_3<VbInfo, CbInfo > TDS;
typedef CGAL::Periodic_3_Delaunay_triangulation_3<P3_Traits, TDS > P3_Delaunay;
typedef P3_Delaunay::Point P3_Point;
typedef P3_Delaunay::Periodic_point PeriodicPoint;
typedef P3_Delaunay::Iso_cuboid Iso_cuboid;
double periodic_function(const P3_Point& p) {
static unsigned long callCount = 0;
callCount++;
return -std::cos(2 * CGAL_PI * p[0]) - std::cos(2 * CGAL_PI * p[1]) - std::cos(2 * CGAL_PI * p[2]);
}
int main() {
Iso_cuboid domain(P3_Point(-0.5, -0.5, -0.5), P3_Point(0.5, 0.5, 0.5));
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> disX(domain.xmin(), domain.xmax());
std::uniform_real_distribution<> disY(domain.ymin(), domain.ymax());
std::uniform_real_distribution<> disZ(domain.zmin(), domain.zmax());
P3_Delaunay T(domain);
std::vector<P3_Point> listOfRandPoint;
for (unsigned long long i=0; i<5000; i++) {
P3_Point randPoint(disX(gen), disY(gen), disZ(gen));
listOfRandPoint.push_back(randPoint);
}
for (unsigned long long i=0; i<listOfRandPoint.size(); i++) {
P3_Delaunay::Vertex_handle vh = T.insert(listOfRandPoint[i]);
vh->info() = periodic_function(listOfRandPoint[i]);
std::cout << "\r" << i << " points inserted." << std::flush;
}
// Now do refinement for 10 times.
int MaxRoundOfRefinement = 10;
for (int iTimes = 0; iTimes < MaxRoundOfRefinement; iTimes++) {
std::vector<P3_Point> points_to_insert;
// The following is a new strategy to refine the mesh: inserting points at the centroids of all cells if they are close to the iso surface.
for (auto cit = T.unique_cells_begin(); cit != T.unique_cells_end(); ++cit) {
double max_f = -std::numeric_limits<double>::infinity();
double min_f = std::numeric_limits<double>::infinity();
// Find max_f and min_f within the cell
for (int i = 0; i < 4; ++i) { // Each cell has 4 vertices
auto vh = cit->vertex(i);
double f = vh->info();
max_f = std::max(max_f, f);
min_f = std::min(min_f, f);
}
// Calculate t using max_f and min_f
double t;
if (max_f != min_f) { // Ensure denominator is not zero
t = (0 - min_f) / (max_f - min_f);
} else {
// If max_f == min_f, we cannot determine a zero-crossing in the traditional sense
continue; // Move to the next cell
}
// Use t value for further processing, if needed
if (t > -0.2 && t < 0.3) {
// Calculate the "real" positions of the vertices considering their offsets
double sum_x = 0, sum_y = 0, sum_z = 0;
int count = 0;
for (int i = 0; i < 4; ++i) { // Each cell has 4 vertices
PeriodicPoint pp = T.periodic_point(cit, i);
P3_Point real_point = T.point(pp); // Converts periodic point to its real position
sum_x += real_point.x();
sum_y += real_point.y();
sum_z += real_point.z();
count++;
}
// Calculate the centroid coordinates
double centroid_x = sum_x / count;
double centroid_y = sum_y / count;
double centroid_z = sum_z / count;
P3_Point centroid(centroid_x, centroid_y, centroid_z);
P3_Traits traits(T.domain());
P3_Point new_point = CGAL::P3T3::internal::robust_canonicalize_point(centroid, traits);
new_point = T.construct_point(new_point);
points_to_insert.push_back(new_point);
}
}
std::cout << "\nRound "<< iTimes << " " << points_to_insert.size() << " new points found." << std::endl;
std::cout << "inserting... " << std::flush;
for (unsigned long long i=0; i<points_to_insert.size(); i++) {
try {
auto vh = T.insert(points_to_insert[i]);
vh->info() = periodic_function(vh->point());
}
catch (const std::exception& e) {
std::cerr << "An error occured during insertion: " << e.what() << std::endl;
}
}
std::cout << "done." << std::endl;
}
std::cout << MaxRoundOfRefinement << " rounds of refinement finished successfully." << std::endl;
return 0;
}
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi,
I've been using the following code to refine a periodic 3D Delaunay mesh. This refined mesh will be later used to extract the iso surface of periodic_function(x,y,z) = 0. The idea is to insert points whenever a unique edge is detected to be "close enough" to the iso surface. The inserted points are at the center of that edge, and the info() is updated. This refinement can go through many rounds.
I found that in the middle of refinement, the code compiled in Release mode gets stuck somewhere when new points are inserted.
The Debug mode sometimes gives the following error:
Sometimes the Debug mode can also be stuck when inserting the new points.
Please help.
Thanks.
Beta Was this translation helpful? Give feedback.
All reactions