EMODnet Quantized Mesh Generator for Cesium
zoom_tiles_scheduler.h
1 // Copyright (c) 2018 Coronis Computing S.L. (Spain)
2 // All rights reserved.
3 //
4 // This file is part of EMODnet Quantized Mesh Generator for Cesium.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 //
19 // Author: Ricard Campos (ricardcd@gmail.com)
20 
21 #ifndef EMODNET_QMGC_ZOOM_SCHEDULER_H
22 #define EMODNET_QMGC_ZOOM_SCHEDULER_H
23 
24 #include <ctb.hpp>
25 
41 {
42 public:
43  ZoomTilesSchedulerStrategy() : m_index(0), m_tilesToProcess() {}
44 
45  virtual void initSchedule(const ctb::TileBounds& zoomBounds) = 0 ;
46 
47  // The root is only composed of two tiles... and should be always present regardless of the computed zoom bounds
48  void initRootSchedule() {
49  m_index = 0;
50  m_tilesToProcess.clear();
51  m_tilesToProcess.emplace_back(ctb::TilePoint(0,0));
52  m_tilesToProcess.emplace_back(ctb::TilePoint(1,0));
53  }
54 
56  ctb::TilePoint getNextTile() {
57  if ( finished() )
58  return ctb::TilePoint(0,0) ; // dummy, should never happen
59  ctb::TilePoint tp = m_tilesToProcess[m_index] ;
60  m_index++ ;
61  return tp ;
62  }
63 
65  int numTiles() { return m_tilesToProcess.size() ; }
66 
68  int currentIndex() { return m_index ; }
69 
71  bool finished() { return m_index >= m_tilesToProcess.size() ; }
72 
73 protected:
74  int m_index ;
75  std::vector<ctb::TilePoint> m_tilesToProcess ;
76 };
77 
78 
79 
85 {
86 public:
89 
91  ZoomTilesScheduler( std::shared_ptr<ZoomTilesSchedulerStrategy> scheduler ) { m_scheduler = scheduler ;}
92 
94  void setScheduler(std::shared_ptr<ZoomTilesSchedulerStrategy> scheduler ) { m_scheduler = scheduler ;}
95 
97  void initSchedule(const ctb::TileBounds& zoomBounds) { m_scheduler->initSchedule(zoomBounds) ; }
98 
99  void initRootSchedule() { m_scheduler->initRootSchedule(); }
100 
101  ctb::TilePoint getNextTile() { return m_scheduler->getNextTile(); }
102  bool finished() { return m_scheduler->finished(); }
103  int numTiles() { return m_scheduler->numTiles(); }
104  int currentIndex() { return m_scheduler->currentIndex(); }
105 
106 private:
107  std::shared_ptr<ZoomTilesSchedulerStrategy> m_scheduler ;
108 };
109 
110 // --- Concrete strategies ---
111 
119 {
120 public:
122  void initSchedule(const ctb::TileBounds& zoomBounds)
123  {
124  m_index = 0 ;
125  m_tilesToProcess.clear() ;
126  for (int ty = zoomBounds.getMinY(); ty <= zoomBounds.getMaxY(); ty++) {
127  for (int tx = zoomBounds.getMinX(); tx <= zoomBounds.getMaxX(); tx++) {
128  m_tilesToProcess.push_back(ctb::TilePoint(tx, ty));
129  }
130  }
131  }
132 };
133 
134 
135 
143 {
144 public:
146  void initSchedule(const ctb::TileBounds& zoomBounds)
147  {
148  m_index = 0 ;
149  m_tilesToProcess.clear() ;
150  for (int tx = zoomBounds.getMinX(); tx <= zoomBounds.getMaxX(); tx++) {
151  for (int ty = zoomBounds.getMinY(); ty <= zoomBounds.getMaxY(); ty++) {
152  m_tilesToProcess.push_back(ctb::TilePoint(tx, ty));
153  }
154  }
155  }
156 };
157 
158 
159 
169 {
170 public:
172  void initSchedule(const ctb::TileBounds& zoomBounds)
173  {
174  m_index = 0 ;
175  m_tilesToProcess.clear() ;
176  for (int ty = zoomBounds.getMinY(); ty <= zoomBounds.getMaxY(); ty++) {
177  if ( ty%2 == 0 ) {
178  for (int tx = zoomBounds.getMinX(); tx <= zoomBounds.getMaxX(); tx+=2) {
179  m_tilesToProcess.push_back(ctb::TilePoint(tx, ty));
180  }
181  }
182  else {
183  for (int tx = zoomBounds.getMinX()+1; tx <= zoomBounds.getMaxX(); tx+=2) {
184  m_tilesToProcess.push_back(ctb::TilePoint(tx, ty));
185  }
186  }
187  }
188 
189  for (int ty = zoomBounds.getMinY(); ty <= zoomBounds.getMaxY(); ty++) {
190  if ( ty%2 == 0 ) {
191  for (int tx = zoomBounds.getMinX()+1; tx <= zoomBounds.getMaxX(); tx+=2) {
192  m_tilesToProcess.push_back(ctb::TilePoint(tx, ty));
193  }
194  }
195  else {
196  for (int tx = zoomBounds.getMinX(); tx <= zoomBounds.getMaxX(); tx+=2) {
197  m_tilesToProcess.push_back(ctb::TilePoint(tx, ty));
198  }
199  }
200  }
201  }
202 };
203 
204 
212 {
213 public:
214  typedef std::vector<std::vector<bool>> VisitedMatrix ;
215 
217  void initSchedule(const ctb::TileBounds& zoomBounds)
218  {
219  m_index = 0 ;
220  m_tilesToProcess.clear() ;
221 
222  unsigned int rows = zoomBounds.getMaxY()-zoomBounds.getMinY()+1 ;
223  unsigned int cols = zoomBounds.getMaxX()-zoomBounds.getMinX()+1 ;
224 
225  VisitedMatrix visited;
226  visited.resize(rows);
227 
228  for(int i=0; i < rows; i++)
229  {
230  visited[i].resize(cols) ;
231  for(int j=0; j < cols; j++)
232  visited[i][j] = false ;
233  }
234 
235  unsigned int midY = zoomBounds.getMinY() + ( (zoomBounds.getMaxY()-zoomBounds.getMinY())/2 ) ;
236  unsigned int midX = zoomBounds.getMinX() + ( (zoomBounds.getMaxX()-zoomBounds.getMinX())/2 ) ;
237 
238  recursiveAddTiles( midX, midY, zoomBounds, visited ) ;
239  }
240 
241 private:
242  void recursiveAddTiles(const int& tx, const int& ty, const ctb::TileBounds& zoomBounds, VisitedMatrix& visited ) {
243  if ( inBounds( tx, ty, zoomBounds ) ) {
244  m_tilesToProcess.push_back(ctb::TilePoint(tx, ty)) ;
245 
246  int txx = tx-zoomBounds.getMinX() ;
247  int tyy = ty-zoomBounds.getMinY() ;
248 
249  visited[tyy][txx] = true ;
250  // Recurse up
251  if ( inBounds(tx+1, ty, zoomBounds) && !visited[tyy][txx+1] )
252  recursiveAddTiles(tx+1, ty, zoomBounds, visited ) ;
253  // Recurse down
254  if ( inBounds(tx-1, ty, zoomBounds) && !visited[tyy][txx-1] )
255  recursiveAddTiles(tx-1, ty, zoomBounds, visited ) ;
256  // Recurse left
257  if ( inBounds(tx, ty-1, zoomBounds) && !visited[tyy-1][txx] )
258  recursiveAddTiles(tx, ty-1, zoomBounds, visited ) ;
259  // Recurse right
260  if ( inBounds(tx, ty+1, zoomBounds) && !visited[tyy+1][txx] )
261  recursiveAddTiles(tx, ty+1, zoomBounds, visited ) ;
262  }
263  }
264 
265  bool inBounds( const int& tx, const int& ty, const ctb::TileBounds& zoomBounds ) const {
266  return tx <= zoomBounds.getMaxX() && tx >= zoomBounds.getMinX() &&
267  ty <= zoomBounds.getMaxY() && ty >= zoomBounds.getMinY() ;
268  }
269 };
270 
271 #include <queue>
272 
273 
281 {
282 public:
283  typedef std::vector<std::vector<bool>> VisitedMatrix ;
284 
286  void initSchedule(const ctb::TileBounds& zoomBounds)
287  {
288  m_index = 0 ;
289  m_tilesToProcess.clear() ;
290 
291  // Initialize the "visited" matrix
292  unsigned int rows = zoomBounds.getMaxY()-zoomBounds.getMinY()+1 ;
293  unsigned int cols = zoomBounds.getMaxX()-zoomBounds.getMinX()+1 ;
294 
295  VisitedMatrix visited;
296  visited.resize(rows);
297 
298  for(int i=0; i < rows; i++)
299  {
300  visited[i].resize(cols) ;
301  for(int j=0; j < cols; j++)
302  visited[i][j] = false ;
303  }
304 
305  // Middle point
306  unsigned int midY = zoomBounds.getMinY() + ( (zoomBounds.getMaxY()-zoomBounds.getMinY())/2 ) ;
307  unsigned int midX = zoomBounds.getMinX() + ( (zoomBounds.getMaxX()-zoomBounds.getMinX())/2 ) ;
308  ctb::TilePoint midPt( midX, midY ) ;
309 
310  // Init the queue with the middle point
311  std::queue<ctb::TilePoint> queue ;
312  queue.push(midPt) ;
313 
314  while (!queue.empty()) {
315  // Pop the next value on the queue
316  ctb::TilePoint tp = queue.front() ;
317  queue.pop() ;
318 
319  int tx = tp.x ;
320  int ty = tp.y ;
321  int txx = tx-zoomBounds.getMinX() ;
322  int tyy = ty-zoomBounds.getMinY() ;
323 
324  if (!visited[tyy][txx]) {
325  // Add the tile if not visited
326  m_tilesToProcess.push_back(tp) ;
327  visited[tyy][txx] = true ;
328 
329  // Visit up
330  if ( inBounds(tx+1, ty, zoomBounds) && !visited[tyy][txx+1] )
331  queue.push(ctb::TilePoint(tx+1, ty)) ;
332  // Visit down
333  if ( inBounds(tx-1, ty, zoomBounds) && !visited[tyy][txx-1] )
334  queue.push(ctb::TilePoint(tx-1, ty)) ;
335  // Visit left
336  if ( inBounds(tx, ty-1, zoomBounds) && !visited[tyy-1][txx] )
337  queue.push(ctb::TilePoint(tx, ty-1)) ;
338  // Visit right
339  if ( inBounds(tx, ty+1, zoomBounds) && !visited[tyy+1][txx] )
340  queue.push(ctb::TilePoint(tx, ty+1)) ;
341  }
342  }
343  }
344 
345 private:
346  bool inBounds( const int& tx, const int& ty, const ctb::TileBounds& zoomBounds ) const {
347  return tx <= zoomBounds.getMaxX() && tx >= zoomBounds.getMinX() &&
348  ty <= zoomBounds.getMaxY() && ty >= zoomBounds.getMinY() ;
349  }
350 };
351 
352 #endif //EMODNET_QMGC_ZOOM_SCHEDULER_H
void initSchedule(const ctb::TileBounds &zoomBounds)
Replication of the ZoomTilesSchedulerBase interphase.
Definition: zoom_tiles_scheduler.h:97
Row-wise scheduler.
Definition: zoom_tiles_scheduler.h:118
Chessboard scheduler.
Definition: zoom_tiles_scheduler.h:168
void initSchedule(const ctb::TileBounds &zoomBounds)
Initialize the schedule given the zoom bounds.
Definition: zoom_tiles_scheduler.h:217
Context class: Allows to change the algorithm at runtime.
Definition: zoom_tiles_scheduler.h:84
void initSchedule(const ctb::TileBounds &zoomBounds)
Initialize the schedule given the zoom bounds.
Definition: zoom_tiles_scheduler.h:286
ZoomTilesScheduler()
Default constructor (remember to set the strategy with setScheduler!)
Definition: zoom_tiles_scheduler.h:88
int numTiles()
Number of tiles in the schedule.
Definition: zoom_tiles_scheduler.h:65
An instance of a ZoomTilesSchedulerStrategy rules the desired order at which tiles in a given zoom sh...
Definition: zoom_tiles_scheduler.h:40
Recursive scheduler.
Definition: zoom_tiles_scheduler.h:280
Recursive scheduler.
Definition: zoom_tiles_scheduler.h:211
Column-wise scheduler.
Definition: zoom_tiles_scheduler.h:142
bool finished()
Marks if the current schedule is finished.
Definition: zoom_tiles_scheduler.h:71
void initSchedule(const ctb::TileBounds &zoomBounds)
Initialize the schedule given the zoom bounds.
Definition: zoom_tiles_scheduler.h:172
void initSchedule(const ctb::TileBounds &zoomBounds)
Initialize the schedule given the zoom bounds.
Definition: zoom_tiles_scheduler.h:146
void setScheduler(std::shared_ptr< ZoomTilesSchedulerStrategy > scheduler)
Allows to change the scheduler algorithm at runtime.
Definition: zoom_tiles_scheduler.h:94
ZoomTilesScheduler(std::shared_ptr< ZoomTilesSchedulerStrategy > scheduler)
Constructor from an scheduler strategy.
Definition: zoom_tiles_scheduler.h:91
ctb::TilePoint getNextTile()
Get the next tile to process.
Definition: zoom_tiles_scheduler.h:56
void initSchedule(const ctb::TileBounds &zoomBounds)
Initialize the schedule given the zoom bounds.
Definition: zoom_tiles_scheduler.h:122
int currentIndex()
The current index in the schedule.
Definition: zoom_tiles_scheduler.h:68