OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimDtedRecord.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: Ken Melero
6 //
7 // Description: This class gives access to the Data Record Description
8 // of a DTED Level 1 file.
9 //
10 // Notes: Each elevation is a true value referenced to meas sea level
11 // (MSL) datum recorded to the nearest meter. The horizontal
12 // position is referenced to precise longitude-latitiude
13 // locations in terms of the current World Geodetic System
14 // (WGS84) determined for each file by reference to the origin
15 // at the southwest corner. The elevations are evenly spaced
16 // in latitude and longitude at the interval designated in the
17 // User Header Label (UHL) in South to North profile sequence.
18 //
19 //********************************************************************
20 // $Id: ossimDtedRecord.cpp 20611 2012-02-27 12:21:51Z gpotts $
21 
22 #include <iostream>
23 
26 #include <ossim/base/ossimCommon.h>
27 #include <ossim/base/ossimEndian.h>
29 
30 static const ossim_uint16 DATA_NULL_VALUE = 0xffff; // -32767
31 static const ossim_uint16 DATA_MIN_VALUE = 0xfffe; // -32766
32 static const ossim_uint16 DATA_MAX_VALUE = 0x7fff; // +32767
33 static const ossim_uint16 DATA_VALUE_MASK = 0x7fff; // 0111 1111 1111 1111
34 static const ossim_uint16 DATA_SIGN_MASK = 0x8000; // 1000 0000 0000 0000
35 static const ossim_uint16 DATA_RECOGNITION_SENTINEL = 0xAA; // 170
36 
37 //***
38 // Offsets from start of data record (one record per longitude line):
39 //***
40 static const int BLOCK_COUNT_OFFSET = 2;
41 static const int LON_INDEX_OFFSET = 4;
42 static const int LAT_INDEX_OFFSET = 6;
43 static const int ELEV_DATA_OFFSET = 8;
44 static const int RECORD_HDR_LENGTH = 12;
45 static const int BYTES_PER_POINT = 2;
46 
47 //**************************************************************************
48 // CONSTRUCTOR
49 //**************************************************************************
51  ossim_int32 offset,
52  ossim_int32 num_points)
53  :
54  theRecSen("170"),
55  theDataBlockCount(0),
56  theLonCount(0),
57  theLatCount(0),
58  theCheckSum(0),
59  thePoints(new ossim_int32[num_points]),
60  thePointsData(new ossim_uint16[num_points]),
61  theComputedCheckSum(0),
62  theNumPoints(num_points),
63  theStartOffset(offset),
64  theStopOffset(offset + RECORD_HDR_LENGTH + (num_points*BYTES_PER_POINT))
65 {
66  // Verify we are at a cell record by checking the Recognition Sentinel.
67  ossim_uint8 buf[1];
68  in.seekg(theStartOffset, std::ios::beg);
69  in.read((char*)buf, 1);
70 
71 #if 0
72  printf("\nBuf: %02X", (int)buf[0]); // Display in HEX
73 #endif
74 
75  if(buf[0] != DATA_RECOGNITION_SENTINEL)
76  {
78  ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimDtedRecord::ossimDtedRecord: reading DTED's data record at: " << theStartOffset
79  << std::endl;
80  return;
81  }
82 
83  // Valid data record, so let's process on.
84  parse(in);
85 
86  //***
87  // Note: The validateCheckSum method works; however, our in-house
88  // dted has bad stored check sums even though the post are good.
89  // So this in temporarily shut off.
90  //***
91  // Verify Check Sum for uncorrupted elevation data.
92  if(validateCheckSum(in) == false)
93  {
94  //***
95  // Note: The validateCheckSum method works; however, our in-house
96  // dted has bad stored check sums even though the posts are good.
97  // So this in temporarily shut off.
98  //***
101  << "FATAL ossimDtedRecord::ossimDtedRecord:"
102  << "\nInvalid checksum in data record at: "
103  << theStartOffset
104  << "\nParsed Check Sum = " << theCheckSum
105  << "\nComputed Check Sum = " << theComputedCheckSum
106  << "\nDTED Elevation File is considered corrupted."
107  << std::endl;
108  return;
109  }
110 }
111 
113 {
114  if (thePoints)
115  {
116  delete [] thePoints;
117  thePoints = NULL;
118  }
119  if (thePointsData)
120  {
121  delete [] thePointsData;
122  thePointsData = NULL;
123  }
124 }
125 
126 //**************************************************************************
127 // parse()
128 //**************************************************************************
130 {
131  // DTED is stored in big endian byte order so swap the bytes if needed.
132  bool swap_bytes = ossim::byteOrder() == OSSIM_LITTLE_ENDIAN ? true : false;
133 
134  ossim_sint16 s;
135 
136  // parse data block count
137  in.seekg(theStartOffset + BLOCK_COUNT_OFFSET, std::ios::beg);
138  in.read((char*)&s, 2);
140  (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);
141 
142  // parse lon count
143  in.seekg(theStartOffset + LON_INDEX_OFFSET, std::ios::beg);
144  in.read((char*)&s, 2);
145  theLonCount =
146  (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);
147 
148  // parse lat count
149  in.seekg(theStartOffset + LAT_INDEX_OFFSET, std::ios::beg);
150  in.read((char*)&s, 2);
151  theLatCount =
152  (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);
153 
154  // Parse all elevation points.
155  in.seekg(theStartOffset + ELEV_DATA_OFFSET, std::ios::beg);
156  for(int i = 0; i < theNumPoints; ++i)
157  {
158  in.read((char*)&s, 2);
159  s = (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);
160  if (s & DATA_SIGN_MASK)
161  {
162  s = (s & DATA_VALUE_MASK) * -1;
163  }
164  thePoints[i] = static_cast<ossim_int32>(s);
165  thePointsData[i] = s;
166  }
167 }
168 
169 //**************************************************************************
170 // validateCheckSum()
171 //**************************************************************************
173 {
174  // DTED is stored in big endian byte order so swap the bytes if needed.
175  bool swap_bytes = ossim::byteOrder() == OSSIM_LITTLE_ENDIAN ? true : false;
176 
177  // Compute the check sum.
178  in.seekg(theStartOffset, std::ios::beg);
180  ossim_int32 bytesToRead = (theNumPoints * 2) + ELEV_DATA_OFFSET;
181  int i = 0;
182 
183  for(i = 0; i < bytesToRead; i++)
184  {
185  ossim_uint8 c;
186  in.read((char*)&c, 1);
187  theComputedCheckSum += static_cast<ossim_uint32>(c);
188  }
189 
190  // Read the stored check sum and swap the byte if needed.
191  in.read((char*)&theCheckSum, 4);
192  if (swap_bytes)
193  {
194  ossimEndian swapper;
195  swapper.swap(theCheckSum);
196  }
197 
198  // Compare computed and parsed checksums.
200  {
201  return false;
202  }
203  return true;
204 }
205 
207 {
208  return theRecSen;
209 }
210 
212 {
213  return theDataBlockCount;
214 }
215 
217 {
218  return theLonCount;
219 }
220 
222 {
223  return theLatCount;
224 }
225 
227 {
228  return theCheckSum;
229 }
230 
232 {
233  return theComputedCheckSum;
234 }
235 
237 {
238  return theNumPoints;
239 }
240 
242 {
243  return thePoints[i];
244 }
245 
247 {
248  return thePointsData[i];
249 }
250 
252 {
253  return thePoints;
254 }
255 
257 {
258  return thePointsData;
259 }
260 
262 {
263  return theStartOffset;
264 }
265 
267 {
268  return theStopOffset;
269 }
270 
271 //**************************************************************************
272 // operator <<
273 //**************************************************************************
275 {
276  os << "\nDTED Record:"
277  << "\n-------------------------------"
278  << "\n Recognition Sentinel: " << rec.theRecSen
279  << "\nData Block Count: " << rec.theDataBlockCount
280  << "\nLon Count: " << rec.theLonCount
281  << "\nLat Count: " << rec.theLatCount
282  << "\nNum Points: " << rec.theNumPoints
283  << "\nParsed Check Sum: " << rec.theCheckSum
284  << "\nComputed Check Sum " << rec.theComputedCheckSum
285  << "\nStart Offset: " << rec.theStartOffset
286  << "\nStop Offset: " << rec.theStopOffset
287  << std::endl;
288  int i = 0;
289 
290  for(i = 0; i < rec.theNumPoints; i++)
291  {
292  os << "\nPoint[" << i << "]: " << rec.thePoints[i];
293  }
294 
295  os << std::endl;
296 
297  return os;
298 }
ossim_int32 startOffset() const
ossim_int32 lonCount() const
void parse(std::istream &in)
ossim_int32 stopOffset() const
ossim_int32 theNumPoints
ossim_int32 theStartOffset
std::ostream & operator<<(std::ostream &os, const ossimDtedRecord &rec)
ossim_int32 theLonCount
ossimString theRecSen
ossimString recognitionSentinel() const
ossim_int32 * points() const
ossimDtedRecord(std::istream &in, ossim_int32 offest, ossim_int32 num_points)
OSSIM_DLL ossimByteOrder byteOrder()
Definition: ossimCommon.cpp:54
static const ossimErrorCode OSSIM_ERROR
unsigned short ossim_uint16
ossim_int32 dataBlockCount() const
ossim_uint32 computedCheckSum() const
ossim_int32 theStopOffset
ossim_int32 getPoint(ossim_int32 i) const
signed short ossim_sint16
bool validateCheckSum(std::istream &in)
unsigned int ossim_uint32
ossim_int32 theDataBlockCount
ossim_int32 latCount() const
ossim_uint16 getPointData(ossim_int32 i) const
ossim_int32 theLatCount
ossim_int32 numPoints() const
ossim_uint32 theComputedCheckSum
std::basic_istream< char > istream
Base class for char input streams.
Definition: ossimIosFwd.h:20
ossim_int32 * thePoints
ossim_uint32 theCheckSum
ossim_uint16 * thePointsData
void swap(ossim_sint8 &)
Definition: ossimEndian.h:26
ossim_uint16 * pointsData() const
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
ossim_uint32 checkSum() const
int ossim_int32