OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimImageElevationHandler.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // File: ossimImageElevationHandler.cpp
4 //
5 // License: LGPL
6 //
7 // See LICENSE.txt file in the top level directory for more details.
8 //
9 // Author: David Burken
10 //
11 // Description: See class desciption in header file.
12 //
13 //----------------------------------------------------------------------------
14 // $Id$
15 
17 #include <ossim/base/ossimCommon.h>
21 #include <ossim/base/ossimGpt.h>
22 #include <ossim/base/ossimTrace.h>
24 
25 #include <iostream> // tmp drb
26 using namespace std;
27 
28 #include <cmath>
29 
30 RTTI_DEF1(ossimImageElevationHandler, "ossimImageElevationHandler" , ossimElevCellHandler)
31 
32 // Define Trace flags for use within this file:
33 static ossimTrace traceDebug ("ossimImageElevationHandler:debug");
34 static const ossim_uint32 MAX_TILE_CACHE_SIZE = 32;
35 
37  :
39  m_rect(),
40  m_tileSize(256,256),
41  m_numTilesPerRow(0),
42  m_mutex()
43 {
45 }
46 
48  :
50  m_rect(),
51  m_tileSize(256,256),
52  m_numTilesPerRow(0),
53  m_mutex()
54 {
56  open(file);
57 }
58 
60 {
61  static const char M[] = "ossimImageElevationHandler::open";
62 
63  bool result = false;
64 
65  if ( isOpen() ) close();
66 
67  if ( file.size() )
68  {
69  //---
70  // NOTE: The false passed to open is flag to NOT open overviews. If code is ever changed
71  // to go between reduced resolution levels this should be changed.
72  //---
73  m_ih = ossimImageHandlerRegistry::instance()->open(file, true, false);
74  if ( m_ih.valid() )
75  {
77  if ( m_geom.valid() )
78  {
79  result = true;
80 
81  // Image rect stored as a drect for ossimImageElevationHandler::pointHasCoverage
82  // method.
87 
88  // Initialize base class stuff.
89  theFilename = file;
90 
92 
93  // Set the ossimElevSource::theGroundRect
94  std::vector<ossimGpt> corner(4);
95  if ( m_geom->getCornerGpts(corner[0], corner[1], corner[2], corner[3]) )
96  {
97  ossimGpt ulGpt(corner[0]);
98  ossimGpt lrGpt(corner[0]);
99  for ( ossim_uint32 i = 1; i < 4; ++i )
100  {
101  if ( corner[i].lon < ulGpt.lon ) ulGpt.lon = corner[i].lon;
102  if ( corner[i].lat > ulGpt.lat ) ulGpt.lat = corner[i].lat;
103  if ( corner[i].lon > lrGpt.lon ) lrGpt.lon = corner[i].lon;
104  if ( corner[i].lat < lrGpt.lat ) lrGpt.lat = corner[i].lat;
105  }
106  theGroundRect = ossimGrect(ulGpt, lrGpt);
107  }
108  else
109  {
111  }
112  }
113  // theAbsLE90 ???
114  // theAbsCE90 ???
115  }
116  }
117 
118  if ( traceDebug() )
119  {
121  << M << " DEBUG:"
122  << "\nmean spacing(meters): " << theMeanSpacing
123  << "\nunding rect: " << theGroundRect
124  << "\nreturn status: " << (result?"true\n":"false\n");
125  }
126 
127  return result;
128 }
129 
130 
132 {
133  close();
134 }
135 
137 {
138  double height = ossim::nan();
139 
140  // Get the image point for the world point.
141  ossimDpt dpt;
142  m_geom->worldToLocal(gpt, dpt);
143 
144  if ( !m_rect.pointWithin(dpt) )
145  return height;
146 
147  // Cast it to an int which will shift to nearest upper left post.
148  ossim_uint32 x0 = static_cast<ossim_uint32>(dpt.x);
149  ossim_uint32 y0 = static_cast<ossim_uint32>(dpt.y);
150 
151  ossimRefPtr<ossimImageData> data = getTile(x0, y0);
152 
153  // Check if we are at the bottom or right edge of the tile to move in one post:
154  ossimIpt data_lr = data->getImageRectangle().lr();
155  if (x0 == static_cast<ossim_uint32>(data_lr.x))
156  --x0;
157  if (y0 == static_cast<ossim_uint32>(data_lr.y))
158  --y0;
159 
160  double p00 = data->getPix( ossimIpt(x0, y0) );
161  double p01 = data->getPix( ossimIpt(x0+1, y0) );
162  double p10 = data->getPix( ossimIpt(x0, y0+1) );
163  double p11 = data->getPix( ossimIpt(x0+1, y0+1) );
164 
165  double xt0 = dpt.x - x0;
166  double yt0 = dpt.y - y0;
167  double xt1 = 1-xt0;
168  double yt1 = 1-yt0;
169 
170  double w00 = xt1*yt1;
171  double w01 = xt0*yt1;
172  double w10 = xt1*yt0;
173  double w11 = xt0*yt0;
174 
175  // Test for null posts and set the corresponding weights to 0:
176  const double NP = data->getNullPix(0);
177 
178  if (p00 == NP)
179  w00 = 0.0;
180  if (p01 == NP)
181  w01 = 0.0;
182  if (p10 == NP)
183  w10 = 0.0;
184  if (p11 == NP)
185  w11 = 0.0;
186 
187 #if 0 /* Serious debug only... */
188  cout << "\np00: " << p00
189  << "\np01: " << p01
190  << "\np10: " << p10
191  << "\np11: " << p11
192  << "\nw00: " << w00
193  << "\nw01: " << w01
194  << "\nw10: " << w10
195  << "\nw11: " << w11
196  << endl;
197 #endif
198 
199  double sum_weights = w00 + w01 + w10 + w11;
200  if (sum_weights)
201  height = (p00*w00 + p01*w01 + p10*w10 + p11*w11) / sum_weights;
202 
203  return height;
204 }
205 
207 {
208  // Establish the tile ID that this post belongs to:
211  ossim_uint32 tile_id = v*m_numTilesPerRow + u;
212 
214 
215  // Search for this tile in the cache:
216  std::lock_guard<std::mutex> lock(m_mutex);
217  vector<TileCacheEntry>::iterator iter = m_tileCache.begin();
218  while ((iter != m_tileCache.end()) && (iter->id != tile_id))
219  ++iter;
220 
221  if (iter != m_tileCache.end())
222  {
223  // Found an entry in the cache:
224  data = iter->data;
225  if (iter != m_tileCache.begin())
226  {
227  // Need to move the entry to the top of the list (current most popular)
228  TileCacheEntry temp = *iter;
229  m_tileCache.erase(iter);
230  m_tileCache.insert(m_tileCache.begin(), temp);
231  }
232  }
233  else
234  {
235  // Didn't find the tile in the cache, read it from the handler and insert into the cache:
236  ossimIpt ul (u*m_tileSize.x, v*m_tileSize.y);
237  ossimIpt lr (ul.x + m_tileSize.x - 1, ul.y + m_tileSize.y - 1);
238  ossimIrect tileRect (ul, lr);
239  ossimRefPtr<ossimImageData> inData = m_ih->getTile(tileRect, 0 );
240  if (inData.valid())
241  {
242  // Always insert at beginning. Need to check for overflow:
243  data = (ossimImageData*) inData->dup();
244  data->assign(inData.get());
245  TileCacheEntry entry (tile_id, data.get());
246  if (m_tileCache.size() == MAX_TILE_CACHE_SIZE)
247  m_tileCache.pop_back();
248  m_tileCache.insert(m_tileCache.begin(), entry);
249  }
250  }
251 
252  return data.get();
253 }
254 
256 {
257  ossimIpt sz(0,0);
258  if ( m_ih.valid() )
259  {
260  sz.x = static_cast<ossim_int32>(m_ih->getNumberOfSamples(0));
261  sz.y = static_cast<ossim_int32>(m_ih->getNumberOfLines(0));
262  }
263  return sz;
264 }
265 
267 {
268  double height = ossim::nan();
269  if ( m_rect.pointWithin(ossimDpt(gridPt)) )
270  {
271  ossimRefPtr<ossimImageData> data = getTile(gridPt.x, gridPt.y);
272  if ( data.valid() )
273  {
274  height = data->getPix(0, 0);
275  if (height == data->getNullPix(0))
276  height = ossim::nan();
277  }
278  }
279  return height;
280 }
281 
283 {
284  *this = copy;
285 }
286 
289 {
290  open(rhs.theFilename);
291  return *this;
292 }
virtual ~ossimImageElevationHandler()
Protected destructor.
ossim_uint32 x
ossimRefPtr< ossimImageGeometry > m_geom
bool pointWithin(const ossimDpt &pt, double epsilon=0.0) const
Definition: ossimDrect.h:781
ossim_float64 width() const
Definition: ossimDrect.h:522
ossimDrect m_rect
Image space rect stored as drect for inlined pointHasCoverage method.
virtual ossimImageHandler * open(const ossimFilename &fileName, bool trySuffixFirst=true, bool openOverview=true) const
open that takes a filename.
ossim_uint32 y
bool valid() const
Definition: ossimRefPtr.h:75
void makeNan()
Definition: ossimGrect.h:284
virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
double y
Definition: ossimDpt.h:165
virtual ossimIpt getSizeOfElevCell() const
METHOD: getSizeOfElevCell Returns the number of post in the cell.
OSSIM_DLL void defaultTileSize(ossimIpt &tileSize)
bool getCornerGpts(ossimGpt &ul, ossimGpt &ur, ossimGpt &lr, ossimGpt &ll) const
Assigns the ossimGpts with the ground coordinates of the four corresponding image corner points...
virtual ossim_float64 getPix(const ossimIpt &position, ossim_uint32 band=0) const
Will return the pixel at location position.
virtual ossimObject * dup() const
virtual void assign(const ossimDataObject *data)
ossimGrect theGroundRect
Elevation source for a generic image opened via ossimImageHandler.
ossim_float64 lon
Definition: ossimGpt.h:266
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if non defined...
std::string::size_type size() const
Definition: ossimString.h:405
const ossimImageElevationHandler & operator=(const ossimImageElevationHandler &rhs)
Hidden from use assignment operator.
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
ossimDpt getMetersPerPixel() const
Returns the GSD associated with this image in the active projection.
virtual double getPostValue(const ossimIpt &gridPt) const
METHOD: getPostValue Returns the value at a given grid point as a double.
virtual ossimIrect getImageRectangle() const
ossimFilename theFilename
Virtual method for reading.
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual void close()
Closes the stream to the file.
ossimImageElevationHandler()
default constructor
ossimRefPtr< ossimImageHandler > m_ih
Pointers to links in chain.
std::vector< TileCacheEntry > m_tileCache
ossim_int32 y
Definition: ossimIpt.h:142
virtual double getHeightAboveMSL(const ossimGpt &)
METHOD: getHeightAboveMSL Height access methods.
double x
Definition: ossimDpt.h:164
bool worldToLocal(const ossimGpt &world_pt, ossimDpt &local_pt) const
Exposes the 3D world-to-local image coordinate reverse projection.
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
static ossimImageHandlerRegistry * instance()
ossim_int32 x
Definition: ossimIpt.h:141
ossim_float64 lat
Definition: ossimGpt.h:265
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
virtual bool open(const ossimFilename &file)
Opens a stream to the srtm cell.
ossimImageData * getTile(ossim_uint32 x, ossim_uint32 y) const
Looks for an elevation tile in the cache first before reading the tile from the input handler...
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
int ossim_int32
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)