File: vsa_isotropic_metric_example.cpp

package info (click to toggle)
cgal 6.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 144,952 kB
  • sloc: cpp: 811,597; ansic: 208,576; sh: 493; python: 411; makefile: 286; javascript: 174
file content (116 lines) | stat: -rw-r--r-- 4,039 bytes parent folder | download | duplicates (4)
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>

#include <CGAL/property_map.h>
#include <CGAL/Variational_shape_approximation.h>
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>

#include <iostream>
#include <fstream>

typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Vector_3 Vector_3;
typedef Kernel::Point_3 Point_3;

typedef CGAL::Surface_mesh<Point_3> Mesh;
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;

typedef boost::property_map<Mesh, boost::vertex_point_t>::type Vertex_point_map;
typedef Mesh::Property_map<face_descriptor, FT> Face_area_map;
typedef Mesh::Property_map<face_descriptor, Point_3> Face_center_map;

namespace VSA = CGAL::Surface_mesh_approximation;

// user-defined "compact" error metric using type Point_3 as proxy
struct Compact_metric_point_proxy
{
  // use point as proxy
  typedef Point_3 Proxy;

  // we keep a precomputed property map to speed up computations
  Compact_metric_point_proxy(const Face_center_map &center_pmap_, const Face_area_map &area_pmap_)
    : center_pmap(center_pmap_), area_pmap(area_pmap_)
  { }

  // compute and return error from a face to a proxy,
  // defined as the Euclidean distance between
  // the face center of mass and proxy point.
  FT compute_error(const face_descriptor &f, const Mesh &, const Proxy &px) const
  {
    return CGAL::sqrt(CGAL::squared_distance(center_pmap[f], px));
  }

  // template functor to compute a best-fit
  // proxy from a range of faces
  template <typename FaceRange>
  Proxy fit_proxy(const FaceRange &faces, const Mesh &) const
  {
    // fitting center
    Vector_3 center = CGAL::NULL_VECTOR;
    FT sum_areas = FT(0.0);
    for(const face_descriptor& f : faces) {
      center = center + (center_pmap[f] - CGAL::ORIGIN) * area_pmap[f];
      sum_areas += area_pmap[f];
    }

    // deal with case where sum = 0
    if (center == CGAL::NULL_VECTOR || sum_areas <= FT(0.0))
    {
      std::cerr << "Error: degenerate geometry." << std::endl;
      std::exit(EXIT_FAILURE);
    }

    center = center / sum_areas;
    return CGAL::ORIGIN + center;
  }

  const Face_center_map center_pmap;
  const Face_area_map area_pmap;
};

typedef CGAL::Variational_shape_approximation<
  Mesh, Vertex_point_map, Compact_metric_point_proxy> Approximation;

int main(int argc, char** argv)
{
  const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/bear.off");

  // reads input surface triangle mesh
  Mesh mesh;
  if(!CGAL::Polygon_mesh_processing::IO::read_polygon_mesh(filename, mesh) ||
     !CGAL::is_triangle_mesh(mesh))
  {
    std::cerr << "Invalid input file." << std::endl;
    return EXIT_FAILURE;
  }

  // constructs precomputed face normal and area map
  Vertex_point_map vpmap = get(boost::vertex_point, const_cast<Mesh &>(mesh));
  Face_area_map area_pmap = mesh.add_property_map<face_descriptor, FT>("f:area", FT(0.0)).first;
  Face_center_map center_pmap = mesh.add_property_map<face_descriptor, Point_3>("f:center", CGAL::ORIGIN).first;

  for(face_descriptor f : faces(mesh))
  {
    const halfedge_descriptor he = halfedge(f, mesh);
    const Point_3 &p0 = vpmap[source(he, mesh)];
    const Point_3 &p1 = vpmap[target(he, mesh)];
    const Point_3 &p2 = vpmap[target(next(he, mesh), mesh)];
    put(area_pmap, f, CGAL::sqrt(CGAL::squared_area(p0, p1, p2)));
    put(center_pmap, f, CGAL::centroid(p0, p1, p2));
  }

  // error metric and fitting function
  Compact_metric_point_proxy error_metric(center_pmap, area_pmap);

  // creates compact metric approximation algorithm instance
  Approximation approx(mesh, vpmap, error_metric);

  // approximates via 200 proxies and 30 iterations
  approx.initialize_seeds(CGAL::parameters::seeding_method(VSA::HIERARCHICAL)
                                           .max_number_of_proxies(200));
  approx.run(30);

  return EXIT_SUCCESS;
}