All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.gov.nasa.worldwind.util.ElevationsUtil Maven / Gradle / Ivy

Go to download

World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.

There is a newer version: 2.0.0-986
Show newest version
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gov.nasa.worldwind.util;

import gov.nasa.worldwind.avlist.*;
import gov.nasa.worldwind.data.ByteBufferRaster;

/**
* @author Lado Garakanidze
* @version $Id: ElevationsUtil.java 1171 2013-02-11 21:45:02Z dcollins $
*/

public class ElevationsUtil
{
   public static final double DTED_DEFAULT_MISSING_SIGNAL = -32767d;
   public static final double SRTM_DEFAULT_MISSING_SIGNAL = -32768d;
   public static final double DEM_DEFAULT_MISSING_SIGNAL = -9999d;

   protected static final double[] knownMissingSignals = {
       DTED_DEFAULT_MISSING_SIGNAL, SRTM_DEFAULT_MISSING_SIGNAL, DEM_DEFAULT_MISSING_SIGNAL
   };

   /**
    * Checks if the value is one of the well-known "nodata" value used in digital elevation model files
    * to specify missing areas / voids.
    *
    * @param value a value to check
    * @return TRUE, if the value is one of the well known "nodata" values
    *
    */
   public static boolean isKnownMissingSignal(Double value)
   {
       if( null != value )
       {
           for(double signal : knownMissingSignals )
           {
               if( value == signal )
                   return true;
           }
       }
       return false;
   }

   /**
    * Rectify elevation raster. For best performance each elevation raster must have correct parameters and values set.
    * The rectify() operation validates that correct Elevation min and max values are set or calculated.
    * All values that beyond min/max and voids, must be marked with "Missing Signal" (aka "nodata" value).
    *
    * @param raster A DataRaster to rectify
    * @throws IllegalArgumentException if raster is null
    */
   public static void rectify(ByteBufferRaster raster) throws IllegalArgumentException
   {
       if( null == raster )
       {
           String msg = Logging.getMessage("nullValue.RasterIsNull");
           Logging.logger().finest(msg);
           throw new IllegalArgumentException(msg);
       }

       int width = raster.getWidth();
       int height = raster.getHeight();

       if( width == 0 || height == 0 )
       {
           // nothing to do
           return;
       }

       double[] minmax= raster.getExtremes();
       if( null == minmax )
       {
           // nothing to do
           return;
       }

       Double minValue = minmax[0];
       Double maxValue = minmax[1];

       Double missingDataSignal = AVListImpl.getDoubleValue(raster, AVKey.MISSING_DATA_SIGNAL, null);

       // check if the minimum value is one of the well known NODATA values
       if (ElevationsUtil.isKnownMissingSignal(minValue)
           || (missingDataSignal != null && missingDataSignal.equals(minValue))
           )
       {
           missingDataSignal = minValue;
           raster.setTransparentValue(missingDataSignal);

           minmax = raster.getExtremes();
           if (null != minmax)
           {
               minValue = minmax[0];
               maxValue = minmax[1];
           }
       }

       BufferWrapper bufferWrapper = raster.getBuffer();
       // Allocate a buffer to hold one row of scalar values.
       double[] array = new double[width];

       boolean needsConversion = false;
       double conversionValue = 1d;

       if( raster.hasKey(AVKey.ELEVATION_UNIT) )
       {
           String unit = raster.getStringValue(AVKey.ELEVATION_UNIT);
           if( AVKey.UNIT_METER.equalsIgnoreCase(unit) )
           {
               needsConversion = false;
           }
           else if( AVKey.UNIT_FOOT.equalsIgnoreCase(unit) )
           {
               needsConversion = true;
               conversionValue = WWMath.convertFeetToMeters(1);
               minValue = WWMath.convertFeetToMeters(minValue);
               maxValue = WWMath.convertFeetToMeters(maxValue);
               raster.setValue(AVKey.ELEVATION_UNIT, AVKey.UNIT_METER);
           }
           else
           {
               needsConversion = false;
               String msg = Logging.getMessage("generic.UnrecognizedElevationUnit", unit);
               Logging.logger().warning(msg);
           }
       }

       boolean rasterHasVoids = false;

       for (int j = 0; j < height; j++)
       {
           bufferWrapper.getDouble( j * width, array, 0, width );
           boolean commitChanges = false;

           for (int i = 0; i < width; i++)
           {
               double value = array[i];

               if( null != missingDataSignal && value == missingDataSignal )
               {
                   rasterHasVoids = true;
               }
               else
               {
                   if( needsConversion )
                   {
                       value *= conversionValue;
                       commitChanges = true;
                       array[i] = value;
                   }

                   if( value < minValue || value > maxValue )
                   {
                       rasterHasVoids = true;

                       if( null != missingDataSignal)
                       {
                           array[i] = missingDataSignal;
                           commitChanges = true;
                       }
                   }
               }
           }

           if( commitChanges )
               bufferWrapper.putDouble( j * width, array, 0, width );
       }

       if( rasterHasVoids )
       {
           if( missingDataSignal != null )
               raster.setValue(AVKey.MISSING_DATA_SIGNAL, missingDataSignal );
       }
       else
       {
           raster.removeKey(AVKey.MISSING_DATA_SIGNAL);
       }

       raster.setValue(AVKey.ELEVATION_MIN, minValue);
       raster.setValue(AVKey.ELEVATION_MAX, maxValue);
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy