DGtal  1.0.0
ParDirCollapse.ih
1 /**
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as
4  * published by the Free Software Foundation, either version 3 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  **/
16 
17 /**
18  * @file ParDirCollapse.ih
19  * @author Bibiana MARTINEZ (\c bibiana.martinez@edu.esiee.fr )
20  * @author Mohamad ONAYSSI (\c mohamad.onayssi@edu.esiee.fr )
21  * @author Mohamed MELLOULI (\c mohamed.mellouli@edu.esiee.fr )
22  * ESIEE Paris
23  *
24  * @author Kacper Pluta (\c kacper.pluta@esiee.fr )
25  * Laboratoire d'Informatique Gaspard-Monge - LIGM, France
26  *
27  *
28  * @date 2015/12/22
29  *
30  *
31  * This file is part of the DGtal library.
32  */
33 
34 #include <vector>
35 #include <stdexcept>
36 
37 ///////////////////////////////////////////////////////////////////////////////
38 // Implementation of inline methods //
39 
40 template < typename CC >
41 inline
42 DGtal::ParDirCollapse<CC >::ParDirCollapse( const KSpace & k ) : K ( k )
43 {
44  complex = nullptr;
45 }
46 
47 template < typename CC >
48 inline
49 bool
50 DGtal::ParDirCollapse< CC >::isValid ( ) const
51 {
52  return complex != nullptr;
53 }
54 
55 template < typename CC >
56 inline
57 void
58 DGtal::ParDirCollapse< CC >::attach ( Alias<CC> pComplex )
59 {
60  complex = &pComplex;
61 }
62 
63 template < typename CC >
64 inline
65 unsigned int
66 DGtal::ParDirCollapse< CC >::eval ( unsigned int iterations )
67 {
68  assert ( isValid() );
69  std::vector<Cell> SUB;
70  unsigned int collapseval = 0;
71  unsigned int removed = 1;
72  typename CC::DefaultCellMapIteratorPriority P;
73  for ( unsigned int i = 0; i < iterations && removed > 0; i++ )
74  {
75  CC boundary = complex->boundary();
76  unsigned int priority = 0;
77  for ( Dimension dir = 0; dir < K.dimension; dir++ )
78  {
79  for ( int orient = -1 ; orient <= 1; orient += 2 )
80  {
81  for ( int dim = K.dimension - 1; dim >= 0; dim-- )
82  {
83  for ( CellMapConstIterator begin = boundary.begin ( dim ); begin != boundary.end ( dim ); ++begin, priority++ )
84  {
85  if ( K.uDim ( begin->first ) == (unsigned int) dim )
86  {
87  Cell G;
88  if ( completeFreepair ( begin, G, orient, dir ) )
89  {
90  SUB.push_back ( G );
91  complex->insertCell ( SUB.back(), priority );
92  SUB.push_back ( begin->first );
93  complex->insertCell ( SUB.back(), priority );
94  }
95  }
96  }
97  removed = DGtal::functions::collapse ( *complex, SUB.begin(), SUB.end(), P, true, true, true );
98  SUB.clear();
99  priority = 0;
100  collapseval += removed;
101  }
102  }
103  }
104  }
105  return collapseval;
106 }
107 
108 template < typename CC >
109 inline
110 bool
111 DGtal::ParDirCollapse< CC >::completeFreepair ( CellMapConstIterator F, Cell & G, int orient, int dir )
112 {
113  if ( F->second.data == CC::FIXED )
114  return false;
115  Cells faces = K.uUpperIncident ( F->first );
116  Dimension dim = K.uDim ( F->first ) + 1;
117  for ( Size j = 0; j < faces.size(); j++ )
118  {
119  if ( complex->findCell ( dim, faces[j] ) != complex->end ( dim ) )
120  {
121  if ( getOrientation ( (*F).first, faces[j] ) == orient && getDirection ( (*F).first, faces[j] ) == dir )
122  {
123  CellMapConstIterator cmIt = complex->findCell ( dim, faces[j] );
124  if ( cmIt->second.data != CC::FIXED )
125  {
126  G = faces[j];
127  return true;
128  }
129  else
130  return false;
131  }
132  }
133  }
134  return false;
135 }
136 
137 template < typename CC >
138 inline
139 int
140 DGtal::ParDirCollapse< CC >::getOrientation( const Cell& F, const Cell& G ) const
141 {
142  Point V = K.uKCoords ( F ) - K.uKCoords ( G );
143  for ( Dimension i = 0; i < K.dimension; i++ )
144  if ( V[i] != 0 ) return V[i];
145  throw std::runtime_error ( "Cells F and G are same!" );
146 }
147 
148 template < typename CC >
149 inline
150 int
151 DGtal::ParDirCollapse< CC >::getDirection ( const Cell& F, const Cell& G ) const
152 {
153  Point V = K.uKCoords ( F ) - K.uKCoords ( G );
154  for ( Dimension i = 0; i< K.dimension; i++ )
155  if ( V[i] != 0 ) return i;
156  throw std::runtime_error ( "Cells F and G are same!" );
157 }
158 
159 template < typename CC >
160 inline
161 void
162 DGtal::ParDirCollapse< CC >::collapseSurface()
163 {
164  while ( eval ( 1 ) )
165  {
166  CellMapConstIterator constIterator = complex->begin ( K.dimension - 1 );
167  CellMapConstIterator itEd = complex->end ( K.dimension - 1 );
168  for ( ; constIterator != itEd; ++constIterator )
169  if ( isNotIncludedInUpperDim ( constIterator ) )
170  complex->insertCell ( constIterator->first, CC::FIXED );
171  }
172 }
173 
174 template < typename CC >
175 inline
176 void
177 DGtal::ParDirCollapse< CC >::collapseIsthmus()
178 {
179  while ( eval ( 1 ) )
180  {
181  CellMapConstIterator constIterator = complex->begin ( K.dimension - 1 );
182  CellMapConstIterator itEd = complex->end ( K.dimension - 1 );
183  for ( ; constIterator != itEd; ++constIterator )
184  if ( isNotIncludedInUpperDim ( constIterator ) && isIsthmus ( constIterator ) )
185  complex->insertCell ( constIterator->first, CC::FIXED );
186  }
187 }
188 
189 template < typename CC >
190 inline
191 bool
192 DGtal::ParDirCollapse< CC >::isNotIncludedInUpperDim ( CellMapConstIterator F )
193 {
194  Cells faces = K.uUpperIncident ( F->first );
195  Dimension dim = K.uDim ( F->first ) + 1;
196  for ( Size i = 0; i < faces.size(); i++ )
197  if ( complex->findCell ( dim, faces[i] ) != complex->end ( dim ) )
198  return false;
199  return true;
200 }
201 
202 template < typename CC >
203 inline
204 bool
205 DGtal::ParDirCollapse< CC >::isIsthmus ( CellMapConstIterator F )
206 {
207  Cells faces = K.uLowerIncident ( F->first );
208  for ( Size i = 0; i < faces.size(); i++ )
209  {
210  int count = 0;
211  if ( K.uDim ( faces[i] ) == K.dimension - 2 )
212  {
213  Cells facesUpper = K.uUpperIncident ( faces[i] );
214  for ( Size j = 0; j < facesUpper.size(); j++ )
215  if ( complex->findCell ( K.dimension - 1, facesUpper[j] ) != complex->end ( K.dimension - 1 ) )
216  count++;
217  if ( count <= 1 )
218  return false;
219  }
220  }
221  return true;
222 }
223 
224 // //
225 ///////////////////////////////////////////////////////////////////////////////