tile_cache.cpp
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // Copyright (c) 2014, Southwest Research Institute® (SwRI®)
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Southwest Research Institute® (SwRI®) nor the
14 // names of its contributors may be used to endorse or promote products
15 // derived from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // *****************************************************************************
29 
31 
32 // C++ standard libraries
33 #include <cmath>
34 #include <cstdlib>
35 #include <algorithm>
36 #include <iostream>
37 #include <exception>
38 
39 // QT libraries
40 #include <QApplication>
41 #include <QEvent>
42 
44 
45 namespace multires_image
46 {
47  TileCache::TileCache(TileSet* tileSet, QGLWidget* widget) :
48  m_tileSet(tileSet),
49  m_widget(widget),
50  m_currentLayer(0),
51  m_currentPosition(0, 0, 0),
52  m_exit(false),
53  m_memorySize(0),
54  m_cacheThread(this),
55  m_freeThread(this),
56  m_renderRequestsLock(QMutex::Recursive),
57  m_renderRequestSetLock(QMutex::Recursive),
58  m_precacheRequestsLock(QMutex::Recursive),
59  m_precacheRequestSetLock(QMutex::Recursive),
60  m_textureLoadedLock(QMutex::Recursive)
61  {
62  connect(this, SIGNAL(SignalLoadTexture(Tile*)),
63  SLOT(LoadTextureSlot(Tile*)), Qt::BlockingQueuedConnection);
64 
65  connect(this, SIGNAL(SignalDeleteTexture(Tile*)),
66  SLOT(DeleteTextureSlot(Tile*)), Qt::BlockingQueuedConnection);
67 
68  m_cacheThread.setPriority(QThread::NormalPriority);
69  m_cacheThread.start();
70 
71  m_freeThread.setPriority(QThread::LowPriority);
72  m_freeThread.start();
73 
74  for (int i = 0; i < m_tileSet->LayerCount(); i++)
75  {
76  m_precacheRequests.push_back(std::queue<Tile*>());
77  }
78  }
79 
81  {
82  m_exit = true;
83  m_cacheThread.wait();
84  m_freeThread.wait();
85  }
86 
88  {
89  tile->LoadTexture();
90  }
91 
93  {
94  tile->UnloadTexture();
95  }
96 
97  void TileCache::Load(Tile* tile)
98  {
99  m_renderRequestsLock.lock();
100  m_renderRequestSetLock.lock();
101 
102  try
103  {
104  if (m_renderRequestSet.count(tile->TileID()) == 0)
105  {
106  m_renderRequests.push(tile);
107  m_renderRequestSet[tile->TileID()] = tile;
108  }
109  }
110  catch(const std::exception& e)
111  {
112  std::cout << "An exception occurred queuing a tile to be cached: " << e.what() << std::endl;
113  }
114 
115  m_renderRequestSetLock.unlock();
116  m_renderRequestsLock.unlock();
117  }
118 
119  void TileCache::Precache(double x, double y)
120  {
121  tf::Point point(x, y, 0);
122  Precache(point);
123  }
124 
125  void TileCache::Precache(const tf::Point& position)
126  {
127  m_currentPosition = position;
128 
129  int sizes[] = {3, 2, 2, 1, 1, 1};
130 
132 
133  for (int i = 1; i <= 5; i++)
134  {
135  int layer = m_currentLayer + i;
136  if (layer < m_tileSet->LayerCount())
137  {
138  PrecacheLayer(layer, m_currentPosition, sizes[i]);
139  }
140 
141  layer = m_currentLayer - i;
142  if (layer >= 0)
143  {
144  PrecacheLayer(layer, m_currentPosition, sizes[i]);
145  }
146  }
147  }
148 
149  void TileCache::PrecacheLayer(int layerNum, const tf::Point& position, int size)
150  {
151  TileSetLayer* layer = m_tileSet->GetLayer(layerNum);
152 
153  int row, column;
154  layer->GetTileIndex(position, row, column);
155 
156  int startRow = std::max(0, row - size);
157  int endRow = std::min(layer->RowCount() - 1, row + size);
158  int startColumn = std::max(0, column - size);
159  int endColumn = std::min(layer->ColumnCount() - 1, column + size);
160 
161  for (int c = startColumn; c <= endColumn; c++)
162  {
163  for (int r = startRow; r <= endRow; r++)
164  {
165  Tile* tile = layer->GetTile(c, r);
166 
167  m_precacheRequestsLock.lock();
169 
170  try
171  {
172  if (m_precacheRequestSet.count(tile->TileID()) == 0)
173  {
174  m_precacheRequests[layerNum].push(tile);
175  m_precacheRequestSet[tile->TileID()] = tile;
176  }
177  }
178  catch (const std::exception& e)
179  {
180  std::cout << "An exception occurred queuing tiles for precaching: " << e.what() << std::endl;
181  }
182 
183  m_precacheRequestSetLock.unlock();
184  m_precacheRequestsLock.unlock();
185  }
186  }
187  }
188 
190  {
191  m_exit = true;
192  }
193 
195  {
196  Q_EMIT SignalLoadTexture(tile);
197 
198  m_memorySize += tile->MemorySize();
200 
201  m_textureLoadedLock.lock();
202 
203  try
204  {
205  m_textureLoaded[tile->TileID()] = tile;
206  }
207  catch (const std::exception& e)
208  {
209  std::cout << "An exception occurred loading texture: " << e.what() << std::endl;
210  }
211 
212  m_textureLoadedLock.unlock();
213 
214  if (tile->Layer() == m_currentLayer)
215  {
216  QApplication::postEvent(m_widget, new QEvent(QEvent::UpdateRequest));
217  }
218  }
219 
221  {
222  Q_EMIT SignalDeleteTexture(tile);
223 
224  m_memorySize -= tile->MemorySize();
226 
227  m_textureLoadedLock.lock();
228 
229  try
230  {
231  m_textureLoaded.erase(tile->TileID());
232  }
233  catch (const std::exception& e)
234  {
235  std::cout << "An exception occurred unloading texture: " << e.what() << std::endl;
236  }
237 
238  m_textureLoadedLock.unlock();
239  }
240 
242  {
243  while (!p->m_exit)
244  {
245  Tile* tile = NULL;
246  p->m_renderRequestsLock.lock();
247 
248  if (p->m_renderRequests.size() > 0)
249  {
250  tile = p->m_renderRequests.top();
251  p->m_renderRequests.pop();
252  }
253 
254  p->m_renderRequestsLock.unlock();
255 
256  if (tile != NULL)
257  {
258  if (!tile->Failed())
259  {
260  if (tile->Layer() == p->m_currentLayer)
261  {
262  int row, column;
263  p->m_tileSet->GetLayer(tile->Layer())->GetTileIndex(p->m_currentPosition, row, column);
264 
265  if (abs(tile->Row() - row) <= 3 || abs(tile->Column() - column) < 3)
266  {
267  if (!tile->TextureLoaded())
268  {
269  if (tile->LoadImageToMemory() == true)
270  {
271  p->LoadTexture(tile);
272  tile->UnloadImage();
273  }
274  else
275  {
276  printf("failed to load image\n");
277  }
278  }
279  }
280  }
281  else
282  {
283  p->m_precacheRequests[tile->Layer()].push(tile);
284  }
285 
286  p->m_renderRequestSetLock.lock();
287  p->m_renderRequestSet.erase(tile->TileID());
288  p->m_renderRequestSetLock.unlock();
289  }
290  else
291  {
292  }
293  }
294  else
295  {
296  p->m_precacheRequestsLock.lock();
297 
298  try
299  {
300  for (uint32_t i = 0; (i < p->m_precacheRequests.size()) && (tile == NULL); i++)
301  {
302  int32_t index = p->m_currentLayer + i;
303  if ((index < (int64_t)p->m_precacheRequests.size()) &&
304  (p->m_precacheRequests[index].size() > 0))
305  {
306  tile = p->m_precacheRequests[index].front();
307  p->m_precacheRequests[index].pop();
308  }
309  else if (i != 0)
310  {
311  index = p->m_currentLayer - i;
312  if (index >= 0 && p->m_precacheRequests[index].size() > 0)
313  {
314  tile = p->m_precacheRequests[index].front();
315  p->m_precacheRequests[index].pop();
316  }
317  }
318  }
319  }
320  catch (const std::exception& e)
321  {
322  std::cout << "An exception occurred precaching texture: " << e.what() << std::endl;
323  }
324 
325  p->m_precacheRequestsLock.unlock();
326 
327  if (tile != NULL && !tile->Failed() && !tile->TextureLoaded())
328  {
329  int row, column;
330  p->m_tileSet->GetLayer(tile->Layer())->GetTileIndex(p->m_currentPosition, row, column);
331  if (abs(tile->Row() - row) <= 3 || abs(tile->Column() - column) <= 3)
332  {
333  if (tile->LoadImageToMemory() == true)
334  {
335  p->LoadTexture(tile);
336 
337  tile->UnloadImage();
338  }
339  else
340  {
341  printf("failed to precache load image\n");
342  }
343  }
344 
345  p->m_precacheRequestSetLock.lock();
346  p->m_precacheRequestSet.erase(tile->TileID());
347  p->m_precacheRequestSetLock.unlock();
348  }
349  }
350 
351  if (tile == NULL)
352  {
353  usleep(10);
354  }
355  }
356  }
357 
359  {
360  while (!p->m_exit)
361  {
362  std::map<int64_t, Tile*>* tiles;
363  p->m_textureLoadedLock.lock();
364 
365  tiles = new std::map<int64_t, Tile*>(p->m_textureLoaded);
366 
367  p->m_textureLoadedLock.unlock();
368 
369  std::map<int64_t, Tile*>::iterator iter;
370 
371  for (iter = tiles->begin(); iter != tiles->end(); ++iter)
372  {
373  Tile* tile = iter->second;
374  int row, column;
375  p->m_tileSet->GetLayer(tile->Layer())->GetTileIndex(p->m_currentPosition, row, column);
376 
377  if (abs(tile->Row() - row) > 6 || abs(tile->Column() - column) > 6)
378  {
379  p->m_renderRequestSetLock.lock();
380  p->m_renderRequestSet.erase(tile->TileID());
381  p->m_renderRequestSetLock.unlock();
382 
383  p->m_precacheRequestSetLock.lock();
384  p->m_precacheRequestSet.erase(tile->TileID());
385  p->m_precacheRequestSetLock.unlock();
386 
387  p->UnloadTexture(tile);
388  }
389  }
390 
391  delete tiles;
392 
393  sleep(2);
394  }
395  }
396 }
tile_cache.h
multires_image::Tile::Row
int Row() const
Definition: tile.h:68
multires_image::TileCache::m_precacheRequestsLock
QMutex m_precacheRequestsLock
Definition: tile_cache.h:122
NULL
#define NULL
multires_image::TileCache::m_precacheRequestSet
std::map< int64_t, Tile * > m_precacheRequestSet
Definition: tile_cache.h:89
multires_image
Definition: multires_view_node.h:51
multires_image::TileSetLayer::GetTileIndex
void GetTileIndex(const tf::Point &position, int &row, int &column) const
Definition: tile_set_layer.cpp:144
multires_image::TileCache::m_renderRequestSet
std::map< int64_t, Tile * > m_renderRequestSet
Definition: tile_cache.h:88
multires_image::Tile::Column
int Column() const
Definition: tile.h:69
multires_image::TileSetLayer
Definition: tile_set_layer.h:45
multires_image::TileCache::~TileCache
~TileCache(void)
Definition: tile_cache.cpp:80
multires_image::TileCache::CacheThread::run
virtual void run()
Definition: tile_cache.cpp:241
multires_image::TileCache::FreeThread::run
virtual void run()
Definition: tile_cache.cpp:358
multires_image::TileCache::PrecacheLayer
void PrecacheLayer(int layer, const tf::Point &position, int size)
Definition: tile_cache.cpp:149
multires_image::Tile
Definition: tile.h:50
multires_image::TileCache::LoadTextureSlot
void LoadTextureSlot(Tile *)
Definition: tile_cache.cpp:87
multires_image::TileSet::GetLayer
TileSetLayer * GetLayer(int layer)
Definition: tile_set.h:61
multires_image::TileCache::Exit
void Exit()
Definition: tile_cache.cpp:189
multires_image::TileCache::SignalDeleteTexture
void SignalDeleteTexture(Tile *)
multires_image::TileCache::Precache
void Precache(const tf::Point &position)
Definition: tile_cache.cpp:125
multires_image::TileSetLayer::GetTile
Tile * GetTile(int column, int row)
Definition: tile_set_layer.h:58
multires_image::TileCache::m_renderRequestSetLock
QMutex m_renderRequestSetLock
Definition: tile_cache.h:121
multires_image::TileCache::CacheThread::p
TileCache * p
Definition: tile_cache.h:102
multires_image::TileSet::LayerCount
int LayerCount()
Definition: tile_set.h:56
multires_image::TileCache::m_widget
QGLWidget * m_widget
Definition: tile_cache.h:79
multires_image::Tile::MemorySize
int MemorySize() const
Definition: tile.h:67
tf::Point
tf::Vector3 Point
multires_image::TileCache::m_exit
bool m_exit
Definition: tile_cache.h:82
multires_image::TileCache::SignalLoadTexture
void SignalLoadTexture(Tile *)
multires_image::Tile::UnloadImage
void UnloadImage()
Definition: tile.cpp:129
multires_image::TileCache::m_currentPosition
tf::Point m_currentPosition
Definition: tile_cache.h:81
multires_image::TileCache::m_precacheRequests
std::vector< std::queue< Tile * > > m_precacheRequests
Definition: tile_cache.h:85
multires_image::Tile::Failed
bool Failed() const
Definition: tile.h:62
tile_set_layer.h
multires_image::Tile::UnloadTexture
void UnloadTexture()
Definition: tile.cpp:176
multires_image::TileCache::m_renderRequestsLock
QMutex m_renderRequestsLock
Definition: tile_cache.h:120
multires_image::TileCache::m_currentLayer
int32_t m_currentLayer
Definition: tile_cache.h:80
multires_image::TileCache::DeleteTextureSlot
void DeleteTextureSlot(Tile *)
Definition: tile_cache.cpp:92
multires_image::TileCache::m_memorySize
int64_t m_memorySize
Definition: tile_cache.h:83
multires_image::TileCache::TileCache
TileCache(TileSet *tileSet, QGLWidget *widget)
Definition: tile_cache.cpp:47
multires_image::Tile::TileID
int64_t TileID() const
Definition: tile.h:65
multires_image::TileCache::m_cacheThread
CacheThread m_cacheThread
Definition: tile_cache.h:117
multires_image::TileCache::LoadTexture
void LoadTexture(Tile *tile)
Definition: tile_cache.cpp:194
multires_image::Tile::Layer
int Layer() const
Definition: tile.h:66
multires_image::TileCache::m_precacheRequestSetLock
QMutex m_precacheRequestSetLock
Definition: tile_cache.h:123
multires_image::TileCache::m_tileSet
TileSet * m_tileSet
Definition: tile_cache.h:78
multires_image::TileCache::m_textureLoadedLock
QMutex m_textureLoadedLock
Definition: tile_cache.h:124
multires_image::TileCache::UnloadTexture
void UnloadTexture(Tile *tile)
Definition: tile_cache.cpp:220
multires_image::TileCache::m_freeThread
FreeThread m_freeThread
Definition: tile_cache.h:118
multires_image::TileCache::m_textureLoaded
std::map< int64_t, Tile * > m_textureLoaded
Definition: tile_cache.h:87
multires_image::Tile::LoadTexture
bool LoadTexture()
Definition: tile.cpp:139
multires_image::TileSetLayer::RowCount
int RowCount()
Definition: tile_set_layer.h:68
multires_image::TileCache::Load
void Load(Tile *tile)
Definition: tile_cache.cpp:97
multires_image::TileSet
Definition: tile_set.h:43
multires_image::Tile::LoadImageToMemory
bool LoadImageToMemory(bool gl=true)
Definition: tile.cpp:80
multires_image::TileSetLayer::ColumnCount
int ColumnCount()
Definition: tile_set_layer.h:69
multires_image::TileCache::m_renderRequests
std::stack< Tile * > m_renderRequests
Definition: tile_cache.h:86
multires_image::Tile::TextureLoaded
bool TextureLoaded() const
Definition: tile.h:63
multires_image::TileCache::SignalMemorySize
void SignalMemorySize(int64_t)


multires_image
Author(s): Marc Alban
autogenerated on Wed Jan 17 2024 03:27:53