File: helper.h

package info (click to toggle)
cgal 6.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 144,952 kB
  • sloc: cpp: 811,597; ansic: 208,576; sh: 493; python: 411; makefile: 286; javascript: 174
file content (248 lines) | stat: -rw-r--r-- 10,386 bytes parent folder | download
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
// Copyright (c) 2018, 2019 GeometryFactory (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v6.1.1/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/helper.h $
// $Id: include/CGAL/Polygon_mesh_processing/internal/Snapping/helper.h 08b27d3db14 $
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s)     : Mael Rouxel-Labbé

#ifndef CGAL_POLYGON_MESH_PROCESSING_INTERNAL_SNAPPING_HELPER_H
#define CGAL_POLYGON_MESH_PROCESSING_INTERNAL_SNAPPING_HELPER_H

#include <CGAL/license/Polygon_mesh_processing/geometric_repair.h>

#include <CGAL/boost/graph/iterator.h>
#include <CGAL/number_utils.h>
#include <CGAL/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>

namespace CGAL {
namespace Polygon_mesh_processing {
namespace internal {

template <typename VertexRange,
          typename HalfedgeOutputIterator,
          typename PolygonMesh>
void vertices_as_halfedges(const VertexRange& vertex_range,
                           const PolygonMesh& pmesh,
                           HalfedgeOutputIterator out)
{
  typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor                vertex_descriptor;

  for(vertex_descriptor v : vertex_range)
    *out++ = halfedge(v, pmesh);
}

// Assigns at each vertex the 'tolerance' value as tolerance,
// but bounded by a percentage of the length of its shortest incident edge
template <typename HalfedgeRange,
          typename ToleranceMap,
          typename PolygonMesh,
          typename NamedParameters = parameters::Default_named_parameters>
void assign_tolerance_with_local_edge_length_bound(const HalfedgeRange& halfedge_range,
                                                   ToleranceMap& tolerance_map,
                                                   const typename GetGeomTraits<PolygonMesh, NamedParameters>::type::FT tolerance,
                                                   PolygonMesh& mesh,
                                                   const NamedParameters& np = parameters::default_values())
{
  typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor                vertex_descriptor;
  typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor              halfedge_descriptor;

  typedef typename GetVertexPointMap<PolygonMesh, NamedParameters>::type              VPM;
  typedef typename GetGeomTraits<PolygonMesh, NamedParameters>::type                  GT;
  typedef typename GT::FT                                                             FT;

  using parameters::get_parameter;
  using parameters::choose_parameter;

  GT gt = choose_parameter<GT>(get_parameter(np, internal_np::geom_traits));
  VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
                             get_property_map(vertex_point, mesh));

  for(halfedge_descriptor hd : halfedge_range)
  {
    const vertex_descriptor vd = target(hd, mesh);
    CGAL::Halfedge_around_target_iterator<PolygonMesh> hit, hend;
    std::tie(hit, hend) = CGAL::halfedges_around_target(vd, mesh);
    CGAL_assertion(hit != hend);

    FT sq_length = gt.compute_squared_distance_3_object()(get(vpm, source(*hit, mesh)),
                                                          get(vpm, target(*hit, mesh)));
    FT min_sq_dist = sq_length;
    ++hit;

    for(; hit!=hend; ++hit)
    {
      sq_length = gt.compute_squared_distance_3_object()(get(vpm, source(*hit, mesh)),
                                                         get(vpm, target(*hit, mesh)));

      if(sq_length < min_sq_dist)
        min_sq_dist = sq_length;
    }

#ifdef CGAL_PMP_SNAP_DEBUG_PP
    std::cout << "tolerance at vd: " << vd << " [" << get(vpm, vd) << "]: min of "
              << 0.9 * CGAL::approximate_sqrt(min_sq_dist) << " AND " << tolerance << std::endl;
#endif
    put(tolerance_map, vd, CGAL::min<FT>(0.9 * CGAL::approximate_sqrt(min_sq_dist), tolerance));
  }
}

template <typename GeomTraits>
bool is_collinear_with_tolerance(const typename GeomTraits::Point_3& p, // va == vb
                                 const typename GeomTraits::Point_3& pa,
                                 const typename GeomTraits::Point_3& pb,
                                 const GeomTraits& gt)
{
  typedef typename GeomTraits::FT                                                     FT;
  typedef typename GeomTraits::Vector_3                                               Vector_3;

  const Vector_3 va = gt.construct_vector_3_object()(p, pa);
  const Vector_3 vb = gt.construct_vector_3_object()(p, pb);
  const FT sp = gt.compute_scalar_product_3_object()(va, vb);

  // To avoid junctions like:
  //  ----va vb-----
  //       | |
  //
  // from being locked since it could be needed in a configuration such as
  // -------------
  // ----va  vb---
  //     |   |
  // later
  if(sp < FT(0))
    return false;

  const FT sq_va_l = gt.compute_squared_distance_3_object()(p, pa);
  const FT sq_vb_l = gt.compute_squared_distance_3_object()(p, pb);
  const FT sq_cos = 0.99999228397046306; // CGAL::square(std::cos(1°));

  return (CGAL::square(sp) >= sq_va_l * sq_vb_l * sq_cos);
}

template <typename PolygonMesh>
struct Snapping_default_visitor
{
  bool m_stop = false;

  bool stop() { return m_stop; }

  // ------------------------------- Preprocessing ------------------------------

  // Called when starting preprocessing phase of the mesh.
  void start_mesh_preprocessing() { }

  // Called at the end of the preprocessing phase of the mesh.
  void end_mesh_preprocessing() { }

  // ------------------------------- Vertex - Vertex -------------------------------

  // Called when starting snapping a range of vertices of `A` and a range of vertices of `B`.
  void start_vertex_vertex_phase() { }

  // Called when finished snapping a range of vertices of `A` and a range of vertices of `B`.
  void end_vertex_vertex_phase() { }

  // Called when trying to find `v`-`v_other` pair (with `v` in `A` and `v_other` in `B`)
  //
  // Available only if vertex-vertex pair detection is based on the kd-tree.
  // Must be threadsafe if parallelism is used.
  template <typename Vertex, typename Mesh>
  void on_vertex_vertex_inquiry(const Vertex /*v*/, const Mesh&) { }

  // Called when a match between two ranges of vertices is found.
  // All vertices in `va` have the same position (and same for `vb`).
  //
  // Must be threadsafe if parallelism is used.
  template <typename VertexContainer, typename Mesh>
  void on_vertex_vertex_match(const VertexContainer& /*va*/, const Mesh&,
                              const VertexContainer& /*vb*/, const Mesh&) { }

  // Called before proceeding with actual vertex-vertex snapping.
  void start_vertex_vertex_snapping() { }

  // Called after proceeding with actual vertex-vertex snapping.
  void end_vertex_vertex_snapping() { }

  // Called before two ranges of vertices are snapped together.
  // All vertices in `va` have the same position (and same for `vb`).
  template <typename VertexContainer, typename Mesh>
  void before_vertex_vertex_snap(const VertexContainer& /*va*/, const Mesh&,
                                 const VertexContainer& /*vb*/, const Mesh&) { }

  // Called after two ranges of vertices have been snapped.
  template <typename VertexContainer, typename Mesh>
  void after_vertex_vertex_snap(const VertexContainer& /*va*/, const Mesh&,
                                const VertexContainer& /*vb*/, const Mesh&) { }

  // -------------------------------  Vertex - Edge -------------------------------

  // Called when starting snapping a range of vertices of A onto edges of B
  void start_first_vertex_edge_phase() { }

  // Called when finished snapping a range of vertices of A onto edges of B
  void end_first_vertex_edge_phase() { }

  // Called when starting snapping a range of vertices of B onto edges of A.
  // Not called if A and B are the same mesh.
  void start_second_vertex_edge_phase() { }

  // Called when starting snapping a range of vertices of B onto edges of A.
  // Not called if A and B are the same mesh.
  void end_second_vertex_edge_phase() { }

  // Called when trying to find `v`-`edge` pair
  //
  // Available only if vertex-vertex pair detection is based on the kd-tree.
  // Must be threadsafe if parallelism is used.
  template <typename Vertex, typename Mesh>
  void on_vertex_edge_inquiry(const Vertex /*v*/, const Mesh& /*tm*/) { }

  // Called when a match between a vertex and an edge is found.
  //
  // Must be threadsafe if parallelism is used.
  template <typename Vertex, typename Edge, typename Mesh, typename Point>
  void on_vertex_edge_match(const Vertex, const Mesh&, const Edge, const Mesh&, const Point&) { }

  // Called before proceeding with actual snapping.
  void start_vertex_edge_snapping() { }

  // Called after proceeding with actual snapping.
  void end_vertex_edge_snapping() { }

  // Called before a new vertex is created.
  template <typename Edge, typename Mesh, typename Point>
  void before_vertex_edge_snap(const Edge, const Mesh&, const Point&) { }

  // Called after a new vertex has been created, splitting an edge.
  template <typename Vertex, typename Mesh>
  void after_vertex_edge_snap(const Vertex /*new_vertex*/, const Mesh&) { }

  // Called after CGAL::Euler::split_face(h1, h2, tm)
  template <typename Halfedge_descriptor, typename Mesh>
  void after_split_face(const Halfedge_descriptor /*h1*/, const Halfedge_descriptor /*h2*/, const Mesh& /*tm*/) { }

  // ------------------------------- Two passes (segmentation or not) ------------------------------

  // Called at the start of the snapping pass that is restricted to compatible patch (first pass).
  void start_patch_snapping() { }

  // Called at the end of the snapping pass that is restricted to compatible patch (first pass).
  void end_patch_snapping() { }

  // Called at the start of the second snapping pass, all elements are potentially compatible (second pass).
  void start_global_snapping() { }

  // Called at the end of the second snapping pass, all elements are potentially compatible (second pass).
  void end_global_snapping() { }
};

} // namespace internal
} // namespace Polygon_mesh_processing
} // namespace CGAL

#endif // CGAL_POLYGON_MESH_PROCESSING_INTERNAL_SNAPPING_HELPER_H