This file is indexed.

/usr/include/CGAL/Polygon_mesh_slicer.h is in libcgal-dev 4.7-4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
// Copyright (c) 2013,2014,2015 GeometryFactory (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s)     : Ilker O. Yaz and Sebastien Loriot

#ifndef CGAL_POLYGON_MESH_SLICER_H
#define CGAL_POLYGON_MESH_SLICER_H

#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_halfedge_graph_segment_primitive.h>
#include <CGAL/tuple.h>

#include <vector>
#include <set>

#include <boost/foreach.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <CGAL/Polygon_mesh_processing/internal/Polygon_mesh_slicer/Traversal_traits.h>
#include <CGAL/Polygon_mesh_processing/internal/Polygon_mesh_slicer/Axis_parallel_plane_traits.h>

#include <boost/variant.hpp>

#include <CGAL/boost/graph/split_graph_into_polylines.h>

namespace CGAL {

/// \ingroup PkgPolygonMeshProcessing
/// Function object that computes the intersection of a plane with
/// a triangulated surface mesh.
///
/// \tparam TriangleMesh a triangulated surface mesh, model of `FaceGraph` and `HalfedgeListGraph`
/// \tparam Traits a model of `AABBGeomTraits`
/// \tparam VertexPointMap a model of `ReadablePropertyMap` with
///         `boost::graph_traits<TriangleMesh>::%vertex_descriptor` as key and
///         `Traits::Point_3` as value type.
///         The default is `typename boost::property_map< TriangleMesh, vertex_point_t>::%type`.
/// \tparam AABBTree must be an instantiation of `CGAL::AABB_tree` able to handle
///         the edges of `TriangleMesh`, having its `edge_descriptor` as primitive id.
///         The default is `CGAL::AABB_tree<CGAL::AABB_traits<
///                  Traits, CGAL::AABB_halfedge_graph_segment_primitive<TriangleMesh> > >`
/// \tparam UseParallelPlaneOptimization if `true`, the code will use specific
///         predicates and constructions in case the functor is called with a plane
///         orthogonal to a frame axis, the non-null coefficient being 1 or -1.
///         The default is `true`.
///
/// The implemenation of this class depends on the package \ref PkgAABB_treeSummary.
/// \todo Shall we document more in details what is required?
///       `Traits` must provide:
///        - `Plane_3`
///        - `Point_3`
///        - `Segment_3`
///        - `Oriented_side_3` with `Oriented_side operator()(Plane_3, Point_3)`
///        - `Do_intersect_3` with `boost::optional<variant<Point_3,Segment_3> operator()(Plane_3,Segment_3)`
///        - `Do_intersect_3` with `bool operator()(Plane_3, Bbox_3)`
///
/// \todo If we keep the traits for plane orthogonal to a frame axis, `Traits` must also provide:
///       - `FT`
///       - `Construct_cartesian_const_iterator_3` with `Iterator operator()(Point_3)` `Iterator` being a random access iterator with `FT` as value type
///       - `Construct_point_3` with `Point_3 operator()(FT,FT,FT)`; `Construct_source_3` with  `const Point_3& operator()(Segment_3)`
///       - `Construct_target_3` with `const Point_3& operator()(Segment_3)`
///
/// \todo `_object()` functions must also be provided
template<class TriangleMesh,
  class Traits,
  class VertexPointMap = typename boost::property_map< TriangleMesh, vertex_point_t>::type,
  class AABBTree = AABB_tree<
                       AABB_traits<Traits,
                         AABB_halfedge_graph_segment_primitive<TriangleMesh> > >,
  bool UseParallelPlaneOptimization=true>
class Polygon_mesh_slicer
{
/// Polygon_mesh typedefs
  typedef typename boost::graph_traits<TriangleMesh>               graph_traits;
  typedef typename graph_traits::vertex_descriptor            vertex_descriptor;
  typedef typename graph_traits::edge_descriptor                edge_descriptor;
  typedef typename graph_traits::halfedge_descriptor        halfedge_descriptor;
  typedef typename graph_traits::face_descriptor                face_descriptor;

/// Geometric typedefs
  typedef typename Traits::Plane_3                                      Plane_3;
  typedef typename Traits::Segment_3                                  Segment_3;
  typedef typename Traits::Point_3                                      Point_3;
  typedef typename Traits::FT                                                FT;

/// typedefs for internal graph to get connectivity of the polylines
  typedef boost::variant<vertex_descriptor, edge_descriptor>     AL_vertex_info;
  typedef boost::adjacency_list <
                              boost::vecS,
                              boost::vecS,
                              boost::undirectedS,
                              AL_vertex_info >                         AL_graph;
  typedef typename AL_graph::vertex_descriptor             AL_vertex_descriptor;
  typedef std::pair<AL_vertex_descriptor, AL_vertex_descriptor>  AL_vertex_pair;
  typedef std::map<vertex_descriptor, AL_vertex_descriptor>        Vertices_map;
  typedef std::pair<const vertex_descriptor,AL_vertex_descriptor>   Vertex_pair;
/// Traversal traits
  typedef Polygon_mesh_slicer_::Traversal_traits<
    AL_graph,
    TriangleMesh,
    VertexPointMap,
    typename AABBTree::AABB_traits,
    Traits >                                           General_traversal_traits;

  typedef Polygon_mesh_slicer_::Traversal_traits<
    AL_graph,
    TriangleMesh,
    VertexPointMap,
    typename AABBTree::AABB_traits,
    Polygon_mesh_slicer_::Axis_parallel_plane_traits<Traits>
  >                                              Axis_parallel_traversal_traits;
/// Auxiliary classes
  // compare the faces using the halfedge descriptors
  struct Compare_face{
    TriangleMesh& m_tmesh;
    Compare_face(TriangleMesh& tmesh)
      :m_tmesh(tmesh)
    {}

    bool operator()(halfedge_descriptor hd1, halfedge_descriptor hd2) const
    {
      return face(hd1,m_tmesh) < face(hd2,m_tmesh);
    }
  };

  typedef std::map< halfedge_descriptor, AL_vertex_pair, Compare_face > AL_edge_map;

  template <class OutputIterator, class Traits_>
  struct Polyline_visitor{
    AL_graph& al_graph;
    TriangleMesh& m_tmesh;
    const Plane_3& m_plane;
    VertexPointMap m_vpmap;
    typename Traits_::Intersect_3 intersect_3;
    OutputIterator out;

    Polyline_visitor( TriangleMesh& tmesh,
                      AL_graph& al_graph,
                      const Plane_3& plane,
                      VertexPointMap vpmap,
                      const Traits_& traits,
                      OutputIterator out)
      : al_graph(al_graph)
      , m_tmesh(tmesh)
      , m_plane(plane)
      , m_vpmap(vpmap)
      , intersect_3( traits.intersect_3_object() )
      , out(out)
    {}

    std::vector< Point_3 > current_poly;
    void start_new_polyline()
    {
      current_poly.clear();
    }
    void add_node(AL_vertex_descriptor node_id)
    {
      AL_vertex_info v = al_graph[node_id];
      if (const vertex_descriptor* vd_ptr = boost::get<vertex_descriptor>(&v) )
      {
        current_poly.push_back( get(m_vpmap, *vd_ptr) );
      }
      else
      {
        edge_descriptor ed = boost::get<edge_descriptor>(v);
        Segment_3 s(
          get(m_vpmap, source(ed, m_tmesh)),
          get(m_vpmap,target(ed, m_tmesh))
        );
        typename cpp11::result_of<typename Traits_::Intersect_3(Plane_3, Segment_3)>::type
          inter = intersect_3(m_plane, s);
        CGAL_assertion(inter != boost::none);
        const Point_3* pt_ptr = boost::get<Point_3>(&(*inter));
        current_poly.push_back( *pt_ptr );
      }
    }

    void end_polyline()
    {
      CGAL_assertion(!current_poly.empty());
      *out++=current_poly;
    }
  };

/// member variables
  const AABBTree* m_tree_ptr;
  TriangleMesh& m_tmesh;
  VertexPointMap m_vpmap;
  Traits m_traits;
  bool m_own_tree;

/// Convenience graph functions
  edge_descriptor next_edge(edge_descriptor ed) const
  {
    return edge( next( halfedge(ed, m_tmesh), m_tmesh), m_tmesh );
  }

  edge_descriptor next_of_opposite_edge(edge_descriptor ed) const
  {
    return edge( next( opposite( halfedge(ed, m_tmesh), m_tmesh), m_tmesh), m_tmesh );
  }

  face_descriptor opposite_face(edge_descriptor ed) const
  {
    return face( opposite( halfedge(ed, m_tmesh), m_tmesh), m_tmesh);
  }
/// Other private functions
  /// handle edge insertion in the adjacency_list graph
  /// we add an edge betweem two edge_descriptor if they
  /// share a common facet
  void update_al_graph_connectivity(
    edge_descriptor ed,
    AL_vertex_descriptor vd,
    AL_edge_map& al_edge_map,
    AL_graph& al_graph) const
  {
      typename AL_edge_map::iterator itm;
      bool new_insertion;

      halfedge_descriptor hd=halfedge(ed, m_tmesh);

      if (face(hd, m_tmesh)!=graph_traits::null_face())
      {
        cpp11::tie(itm, new_insertion) =
          al_edge_map.insert( std::pair< halfedge_descriptor, AL_vertex_pair >
            (hd, AL_vertex_pair(vd, AL_graph::null_vertex())) );
        if (!new_insertion)
        {
          CGAL_assertion(itm->second.second==AL_graph::null_vertex());
          itm->second.second=vd;
          add_edge( itm->second.first,
                    itm->second.second,
                    al_graph);
        }
      }

      hd=opposite(hd, m_tmesh);
      if (face(hd, m_tmesh)!=graph_traits::null_face())
      {
        cpp11::tie(itm, new_insertion) =
          al_edge_map.insert( std::pair< halfedge_descriptor, AL_vertex_pair >
            (hd, AL_vertex_pair(vd, AL_graph::null_vertex())) );
        if (!new_insertion)
        {
          CGAL_assertion(itm->second.second==AL_graph::null_vertex());
          itm->second.second=vd;
          add_edge( itm->second.first,
                    itm->second.second,
                    al_graph);
        }
      }
  }

  std::pair<int, FT>
  axis_parallel_plane_info(const Plane_3& plane) const
  {
    FT a = m_traits.compute_a_3_object()(plane);
    FT b = m_traits.compute_b_3_object()(plane);
    FT c = m_traits.compute_c_3_object()(plane);
    FT d = m_traits.compute_d_3_object()(plane);

    if (a==0)
    {
      if (b==0)
      {
        if (c==1 || c==-1)
          return std::pair<int,FT>(2, -d*c); /// z=-d
      }
      else
      {
        if (c==0 && (b==1 || b==-1))
          return std::pair<int,FT>(1, -d*b); /// y=-d
      }
    }
    else
      if (b==0 && c==0 && ( a==1 || a==-1))
        return std::pair<int,FT>(0, -d*a); /// x=-d
    return std::pair<int,FT>(-1, 0);
  }

public:

  /**
  * Constructor using `edges(tmesh)` to initialize the
  * internal `AABB_tree`.
  * @param tmesh the triangulated surface mesh to be sliced.
  *              It must be valid and non modified as long
  *              as the functor is used.
  * @param vpmap an instance of the vertex point property map associated to `tmesh`
  * @param traits a traits class instance, can be omitted
  */
  Polygon_mesh_slicer(const TriangleMesh& tmesh,
                      VertexPointMap vpmap,
                      const Traits& traits = Traits())
  : m_tmesh(const_cast<TriangleMesh&>(tmesh))
  , m_vpmap(vpmap)
  , m_traits(traits)
  , m_own_tree(true)
  {
    m_tree_ptr = new AABBTree(edges(m_tmesh).first,
                              edges(m_tmesh).second,
                              m_tmesh,
                              m_vpmap);
  }

  /**
  * Constructor using a pre-built `AABB_tree` of edges provided by the user.
  * @param tmesh the triangulated surface mesh to be sliced.
  *              It must be valid and non modified as long
  *              as the functor is used.
  * @param tree must be initialized with all the edges of `tmesh`
  * @param vpmap an instance of the vertex point property map associated to `tmesh`
  * @param traits a traits class instance, can be omitted
  */
  Polygon_mesh_slicer(const TriangleMesh& tmesh,
                      const AABBTree& tree,
                      VertexPointMap vpmap,
                      const Traits& traits = Traits())
    : m_tree_ptr(&tree)
    , m_tmesh(const_cast<TriangleMesh&>(tmesh))
    , m_vpmap(vpmap)
    , m_traits(traits)
    , m_own_tree(false)
  { }

  /**
  * Constructor using `edges(tmesh)` to initialize the
  * internal `AABB_tree`. The vertex point property map used
  * is `get(CGAL::vertex_point, tmesh)`
  * @param tmesh the triangulated surface mesh to be sliced.
  *              It must be valid and non modified as long
  *              as the functor is used.
  * @param traits a traits class instance, can be omitted
  */
  Polygon_mesh_slicer(const TriangleMesh& tmesh,
                      const Traits& traits = Traits())
  : m_tmesh(const_cast<TriangleMesh&>(tmesh))
  , m_vpmap(get(boost::vertex_point, m_tmesh))
  , m_traits(traits)
  , m_own_tree(true)
  {
    m_tree_ptr = new AABBTree(edges(m_tmesh).first,
                              edges(m_tmesh).second,
                              m_tmesh,
                              m_vpmap);
  }

  /**
  * Constructor using a `AABB_tree` provided by the user.
  * The vertex point property map used is `get(CGAL::vertex_point, tmesh)`
  * @param tmesh the triangulated surface mesh to be sliced.
  *              It must be valid and non modified as long
  *              as the functor is used.
  * @param tree must be initialized with all the edges of `tmesh`
  * @param traits a traits class instance, can be omitted
  */
  Polygon_mesh_slicer(const TriangleMesh& tmesh,
                      const AABBTree& tree,
                      const Traits& traits = Traits())
    : m_tree_ptr(&tree)
    , m_tmesh(const_cast<TriangleMesh&>(tmesh))
    , m_vpmap(get(boost::vertex_point, m_tmesh))
    , m_traits(traits)
    , m_own_tree(false)
  { }

  /**
   * Constructs the intersecting polylines of `plane` with the input triangulated surface mesh.
   * @tparam OutputIterator an output iterator accepting polylines.
   *              A polyline is provided as `std::vector<Traits::Point_3>`.
   *              A polyline is closed if its first and last point are identical.
   * @param plane the plane to intersect the triangulated surface mesh with
   * @param out output iterator of polylines
   */
  template <class OutputIterator>
  OutputIterator operator() (const Plane_3& plane,
                             OutputIterator out) const
  {
    CGAL_precondition(!plane.is_degenerate());

    // containers for storing edges wrt their position with the plane
    std::set<edge_descriptor> all_coplanar_edges;
    std::vector<edge_descriptor> iedges;
    Vertices_map vertices;

    // get all edges intersected by the plane and classify them

    std::pair<int, FT> app_info = axis_parallel_plane_info(plane);
    if (!UseParallelPlaneOptimization || app_info.first==-1)
    {
      General_traversal_traits ttraits(
        all_coplanar_edges,
        iedges,
        vertices,
        m_tmesh,
        m_vpmap,
        m_tree_ptr->traits(),
        m_traits);
      m_tree_ptr->traversal(plane, ttraits);
    }
    else
    {
      Polygon_mesh_slicer_::Axis_parallel_plane_traits<Traits>
        traits(app_info.first, app_info.second, m_traits);

      Axis_parallel_traversal_traits ttraits(
        all_coplanar_edges,
        iedges,
        vertices,
        m_tmesh,
        m_vpmap,
        m_tree_ptr->traits(),
        traits);
      m_tree_ptr->traversal(plane, ttraits);
    }

    // init output graph
    AL_graph al_graph;

    // add nodes for each vertex in the plane
    BOOST_FOREACH(Vertex_pair& vdp, vertices)
    {
      vdp.second=add_vertex(al_graph);
      al_graph[vdp.second]=vdp.first;
    }

    Compare_face less_face(m_tmesh);
    AL_edge_map al_edge_map( less_face );

    // Filter coplanar edges: we consider only coplanar edges incident to one non-coplanar facet
    //   for each such edge, add the corresponding nodes in the adjacency-list graph as well as
    //   the edge
    BOOST_FOREACH(const edge_descriptor ed, all_coplanar_edges)
    {
      if (  face(halfedge(ed, m_tmesh), m_tmesh)==graph_traits::null_face() ||
            opposite_face(ed)==graph_traits::null_face()  ||
            !all_coplanar_edges.count( next_edge(ed) ) ||
            !all_coplanar_edges.count( next_of_opposite_edge(ed) ) )
      {
        typename Vertices_map::iterator it_insert1, it_insert2;
        bool is_new;

        // Each coplanar edge is connecting two nodes
        //  handle source
        cpp11::tie(it_insert1, is_new) =
          vertices.insert(
              Vertex_pair(
                source(ed,m_tmesh), AL_graph::null_vertex()
              )
          );
        if (is_new)
        {
          it_insert1->second=add_vertex(al_graph);
          al_graph[it_insert1->second]=it_insert1->first;
        }
        //  handle target
        cpp11::tie(it_insert2, is_new) =
          vertices.insert(
              Vertex_pair(
                target(ed,m_tmesh), AL_graph::null_vertex()
              )
          );
        if (is_new)
        {
          it_insert2->second=add_vertex(al_graph);
          al_graph[it_insert2->second]=it_insert2->first;
        }
        // add the edge into the adjacency-list graph
        CGAL_assertion( it_insert1->second!=AL_graph::null_vertex() );
        CGAL_assertion( it_insert2->second!=AL_graph::null_vertex() );
        add_edge(it_insert1->second, it_insert2->second, al_graph);
      }
    }

    // for each edge intersected in its interior, creates a node in
    // an adjacency-list graph and put an edge between two such nodes
    // when the corresponding edges shares a common face
    BOOST_FOREACH(edge_descriptor ed, iedges)
    {
      AL_vertex_descriptor vd=add_vertex(al_graph);
      al_graph[vd]=ed;
      update_al_graph_connectivity(ed, vd, al_edge_map, al_graph);
    }

    // If one of the node above is not connected in its two incident faces
    // then it must be connected to a vertex (including those in the set
    // of coplanar edges)
    typedef std::pair<halfedge_descriptor, AL_vertex_pair> Halfedge_and_vertices;
    BOOST_FOREACH(Halfedge_and_vertices hnv,al_edge_map)
    {
      if (hnv.second.second==AL_graph::null_vertex())
      {
        //get the edge and test opposite vertices (if the edge is not on the boundary)
        vertex_descriptor vd = target( next(hnv.first, m_tmesh), m_tmesh);
        typename Vertices_map::iterator itv=vertices.find(vd);
        CGAL_assertion( itv!=vertices.end() );
        add_edge(itv->second, hnv.second.first, al_graph);
      }
    }

    CGAL_assertion(num_vertices(al_graph)==iedges.size()+vertices.size());

    // now assemble the edges of al_graph to define polylines,
    // putting them in the output iterator
    if (!UseParallelPlaneOptimization || app_info.first==-1)
    {
      Polyline_visitor<OutputIterator, Traits> visitor(m_tmesh, al_graph, plane, m_vpmap, m_traits, out);
      split_graph_into_polylines(al_graph, visitor);
      return visitor.out;
    }
    else
    {
      typedef Polygon_mesh_slicer_::Axis_parallel_plane_traits<Traits> App_traits;
      App_traits app_traits(app_info.first, app_info.second, m_traits);

      Polyline_visitor<OutputIterator, App_traits> visitor
        (m_tmesh, al_graph, plane, m_vpmap, app_traits, out);
      split_graph_into_polylines(al_graph, visitor);
      return visitor.out;
    }
  }

  ~Polygon_mesh_slicer()
  {
    if (m_own_tree) delete m_tree_ptr;
  }
};

}// end of namespace CGAL
#endif //CGAL_POLYGON_MESH_SLICER_H