Skip to content

Commit 33c7868

Browse files
committed
Add a robust unfolding traits class
This is an option for getting around the lack of robustness when unfolding adjacent faces, without the full overhead of an exact precision kernel.
1 parent 1c6fd7f commit 33c7868

File tree

3 files changed

+121
-8
lines changed

3 files changed

+121
-8
lines changed

Polyhedron_shortest_path/doc/Polyhedron_shortest_path/Polyhedron_shortest_path.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ In order to use the algorithm, one creates an instance of the `Polyhedron_shorte
8989
\subsection Polyhedron_shortest_pathUnfoldingMethods Face Unfolding/Layout Methods
9090
In order to effectively compute the distance along the surface, it is necessary to unfold sequences of faces, edge-to-edge, out into a common plane. The functor `Project_triangle_3_to_triangle_2` provides an initial layout of the first face in a sequence, by rotating a given face into the XY plane. `Flatten_triangle_3_along_segment_2` unfolds a triangle into the plane, using a specified segment as a base. Since this results in a chain of constructed triangles in the plane, exact representation types such as CORE::Expr or leda::real will process extremely slow (effectively adding an \f$O(n)\f$ factor to any computation) and therefore their use with this algorithm is not recommended.
9191

92+
If more robustness is needed, consider using the `Polyhedron_shortest_path_default_traits_with_robust_unfolding` traits class; it implements the unfolding methods using an exact kernel in isolation, avoiding intermediate roundoff error within each operation, while still keeping the overall algorithm from becoming too slow (however it will still take much longer than with an inexact kernel).
93+
9294
\subsection Polyhedron_shortest_pathBarycentric Barycentric Coordinates and Face Locations
9395

9496
The source locations of the algorithm are specified either using vertices (specifically `boost::GraphTraits<FaceGraph>::vertex_descriptor>`, or face/location pairs, where the location is represented using a <em>Barycentric Coordinate</em> in the face. Given a point \f$p\f$ that lies inside and on the plane of triangle \f$(A,B,C)\f$, its barycentric coordinate is a real-valued triple \f$(b_0,b_1,b_2)\f$ such that \f$p = b_0\cdot~A + b_1\cdot~B + b_2\cdot~C\f$.

Polyhedron_shortest_path/include/CGAL/Polyhedron_shortest_path/Polyhedron_shortest_path_traits.h

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ model as required by the Polyhedron_shortest_path algorithm
2727
2828
\tparam F The faceGraph type the algorithm is to act on
2929
30-
\cgalModels `FaceGraphShortestPathTraits`
30+
\cgalModels `PolyhedronShortestPathTraits`
3131
*/
3232
template <
3333
class K,
@@ -155,6 +155,53 @@ std::ostream& operator<<(std::ostream& os, typename Polyhedron_shortest_path_def
155155
return os << b[0] << " " << b[1] << " " << b[2];
156156
}
157157

158+
159+
160+
/*!
161+
\ingroup PkgPolyhedronShortestPathTraitsClasses
162+
163+
\brief Provides an implementation of the FaceGraphShortestPathTraits
164+
model as required by the Polyhedron_shortest_path algorithm
165+
166+
\tparam K The kernel type whose geometric primitives to use
167+
168+
\tparam F The faceGraph type the algorithm is to act on
169+
170+
\cgalModels `PolyhedronShortestPathTraits`
171+
*/
172+
template <
173+
class K,
174+
class F>
175+
class Polyhedron_shortest_path_default_traits_with_robust_unfolding : public Polyhedron_shortest_path_default_traits<K,F>
176+
{
177+
public:
178+
typedef K Kernel;
179+
typedef typename PolyhedronShortestPath::Robust_project_triangle_3_to_triangle_2<K> Project_triangle_3_to_triangle_2;
180+
typedef typename PolyhedronShortestPath::Robust_flatten_triangle_3_along_segment_2<K> Flatten_triangle_3_along_segment_2;
181+
182+
private:
183+
184+
Project_triangle_3_to_triangle_2 m_robust_project_triangle_3_to_triangle_2_object;
185+
Flatten_triangle_3_along_segment_2 m_robust_flatten_triangle_3_along_segment_2;
186+
187+
public:
188+
189+
Polyhedron_shortest_path_default_traits_with_robust_unfolding()
190+
{
191+
}
192+
193+
Polyhedron_shortest_path_default_traits_with_robust_unfolding(const Kernel& kernel)
194+
: Polyhedron_shortest_path_default_traits<K,F>(kernel)
195+
, m_robust_project_triangle_3_to_triangle_2_object(kernel)
196+
, m_robust_flatten_triangle_3_along_segment_2(kernel)
197+
{
198+
}
199+
200+
Project_triangle_3_to_triangle_2 project_triangle_3_to_triangle_2_object() const { return m_robust_project_triangle_3_to_triangle_2_object; }
201+
Flatten_triangle_3_along_segment_2 flatten_triangle_3_along_segment_2_object() const { return m_robust_flatten_triangle_3_along_segment_2; }
202+
};
203+
158204
} // namespace CGAL
159205

206+
160207
#endif // CGAL_POLYHEDRON_SHORTEST_PATH_TRAITS_H

Polyhedron_shortest_path/include/CGAL/Polyhedron_shortest_path/function_objects.h

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#include <CGAL/Polyhedron_shortest_path/internal/misc_functions.h>
1515

16+
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
17+
1618
#ifndef CGAL_POLYHEDRON_SHORTEST_PATH_INTERNAL_FUNCTION_OBJECTS_H
1719
#define CGAL_POLYHEDRON_SHORTEST_PATH_INTERNAL_FUNCTION_OBJECTS_H
1820

@@ -194,7 +196,7 @@ class Project_triangle_3_to_triangle_2
194196
private:
195197
Parametric_distance_along_segment_3<K> m_parametric_distance_along_segment_3;
196198
Compute_squared_distance_3 m_compute_squared_distance_3;
197-
Construct_line_3 m_constuct_line_3;
199+
Construct_line_3 m_construct_line_3;
198200
Construct_projected_point_3 m_construct_projected_point_3;
199201
mutable Construct_vertex_3 m_construct_vertex_3;
200202
Construct_vector_3 m_construct_vector_3;
@@ -208,7 +210,7 @@ class Project_triangle_3_to_triangle_2
208210

209211
Project_triangle_3_to_triangle_2(const K& kernel)
210212
: m_compute_squared_distance_3(kernel.compute_squared_distance_3_object())
211-
, m_constuct_line_3(kernel.constuct_line_3_object())
213+
, m_construct_line_3(kernel.construct_line_3_object())
212214
, m_construct_vertex_3(kernel.construct_vertex_3_object())
213215
, m_construct_projected_point_3(kernel.construct_projected_point_3_object())
214216
, m_construct_vector_3(kernel.construct_vector_3_object())
@@ -222,7 +224,7 @@ class Project_triangle_3_to_triangle_2
222224
Vector_3 v01(m_construct_vector_3(m_construct_vertex_3(t3, 0), m_construct_vertex_3(t3, 1)));
223225
Vector_3 v02(m_construct_vector_3(m_construct_vertex_3(t3, 0), m_construct_vertex_3(t3, 2)));
224226

225-
Line_3 baseSegment(m_constuct_line_3(m_construct_vertex_3(t3, 0), m_construct_vertex_3(t3, 1)));
227+
Line_3 baseSegment(m_construct_line_3(m_construct_vertex_3(t3, 0), m_construct_vertex_3(t3, 1)));
226228

227229
//FT scalePoint = (v01 * v02) / (v01 * v01);
228230
Point_3 projectedLocation3d(m_construct_projected_point_3(baseSegment, m_construct_vertex_3(t3, 2)));
@@ -238,6 +240,36 @@ class Project_triangle_3_to_triangle_2
238240
}
239241
};
240242

243+
template<class K>
244+
class Robust_project_triangle_3_to_triangle_2
245+
{
246+
public:
247+
typedef typename K::Triangle_3 Triangle_3;
248+
typedef typename K::Triangle_2 Triangle_2;
249+
typedef Exact_predicates_exact_constructions_kernel_with_sqrt EKSQRT;
250+
typedef Project_triangle_3_to_triangle_2<EKSQRT> Exact_project_triangle_3_to_triangle_2;
251+
typedef Cartesian_converter<K, EKSQRT> To_exact;
252+
typedef Cartesian_converter<EKSQRT, K> Back_from_exact;
253+
254+
public:
255+
Robust_project_triangle_3_to_triangle_2()
256+
{
257+
}
258+
259+
Robust_project_triangle_3_to_triangle_2(const K& kernel)
260+
{
261+
}
262+
263+
Triangle_2 operator() (const Triangle_3& t3) const
264+
{
265+
Exact_project_triangle_3_to_triangle_2 ept3t2;
266+
To_exact to_exact;
267+
Back_from_exact back_from_exact;
268+
269+
return back_from_exact(ept3t2(to_exact(t3)));
270+
}
271+
};
272+
241273
template<class K>
242274
class Flatten_triangle_3_along_segment_2
243275
{
@@ -273,7 +305,7 @@ class Flatten_triangle_3_along_segment_2
273305

274306
Parametric_distance_along_segment_3<K> m_parametric_distance_along_segment_3;
275307
Compute_squared_distance_3 m_compute_squared_distance_3;
276-
Construct_projected_point_3 m_constrct_projected_point_3;
308+
Construct_projected_point_3 m_construct_projected_point_3;
277309
Construct_perpendicular_vector_2 m_construct_perpendicular_vector_2;
278310
Construct_sum_of_vectors_2 m_construct_sum_of_vectors_2;
279311
Construct_scaled_vector_2 m_construct_scaled_vector_2;
@@ -294,7 +326,7 @@ class Flatten_triangle_3_along_segment_2
294326

295327
Flatten_triangle_3_along_segment_2(const K& kernel)
296328
: m_compute_squared_distance_3(kernel.compute_squared_distance_3_object())
297-
, m_constrct_projected_point_3(kernel.constrct_projected_point_3_object())
329+
, m_construct_projected_point_3(kernel.construct_projected_point_3_object())
298330
, m_construct_perpendicular_vector_2(kernel.construct_perpendicular_vector_2_object())
299331
, m_construct_sum_of_vectors_2(kernel.construct_sum_of_vectors_2_object())
300332
, m_construct_scaled_vector_2(kernel.construct_scaled_vector_2_object())
@@ -312,7 +344,7 @@ class Flatten_triangle_3_along_segment_2
312344

313345
result_type operator() (const Triangle_3& t3, size_t edgeIndex, const Segment_2& segment) const
314346
{
315-
Point_3 projectedLocation3d(m_constrct_projected_point_3(m_construct_line_3(m_construct_vertex_3(t3, edgeIndex), m_construct_vertex_3(t3, edgeIndex + 1)), m_construct_vertex_3(t3, edgeIndex + 2)));
347+
Point_3 projectedLocation3d(m_construct_projected_point_3(m_construct_line_3(m_construct_vertex_3(t3, edgeIndex), m_construct_vertex_3(t3, edgeIndex + 1)), m_construct_vertex_3(t3, edgeIndex + 2)));
316348
FT scalePoint = m_parametric_distance_along_segment_3(m_construct_segment_3(m_construct_vertex_3(t3, edgeIndex), m_construct_vertex_3(t3, edgeIndex + 1)), projectedLocation3d);
317349
FT triangleHeight = CGAL::internal::select_sqrt(m_compute_squared_distance_3(projectedLocation3d, m_construct_vertex_3(t3, edgeIndex + 2)));
318350

@@ -331,6 +363,38 @@ class Flatten_triangle_3_along_segment_2
331363
}
332364
};
333365

366+
template<class K>
367+
class Robust_flatten_triangle_3_along_segment_2
368+
{
369+
public:
370+
typedef typename K::Triangle_3 Triangle_3;
371+
typedef typename K::Segment_2 Segment_2;
372+
typedef typename K::Triangle_2 Triangle_2;
373+
374+
typedef Exact_predicates_exact_constructions_kernel_with_sqrt EKSQRT;
375+
typedef Flatten_triangle_3_along_segment_2<EKSQRT> Exact_flatten_triangle_3_along_segment_2;
376+
typedef Cartesian_converter<K, EKSQRT> To_exact;
377+
typedef Cartesian_converter<EKSQRT, K> Back_from_exact;
378+
379+
public:
380+
Robust_flatten_triangle_3_along_segment_2()
381+
{
382+
}
383+
384+
Robust_flatten_triangle_3_along_segment_2(const K& kernel)
385+
{
386+
}
387+
388+
Triangle_2 operator() (const Triangle_3& t3, size_t edgeIndex, const Segment_2& segment) const
389+
{
390+
Exact_flatten_triangle_3_along_segment_2 eft3as2;
391+
To_exact to_exact;
392+
Back_from_exact back_from_exact;
393+
394+
return back_from_exact(eft3as2(to_exact(t3), edgeIndex, to_exact(segment)));
395+
}
396+
};
397+
334398
template <class K>
335399
class Compare_relative_intersection_along_segment_2
336400
{
@@ -473,7 +537,7 @@ class Is_saddle_vertex
473537
{
474538
}
475539

476-
Is_saddle_vertex(const Kernel& kernel, const Project_triangle_3_to_triangle_2& pt3tt2, const Flatten_triangle_3_along_segment_2& ft3as2, const Orientation_2& o2)
540+
Is_saddle_vertex(const Kernel& kernel, const Project_triangle_3_to_triangle_2& pt3tt2, const Flatten_triangle_3_along_segment_2& ft3as2)
477541
: m_orientation_2(kernel.orientation_2_object())
478542
, m_construct_triangle_3(kernel.construct_triangle_3_object())
479543
, m_construct_vertex_2(kernel.construct_vertex_2_object())

0 commit comments

Comments
 (0)