void ossimDtedHandler::readPostsFromFile( DtedHeight &postData, int offset) { OpenThreads::ScopedLock <OpenThreads::Mutex> lock( m_fileStrMutex ); ossim_sint16 ss; ossim_uint16 us; int postCount = 0; // read the posts in blocks 2x2. for ( int column = 0; column < NUM_POSTS_PER_BLOCK ; ++column ) { m_fileStr.seekg( offset, std::ios::beg ); for ( int row = 0; row < NUM_POSTS_PER_BLOCK ; ++row ) { if ( !m_fileStr.eof() ) { us = 0; m_fileStr.read( ( char* ) &us, POST_SIZE ); // check the read was ok if ( m_fileStr.good() ) { postData.m_posts[postCount].m_status = true; } else { // reset the goodbit m_fileStr.clear(); } ss = convertSignedMagnitude( us ); postData.m_posts[postCount].m_height = ss; } postCount++; } offset += m_dtedRecordSizeInBytes; } }
double ossimDtedHandler::getPostValue(const ossimIpt& gridPt) const { static const char MODULE[] = "ossimDtedHandler::getPostValue"; // Do some error checking. if ( gridPt.x < 0.0 || gridPt.y < 0.0 || gridPt.x > (m_numLonLines - 1) || gridPt.y > (m_numLatPoints - 1) ) { if(traceDebug()) { ossimNotify(ossimNotifyLevel_WARN) << "WARNING " << MODULE << ": No intersection..." << std::endl; } return ossim::nan(); } if (!isOpen()) { return ossim::nan(); } int offset = m_offsetToFirstDataRecord + gridPt.x * m_dtedRecordSizeInBytes + gridPt.y * 2 + DATA_RECORD_OFFSET_TO_POST; // Put the file pointer at the start of the first elevation post. m_fileStr.seekg(offset, std::ios::beg); ossim_uint16 us; // Get the post. m_fileStr.read((char*)&us, POST_SIZE); return double(convertSignedMagnitude(us)); }
void ossimDtedHandler::gatherStatistics() { //*** // Check to see if there is a statistics file already. If so; do a lookup // for the min and max values. //*** ossimFilename stats_file = theFilename;//theFilename.path(); stats_file.setExtension("statistics"); if (traceDebug()) { ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimDtedHandler::gatherStatistics(): Looking for " << stats_file << " statistics file..." << std::endl; } ossimKeywordlist kwl; const char* min_str = NULL; const char* max_str = NULL; if (stats_file.exists()) { if (kwl.addFile(stats_file)) { // Look for the min_pixel_value keyword. min_str = kwl.find(ossimKeywordNames::MIN_VALUE_KW); max_str = kwl.find(ossimKeywordNames::MAX_VALUE_KW); } } if (min_str && max_str) { theMinHeightAboveMSL = atoi(min_str); theMaxHeightAboveMSL = atoi(max_str); } else if (theComputeStatsFlag&&!m_memoryMap.size()) // Scan the cell and gather the statistics... { if(traceDebug()) { ossimNotify(ossimNotifyLevel_NOTICE) << "NOTICE ossimDtedHandler::gatherStatistics():" << " scanning for min/max" << "\nThis may take a while..." << std::endl; } // Start off with the min and max pegged. theMinHeightAboveMSL = 32767; theMaxHeightAboveMSL = -32767; // Put the file pointer at the start of the first elevation post. m_fileStr.seekg(m_offsetToFirstDataRecord, std::ios::beg); //--- // Loop through all records and scan for lowest min and highest max. // Each record contains a row of latitude points for a given longitude. // There are eight bytes in front of the post and four checksum bytes at // the end so ignore them. //--- for (ossim_int32 i=0; i<m_numLonLines; ++i) // longitude direction { m_fileStr.seekg(DATA_RECORD_OFFSET_TO_POST, std::ios::cur); for (ossim_int32 j=0; j<m_numLatPoints; ++j) // latitude direction { ossim_uint16 us; ossim_sint16 ss; m_fileStr.read((char*)&us, POST_SIZE); ss = convertSignedMagnitude(us); if (ss < theMinHeightAboveMSL && ss != NULL_POST) { theMinHeightAboveMSL = ss; } if (ss > theMaxHeightAboveMSL) { theMaxHeightAboveMSL = ss; } } m_fileStr.seekg(DATA_RECORD_CHECKSUM_SIZE, std::ios::cur); } // Add the stats to the keyword list. kwl.add(ossimKeywordNames::MIN_VALUE_KW, theMinHeightAboveMSL); kwl.add(ossimKeywordNames::MAX_VALUE_KW, theMaxHeightAboveMSL); // Write out the statistics file. kwl.write(stats_file.c_str()); } if (traceDebug()) { ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimDtedHandler::gatherStatistics:" << "\ntheMinHeightAboveMSL: " << theMinHeightAboveMSL << "\ntheMaxHeightAboveMSL: " << theMaxHeightAboveMSL << std::endl; } }
double ossimDtedHandler::getHeightAboveMSL(const ossimGpt& gpt, bool readFromFile) { // Establish the grid indexes: double xi = (gpt.lon - m_swCornerPost.lon) / m_lonSpacing; double yi = (gpt.lat - m_swCornerPost.lat) / m_latSpacing; // Check for right edge. int x0 = static_cast<int>(xi); int y0 = static_cast<int>(yi); if(x0 == (m_numLonLines-1)) { --x0; // Move over one post. } // Check for top edge. // if (gpt.lat == theGroundRect.ul().lat) if(y0 == (m_numLatPoints-1)) { --y0; // Move down one post. } // Do some error checking. if ( xi < 0.0 || yi < 0.0 || x0 > (m_numLonLines - 2.0) || y0 > (m_numLatPoints - 2.0) ) { return ossim::nan(); } //*** // Grab the four points from the dted cell needed. These are big endian, // signed magnitude shorts so they must be interpreted accordingly. //*** int offset = m_offsetToFirstDataRecord + x0 * m_dtedRecordSizeInBytes + y0 * 2 + DATA_RECORD_OFFSET_TO_POST; /// read the posts from the DTED file. DtedHeight postData; // if ( readFromFile ) { readPostsFromFile( postData, offset ); } else { ossim_uint8* buf = &m_memoryMap.front(); { ossim_uint16 us; memcpy(&us, buf+offset, POST_SIZE); postData.m_posts[0].m_height = convertSignedMagnitude(us); memcpy(&us, buf+offset+POST_SIZE, POST_SIZE); postData.m_posts[1].m_height = convertSignedMagnitude(us); // Move over to the next column. offset += m_dtedRecordSizeInBytes; memcpy(&us, buf+offset, POST_SIZE); postData.m_posts[2].m_height = convertSignedMagnitude(us); memcpy(&us, buf+offset+POST_SIZE, POST_SIZE); postData.m_posts[3].m_height = convertSignedMagnitude(us); } } // Perform bilinear interpolation: double wx1 = xi - x0; double wy1 = yi - y0; double wx0 = 1.0 - wx1; double wy0 = 1.0 - wy1; postData.m_posts[0].m_weight = wx0*wy0; postData.m_posts[1].m_weight = wx0*wy1; postData.m_posts[2].m_weight = wx1*wy0; postData.m_posts[3].m_weight = wx1*wy1; #if 0 /* Serious debug only... */ postData.debug(); #endif return postData.calcHeight(); }
double ossimDtedHandler::getHeightAboveMSLMemory(const ossimGpt& gpt) { ossim_uint8* buf = &m_memoryMap.front(); // Establish the grid indexes: double xi = (gpt.lon - m_swCornerPost.lon) / m_lonSpacing; double yi = (gpt.lat - m_swCornerPost.lat) / m_latSpacing; // Check for right edge. int x0 = static_cast<int>(xi); int y0 = static_cast<int>(yi); // Check for right edge. // if (gpt.lon == theGroundRect.lr().lon) if(x0 == (m_numLonLines-1)) { --x0; // Move over one post. } // Check for top edge. // if (gpt.lat == theGroundRect.ul().lat) if(y0 == (m_numLatPoints-1)) { --y0; // Move down one post. } // Do some error checking. if ( xi < 0.0 || yi < 0.0 || x0 > (m_numLonLines - 2.0) || y0 > (m_numLatPoints - 2.0) ) { return ossim::nan(); } double p00; double p01; double p10; double p11; //*** // Grab the four points from the dted cell needed. These are big endian, // signed magnitude shorts so they must be interpreted accordingly. //*** ossim_uint64 offset = m_offsetToFirstDataRecord + x0 * m_dtedRecordSizeInBytes + y0 * 2 + DATA_RECORD_OFFSET_TO_POST; { ossim_uint16 us; memcpy(&us, buf+offset, POST_SIZE); p00 = convertSignedMagnitude(us); memcpy(&us, buf+offset+POST_SIZE, POST_SIZE); p01 = convertSignedMagnitude(us); // Move over to the next column. offset += m_dtedRecordSizeInBytes; memcpy(&us, buf+offset, POST_SIZE); p10 = convertSignedMagnitude(us); memcpy(&us, buf+offset+POST_SIZE, POST_SIZE); p11 = convertSignedMagnitude(us); } // Perform bilinear interpolation: double wx1 = xi - x0; double wy1 = yi - y0; double wx0 = 1.0 - wx1; double wy0 = 1.0 - wy1; double w00 = wx0*wy0; double w01 = wx0*wy1; double w10 = wx1*wy0; double w11 = wx1*wy1; //*** // Test for null posts and set the corresponding weights to 0: //*** if (p00 == NULL_POST) w00 = 0.0; if (p01 == NULL_POST) w01 = 0.0; if (p10 == NULL_POST) w10 = 0.0; if (p11 == NULL_POST) w11 = 0.0; #if 0 /* Serious debug only... */ cout << "\np00: " << p00 << "\np01: " << p01 << "\np10: " << p10 << "\np11: " << p11 << "\nw00: " << w00 << "\nw01: " << w01 << "\nw10: " << w10 << "\nw11: " << w11 << std::endl; #endif double sum_weights = w00 + w01 + w10 + w11; if (sum_weights) { return (p00*w00 + p01*w01 + p10*w10 + p11*w11) / sum_weights; } return ossim::nan(); }