DGtal  1.5.beta
NeighborhoodConvexityAnalyzer.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 NeighborhoodConvexityAnalyzer.ih
19  * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20  * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
21  *
22  * @date 2021/06/16
23  *
24  * Implementation of inline methods defined in NeighborhoodConvexityAnalyzer.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 
30 //////////////////////////////////////////////////////////////////////////////
31 #include <cstdlib>
32 //////////////////////////////////////////////////////////////////////////////
33 
34 //-----------------------------------------------------------------------------
35 template < typename TKSpace, int K >
36 template < typename PointPredicate >
37 void
38 DGtal::NeighborhoodConvexityAnalyzer<TKSpace,K>::
39 setCenter( Point c, const PointPredicate& X )
40 {
41  ASSERT( myDomain.isInside( c ) );
42  myCenter = c;
43  myNbInX = 0;
44  myComputations = 0;
45  myResults = 0;
46  Domain local_domain( c - Point::diagonal( radius() ),
47  c + Point::diagonal( radius() ) );
48  Size bit = 0;
49  myCfgX.reset();
50  for ( auto q : local_domain )
51  {
52  if ( q == c )
53  {
54  myCenterInX = X( q );
55  }
56  else if ( myDomain.isInside( q ) )
57  {
58  if ( X( q ) )
59  {
60  myCfgX.set( bit );
61  ++myNbInX;
62  }
63  }
64  bit += 1;
65  }
66  myBasicCfgX.clear();
67  computeBasicConfigurations( myCfgX, myBasicCfgX );
68 }
69 
70 //-----------------------------------------------------------------------------
71 template < typename TKSpace, int K >
72 void
73 DGtal::NeighborhoodConvexityAnalyzer<TKSpace,K>::
74 getLocalX( std::vector< Point >& localX, bool with_center ) const
75 {
76  Domain local_domain( myCenter - Point::diagonal( radius() ),
77  myCenter + Point::diagonal( radius() ) );
78  Size bit = 0;
79  for ( auto q : local_domain )
80  {
81  if ( q == myCenter ) {
82  if ( with_center )
83  localX.push_back( myCenter );
84  } else if ( myDomain.isInside( q ) ) {
85  if ( myCfgX.test( bit ) )
86  localX.push_back( q );
87  }
88  ++bit;
89  }
90 }
91 //-----------------------------------------------------------------------------
92 template < typename TKSpace, int K >
93 void
94 DGtal::NeighborhoodConvexityAnalyzer<TKSpace,K>::
95 getLocalCompX( std::vector< Point >& localCompX, bool with_center ) const
96 {
97  Domain local_domain( myCenter - Point::diagonal( radius() ),
98  myCenter + Point::diagonal( radius() ) );
99  Size bit = 0;
100  for ( auto q : local_domain )
101  {
102  if ( q == myCenter ) {
103  if ( with_center )
104  localCompX.push_back( myCenter );
105  } else if ( myDomain.isInside( q ) ) {
106  if ( ! myCfgX.test( bit ) )
107  localCompX.push_back( q );
108  }
109  ++bit;
110  }
111 }
112 
113 //-----------------------------------------------------------------------------
114 template < typename TKSpace, int K >
115 bool
116 DGtal::NeighborhoodConvexityAnalyzer<TKSpace,K>::
117 checkBasicConfigurationsFullConvexity
118 ( bool compX, bool with_center ) const
119 {
120  if ( ! compX )
121  { // shape X
122  const Size mask_center = with_center ? 0x10 : 0;
123  for ( auto cfg : myBasicCfgX )
124  if ( ! myBasicFullConvexityTable[ cfg.to_ulong() | mask_center ] )
125  return false;
126  }
127  else
128  { // complementary of shape X
129  const Size mask_center = with_center ? 0x1ff : 0x1ef;
130  for ( auto cfg : myBasicCfgX )
131  if ( ! myBasicFullConvexityTable[ (~cfg.to_ulong()) & mask_center ] )
132  return false;
133  }
134  return true;
135 }
136 //-----------------------------------------------------------------------------
137 template < typename TKSpace, int K >
138 bool
139 DGtal::NeighborhoodConvexityAnalyzer<TKSpace,K>::
140 checkBasicConfigurations0Convexity
141 ( bool compX, bool with_center ) const
142 {
143  if ( ! compX )
144  { // shape X
145  const Size mask_center = with_center ? 0x10 : 0;
146  for ( auto cfg : myBasicCfgX )
147  if ( ! myBasic0ConvexityTable[ cfg.to_ulong() | mask_center ] )
148  return false;
149  }
150  else
151  { // complementary of shape X
152  const Size mask_center = with_center ? 0x1ff : 0x1ef;
153  for ( auto cfg : myBasicCfgX )
154  if ( ! myBasic0ConvexityTable[ (~cfg.to_ulong()) & mask_center ] )
155  return false;
156  }
157  return true;
158 }
159 //-----------------------------------------------------------------------------
160 template < typename TKSpace, int K >
161 void
162 DGtal::NeighborhoodConvexityAnalyzer<TKSpace,K>::
163 computeBasicConfigurations
164 ( Configuration cfg, std::vector< BasicConfiguration > & result ) const
165 {
166  if ( dimension == 2 ) result.push_back( cfg.to_ulong() );
167  else
168  {
169  for ( Dimension i = 0; i < dimension; i++ )
170  for ( Dimension j = i+1; j < dimension; j++ )
171  result.push_back( computeCentralBasicConfiguration( cfg, i, j ) );
172  }
173 }
174 
175 //-----------------------------------------------------------------------------
176 template < typename TKSpace, int K >
177 typename DGtal::NeighborhoodConvexityAnalyzer<TKSpace,K>::BasicConfiguration
178 DGtal::NeighborhoodConvexityAnalyzer<TKSpace,K>::
179 computeCentralBasicConfiguration
180 ( Configuration cfg, Dimension i, Dimension j ) const
181 {
182  Size incr_i = 1;
183  Size incr_j = 1;
184  for ( Dimension d = 0; d < i; ++d ) { incr_i *= 2*K+1; }
185  for ( Dimension d = 0; d < j; ++d ) { incr_j *= 2*K+1; }
186  BasicConfiguration basic;
187  basic[ 0 ] = cfg[ middle - incr_i - incr_j ];
188  basic[ 1 ] = cfg[ middle - incr_j ];
189  basic[ 2 ] = cfg[ middle + incr_i - incr_j ];
190  basic[ 3 ] = cfg[ middle - incr_i ];
191  basic[ 4 ] = cfg[ middle ];
192  basic[ 5 ] = cfg[ middle + incr_i ];
193  basic[ 6 ] = cfg[ middle - incr_i + incr_j ];
194  basic[ 7 ] = cfg[ middle + incr_j ];
195  basic[ 8 ] = cfg[ middle + incr_i + incr_j ];
196  return basic;
197 }
198 
199 //-----------------------------------------------------------------------------
200 template < typename TKSpace, int K >
201 void
202 DGtal::NeighborhoodConvexityAnalyzer<TKSpace,K>::
203 computeBasicFullConvexityTable()
204 {
205  typedef KhalimskySpaceND< 2, int > K2;
206  typedef K2::Point Point2;
207  typedef K2::Space Z2;
208  typedef DigitalConvexity< K2 > DigConv2;
209  typedef HyperRectDomain< Z2 > Domain2;
210  DigConv2 dconv2( Point2::diagonal( -2 ), Point2::diagonal( 2 ) );
211  Point2 p1 = Point2::diagonal( -1 );
212  Point2 p2 = Point2::diagonal( 1 );
213  Point2 c = Point2::diagonal( 0 );
214  Domain2 domain( p1, p2 );
215  for ( unsigned int cfg = 0; cfg < 512; cfg++ )
216  {
217  // Building a configuration.
218  std::vector< Point2 > X;
219  unsigned int mask = 1;
220  for ( auto it = domain.begin(); it != domain.end(); ++it )
221  {
222  const Point2 p = *it;
223  if ( cfg & mask ) X.push_back( p );
224  mask <<= 1;
225  }
226  myBasicFullConvexityTable[ cfg ] = dconv2.isFullyConvex( X );
227  myBasic0ConvexityTable [ cfg ] = dconv2.is0Convex ( X );
228  }
229 }
230 
231 ///////////////////////////////////////////////////////////////////////////////
232 // Implementation of inline functions //
233 
234 
235 // //
236 ///////////////////////////////////////////////////////////////////////////////