Skip to Content.
Sympa Menu

cgal-discuss - [cgal-discuss] make_mesh_3 results in non-manifold edges in surface mesh

Subject: CGAL users discussion list

List archive

[cgal-discuss] make_mesh_3 results in non-manifold edges in surface mesh


Chronological Thread 
  • From: Patrick <>
  • To:
  • Subject: [cgal-discuss] make_mesh_3 results in non-manifold edges in surface mesh
  • Date: Sun, 20 Nov 2016 19:35:56 +0100
  • Authentication-results: mail2-smtp-roc.national.inria.fr; spf=None ; spf=Pass ; spf=None
  • Ironport-phdr: 9a23:YOVl9xN3TvP6fAWlhO8l6mtUPXoX/o7sNwtQ0KIMzox0K/r8rarrMEGX3/hxlliBBdydsKMfzbCM+Pm5AiRAuc/H6y9SNsQUFlcssoY/oU8JOIa9E0r1LfrnPWQRPf9pcxtbxUy9KlVfA83kZlff8TWY5D8WHQjjZ0IufrymUt2as8Pi3O+7/9jfYh5DmSGmSbJ0NhS/6wvL5ecMho43Eq8t0BrCoTMcY+1KwGpuDV2Wlhf4oMy3+cgwoGxrp/s9+psYAu3BdKMiQOkAAQ==

Hi,

I've been using CGAL to mesh (approximations to) fattened gyroid surfaces, confined to a box from an implicit function. Attached is a simple example code. Unfortunately, this results in a surface mesh containing a non-manifold edge (with 4 faces attached to it). this problem seems to persist in the tet mesh that was generated (I wrote a little program to recalculate its surface mesh). Am I making some silly mistake here? Is there any way to fix it?

Thanks,
Patrick
#include <iostream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Implicit_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h>
//#include "utils.hpp"

using std::abs;
using std::min;
using std::max;
using std::string;

const double pi = 3.14159265358979323846;

template <class type>
inline type
min( type a, type b, type c ) {
  const type m = std::min( a, b );
  return std::min( m, c );
}

template <class type>
inline type
max( type a, type b, type c ) {
  const type m = std::max( a, b );
  return std::max( m, c );
}

template <class type>
inline type
sqr( type a ) {
   return a*a;
}


typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::FT FT;
typedef K::Point_3 Point;
typedef FT (Function)(const Point&);
typedef CGAL::Implicit_mesh_domain_3<Function,K> Mesh_domain;
//#ifdef CGAL_CONCURRENT_MESH_3
typedef CGAL::Parallel_tag Concurrency_tag;
//#else
//typedef CGAL::Sequential_tag Concurrency_tag;
//#endif
// Triangulation
typedef CGAL::Mesh_triangulation_3<Mesh_domain,CGAL::Default,Concurrency_tag>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
// Criteria
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;

// To avoid verbose function and named parameters call
using namespace CGAL::parameters;
// Function

// ---- Start here to define volume ---- 

const FT box_size_x = 4.0; // box goes from x=0 to x=box_size_x!
const FT box_size_y = 4.0; // box goes from y=0 to y=box_size_y!
const FT box_size_z = 4.0; // box goes from z=0 to z=box_size_z!

const FT factor = 1.0;

const FT num_unit_x = 1.0;
const FT num_unit_y = 1.0;
const FT num_unit_z = 1.0;

const FT thickness = 0.8;

FT gyroid (const Point &p) {
  
  const FT x = p.x(), y = p.y(), z = p.z();
  
  const FT scale_x = num_unit_x*2.0*pi / box_size_x;
  const FT scale_y = num_unit_y*2.0*pi / box_size_y;
  const FT scale_z = num_unit_z*2.0*pi / box_size_z;
  
  return abs(cos(scale_x*x) * sin(scale_y*y) + cos(scale_y*y)*sin(scale_z*z) + cos(scale_z*z)*sin(scale_x*x)) - thickness;
}

FT box (const Point &p) {
	const FT x = p.x(), y = p.y(), z = p.z();
	const FT x_center = box_size_x/2.0, y_center = box_size_y/2.0, z_center = box_size_z/2.0;
	return max(2.0/(factor*box_size_x) * abs(x-x_center), 2.0/(factor*box_size_y) * abs(y-y_center), 2.0/(factor*box_size_z) * abs(z-z_center))-1.0;
}

FT impl_function (const Point&p) {
	return max(gyroid(p),box(p));
    //return min(box(p), schwp(p));
	//return min(box(p), ellipse(p));
}

// parameters
const FT fa = 30.0;  // This parameter controls the shape of surface facets. Actually, 
                        // it is a lower bound for the angle (in degree) of 
	                    // surface facets. When boundary surfaces are smooth, the 
                        // termination of the meshing process is guaranteed if the angular bound is at most 30 degrees.
const FT fs = 0.1;    // This parameter controls the size of surface facets. 
                        // Actually, each surface facet has a surface 
                        // Delaunay ball which is a ball circumscribing the surface 
                        // facet and centered on the surface patch. The parameter facet_size 
                        // is either a constant or a spatially variable scalar field, providing an 
                        // upper bound for the radii of surface Delaunay balls.
const FT fd = 0.025; // This parameter controls the approximation error of boundary and 
	                      // subdivision surfaces. Actually, it is either a constant or a spatially
	                      // variable scalar field. It provides an upper bound for the distance 
	                      // between the circumcenter of a surface facet and the center of a 
	                      // surface Delaunay ball of this facet.
// facet_topology = 1.0   // This parameters controls the set of topological constraints which have to 
	                      // be verified by each surface facet. By default, each vertex of a surface facet has 
	                      // to be located on a surface patch, on a curve segment, or on a corner. It can also 
	                      // be set to check whether the three vertices of a surface facet belongs to the same 
	                      // surface patch. This has to be done cautiously, as such a criteria needs that 
	                      // each surface patches intersection is an input 1-dimensional feature.
const FT crer = 1.8; // This parameter controls the shape of mesh cells (but can't filter slivers, as 
	                            // we discussed earlier). Actually, it is an upper bound for the ratio between the 
	                            // circumradius of a mesh tetrahedron and its shortest edge. There is a theoretical 
	                            // bound for this parameter: the Delaunay refinement process is guaranteed to 
	                            // terminate for values of cell_radius_edge_ratio bigger than 2.
const FT cs = 0.1;             // This parameter controls the size of mesh tetrahedra. It is either a scalar or a 
                                // spatially variable scalar field. It provides an upper bound on the circumradii of
                                // the mesh tetrahedra.

int main()
{
  // Domain (Warning: Sphere_3 constructor uses squared radius !)
  const Point center(box_size_x/2.0, box_size_y/2.0, box_size_z/2.0);
  const FT radsq = sqr(factor*box_size_x/2.0) + sqr(factor*box_size_y/2.0) + sqr(factor*box_size_z/2.0)+0.1;
  //std::cerr << impl_function(center);
  Mesh_domain domain(impl_function,
                     K::Sphere_3(center, radsq));
  // Mesh criteria
  Mesh_criteria criteria(facet_angle=fa, facet_size=fs, facet_distance=fd,
                         cell_radius_edge_ratio=crer, cell_size=cs);
  
  // Mesh generation
  //C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, odt(), perturb(), exude());
  C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria);
  // Output
  std::ofstream medit_file("out.mesh");
  c3t3.output_to_medit(medit_file);
  medit_file.close();
  std::ofstream off_file("out.off");
  c3t3.output_boundary_to_off(off_file);
  off_file.close();
  return 0;
}



Archive powered by MHonArc 2.6.18.

Top of Page