public HeightMap GetHeightMap(FileMetadata metadata) { HeightMap heightMap = new HeightMap(metadata.Width, metadata.Height); heightMap.Count = heightMap.Width * heightMap.Height; var coords = new List <GeoPoint>(heightMap.Count); _hgtStream.Seek(0, SeekOrigin.Begin); // metadata.BitsPerSample // When 16 we have 2 bytes per sample // When 32 we have 4 bytes per sample int bytesPerSample = metadata.BitsPerSample / 8; byte[] byteScanline = new byte[metadata.ScanlineSize]; for (int y = 0; y < metadata.Height; y++) { _hgtStream.Read(byteScanline, 0, metadata.ScanlineSize); double latitude = metadata.PhysicalStartLat + (metadata.pixelSizeY * y); for (int x = 0; x < metadata.Width; x++) { double longitude = metadata.PhysicalStartLon + (metadata.pixelSizeX * x); float heightValue = 0; byte[] heightBytes = new byte[bytesPerSample];; if (BitConverter.IsLittleEndian) { // reverse bytes for (int i = 0; i < bytesPerSample; i++) { heightBytes[i] = byteScanline[x * bytesPerSample + bytesPerSample - i - 1]; } switch (metadata.SampleFormat) { case RasterSampleFormat.FLOATING_POINT: heightValue = BitConverter.ToSingle(heightBytes, 0); break; case RasterSampleFormat.INTEGER: heightValue = BitConverter.ToInt16(heightBytes, 0); break; case RasterSampleFormat.UNSIGNED_INTEGER: heightValue = BitConverter.ToUInt16(heightBytes, 0); break; default: throw new Exception("Sample format unsupported."); } } else { switch (metadata.SampleFormat) { case RasterSampleFormat.FLOATING_POINT: heightValue = BitConverter.ToSingle(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.INTEGER: heightValue = BitConverter.ToInt16(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.UNSIGNED_INTEGER: heightValue = BitConverter.ToUInt16(byteScanline, x * bytesPerSample); break; default: throw new Exception("Sample format unsupported."); } } if (heightValue < 32768) { heightMap.Minimum = Math.Min(metadata.MinimumAltitude, heightValue); heightMap.Maximum = Math.Max(metadata.MaximumAltitude, heightValue); } else { heightValue = 0; } coords.Add(new GeoPoint(latitude, longitude, heightValue)); } } heightMap.Coordinates = coords; return(heightMap); }
public FileMetadata ParseMetaData(DEMFileDefinition format) { FileMetadata metadata = new FileMetadata(_filename, format); int numPixels = _fileBytesCount == HGTFile.HGT1201 ? 1201 : 3601; if (format.Registration == DEMFileRegistrationMode.Grid) { /// metadata.Height = numPixels; metadata.Width = numPixels; metadata.PixelScaleX = 1d / (numPixels - 1); metadata.PixelScaleY = 1d / (numPixels - 1); metadata.pixelSizeX = metadata.PixelScaleX; metadata.pixelSizeY = -metadata.PixelScaleY; // fileName gives is coordinates of center of first lower left pixel (south west) // example N08E003.hgt string fileTitle = Path.GetFileNameWithoutExtension(_filename); int latSign = fileTitle.Substring(0, 1) == "N" ? 1 : -1; int lonSign = fileTitle.Substring(3, 1) == "E" ? 1 : -1; int lat = int.Parse(fileTitle.Substring(1, 2)) * latSign; int lon = int.Parse(fileTitle.Substring(4, 3)) * lonSign; metadata.DataStartLon = lon; metadata.DataStartLat = lat; metadata.DataEndLon = lon + 1; metadata.DataEndLat = lat + 1; metadata.PhysicalStartLat = metadata.DataStartLat + (metadata.pixelSizeY / 2.0); metadata.PhysicalStartLon = metadata.DataStartLon - (metadata.pixelSizeX / 2.0); metadata.PhysicalEndLon = metadata.Width * metadata.pixelSizeX + metadata.DataStartLon; metadata.PhysicalEndLat = metadata.DataStartLat + metadata.Height * Math.Abs(metadata.pixelSizeY); metadata.ScanlineSize = numPixels * 2; // 16 bit signed integers metadata.BitsPerSample = 16; // Add other information about the data metadata.SampleFormat = RasterSampleFormat.INTEGER; // TODO: Read this from tiff metadata or determine after parsing metadata.NoDataValue = "-32768"; } else { throw new NotSupportedException("HGT files should always be grid registered, not cell registered."); /// //metadata.Height = numPixels; //metadata.Width = numPixels; //metadata.PixelScaleX = 1d / numPixels; //metadata.PixelScaleY = 1d / numPixels; //metadata.pixelSizeX = metadata.PixelScaleX; //metadata.pixelSizeY = -metadata.PixelScaleY; //// fileName gives is coordinates of center of first lower left pixel (south west) //// example N08E003.hgt //string fileTitle = Path.GetFileNameWithoutExtension(_filename); //int latSign = fileTitle.Substring(0, 1) == "N" ? 1 : -1; //int lonSign = fileTitle.Substring(3, 1) == "E" ? 1 : -1; //int lat = int.Parse(fileTitle.Substring(1, 2)) * latSign; //int lon = int.Parse(fileTitle.Substring(4, 3)) * lonSign; //metadata.OriginLongitude = lon; //metadata.OriginLatitude = lat + 1; //metadata.StartLat = metadata.OriginLatitude + (metadata.pixelSizeY / 2.0); //metadata.StartLon = metadata.OriginLongitude + (metadata.pixelSizeX / 2.0); //metadata.ScanlineSize = numPixels * 2; // 16 bit signed integers //metadata.BitsPerSample = 16; //// Add other information about the data //metadata.SampleFormat = RasterSampleFormat.INTEGER; //// TODO: Read this from tiff metadata or determine after parsing //metadata.NoDataValue = "-32768"; //return metadata; } return(metadata); }
public HeightMap GetHeightMapInBBox(BoundingBox bbox, FileMetadata metadata, float noDataValue = float.MinValue) { // metadata.BitsPerSample // When 16 we have 2 bytes per sample // When 32 we have 4 bytes per sample int bytesPerSample = metadata.BitsPerSample / 8; byte[] byteScanline = new byte[metadata.ScanlineSize]; int registrationOffset = metadata.FileFormat.Registration == DEMFileRegistrationMode.Grid ? 1 : 0; int yNorth = (int)Math.Floor((bbox.yMax - metadata.PhysicalEndLat) / metadata.pixelSizeY); int ySouth = (int)Math.Ceiling((bbox.yMin - metadata.PhysicalEndLat) / metadata.pixelSizeY); int xWest = (int)Math.Floor((bbox.xMin - metadata.PhysicalStartLon) / metadata.pixelSizeX); int xEast = (int)Math.Ceiling((bbox.xMax - metadata.PhysicalStartLon) / metadata.pixelSizeX); xWest = Math.Max(0, xWest); xEast = Math.Min(metadata.Width - 1 - registrationOffset, xEast); yNorth = Math.Max(0, yNorth); ySouth = Math.Min(metadata.Height - 1 - registrationOffset, ySouth); HeightMap heightMap = new HeightMap(xEast - xWest + 1, ySouth - yNorth + 1); heightMap.Count = heightMap.Width * heightMap.Height; var coords = new List <GeoPoint>(heightMap.Count); heightMap.BoundingBox = new BoundingBox(0, 0, 0, 0); // Set position to ystart _hgtStream.Seek(yNorth * metadata.ScanlineSize, SeekOrigin.Begin); for (int y = yNorth; y <= ySouth; y++) { _hgtStream.Read(byteScanline, 0, metadata.ScanlineSize); double latitude = metadata.DataEndLat + (metadata.pixelSizeY * y); // bounding box if (y == yNorth) { heightMap.BoundingBox.yMax = latitude; heightMap.BoundingBox.xMin = metadata.DataStartLon + (metadata.pixelSizeX * xWest); heightMap.BoundingBox.xMax = metadata.DataStartLon + (metadata.pixelSizeX * xEast); } else if (y == ySouth) { heightMap.BoundingBox.yMin = latitude; } for (int x = xWest; x <= xEast; x++) { double longitude = metadata.DataStartLon + (metadata.pixelSizeX * x); byte[] heightBytes = new byte[bytesPerSample]; float heightValue = 0; if (BitConverter.IsLittleEndian) { // reverse bytes for (int i = 0; i < bytesPerSample; i++) { heightBytes[i] = byteScanline[x * bytesPerSample + bytesPerSample - i - 1]; } switch (metadata.SampleFormat) { case RasterSampleFormat.FLOATING_POINT: heightValue = BitConverter.ToSingle(heightBytes, 0); break; case RasterSampleFormat.INTEGER: heightValue = BitConverter.ToInt16(heightBytes, 0); break; case RasterSampleFormat.UNSIGNED_INTEGER: heightValue = BitConverter.ToUInt16(heightBytes, 0); break; default: throw new Exception("Sample format unsupported."); } } else { switch (metadata.SampleFormat) { case RasterSampleFormat.FLOATING_POINT: heightValue = BitConverter.ToSingle(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.INTEGER: heightValue = BitConverter.ToInt16(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.UNSIGNED_INTEGER: heightValue = BitConverter.ToUInt16(byteScanline, x * bytesPerSample); break; default: throw new Exception("Sample format unsupported."); } } if (heightValue < -10) { heightMap.Minimum = Math.Min(heightMap.Minimum, heightValue); heightMap.Maximum = Math.Max(heightMap.Maximum, heightValue); } else if (heightValue < 32768) { heightMap.Minimum = Math.Min(heightMap.Minimum, heightValue); heightMap.Maximum = Math.Max(heightMap.Maximum, heightValue); } else { heightValue = (float)noDataValue; } coords.Add(new GeoPoint(latitude, longitude, heightValue)); } } Debug.Assert(heightMap.Width * heightMap.Height == coords.Count); heightMap.Coordinates = coords; return(heightMap); }
private float GetElevationAtPoint(RasterFileDictionary adjacentTiles, FileMetadata metadata, double lat, double lon, float lastElevation, IInterpolator interpolator) { return(GetElevationAtPoint(adjacentTiles[metadata], adjacentTiles, metadata, lat, lon, lastElevation, interpolator ?? GetInterpolator(InterpolationMode.Bilinear))); }
private float GetElevationAtPoint(IRasterFile mainRaster, RasterFileDictionary adjacentTiles, FileMetadata metadata, double lat, double lon, float lastElevation, IInterpolator interpolator) { float heightValue = 0; try { //const double epsilon = (Double.Epsilon * 100); float noData = metadata.NoDataValueFloat; double yPixel, xPixel, xInterpolationAmount, yInterpolationAmount; // pixel coordinates interpolated if (metadata.FileFormat.Registration == DEMFileRegistrationMode.Grid) { yPixel = Math.Sign(metadata.pixelSizeY) == 1 ? (metadata.DataEndLat - lat) / metadata.pixelSizeY : (lat - metadata.DataEndLat) / metadata.pixelSizeY; xPixel = (lon - metadata.DataStartLon) / metadata.pixelSizeX; // If at pixel center (ending by .5, .5), we are on the data point, so no need for adjacent raster checks xInterpolationAmount = (double)(xPixel) % 1d; yInterpolationAmount = (double)(yPixel) % 1d; } else { // In cell registration mode, the actual data point is at pixel center // If at pixel center (ending by .5, .5), we are on the data point, so no need for adjacent raster checks yPixel = Math.Sign(metadata.pixelSizeY) == 1 ? ((metadata.PhysicalEndLat + metadata.pixelSizeY / 2) - lat) / metadata.pixelSizeY : (lat - (metadata.PhysicalEndLat + metadata.pixelSizeY / 2)) / metadata.pixelSizeY; xPixel = (lon - (metadata.PhysicalStartLon + metadata.pixelSizeX / 2)) / metadata.pixelSizeX; xInterpolationAmount = Math.Abs((double)(xPixel) % 1d); yInterpolationAmount = Math.Abs((double)(yPixel) % 1d); } bool xOnDataPoint = Math.Abs(xInterpolationAmount) < EPSILON; bool yOnDataPoint = Math.Abs(yInterpolationAmount) < EPSILON; // If xOnGrid and yOnGrid, we are on a grid intersection, and that's all // TODO fix that // When cell registered, this true when interpolation is 0.5 / 0.5 // When grid registered, this is true if (xOnDataPoint && yOnDataPoint) { int x = (int)Math.Round(xPixel, 0); int y = (int)Math.Round(yPixel, 0); var tile = FindTile(metadata, adjacentTiles, x, y, out x, out y); heightValue = mainRaster.GetElevationAtPoint(tile, x, y); } else { int xCeiling = (int)Math.Ceiling(xPixel); int xFloor = (int)Math.Floor(xPixel); int yCeiling = (int)Math.Ceiling(yPixel); int yFloor = (int)Math.Floor(yPixel); // Get 4 grid nearest points (DEM grid corners) // If not yOnGrid and not xOnGrid we are on grid horizontal line // We need elevations for top, bottom, left and right grid points (along x axis and y axis) float northWest = GetElevationAtPoint(metadata, adjacentTiles, xFloor, yFloor, noData); float northEast = GetElevationAtPoint(metadata, adjacentTiles, xCeiling, yFloor, noData); float southWest = GetElevationAtPoint(metadata, adjacentTiles, xFloor, yCeiling, noData); float southEast = GetElevationAtPoint(metadata, adjacentTiles, xCeiling, yCeiling, noData); float avgHeight = GetAverageExceptForNoDataValue(noData, NO_DATA_OUT, southWest, southEast, northWest, northEast); if (northWest == noData) { northWest = avgHeight; } if (northEast == noData) { northEast = avgHeight; } if (southWest == noData) { southWest = avgHeight; } if (southEast == noData) { southEast = avgHeight; } heightValue = (float)interpolator.Interpolate(southWest, southEast, northWest, northEast, xInterpolationAmount, yInterpolationAmount); } if (heightValue == NO_DATA_OUT) { heightValue = lastElevation; } } catch (Exception e) { _logger?.LogError(e, $"Error while getting elevation data : {e.Message}{Environment.NewLine}{e.ToString()}"); throw; } return(heightValue); }
public bool IsBboxIntersectingTile(FileMetadata tileMetadata, BoundingBox bbox) { BoundingBox tileBBox = tileMetadata.BoundingBox; return((tileBBox.xMax >= bbox.xMin && tileBBox.xMin <= bbox.xMax) && (tileBBox.yMax >= bbox.yMin && tileBBox.yMin <= bbox.yMax)); }
public bool IsPointInTile(FileMetadata tileMetadata, GeoPoint point) { return(IsPointInTile(tileMetadata, point.Latitude, point.Longitude)); }
public HeightMap GetHeightMapInBBox(BoundingBox bbox, FileMetadata metadata, float noDataValue = 0) { int yStart = 0; int yEnd = 0; int xStart = 0; int xEnd = 0; if (metadata.FileFormat.Registration == DEMFileRegistrationMode.Grid) { yStart = (int)Math.Floor((bbox.yMax - metadata.PhysicalEndLat) / metadata.pixelSizeY); yEnd = (int)Math.Ceiling((bbox.yMin - metadata.PhysicalEndLat) / metadata.pixelSizeY); xStart = (int)Math.Floor((bbox.xMin - metadata.PhysicalStartLon) / metadata.pixelSizeX); xEnd = (int)Math.Ceiling((bbox.xMax - metadata.PhysicalStartLon) / metadata.pixelSizeX); } else { yStart = (int)Math.Floor((bbox.yMax - metadata.DataEndLat) / metadata.pixelSizeY); yEnd = (int)Math.Ceiling((bbox.yMin - metadata.DataEndLat) / metadata.pixelSizeY); xStart = (int)Math.Floor((bbox.xMin - metadata.DataStartLon) / metadata.pixelSizeX); xEnd = (int)Math.Ceiling((bbox.xMax - metadata.DataStartLon) / metadata.pixelSizeX); } // Tiled geotiffs like aster have overlapping 1px borders int overlappingPixel = this.IsTiled ? 1 : 0; xStart = Math.Max(0, xStart); xEnd = Math.Min(metadata.Width - 1, xEnd) - overlappingPixel; yStart = Math.Max(0, yStart); yEnd = Math.Min(metadata.Height - 1, yEnd) - overlappingPixel; HeightMap heightMap = new HeightMap(xEnd - xStart + 1, yEnd - yStart + 1); heightMap.Count = heightMap.Width * heightMap.Height; var coords = new List <GeoPoint>(heightMap.Count); heightMap.BoundingBox = new BoundingBox(0, 0, 0, 0); if (this.IsTiled) { // Tiled rasters are composed of multiple "sub" images // TODO store in metadata int tileWidth = this.TileWidth; int tileHeight = this.TileHeight; int tileSize = this.TileSize; byte[] buffer; for (int y = yStart; y <= yEnd; y++) { double latitude = metadata.DataEndLat + (metadata.pixelSizeY * y); // bounding box if (y == yStart) { heightMap.BoundingBox.yMax = latitude; heightMap.BoundingBox.xMin = metadata.DataStartLon + (metadata.pixelSizeX * xStart); heightMap.BoundingBox.xMax = metadata.DataStartLon + (metadata.pixelSizeX * xEnd); } else if (y == yEnd) { heightMap.BoundingBox.yMin = latitude; } for (int x = xStart; x <= xEnd; x++) { double longitude = metadata.DataStartLon + (metadata.pixelSizeX * x); var tileX = (x / tileWidth) * tileWidth; var tileY = (y / tileHeight) * tileHeight; if (tilesCache == null) { tilesCache = new Dictionary <int, byte[]>(); } var tileKey = (x / tileWidth) + (y / tileHeight) * (metadata.Width / tileWidth + 1); if (!tilesCache.TryGetValue(tileKey, out buffer)) { buffer = new byte[tileSize]; TiffFile.ReadTile(buffer, 0, tileX, tileY, 0, 0); tilesCache.Add(tileKey, buffer); } var offset = x - tileX + (y - tileY) * tileHeight; float heightValue = GetElevationAtPoint(metadata, offset, buffer); if (heightValue <= 0) { heightMap.Minimum = Math.Min(heightMap.Minimum, heightValue); heightMap.Maximum = Math.Max(heightMap.Maximum, heightValue); } else if (heightValue < 32768) { heightMap.Minimum = Math.Min(heightMap.Minimum, heightValue); heightMap.Maximum = Math.Max(heightMap.Maximum, heightValue); } else { heightValue = (float)noDataValue; } coords.Add(new GeoPoint(latitude, longitude, heightValue)); } } } else { // metadata.BitsPerSample // When 16 we have 2 bytes per sample // When 32 we have 4 bytes per sample int bytesPerSample = metadata.BitsPerSample / 8; byte[] byteScanline = new byte[metadata.ScanlineSize]; double endLat = metadata.DataEndLat + metadata.pixelSizeY / 2d; double startLon = metadata.DataStartLon + metadata.pixelSizeX / 2d; for (int y = yStart; y <= yEnd; y++) { TiffFile.ReadScanline(byteScanline, y); // TODO: handle Cell registered DEMs: lat is 1/2 pixel off double latitude = endLat + (metadata.pixelSizeY * y); // bounding box if (y == yStart) { heightMap.BoundingBox.yMax = latitude; heightMap.BoundingBox.xMin = startLon + (metadata.pixelSizeX * xStart); heightMap.BoundingBox.xMax = startLon + (metadata.pixelSizeX * xEnd); } else if (y == yEnd) { heightMap.BoundingBox.yMin = latitude; } for (int x = xStart; x <= xEnd; x++) { double longitude = startLon + (metadata.pixelSizeX * x); float heightValue = 0; switch (metadata.SampleFormat) { case RasterSampleFormat.FLOATING_POINT: heightValue = BitConverter.ToSingle(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.INTEGER: heightValue = BitConverter.ToInt16(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.UNSIGNED_INTEGER: heightValue = BitConverter.ToUInt16(byteScanline, x * bytesPerSample); break; default: throw new Exception("Sample format unsupported."); } if (heightValue <= 0) { heightMap.Minimum = Math.Min(heightMap.Minimum, heightValue); heightMap.Maximum = Math.Max(heightMap.Maximum, heightValue); } else if (heightValue < 32768) { heightMap.Minimum = Math.Min(heightMap.Minimum, heightValue); heightMap.Maximum = Math.Max(heightMap.Maximum, heightValue); } else { heightValue = (float)noDataValue; } coords.Add(new GeoPoint(latitude, longitude, heightValue)); } } } Debug.Assert(heightMap.Width * heightMap.Height == coords.Count); heightMap.Coordinates = coords; return(heightMap); }
public HeightMap GetHeightMap(FileMetadata metadata) { if (this.isTiled) { throw new NotImplementedException("Whole height map with tile geoTiff is not implemented"); } HeightMap heightMap = new HeightMap(metadata.Width, metadata.Height); heightMap.Count = heightMap.Width * heightMap.Height; var coords = new List <GeoPoint>(heightMap.Count); // metadata.BitsPerSample // When 16 we have 2 bytes per sample // When 32 we have 4 bytes per sample int bytesPerSample = metadata.BitsPerSample / 8; byte[] byteScanline = new byte[metadata.ScanlineSize]; for (int y = 0; y < metadata.Height; y++) { TiffFile.ReadScanline(byteScanline, y); double latitude = metadata.DataStartLat + (metadata.pixelSizeY * y); for (int x = 0; x < metadata.Width; x++) { double longitude = metadata.DataStartLon + (metadata.pixelSizeX * x); float heightValue = 0; switch (metadata.SampleFormat) { case RasterSampleFormat.FLOATING_POINT: heightValue = BitConverter.ToSingle(byteScanline, x * metadata.BitsPerSample / 8); break; case RasterSampleFormat.INTEGER: heightValue = BitConverter.ToInt16(byteScanline, x * metadata.BitsPerSample / 8); break; case RasterSampleFormat.UNSIGNED_INTEGER: heightValue = BitConverter.ToUInt16(byteScanline, x * metadata.BitsPerSample / 8); break; default: throw new Exception("Sample format unsupported."); } if (heightValue < 32768) { heightMap.Minimum = Math.Min(metadata.MinimumAltitude, heightValue); heightMap.Maximum = Math.Max(metadata.MaximumAltitude, heightValue); } else { heightValue = 0; } coords.Add(new GeoPoint(latitude, longitude, heightValue)); } } heightMap.Coordinates = coords; return(heightMap); }
public FileMetadata ParseMetaData(DEMFileDefinition fileFormat) { try { string ncolsLine = _streamReader.ReadLine(); string nrowsLine = _streamReader.ReadLine(); string xllcornerLine = _streamReader.ReadLine(); string yllcornerLine = _streamReader.ReadLine(); string cellsizeLine = _streamReader.ReadLine(); string NODATA_valueLine = _streamReader.ReadLine(); DebugCheckRegistrationType(fileFormat.Registration, xllcornerLine, yllcornerLine); int ncols = int.Parse(ncolsLine.Split(SEPARATOR, StringSplitOptions.RemoveEmptyEntries)[1]); int nrows = int.Parse(nrowsLine.Split(SEPARATOR, StringSplitOptions.RemoveEmptyEntries)[1]); double xllcorner = double.Parse(xllcornerLine.Split(SEPARATOR, StringSplitOptions.RemoveEmptyEntries)[1], CultureInfo.InvariantCulture); double yllcorner = double.Parse(yllcornerLine.Split(SEPARATOR, StringSplitOptions.RemoveEmptyEntries)[1], CultureInfo.InvariantCulture); double cellsize = double.Parse(cellsizeLine.Split(SEPARATOR, StringSplitOptions.RemoveEmptyEntries)[1], CultureInfo.InvariantCulture); float NODATA_value = float.Parse(NODATA_valueLine.Split(SEPARATOR, StringSplitOptions.RemoveEmptyEntries)[1], CultureInfo.InvariantCulture); FileMetadata metadata = new FileMetadata(_filename, fileFormat); metadata.Height = nrows; metadata.Width = ncols; metadata.PixelScaleX = cellsize; metadata.PixelScaleY = cellsize; metadata.pixelSizeX = cellsize; metadata.pixelSizeY = -cellsize; if (fileFormat.Registration == DEMFileRegistrationMode.Grid) { metadata.DataStartLat = yllcorner; metadata.DataStartLon = xllcorner; metadata.DataEndLat = yllcorner + metadata.Height * metadata.pixelSizeY; metadata.DataEndLon = xllcorner + metadata.Width * metadata.pixelSizeX; metadata.PhysicalStartLat = yllcorner; metadata.PhysicalStartLon = xllcorner; metadata.PhysicalEndLat = metadata.DataEndLat; metadata.PhysicalEndLon = metadata.DataEndLon; } else { metadata.DataStartLat = Math.Round(yllcorner + (metadata.pixelSizeY / 2.0), 10); metadata.DataStartLon = Math.Round(xllcorner - (metadata.PixelScaleX / 2.0), 10); metadata.DataEndLat = yllcorner + metadata.Height * cellsize; metadata.DataEndLon = xllcorner + metadata.Width * cellsize; metadata.DataEndLat = Math.Round(metadata.DataEndLat - (metadata.PixelScaleY / 2.0), 10); metadata.DataEndLon = Math.Round(metadata.DataEndLon - (metadata.PixelScaleX / 2.0), 10); metadata.PhysicalStartLat = metadata.DataStartLat; metadata.PhysicalStartLon = metadata.DataStartLon; metadata.PhysicalEndLat = metadata.DataEndLat; metadata.PhysicalEndLon = metadata.DataEndLon; } metadata.SampleFormat = RasterSampleFormat.FLOATING_POINT; metadata.NoDataValue = NODATA_value.ToString(); return(metadata); } catch (Exception) { throw; } }
public FileMetadata ParseMetaData(DEMFileDefinition format) { FileMetadata metadata = new FileMetadata(FilePath, format); /// metadata.Height = TiffFile.GetField(TiffTag.IMAGELENGTH)[0].ToInt(); metadata.Width = TiffFile.GetField(TiffTag.IMAGEWIDTH)[0].ToInt(); /// FieldValue[] modelPixelScaleTag = TiffFile.GetField(TiffTag.GEOTIFF_MODELPIXELSCALETAG); FieldValue[] modelTiepointTag = TiffFile.GetField(TiffTag.GEOTIFF_MODELTIEPOINTTAG); byte[] modelPixelScale = modelPixelScaleTag[1].GetBytes(); double pixelSizeX = BitConverter.ToDouble(modelPixelScale, 0); double pixelSizeY = BitConverter.ToDouble(modelPixelScale, 8) * -1; metadata.pixelSizeX = pixelSizeX; metadata.pixelSizeY = pixelSizeY; metadata.PixelScaleX = BitConverter.ToDouble(modelPixelScale, 0); metadata.PixelScaleY = BitConverter.ToDouble(modelPixelScale, 8); // Ignores first set of model points (3 bytes) and assumes they are 0's... byte[] modelTransformation = modelTiepointTag[1].GetBytes(); metadata.DataStartLon = BitConverter.ToDouble(modelTransformation, 24); metadata.DataStartLat = BitConverter.ToDouble(modelTransformation, 32); metadata.DataEndLon = metadata.DataStartLon + metadata.Width * pixelSizeX; metadata.DataEndLat = metadata.DataStartLat + metadata.Height * pixelSizeY; if (metadata.DataStartLon > metadata.DataEndLon) { double temp = metadata.DataStartLon; metadata.DataStartLon = metadata.DataEndLon; metadata.DataEndLon = temp; } if (metadata.DataStartLat > metadata.DataEndLat) { double temp = metadata.DataStartLat; metadata.DataStartLat = metadata.DataEndLat; metadata.DataEndLat = temp; } if (format.Registration == DEMFileRegistrationMode.Grid) { metadata.PhysicalStartLat = metadata.DataStartLat; metadata.PhysicalStartLon = metadata.DataStartLon; metadata.PhysicalEndLat = metadata.DataEndLat; metadata.PhysicalEndLon = metadata.DataEndLon; metadata.DataStartLat = Math.Round(metadata.DataStartLat + (metadata.PixelScaleY / 2.0), 10); metadata.DataStartLon = Math.Round(metadata.DataStartLon + (metadata.PixelScaleX / 2.0), 10); metadata.DataEndLat = Math.Round(metadata.DataEndLat - (metadata.PixelScaleY / 2.0), 10); metadata.DataEndLon = Math.Round(metadata.DataEndLon - (metadata.PixelScaleX / 2.0), 10); } else { metadata.PhysicalStartLat = metadata.DataStartLat; metadata.PhysicalStartLon = metadata.DataStartLon; metadata.PhysicalEndLat = metadata.DataEndLat; metadata.PhysicalEndLon = metadata.DataEndLon; } var scanline = new byte[TiffFile.ScanlineSize()]; metadata.ScanlineSize = TiffFile.ScanlineSize(); // Grab some raster metadata metadata.BitsPerSample = TiffFile.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt(); var sampleFormat = TiffFile.GetField(TiffTag.SAMPLEFORMAT); // Add other information about the data metadata.SampleFormat = sampleFormat[0].Value.ToString(); // TODO: Read this from tiff metadata or determine after parsing metadata.NoDataValue = "-10000"; metadata.WorldUnits = "meter"; return(metadata); }
public HeightMap GetHeightMapInBBox(BoundingBox bbox, FileMetadata metadata, float noDataValue = float.MinValue) { if (_data == null) { ReadAllFile(metadata); } int registrationOffset = metadata.FileFormat.Registration == DEMFileRegistrationMode.Grid ? 1 : 0; int yNorth = (int)Math.Floor((bbox.yMax - metadata.PhysicalEndLat) / metadata.pixelSizeY); int ySouth = (int)Math.Ceiling((bbox.yMin - metadata.PhysicalEndLat) / metadata.pixelSizeY); int xWest = (int)Math.Floor((bbox.xMin - metadata.PhysicalStartLon) / metadata.pixelSizeX); int xEast = (int)Math.Ceiling((bbox.xMax - metadata.PhysicalStartLon) / metadata.pixelSizeX); xWest = Math.Max(0, xWest); xEast = Math.Min(metadata.Width - 1 - registrationOffset, xEast); yNorth = Math.Max(0, yNorth); ySouth = Math.Min(metadata.Height - 1 - registrationOffset, ySouth); HeightMap heightMap = new HeightMap(xEast - xWest + 1, ySouth - yNorth + 1); heightMap.Count = heightMap.Width * heightMap.Height; var coords = new List <GeoPoint>(heightMap.Count); heightMap.BoundingBox = new BoundingBox(0, 0, 0, 0); for (int y = yNorth; y <= ySouth; y++) { double latitude = metadata.DataEndLat + (metadata.pixelSizeY * y); // bounding box if (y == yNorth) { heightMap.BoundingBox.yMax = latitude; heightMap.BoundingBox.xMin = metadata.DataStartLon + (metadata.pixelSizeX * xWest); heightMap.BoundingBox.xMax = metadata.DataStartLon + (metadata.pixelSizeX * xEast); } if (y == ySouth) { heightMap.BoundingBox.yMin = latitude; } for (int x = xWest; x <= xEast; x++) { double longitude = metadata.DataStartLon + (metadata.pixelSizeX * x); float heightValue = float.Parse(_data[y][x], CultureInfo.InvariantCulture); if (heightValue == metadata.NoDataValueFloat) { heightValue = noDataValue; } heightMap.Minimum = Math.Min(heightMap.Minimum, heightValue); heightMap.Maximum = Math.Max(heightMap.Maximum, heightValue); coords.Add(new GeoPoint(latitude, longitude, heightValue)); } } heightMap.BoundingBox.zMin = heightMap.Minimum; heightMap.BoundingBox.zMax = heightMap.Maximum; Debug.Assert(heightMap.Width * heightMap.Height == coords.Count); heightMap.Coordinates = coords; return(heightMap); }
public HeightMap GetHeightMap(FileMetadata metadata) { throw new NotImplementedException(); }
public static FileMetadata Migrate(IRasterService rasterService, ILogger logger, FileMetadata oldMetadata, string dataRootDirectory, DEMDataSet dataSet) { if (oldMetadata != null) { logger.LogInformation($"Migration metadata file {oldMetadata.Filename} from {oldMetadata.Version} to {FileMetadata.FILEMETADATA_VERSION}"); // 2.2 version requires regeneration oldMetadata = rasterService.ParseMetadata(Path.Combine(rasterService.LocalDirectory, oldMetadata.Filename), dataSet.FileFormat); //switch (oldMetadata.Version) //{ // case "2.0": // // 2.1 : relative path // // Find dataset root within path // DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(oldMetadata.Filename)); // while (dir.Name != dataSet.Name) // { // dir = dir.Parent; // } // dir = dir.Parent; // // replace directory // oldMetadata.Filename = oldMetadata.Filename.Replace(dir.FullName, dataRootDirectory); // Uri fullPath = new Uri(oldMetadata.Filename, UriKind.Absolute); // if (!(dataRootDirectory.Last() == Path.DirectorySeparatorChar)) // dataRootDirectory += Path.DirectorySeparatorChar; // Uri relRoot = new Uri(dataRootDirectory, UriKind.Absolute); // oldMetadata.Filename = Uri.UnescapeDataString(relRoot.MakeRelativeUri(fullPath).ToString()); // oldMetadata.FileFormat = dataSet.FileFormat; // break; // case "2.1": // // 2.2 : [Metadata regneration required] file format is now mapped to DEMFileDefinition, lat/lon bounds names changed for clarity, file format changed from DEMFileFormat (name + file extenstion) // // // // to DEMFileDefinition // oldMetadata.FileFormat = dataSet.FileFormat; // break; // default: // // DEMFileFormat // oldMetadata.FileFormat = dataSet.FileFormat; // break; //} // set version and fileFormat oldMetadata.Version = FileMetadata.FILEMETADATA_VERSION; } return(oldMetadata); }
public HeightMap GetHeightMapInBBox(BoundingBox bbox, FileMetadata metadata, float noDataValue = 0) { // metadata.BitsPerSample // When 16 we have 2 bytes per sample // When 32 we have 4 bytes per sample int bytesPerSample = metadata.BitsPerSample / 8; byte[] byteScanline = new byte[metadata.ScanlineSize]; int yStart = (int)Math.Floor((bbox.yMax - metadata.StartLat) / metadata.pixelSizeY); int yEnd = (int)Math.Ceiling((bbox.yMin - metadata.StartLat) / metadata.pixelSizeY); int xStart = (int)Math.Floor((bbox.xMin - metadata.StartLon) / metadata.pixelSizeX); int xEnd = (int)Math.Ceiling((bbox.xMax - metadata.StartLon) / metadata.pixelSizeX); xStart = Math.Max(0, xStart); xEnd = Math.Min(metadata.Width - 1, xEnd); yStart = Math.Max(0, yStart); yEnd = Math.Min(metadata.Height - 1, yEnd); HeightMap heightMap = new HeightMap(xEnd - xStart + 1, yEnd - yStart + 1); heightMap.Count = heightMap.Width * heightMap.Height; var coords = new List <GeoPoint>(heightMap.Count); heightMap.BoundingBox = new BoundingBox(0, 0, 0, 0); for (int y = yStart; y <= yEnd; y++) { TiffFile.ReadScanline(byteScanline, y); double latitude = metadata.StartLat + (metadata.pixelSizeY * y); // bounding box if (y == yStart) { heightMap.BoundingBox.yMax = latitude; heightMap.BoundingBox.xMin = metadata.StartLon + (metadata.pixelSizeX * xStart); heightMap.BoundingBox.xMax = metadata.StartLon + (metadata.pixelSizeX * xEnd); } else if (y == yEnd) { heightMap.BoundingBox.yMin = latitude; } for (int x = xStart; x <= xEnd; x++) { double longitude = metadata.StartLon + (metadata.pixelSizeX * x); float heightValue = 0; switch (metadata.SampleFormat) { case RasterSampleFormat.FLOATING_POINT: heightValue = BitConverter.ToSingle(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.INTEGER: heightValue = BitConverter.ToInt16(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.UNSIGNED_INTEGER: heightValue = BitConverter.ToUInt16(byteScanline, x * bytesPerSample); break; default: throw new Exception("Sample format unsupported."); } if (heightValue <= 0) { heightMap.Minimum = Math.Min(heightMap.Minimum, heightValue); heightMap.Maximum = Math.Max(heightMap.Maximum, heightValue); } else if (heightValue < 32768) { heightMap.Minimum = Math.Min(heightMap.Minimum, heightValue); heightMap.Maximum = Math.Max(heightMap.Maximum, heightValue); } else { heightValue = (float)noDataValue; } coords.Add(new GeoPoint(latitude, longitude, heightValue)); } } Debug.Assert(heightMap.Width * heightMap.Height == coords.Count); heightMap.Coordinates = coords; return(heightMap); }
private float GetHGTValue(FileMetadata metadata, int x, int y) { int bytesPerSample = metadata.BitsPerSample / 8; byte[] byteScanline = new byte[metadata.ScanlineSize]; _hgtStream.Seek(metadata.ScanlineSize * y, SeekOrigin.Begin); _hgtStream.Read(byteScanline, 0, metadata.ScanlineSize); double latitude = metadata.StartLat + (metadata.pixelSizeY * y); double longitude = metadata.StartLon + (metadata.pixelSizeX * x); float heightValue = 0; byte[] heightBytes = new byte[bytesPerSample]; if (BitConverter.IsLittleEndian) { // reverse bytes for (int i = 0; i < bytesPerSample; i++) { heightBytes[i] = byteScanline[x * bytesPerSample + bytesPerSample - i - 1]; } switch (metadata.SampleFormat) { case RasterSampleFormat.FLOATING_POINT: heightValue = BitConverter.ToSingle(heightBytes, 0); break; case RasterSampleFormat.INTEGER: heightValue = BitConverter.ToInt16(heightBytes, 0); break; case RasterSampleFormat.UNSIGNED_INTEGER: heightValue = BitConverter.ToUInt16(heightBytes, 0); break; default: throw new Exception("Sample format unsupported."); } } else { switch (metadata.SampleFormat) { case RasterSampleFormat.FLOATING_POINT: heightValue = BitConverter.ToSingle(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.INTEGER: heightValue = BitConverter.ToInt16(byteScanline, x * bytesPerSample); break; case RasterSampleFormat.UNSIGNED_INTEGER: heightValue = BitConverter.ToUInt16(byteScanline, x * bytesPerSample); break; default: throw new Exception("Sample format unsupported."); } } return(heightValue); }