1 // Copyright (c) 2012-2016 GeometryFactory Sarl (France).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Mesh_3/include/CGAL/Mesh_3/experimental/Facet_topological_criterion_with_adjacency.h $
7 // $Id: Facet_topological_criterion_with_adjacency.h 58b10a3 2020-03-26T18:58:50+01:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 // Author(s)     : Laurent Rineau
11 
12 #ifndef CGAL_MESH_3_FACET_TOPOLOGICAL_CRITERION_WITH_ADJACENCY_H
13 #define CGAL_MESH_3_FACET_TOPOLOGICAL_CRITERION_WITH_ADJACENCY_H
14 
15 #include <CGAL/license/Mesh_3.h>
16 
17 #include <CGAL/Mesh_3/mesh_standard_criteria.h>
18 #include <CGAL/number_utils.h>
19 #include <CGAL/array.h>
20 
21 namespace CGAL {
22 
23 namespace Mesh_3 {
24 
25 template <typename Tr, typename MeshDomain, typename Visitor_>
26 class Facet_topological_criterion_with_adjacency :
27 public Mesh_3::Abstract_criterion<Tr, Visitor_>
28 {
29 private:
30   typedef typename Tr::Facet Facet;
31 
32   typedef Mesh_3::Abstract_criterion<Tr,Visitor_> Base;
33   typedef typename Base::Quality Quality;
34   typedef typename Base::Is_bad  Is_bad;
35 
36   typedef Facet_topological_criterion_with_adjacency<Tr,MeshDomain, Visitor_> Self;
37 
38   typedef typename Tr::Geom_traits::FT FT;
39 
40   const MeshDomain* domain;
41 
42 public:
43   /// Constructor
Facet_topological_criterion_with_adjacency(const MeshDomain * domain)44   Facet_topological_criterion_with_adjacency(const MeshDomain* domain)
45     : domain(domain)
46   {}
47 
48   /// Destructor
~Facet_topological_criterion_with_adjacency()49   virtual ~Facet_topological_criterion_with_adjacency() {}
50 
51 protected:
do_accept(Visitor_ & v)52   virtual void do_accept(Visitor_& v) const
53   {
54     v.visit(*this);
55   }
56 
do_clone()57   virtual Self* do_clone() const
58   {
59     // Call copy ctor on this
60     return new Self(*this);
61   }
62 
do_is_bad(const Tr &,const Facet & f)63   virtual Is_bad do_is_bad (const Tr& /*tr*/, const Facet& f) const
64   {
65     typedef typename Tr::Vertex_handle  Vertex_handle;
66     typedef typename Tr::Cell_handle    Cell_handle;
67 
68     const Cell_handle& ch = f.first;
69     const int& i = f.second;
70 
71     typedef typename MeshDomain::Surface_patch_index Patch_index;
72 
73     const Patch_index patch_index = ch->surface_patch_index(i);
74 
75     typedef std::vector<Patch_index> Index_set;
76 
77     int nb_vertices_on_curves = 0;
78 
79     for(int k = 0; k < 3; ++k) {
80       const Vertex_handle v = ch->vertex((i+k+1)&3);
81       switch(v->in_dimension()) {
82       case 0:
83         {
84           ++nb_vertices_on_curves; // corners are on curves
85           const typename MeshDomain::Corner_index corner_id =
86             domain->corner_index(v->index());
87 
88           Index_set set;
89           domain->get_corner_incidences(corner_id, std::back_inserter(set));
90           if(std::find(set.begin(), set.end(), patch_index) == set.end()) {
91 #ifdef CGAL_MESH_3_DEBUG_FACET_CRITERIA
92             std::cerr << "Bad facet "
93                          "(Facet_topological_criterion_with_adjacency: corner #"
94                       << corner_id << ", point " << v->point()
95                       << ", is not incident to patch #" << patch_index << ")"
96                       << std::endl;
97 #endif
98             return Is_bad(Quality(1)); // bad!
99           }
100         }
101         break;
102       case 1:
103         {
104           ++nb_vertices_on_curves;
105           const typename MeshDomain::Curve_index curve_id =
106             domain->curve_index(v->index());
107           Index_set set;
108           domain->get_incidences(curve_id, std::back_inserter(set));
109           if(std::find(set.begin(), set.end(), patch_index) == set.end()) {
110 #ifdef CGAL_MESH_3_DEBUG_FACET_CRITERIA
111             std::cerr << "Bad facet "
112                          "(Facet_topological_criterion_with_adjacency: curve #"
113                       << curve_id << ", at point " << v->point()
114                       << ", is not incident to patch #" << patch_index << ")"
115                       << std::endl;
116 #endif
117             return Is_bad(Quality(1)); // bad!
118           }
119         }
120         break;
121       case 2:
122         if(domain->surface_patch_index(v->index()) != patch_index) {
123 #ifdef CGAL_MESH_3_DEBUG_FACET_CRITERIA
124           std::cerr << "Bad facet (Facet_topological_criterion_with_adjacency: "
125                        "vertex at point "
126                     << v->point() << " is not on patch #" << patch_index << ")"
127                     << std::endl;
128 #endif
129           return Is_bad(Quality(1)); // bad!
130         }
131         break;
132       default:
133         return Is_bad(Quality(1));
134         break;
135       }
136     }
137     if(nb_vertices_on_curves == 3) {
138 #ifdef CGAL_MESH_3_DEBUG_FACET_CRITERIA
139       std::cerr << "Bad facet (Facet_topological_criterion_with_adjacency: "
140                    "three points on a curve)\n";
141 #endif
142       return Is_bad(Quality(1)); // bad!
143       // All vertices are on curves. That means that the facet could be on
144       // several different patches. Let's disallow that.
145     }
146     return Is_bad();
147   }
148 }; // end class Facet_topological_criterion_with_adjacency
149 
150 } // end namespace Mesh_3
151 
152 } // end namespace CGAL
153 
154 #endif // CGAL_MESH_3_FACET_TOPOLOGICAL_CRITERION_WITH_ADJACENCY_H
155