Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
 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)));
 }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
        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));
        }
Exemplo n.º 7
0
 public bool IsPointInTile(FileMetadata tileMetadata, GeoPoint point)
 {
     return(IsPointInTile(tileMetadata, point.Latitude, point.Longitude));
 }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
0
        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;
            }
        }
Exemplo n.º 11
0
        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);
        }
Exemplo n.º 12
0
        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);
        }
Exemplo n.º 13
0
 public HeightMap GetHeightMap(FileMetadata metadata)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 14
0
        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);
        }
Exemplo n.º 15
0
        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);
        }
Exemplo n.º 16
0
        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);
        }