File: generate_surface_mesh.cpp

package info (click to toggle)
pygalmesh 0.9.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,152 kB
  • sloc: cpp: 2,254; python: 1,607; makefile: 44
file content (102 lines) | stat: -rw-r--r-- 2,490 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#define CGAL_SURFACE_MESHER_VERBOSE 1

#include "generate_surface_mesh.hpp"

#include <CGAL/Surface_mesh_default_triangulation_3.h>
#include <CGAL/Complex_2_in_triangulation_3.h>
#include <CGAL/make_surface_mesh.h>
#include <fstream>
#include <CGAL/IO/Complex_2_in_triangulation_3_file_writer.h>
#include <CGAL/Implicit_surface_3.h>

namespace pygalmesh {

// default triangulation for Surface_mesher
typedef CGAL::Surface_mesh_default_triangulation_3 Tr;
// c2t3
typedef CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
typedef Tr::Geom_traits GT;

// Wrapper for DomainBase for translating to GT.
class CgalDomainWrapper
{
  public:
  explicit CgalDomainWrapper(const std::shared_ptr<DomainBase> & domain):
    domain_(domain)
  {
  }

  virtual ~CgalDomainWrapper() = default;

  virtual
  GT::FT
  operator()(GT::Point_3 p) const
  {
    return domain_->eval({p.x(), p.y(), p.z()});
  }

  private:
  const std::shared_ptr<DomainBase> domain_;
};

typedef CGAL::Implicit_surface_3<GT, CgalDomainWrapper> Surface_3;

void
generate_surface_mesh(
    const std::shared_ptr<pygalmesh::DomainBase> & domain,
    const std::string & outfile,
    const double bounding_sphere_radius,
    const double min_facet_angle,
    const double max_radius_surface_delaunay_ball,
    const double max_facet_distance,
    const bool verbose,
    const int seed
    )
{
  CGAL::get_default_random() = CGAL::Random(seed);

  const double bounding_sphere_radius2 = bounding_sphere_radius > 0 ?
    bounding_sphere_radius*bounding_sphere_radius :
    // add a little wiggle room
    1.01 * domain->get_bounding_sphere_squared_radius();

  Tr tr;  // 3D-Delaunay triangulation
  C2t3 c2t3 (tr);  // 2D-complex in 3D-Delaunay triangulation

  const auto d = CgalDomainWrapper(domain);
  Surface_3 surface(
      d,
      GT::Sphere_3(CGAL::ORIGIN, bounding_sphere_radius2)
      );

  CGAL::Surface_mesh_default_criteria_3<Tr> criteria(
      min_facet_angle,
      max_radius_surface_delaunay_ball,
      max_facet_distance
      );

  if (!verbose) {
    // suppress output
    std::cout.setstate(std::ios_base::failbit);
    std::cerr.setstate(std::ios_base::failbit);
  }
  CGAL::make_surface_mesh(
      c2t3,
      surface,
      criteria,
      CGAL::Non_manifold_tag()
      );
  if (!verbose) {
    std::cout.clear();
    std::cerr.clear();
  }

  // Output
  std::ofstream off_file(outfile);
  CGAL::output_surface_facets_to_off(off_file, c2t3);
  off_file.close();

  return;
}

} // namespace pygalmesh