#ifdef WIN32 #include using namespace std; #else #include #include #endif #ifndef INCLUDED_DEMPROFILE_HXX #include "DEMProfile.hxx" #endif #ifndef INCLUDED_DEMGRID_HXX #include "DEMGrid.hxx" #endif #ifndef INCLUDED_DEMHEADER_HXX #include "DEMHeader.hxx" #endif #ifndef INCLUDED_DEMPOINT_HXX #include "DEMPoint.hxx" #endif #ifndef INCLUDED_DEMUTIL_HXX #include "DEMUtil.hxx" #endif DEMGrid::DEMGrid(float missingDataValue) : _missDataVal(missingDataValue), _width(0), _height(0), _grid(0), _firstTime(true), _curProfile(0) { } DEMGrid::~DEMGrid() { delete _grid; } long DEMGrid::read(istream& dem, bool incrementalRead) { if (_firstTime) { dem >> _header; } long retval; if (_header.getGroundRefSysCode() == 0) // Geographic retval = fillGeographic(dem,incrementalRead); else retval = fillUTM(dem,incrementalRead); // This may not work if it's // really in State Plane. if (_firstTime) _firstTime = false; return retval; } DEMHeader const& DEMGrid::getHeader() const { return _header; } long DEMGrid::getWidth() const { return _width; } long DEMGrid::getHeight() const { return _height; } float DEMGrid::getElevation(long x, long y) const { if (_grid == 0) return _missDataVal; if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return _missDataVal; return _grid[(y * _width) + x]; } float DEMGrid::getMissingDataValue() const { return _missDataVal; } long DEMGrid::fillGeographic(istream& dem,bool incrementalRead) { if (_firstTime) { _curProfile = 0; _width = _header.getProfileColumns(); } while (_curProfile < _width) { _profiles.push_back(DEMProfile()); dem >> _profiles.back(); _curProfile++; if (incrementalRead) return _width - _curProfile + 1; } // Assume all profiles have as many elevations as the first. _height = _profiles[0].getNumberOfElevations(); _grid = new float[_width * _height]; DEMPoint sw_corner = _profiles[0].getProfileLocation(); _northwest_x = sw_corner.getX(); _northwest_y = sw_corner.getY() + ((_profiles[0].getNumberOfElevations() - 1) * _header.getSpatialResY()); long i,j; for (i = 0; i < _width; i++) { DEMElevationVector const& elev = _profiles[i].getElevations(); for (j = 0; j < elev.size(); j++) { setElevation(i, _height - j - 1, elev[j]); } } _profiles.erase(_profiles.begin(), _profiles.end()); return 0; } long DEMGrid::fillUTM(istream& dem, bool incrementalRead) { // 7.5 UTM DEMs are small enough we can get away with doing this stupid... long i; long x,y; // static vector profiles; if (_firstTime) { _curProfile = 0; _width = _header.getProfileColumns(); } while (_curProfile < _width) { _profiles.push_back(DEMProfile()); dem >> _profiles.back(); _curProfile++; if (incrementalRead) return _width - _curProfile + 1; } double dy = _header.getSpatialResY(); // Determine min and max Y values. // Some DEMs can have profiles which do not have any // elevations, and erroneous (x,y) values. I suspect // these are probably illegal DEMs, but we'll try to // do the right thing anyway. DEMPoint curpoint; i = 0; while ((_profiles[i].getNumberOfElevations() == 0) && (i < _profiles.size())) i++; if (i < _profiles.size()) curpoint = _profiles[i].getProfileLocation(); else { // XXX This isn't the best way to handle this... cerr << "Yikes! All profiles have zero elevations!\n"; exit(1); } double miny, maxy; miny = curpoint.getY(); maxy = miny; double profymin, profymax; // Min and max y values for current profile. for (i = 0; i < _profiles.size(); i++) { if (_profiles[i].getNumberOfElevations() > 0) { curpoint = _profiles[i].getProfileLocation(); profymin = curpoint.getY(); profymax = profymin + ((_profiles[i].getNumberOfElevations() - 1) * dy); if (profymin < miny) miny = profymin; if (profymax > maxy) maxy = profymax; } } // We now have minimum and maximum y values over all profiles in the DEM. // Allocate a rectangular array large enough to hold them. _height = static_cast(((maxy - miny) / dy) + 1); _grid = new float[_width * _height]; // Fill grid with the "missing data" value. for (i = 0; i < _width * _height; i++) _grid[i] = _missDataVal; DEMPoint sw_corner = _profiles[0].getProfileLocation(); _northwest_x = sw_corner.getX(); _northwest_y = maxy; // Now, insert the elevations in the profiles in the appropriate place in the grid. long startpos; for (x = 0; x < _width; x++) { DEMElevationVector const& elev = _profiles[x].getElevations(); curpoint = _profiles[x].getProfileLocation(); startpos = static_cast((curpoint.getY() - miny) / dy); for (y = 0; y < elev.size(); y++) { setElevation(x, _height - startpos - y - 1, elev[y]); } } _profiles.erase(_profiles.begin(), _profiles.end()); return 0; } void DEMGrid::getGroundCoords(long x, long y, double& ground_x, double& ground_y) { ground_x = _northwest_x + (x * _header.getSpatialResX()); ground_y = _northwest_y - (y * _header.getSpatialResY()); }