1 /*
2  * Copyright (C) 2010-2011 Dmitry Marakasov
3  *
4  * This file is part of glosm.
5  *
6  * glosm 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  * glosm 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 glosm.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef TILEMANAGER_HH
21 #define TILEMANAGER_HH
22 
23 #include <glosm/BBox.hh>
24 #include <glosm/Projection.hh>
25 
26 #include <pthread.h>
27 
28 #include <list>
29 #include <map>
30 #include <set>
31 
32 class Geometry;
33 class GeometryDatasource;
34 class Viewer;
35 class Tile;
36 
37 /**
38  * Generic quadtree tile manager
39  *
40  * This class is serves as a base class for layers and manages tile
41  * loading, displaying and disposal.
42  *
43  * @todo this class is planned to handle multilayer tile hierarchies,
44  * however for now level is fixed
45  */
46 class TileManager {
47 public:
48 	enum RequestFlags {
49 		SYNC = 0x01,
50 		BLOB = 0x02,
51 	};
52 
53 protected:
54 	/**
55 	 * Tile identifier
56 	 */
57 	struct TileId {
58 		int level;
59 		int x;
60 		int y;
61 
TileIdTileManager::TileId62 		TileId(int lev, int xx, int yy) : level(lev), x(xx), y(yy) {
63 		}
64 
operator ==TileManager::TileId65 		inline bool operator==(const TileId& other) const {
66 			return x == other.x && y == other.y && level == other.level;
67 		}
68 
operator !=TileManager::TileId69 		inline bool operator!=(const TileId& other) const {
70 			return x != other.x || y != other.y || level != other.level;
71 		}
72 	};
73 
74 	/**
75 	 * Single node of a quadtree
76 	 */
77 	struct QuadNode {
78 		Tile* tile;
79 		int generation;
80 		BBoxi bbox;
81 
82 		QuadNode* childs[4];
83 
QuadNodeTileManager::QuadNode84 		QuadNode() : tile(NULL), generation(0), bbox(BBoxi::ForGeoTile(0, 0, 0)) {
85 			childs[0] = childs[1] = childs[2] = childs[3] = NULL;
86 		}
87 	};
88 
89 	/**
90 	 * Single tile loading request
91 	 */
92 	struct TileTask {
93 		TileId id;
94 		BBoxi bbox;
95 
TileTaskTileManager::TileTask96 		TileTask(const TileId& i, const BBoxi& b) : id(i), bbox(b) {
97 		}
98 	};
99 
100 	/**
101 	 * Holder of data for LoadLocality request
102 	 */
103 	struct RecLoadTilesInfo {
104 		enum Modes {
105 			BBOX,
106 			LOCALITY
107 		};
108 
109 		union {
110 			const Viewer* viewer;
111 			const BBoxi* bbox;
112 		};
113 
114 		int mode;
115 		int flags;
116 		Vector3i viewer_pos;
117 		float closest_distance;
118 		int queue_size;
119 
RecLoadTilesInfoTileManager::RecLoadTilesInfo120 		RecLoadTilesInfo() : queue_size(0) {
121 		}
122 	};
123 
124 protected:
125 	typedef std::list<TileTask> TilesQueue;
126 	typedef std::vector<QuadNode**> GCQueue;
127 
128 protected:
129 	/* @todo it would be optimal to delegate these to layer via either
130 	 * virtual methods or templates */
131 	int level_;
132 	float range_;
133 	volatile int flags_;
134 	bool height_effect_;
135 	size_t size_limit_;
136 
137 	const Projection projection_;
138 
139 	mutable pthread_mutex_t tiles_mutex_;
140 	/* protected by tiles_mutex_ */
141 	QuadNode root_;
142 	int generation_;
143 	size_t total_size_;
144 	int tile_count_;
145 	/* /protected by tiles_mutex_ */
146 
147 	mutable pthread_mutex_t queue_mutex_;
148 	pthread_cond_t queue_cond_;
149 	/* protected by queue_mutex_ */
150 	TilesQueue queue_;
151 	TileId loading_;
152 	/* /protected by queue_mutex_ */
153 
154 	pthread_t loading_thread_;
155 	volatile bool thread_die_flag_;
156 
157 protected:
158 	/**
159 	 * Constructs Tile
160 	 */
161 	TileManager(const Projection projection);
162 
163 	/**
164 	 * Destructor
165 	 */
166 	virtual ~TileManager();
167 
168 	/**
169 	 * Spawns a single tile with specified bbox
170 	 */
171 	virtual Tile* SpawnTile(const BBoxi& bbox, int flags) const = 0;
172 
173 	/**
174 	 * Recursive tile loading function for viewer's locality
175 	 *
176 	 * @todo remove code duplication with RecLoadTilesBBox
177 	 */
178 	void RecLoadTilesLocality(RecLoadTilesInfo& info, QuadNode** pnode, int level = 0, int x = 0, int y = 0);
179 
180 	/**
181 	 * Recursive tile loading function for given bbox
182 	 *
183 	 * @todo remove code duplication with RecLoadTilesLocality
184 	 */
185 	void RecLoadTilesBBox(RecLoadTilesInfo& info, QuadNode** pnode, int level = 0, int x = 0, int y = 0);
186 
187 	/**
188 	 * Recursive function that places tile into specified quadtree point
189 	 */
190 	void RecPlaceTile(QuadNode* node, Tile* tile, int level = 0, int x = 0, int y = 0);
191 
192 	/**
193 	 * Recursive function for tile rendering
194 	 */
195 	void RecRenderTiles(QuadNode* node, const Viewer& viewer);
196 
197 	/**
198 	 * Recursive function for destroying tiles and quadtree nodes
199 	 */
200 	void RecDestroyTiles(QuadNode* node);
201 
202 	/**
203 	 * Recursive function for garbage collecting unneeded tiles
204 	 */
205 	void RecGarbageCollectTiles(QuadNode* node, GCQueue& gcqueue);
206 
207 	/**
208 	 * Thread function for tile loading
209 	 */
210 	void LoadingThreadFunc();
211 
212 	/**
213 	 * Static wrapper for thread function
214 	 */
215 	static void* LoadingThreadFuncWrapper(void* arg);
216 
217 	/**
218 	 * Loads tiles
219 	 */
220 	void Load(RecLoadTilesInfo& info);
221 
222 protected:
223 	/**
224 	 * Renders visible tiles
225 	 */
226 	void Render(const Viewer& viewer);
227 
228 protected:
229 	static bool GenerationCompare(QuadNode** x, QuadNode** y);
230 
231 public:
232 	/**
233 	 * Loads square area of tiles
234 	 */
235 	void LoadArea(const BBoxi& bbox, int flags = 0);
236 
237 	/**
238 	 * Loads tiles in locality of Viewer
239 	 */
240 	void LoadLocality(const Viewer& viewer, int flags = 0);
241 
242 	/**
243 	 * Destroys unneeded tiles
244 	 */
245 	void GarbageCollect();
246 
247 	/**
248 	 * Destroys all tiles
249 	 */
250 	void Clear();
251 
252 	/**
253 	 * Sets designated tile level
254 	 *
255 	 * @param level desired level
256 	 */
257 	void SetLevel(int level);
258 
259 	/**
260 	 * Sets range in which tiles are visible
261 	 *
262 	 * @param range range in meters
263 	 */
264 	void SetRange(float range);
265 
266 	/**
267 	 * Sets flags for tile spawinig
268 	 *
269 	 * @param flags flags
270 	 * @see GeometryGenerator::GetGeometry
271 	 */
272 	void SetFlags(int flags);
273 
274 	/**
275 	 * Sets mode of taking viewer height into account
276 	 *
277 	 * @param enabled if true, height is taken into account
278 	 *        when calculating distance from viewer to tile
279 	 */
280 	void SetHeightEffect(bool enabled);
281 
282 	/**
283 	 * Sets limit on cumulative tiles size
284 	 *
285 	 * @param limit size limit in bytes
286 	 */
287 	void SetSizeLimit(size_t limit);
288 };
289 
290 #endif
291