source: Revenant/geoworld/src/stratum.cpp@ 8125274

port/mars-tycoon
Last change on this file since 8125274 was 25c4774, checked in by Jonathan Neufeld <support@…>, 3 years ago

(TEST) Corrected bug using wrong z-base (still not sure what this is)

  • Property mode set to 100644
File size: 15.1 KB
Line 
1#include "stratum.h"
2
3#include "mindb.h"
4
5#include <mars_streams.h>
6
7namespace geoworld
8{
9 StratumView::~StratumView()
10 {
11 { GW_SCOPED_LOCK(atomic);
12 assert(_nViewRefCount == 0);
13 if (_nViewRefCount > 0)
14 throw Ex("Still open views on GeoWorldPage instance");
15 }
16 }
17
18 const StratumView * StratumView::createView( const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nShallow, const WorldUnit nRight, const WorldUnit nBottom, const WorldUnit nDeep ) const
19 {
20 { GW_SCOPED_LOCK(atomic);
21 ++_nViewRefCount;
22 return new StratumView (
23 &_data,
24 mars::BBox< WorldUnit > (nLeft, nTop, nRight, nBottom),
25 nShallow,
26 nDeep,
27 0,
28 lod
29 );
30 }
31 }
32
33 const StratumView * StratumView::createView( const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nRight, const WorldUnit nBottom ) const
34 {
35 { GW_SCOPED_LOCK(atomic);
36 ++_nViewRefCount;
37 return new StratumView (
38 this,
39 mars::BBox< WorldUnit > (nLeft, nTop, nRight, nBottom)
40 );
41 }
42 }
43
44 StratumView * StratumView::createView( const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nShallow, const WorldUnit nRight, const WorldUnit nBottom, const WorldUnit nDeep )
45 {
46 { GW_SCOPED_LOCK(atomic);
47 ++_nViewRefCount;
48 return new StratumView (
49 &_data,
50 mars::BBox< WorldUnit > (nLeft, nTop, nRight, nBottom),
51 nShallow,
52 nDeep,
53 0,
54 lod
55 );
56 }
57 }
58
59 StratumView * StratumView::createView( const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nRight, const WorldUnit nBottom )
60 {
61 { GW_SCOPED_LOCK(atomic);
62 ++_nViewRefCount;
63 return new StratumView (
64 this,
65 mars::BBox< WorldUnit > (nLeft, nTop, nRight, nBottom)
66 );
67 }
68 }
69
70 void StratumView::fetchViewElements( std::set< GeoStratumField::Element > & st ) const
71 {
72 for (size_t j = 0; j < height; ++j)
73 for (size_t i = 0; i < width; ++i)
74 {
75 GeoHeightMap::Precision zi = (*_data.baseview)(i, j);
76
77 if (zi >= _z.minimum)
78 {
79 for (size_t c = 0; c < _data.fields.size(); ++c)
80 {
81 const GeoStratumField::View & view = *_data.fields[c];
82 const GeoStratumField::AltitudePrecision nAlt = view.altitude(i, j);
83
84 if (zi >= _z.minimum && ((zi - nAlt) <= _z.maximum || c == _data.fields.size() - 1))
85 st.insert(view.getElement(i, j));
86
87 zi -= nAlt;
88 }
89 } else
90 st.insert(_data.fields.front() ->getElement(i, j));
91 }
92 }
93
94 void StratumView::fetchViewIndices( std::set< unsigned short > & st ) const
95 {
96 for (size_t j = 0; j < height; ++j)
97 for (size_t i = 0; i < width; ++i)
98 {
99 GeoHeightMap::Precision zi = (*_data.baseview)(i, j);
100 size_t ii = 0;
101
102 if (zi >= _z.minimum)
103 {
104 for (size_t c = 0; c < _data.fields.size(); ++c)
105 {
106 const GeoStratumField::View & view = *_data.fields[c];
107 const GeoStratumField::AltitudePrecision nAlt = view.altitude(i, j);
108
109 if (zi >= _z.minimum && ((zi - nAlt) <= _z.maximum || c == _data.fields.size() - 1))
110 st.insert(view(i, j).mindex + ii);
111
112 zi -= nAlt;
113 ii += _counts[c];
114 }
115 } else
116 st.insert((*_data.fields.front())(i, j).mindex);
117 }
118 }
119
120 unsigned short StratumView::getIndex (const WorldUnit x, const WorldUnit y, const WorldUnit z) const
121 {
122 assert(z >> lod >= _zBase && (z >> lod) < static_cast< WorldUnit > (_z.delta));
123 const signed int
124 xlo = static_cast< signed int > (x >> lod),
125 ylo = static_cast< signed int > (y >> lod),
126 zalo = static_cast< signed int > (z >> lod) + _zBasedMin; // TODO: Check base
127
128 GeoHeightMap::Precision zi = (*_data.baseview)(xlo, ylo);
129 size_t ii = 0;
130
131 if (zi >= _z.minimum)
132 {
133 for (size_t c = 0; c < _data.fields.size(); ++c)
134 {
135 const GeoStratumField::View & view = *_data.fields[c];
136
137 zi -= view.altitude(xlo, ylo);
138 if (zi < zalo)
139 return view(xlo, ylo).mindex + ii;
140
141 ii += _counts[c];
142 }
143 return (*_data.fields.back())(xlo, ylo).mindex + ii - _counts.back();
144 } else
145 return (*_data.fields.front())(xlo, ylo).mindex;
146 }
147
148 const GeoStratumField::Element & StratumView::getElement( const WorldUnit x, const WorldUnit y, const WorldUnit z ) const
149 {
150 assert(z >> lod >= _zBase && (z >> lod) < static_cast< WorldUnit > (_z.delta));
151 const signed int
152 xlo = static_cast< signed int > (x >> lod),
153 ylo = static_cast< signed int > (y >> lod),
154 zalo = static_cast< signed int > (z >> lod) + _zBasedMin; // TODO: Check base
155
156 GeoHeightMap::Precision zi = (*_data.baseview)(xlo, ylo);
157
158 if (zi >= _z.minimum)
159 {
160 for (size_t c = 0; c < _data.fields.size(); ++c)
161 {
162 const GeoStratumField::View & view = *_data.fields[c];
163
164 zi -= view.altitude(xlo, ylo);
165 if (zi < zalo)
166 return view.getElement(xlo, ylo);
167 }
168 return _data.fields.back() ->getElement(xlo, ylo);
169 } else
170 return _data.fields.front() ->getElement(xlo, ylo);
171 }
172
173 const GeoStratumField::Element & StratumView::getDominantElement( std::vector< unsigned short > & indices ) const
174 {
175 std::sort(indices.begin(), indices.end());
176
177 unsigned short
178 countMax = 0,
179 idx = indices[0],
180 idxMax = indices[0],
181 count = 0;
182
183 for (size_t c = 0; c < indices.size(); ++c)
184 {
185 if (indices[c] != idx)
186 {
187 if (count > countMax)
188 {
189 idxMax = idx;
190 countMax = count;
191 }
192 count = 1;
193 idx = indices[c];
194 } else
195 ++count;
196 }
197
198 return getElement(idxMax);
199 }
200
201 const GeoStratumField::Element & StratumView::getDominantElementVN3( const WorldUnit x, const WorldUnit y, const WorldUnit z ) const
202 {
203 std::vector< unsigned short > indices (6);
204
205 indices[0] = getIndex(x - _one, y, z);
206 indices[1] = getIndex(x, y - _one, z);
207 indices[2] = getIndex(x, y, z - _one);
208 indices[3] = getIndex(x + _one, y, z);
209 indices[4] = getIndex(x, y + _one, z);
210 indices[5] = getIndex(x, y, z + _one);
211
212 return getDominantElement(indices);
213 }
214
215 const GeoStratumField::Element & StratumView::getDominantElementVN( const WorldUnit x, const WorldUnit y ) const
216 {
217 std::vector< unsigned short > indices (4);
218 const signed int
219 xlo = x >> lod,
220 ylo = y >> lod;
221
222 indices[0] = getIndex(x - _one, y, (static_cast< WorldUnit > ((*_data.baseview)(xlo - 1, ylo)) << lod) - _zBasedMin);
223 indices[1] = getIndex(x, y - _one, (static_cast< WorldUnit > ((*_data.baseview)(xlo, ylo - 1)) << lod) - _zBasedMin);
224 indices[3] = getIndex(x + _one, y, (static_cast< WorldUnit > ((*_data.baseview)(xlo + 1, ylo)) << lod) - _zBasedMin);
225 indices[4] = getIndex(x, y + _one, (static_cast< WorldUnit > ((*_data.baseview)(xlo, ylo + 1)) << lod) - _zBasedMin);
226
227 return getDominantElement(indices);
228 }
229
230 void StratumView::releaseView( const StratumView * pView ) const
231 {
232 { GW_SCOPED_LOCK(atomic);
233 delete pView;
234 --_nViewRefCount;
235 }
236 }
237
238 void StratumView::updateIndexMap()
239 {
240 size_t nInc = 0;
241
242 // DEPS: _idx0map - Implication made in fetchSurfaceViewIndices()
243 _idx0map.clear();
244 for (size_t c = 0; c < _data.fields.size(); ++c)
245 {
246 const size_t nLen = _data.fields[c] ->elementCount();
247
248 _counts[c] = nLen;
249 for (size_t i = 0; i < nLen; ++i)
250 _idx0map.push_back(std::pair< size_t, size_t > (c, nInc));
251
252 nInc += nLen;
253 }
254 }
255
256 StratumView::StratumView( StratumData * pParentData, const mars::BBox< WorldUnit > & bbox, const WorldUnit z0, const WorldUnit zN, const WorldUnit zBase, const unsigned short nLOD )
257 : _data(
258 pParentData,
259 static_cast< unsigned short > (bbox.left >> nLOD),
260 static_cast< unsigned short > (bbox.top >> nLOD),
261 static_cast< unsigned short > (bbox.right >> nLOD),
262 static_cast< unsigned short > (bbox.bottom >> nLOD)
263 ),
264 layers(pParentData->fields.size()),
265 _counts(pParentData->fields.size()),
266 width (static_cast< unsigned short > (bbox.getWidth() >> nLOD)),
267 height (static_cast< unsigned short > (bbox.getHeight() >> nLOD)),
268 abswidth (bbox.getWidth()),
269 absheight (bbox.getHeight()),
270 absdepth(zN - z0),
271 _zBase(static_cast< GeoHeightMap::Precision > (zBase >> nLOD)),
272 _zBasedMin(static_cast< GeoHeightMap::Precision > ((z0 - zBase) >> nLOD)),
273 depth(static_cast< unsigned short > ((zN - z0) >> nLOD)),
274 lod(nLOD),
275 _z(static_cast< GeoHeightMap::Precision > (z0 >> nLOD), static_cast< GeoHeightMap::Precision > (zN >> nLOD)),
276 _nViewRefCount(0),
277 _one(1 << nLOD)
278 {
279 assert(zBase >> nLOD > std::numeric_limits< signed short >::lowest());
280 assert((zN - z0) >> nLOD < 1 << 15); // Must fit into a WORD
281 updateIndexMap();
282 }
283
284 StratumView::StratumView(const size_t nLayers, const mars::BBox< WorldUnit > & bbox, const WorldUnit z0, const WorldUnit zN, const WorldUnit zBase, const unsigned short nLOD, const mars::GridType engt /*= mars::Normal*/ )
285 : _data(
286 nLayers,
287 static_cast< unsigned short > (bbox.getWidth() >> nLOD),
288 static_cast< unsigned short > (bbox.getHeight() >> nLOD),
289 engt
290 ),
291 layers(nLayers),
292 _counts(nLayers),
293 width (static_cast< unsigned short > (bbox.getWidth() >> nLOD)),
294 height (static_cast< unsigned short > (bbox.getHeight() >> nLOD)),
295 abswidth (bbox.getWidth()),
296 absheight (bbox.getHeight()),
297 absdepth(zN - z0),
298 _zBase(static_cast< GeoHeightMap::Precision > (zBase >> nLOD)),
299 _zBasedMin(static_cast< GeoHeightMap::Precision > ((z0 - zBase) >> nLOD)),
300 depth(static_cast< unsigned short > ((zN - z0) >> nLOD)),
301 lod(nLOD),
302 _z(static_cast< GeoHeightMap::Precision > (z0 >> nLOD), static_cast< GeoHeightMap::Precision > (zN >> nLOD)),
303 _nViewRefCount(0),
304 _one(1 << nLOD)
305 {
306 assert(zBase >> nLOD > std::numeric_limits< signed short >::lowest());
307 assert((zN - z0) >> nLOD < 1 << 15); // Must fit into a WORD
308 }
309
310 StratumView::StratumView( const StratumView * const pParent, const mars::BBox< WorldUnit > & bbox )
311 : _data(
312 &pParent->_data,
313 static_cast< unsigned short > (bbox.left >> pParent->lod),
314 static_cast< unsigned short > (bbox.top >> pParent->lod),
315 static_cast< unsigned short > (bbox.right >> pParent->lod),
316 static_cast< unsigned short > (bbox.bottom >> pParent->lod)
317 ),
318 layers(pParent->_data.fields.size()),
319 _counts(pParent->_data.fields.size()),
320 width (static_cast< unsigned short > (bbox.getWidth() >> pParent->lod)),
321 height (static_cast< unsigned short > (bbox.getHeight() >> pParent->lod)),
322 abswidth (bbox.getWidth()),
323 absheight (bbox.getHeight()),
324 absdepth(pParent->absdepth),
325 depth(pParent->depth),
326 lod(pParent->lod),
327 _zBase(pParent->_zBase),
328 _zBasedMin(pParent->_zBasedMin),
329 _z(pParent->_z),
330 _nViewRefCount(0),
331 _one(pParent->_one)
332 {
333 updateIndexMap();
334 }
335
336 void StratumView::applyDEM ( const GeoHeightMap::View & hmv, const unsigned short nDEMLOD )
337 {
338 const unsigned short nDeltaLOD = lod - nDEMLOD;
339 const size_t nInc = 1 << nDeltaLOD;
340
341 assert(nDEMLOD <= lod);
342 assert(hmv.width << nDEMLOD == width << lod && hmv.height << nDEMLOD == height << lod);
343
344 if (nInc == 1)
345 (*_data.baseview) << hmv;
346 else
347 {
348 for (size_t j = 0, v = 0; j < absheight; j += nInc, ++v)
349 for (size_t i = 0, u = 0; i < abswidth; i += nInc, ++u)
350 _data.baseview->setn(u, v, hmv(i, j) >> nDeltaLOD);
351 }
352 }
353
354 mars::Range< WorldUnit > StratumView::getRange() const
355 {
356 double f;
357 WorldUnit
358 nMin = std::numeric_limits< WorldUnit >::max(),
359 nMax = std::numeric_limits< WorldUnit >::min();
360
361 for (size_t j = 0; j < height; ++j)
362 for (size_t i = 0; i < width; ++i)
363 {
364 f = (getBase())(i, j);
365 if (f > nMax)
366 nMax = static_cast< WorldUnit > (f);
367
368 for (StratumData::FieldList::const_iterator k = beginFields(); k != endFields(); ++k)
369 f -= (**k)(i, j).altitude;
370
371 if (f < nMin)
372 nMin = static_cast< WorldUnit > (f);
373 }
374
375 return mars::Range< WorldUnit > ((nMin - _zBasedMin) << lod, (nMax - _zBasedMin) << lod);
376 }
377
378 std::ostream & Stratum::operator >> ( std::ostream & outs ) const
379 {
380 {
381 std::vector< std::string > vsDefs;
382 mars::ObjectStream outs2 (&outs);
383
384 for (StratumData::FieldList::const_iterator i = beginFields(); i != endFields(); ++i)
385 {
386 for (GeoStratumField::ElementList::const_iterator j = (*i)->beginElements(); j != (*i)->endElements(); ++j)
387 vsDefs.push_back(j->getName());
388
389 outs2 << vsDefs;
390 vsDefs.clear();
391 }
392 }
393
394 static_cast< const GeoHeightMap & > (this->getBase()) >> outs;
395 for (StratumData::FieldList::const_iterator i = beginFields(); i != endFields(); ++i)
396 {
397 *static_cast< const GeoStratumField * > (&**i) >> outs;
398 }
399 return outs;
400 }
401
402 std::istream & Stratum::operator << ( std::istream & ins )
403 {
404 {
405 std::vector< std::string > vsDefs;
406 mars::ObjectStream ins2 (&ins);
407
408 for (StratumData::FieldList::iterator i = beginFields(); i != endFields(); ++i)
409 {
410 ins2 >> vsDefs;
411
412 (*i)->clearRegs();
413 for (std::vector< std::string >::const_iterator j = vsDefs.begin(); j != vsDefs.end(); ++j)
414 (*i)->reg(*j);
415 }
416 }
417
418 static_cast< GeoHeightMap & > (this->getBase()) << ins;
419 size_t c = 0;
420 for (StratumData::FieldList::iterator i = beginFields(); i != endFields(); ++i, ++c)
421 {
422 *static_cast< GeoStratumField * > (&**i) << ins;
423 }
424 return ins;
425 }
426
427 Stratum::Stratum( const size_t nLayers, const WorldUnit nWidth, const WorldUnit nHeight, const WorldUnit nDepth, const unsigned short nLOD, const mars::GridType engt /*= mars::Normal*/ )
428 : StratumView(
429 nLayers,
430 mars::BBox< WorldUnit > (0, 0, nWidth - 1, nHeight - 1),
431 std::numeric_limits< signed short >::min() / 2,
432 std::numeric_limits< signed short >::max() / 2,
433 0,
434 nLOD, engt
435 ),
436 _nActualDepth(nDepth)
437 {
438 assert((nWidth >> nLOD) < (1 << 16) && (nHeight >> nLOD) < (1 << 16)); // Must be small enough to fit into an unsigned short
439 }
440
441 void StratumData::operator >> ( StratumData & dest ) const
442 {
443 assert(fields.size() == dest.fields.size());
444 *baseview >> *dest.baseview;
445 for (size_t c = 0; c < fields.size(); ++c)
446 *fields[c] >> *dest.fields[c];
447 }
448
449 void StratumData::operator << ( const StratumData & src )
450 {
451 assert(fields.size() == src.fields.size());
452 *baseview << *src.baseview;
453 for (size_t c = 0; c < fields.size(); ++c)
454 *fields[c] << *src.fields[c];
455 }
456
457 StratumData::StratumData( StratumData * pParent, const unsigned short nLeft, const unsigned short nTop, const unsigned short nRight, const unsigned short nBottom )
458 : _pParent(pParent), fields(pParent->fields.size())
459 {
460 assert(pParent != NULL);
461
462 baseview = pParent->baseview->createView(nLeft, nTop, nRight, nBottom);
463 for (size_t c = 0; c < fields.size(); ++c)
464 fields[c] = pParent->fields[c] ->createView(nLeft, nTop, nRight, nBottom);
465 }
466
467 StratumData::StratumData( const size_t nLayers, const unsigned short nWidth, const unsigned short nHeight, const mars::GridType engt /*= mars::Normal*/ )
468 : _pParent(NULL), fields(nLayers), baseview (new GeoHeightMap(nWidth, nHeight, engt))
469 {
470 for (size_t c = 0; c < fields.size(); ++c)
471 fields[c] = new GeoStratumField(nWidth, nHeight, engt);
472 }
473
474 StratumData::~StratumData()
475 {
476 if (_pParent == NULL)
477 {
478 delete baseview;
479 for (FieldList::iterator i = fields.begin(); i != fields.end(); ++i)
480 delete *i;
481 } else
482 {
483 _pParent->baseview->releaseView(baseview);
484 for (size_t c = 0; c < fields.size(); ++c)
485 _pParent->fields[c] ->releaseView(fields[c]);
486 }
487 }
488
489 void StratumData::copySection( StratumData & dest, const signed int x, const signed int y ) const
490 {
491 assert(fields.size() == dest.fields.size());
492 *dest.baseview << GeoHeightMap::View::Offset (baseview, x, y);
493 for (size_t c = 0; c < fields.size(); ++c)
494 *dest.fields[c] << GeoStratumField::View::Offset(fields[c], x, y);
495 }
496
497}
Note: See TracBrowser for help on using the repository browser.