File: successive_wraps.cpp

package info (click to toggle)
cgal 6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 144,912 kB
  • sloc: cpp: 810,858; ansic: 208,477; sh: 493; python: 411; makefile: 286; javascript: 174
file content (135 lines) | stat: -rw-r--r-- 5,235 bytes parent folder | download | duplicates (2)
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// In this example, we reuse the underlying triangulation of the previous state, and carve using
// a new (smaller) alpha value. This enables considerable speed-up: the cumulated time taken
// to run `n` successive instances of `{alpha_wrap(alpha_i)}_(i=1...n)` will be roughly equal
// to the time taken to the single instance of alpha_wrap(alpha_n) from scratch.
//
// The speed-up increases with the number of intermediate results, and on the gap between
// alpha values: if alpha_2 is close to alpha_1, practically no new computation are required,
// and the speed-up is almost 100%.
//
// -------------------------------- !! Warning !! --------------------------------------------------
// The result of:
//   > alpha_wrap(alpha_1, ...)
//   > alpha_wrap(alpha_2, ..., reuse)
// is not exactly identical to calling directly:
//   > alpha_wrap(alpha_2, ..., do_not_reuse)
// because the queues are sorted slightly differently and the AABB tree is rebuilt differently
// to optimize the runtime.
// -------------------------------------------------------------------------------------------------

#include "output_helper.h"

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>

#include <CGAL/alpha_wrap_3.h>
#include <CGAL/Polygon_mesh_processing/bbox.h>
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
#include <CGAL/Real_timer.h>

#include <iostream>
#include <string>

namespace PMP = CGAL::Polygon_mesh_processing;

using K = CGAL::Exact_predicates_inexact_constructions_kernel;
using FT = K::FT;
using Point_3 = K::Point_3;

using Mesh = CGAL::Surface_mesh<Point_3>;

int main(int argc, char** argv)
{
  std::cout.precision(17);
  std::cerr.precision(17);

  // Read the input
  const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/cube.off");
  std::cout << "Reading " << filename << "..." << std::endl;

  Mesh mesh;
  if(!PMP::IO::read_polygon_mesh(filename, mesh) || is_empty(mesh) || !is_triangle_mesh(mesh))
  {
    std::cerr << "Invalid input:" << filename << std::endl;
    return EXIT_FAILURE;
  }

  std::cout << "Input: " << num_vertices(mesh) << " vertices, " << num_faces(mesh) << " faces" << std::endl;

  const CGAL::Bbox_3 bbox = CGAL::Polygon_mesh_processing::bbox(mesh);
  const double diag_length = std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
                                       CGAL::square(bbox.ymax() - bbox.ymin()) +
                                       CGAL::square(bbox.zmax() - bbox.zmin()));

  // We want decreasing alphas, and these are relative ratios, so they need to be increasing
  const std::vector<FT> relative_alphas = { 1, 50, 100, 150, 200, 250 };
  const FT relative_offset = 600;

  // ===============================================================================================
  // Naive approach:

  CGAL::Real_timer t;
  double total_time = 0.;

  for(std::size_t i=0; i<relative_alphas.size(); ++i)
  {
    t.reset();
    t.start();

    const double alpha = diag_length / relative_alphas[i];
    const double offset = diag_length / relative_offset;
    std::cout << ">>> [" << i << "] alpha: " << alpha << " offset: " << offset << std::endl;

    Mesh wrap;
    CGAL::alpha_wrap_3(mesh, alpha, offset, wrap);

    t.stop();
    std::cout << "  Result: " << num_vertices(wrap) << " vertices, " << num_faces(wrap) << " faces" << std::endl;
    std::cout << "  Elapsed time: " << t.time() << " s." << std::endl;

    total_time += t.time();
  }

  std::cout << "Total elapsed time (naive): " << total_time << " s.\n" << std::endl;

  // ===============================================================================================
  // Re-use approach

  total_time = 0.;
  t.reset();

  using Oracle = CGAL::Alpha_wraps_3::internal::Triangle_mesh_oracle<K>;
  using Wrapper = CGAL::Alpha_wraps_3::internal::Alpha_wrapper_3<Oracle>;
  Wrapper wrapper; // contains the triangulation that is being refined iteratively

  for(std::size_t i=0; i<relative_alphas.size(); ++i)
  {
    t.reset();
    t.start();

    const double alpha = diag_length / relative_alphas[i];
    const double offset = diag_length / relative_offset;
    std::cout << ">>> [" << i << "] alpha: " << alpha << " offset: " << offset << std::endl;

    // The triangle mesh oracle should be initialized with alpha to internally perform a split
    // of too-big facets while building the AABB Tree. This split in fact yields a significant
    // speed-up for meshes with elements that are large compared to alpha. This speed-up makes it
    // faster to re-build the AABB tree for every value of alpha than to use a non-optimized tree.
    Oracle oracle(alpha);
    oracle.add_triangle_mesh(mesh, CGAL::parameters::default_values());
    wrapper.oracle() = oracle;

    Mesh wrap;
    wrapper(alpha, offset, wrap, CGAL::parameters::refine_triangulation((i != 0)));

    t.stop();
    std::cout << "  Result: " << num_vertices(wrap) << " vertices, " << num_faces(wrap) << " faces" << std::endl;
    std::cout << "  Elapsed time: " << t.time() << " s." << std::endl;

    total_time += t.time();
  }

  std::cout << "Total elapsed time (successive): " << total_time << " s." << std::endl;

  return EXIT_SUCCESS;
}