Programming with JViews Maps > Introducing the Main Classes > Map Specific Manager Properties > Altitude Management

The class relationship for altitude management is shown in Figure 1.2.

map_altman.png

Figure 1.2 Altitude Management UML Diagram

This section describes:

The source code for the Map Builder demonstration, which contains all of the code described in this section, can be found at <installdir>/jviews-maps81/samples/mapbuilder/index.html

The Altitude Provider Property

Terrain analysis computations are based on the IlvAltitudeProviderProperty of the manager and its underlying IlvAltitudeProvider, which is responsible for providing altitudes for each point on a map.

Accessing the Altitude Provider

You can access the altitude provider by calling:

IlvAltitudeProvider provider = IlvAltitudeProviderProperty.GetAltitudeProvider(manager);

If you do not set a specific provider to this property, this method creates or returns an instance of IlvDefaultAltitudeProvider.

This provider supports GTOPO30 and DTED data sources.

Any other Digital Elevation Model can be integrated by providing the graphic objects with an IlvAltitudeDataSource property, see Retrieving the Altitude Attached to a Graphic Object.

Altitude Provider Property Uses

The IlvJMouseCoordinateViewer Bean uses altitude property information to provide altitude information whenever the mouse is over an altitude providing map object. Many other features of JViews Maps also use this information.

Attaching an Altitude Data Source to a Graphic Object

If you have read an image containing elevation data with an IlvRasterAbstractReader, for an example, see Writing a Raster Reader for DEM Data; you can reuse its altitude information to provide altitude data by using an IlvRasterAltitudeDataSource instance.

You first need to decide on the structure of the attribute property, for example, for a property containing only altitude data:

IlvAttributeInfoProperty info = new IlvAttributeInfoProperty(
new String[] { "myAltitudeDataSourcePropertyName" },
new Class[] { IlvRasterAltitudeDataSource.class },
new boolean[] { true });

You can then reuse this structural information with different altitude data sources, and set it as the graphic object property:

IlvFeatureAttribute value[] = { new IlvRasterAltitudeDataSource(rasterImageReader, imageIndex) };
graphic.setNamedProperty(new IlvFeatureAttributeProperty(info, value);

Retrieving the Altitude Attached to a Graphic Object

If you use the default altitude management described in The Altitude Provider Property, you can also retrieve the altitude attached to an object as follows:

  1. Get the attribute properties of the graphic object:
IlvAttributeProperty property = (IlvAttributeProperty) graphic.getNamedProperty(IlvAttributeProperty.NAME);
  1. You should find the altitude data source in that property:
IlvAltitudeDataSource ads = (IlvAltitudeDataSource)property.getValue("myAltitudeDataSourcePropertyName");
  1. As the data source object provides only altitude information for a specific latitude/longitude pair, you may need to transform the coordinates into latitude and longitude. Here is an example that converts a mouse location into such a pair:
// transform the mouse point into manager coordinates
IlvPoint pt=new IlvPoint(mouseLocation.x,mouseLocation.y);
view.getTransformer().inverse(pt);
IlvProjectionUtil.invertY(pt);
try {
  // compute the coordinate transformation from manager coordinates to lat/lon
  IlvCoordinateSystem cs = IlvCoordinateSystemProperty.GetCoordinateSystem(view.getManager());
  IlvCoordinateTransformation ct = IlvCoordinateTransformation.CreateTransformation(cs,
                                                IlvGeographicCoordinateSystem.KERNEL);
  // transform the point into lat/lon
  IlvCoordinate c = new IlvCoordinate(pt.x, pt.y);
  ct.transform(c, c);
  // retrieve the altitude
} catch (IlvCoordinateTransformationException e) {
}
  1. You can then obtain the altitude. You should check if its value is a valid double, because the default data source and default provider of the manager return a Double.NaN value when there is no altitude information available.
    double alt = ads.getAltitude(c.x, c.y, 0);
    if(!Double.isNaN(alt)){
       return alt;
    }

Writing a Raster Reader for DEM Data

To read a new Digital Elevation Model (DEM) file format, you should write a subclass of IlvRasterAbstractReader.

Creating the Reader

The following example shows how a reader can load a list of raster DEM files using the addMap method.

public class MyDEMReader extends IlvRasterAbstractReader {
    // list of files to be read.
    private ArrayList filenameList = new ArrayList();
    /** default constructor */
    public MyDEMReader() {
    }

The addMap method has to compute the IlvRasterProperties and IlvRasterMappedBuffer attached to the file name, see Raster Image Management, and then add this information to the list managed by the reader. As this step is heavily dependant upon format, only a summary is provided here.

    public void addMap(final String filename) throws IOException {
        IlvRasterProperties loadingRaster = read/compute raster properties ...
        IlvRasterMappedBuffer source= read/compute raster pixel values...
        loadingRaster.setBaseName(filename);// to retrieve the file name when serializing data.
        addRaster(loadingRaster, source);
    }
Using the Map Load and Save Features

If you want to take advantage of map load and save features, you have to manage the serialization of the reader, that is, provide methods that perform the following functions:

    public void write(IlvOutputStream stream) throws IOException {
        super.write(stream);
        int imageCount = getImageCount();
        for (int i = 0; i < imageCount; i++) {
            IlvRasterProperties props=getRasterProperties(i);
            stream.write("filename"+i,props.getBaseName());
        }
    }
 public MyDEMReader(IlvInputStream stream) throws IlvReadFileException {
      super(stream);
      try {
             for(int count=0;true;count++) {
              String filename = stream.readString("filename"+count);
              filenameList.add(filename);
          }
      } catch (IlvReadFileException e1) {
          // No more filenames to read
      }
    }
    public void reload(IlvThreadMonitoringData monitorInfo) {
        super.reload(monitorInfo);
        // clear all images
        dispose();
        // save the known filenames in a temporary array - the addMap would else add them again.
        String[] filenames = (String[])filenameList.toArray(new String[0]);
        // clear the file name list
        filenameList.clear();
        for (int i = 0; i < filenames.length; i++) {
            try {
                // load each file
                addMap(filenames[i]);
                if (monitorInfo != null) {
                    // update the thread monitoring information, if necessary
                    int percent = Math.round(i/(float)filenames.length
                    * 100);
                    monitorInfo.updateProgress(percent);
                }
            } catch (IOException e) {
                new IlvExceptionMessage(e,null);
            }
        }
    }
Using the IlvRasterAltitudeDataSource Class as the Altitude Provider

If the pixel values stored in the IlvRasterMappedBuffer are altitudes, you can use the IlvRasterAltitudeDataSource class directly as the altitude provider, and use it in the IlvFeatureAttributeProperty of every image that this reader creates:

    public IlvFeatureAttributeProperty getProperties(int imageIndex) {
          IlvAttributeInfoProperty info = new IlvAttributeInfoProperty(
              new String[] { " myAltitudeDataSourcePropertyName" },
              new Class[] { IlvRasterAltitudeDataSource.class },
              new boolean[] { true });
          IlvFeatureAttribute values[] = new IlvFeatureAttribute[] { 
             new IlvRasterAltitudeDataSource(this,imageIndex) 
          };
          return new IlvFeatureAttributeProperty(info, values);
      }

See also, Attaching an Altitude Data Source to a Graphic Object.

Managing Coordinates

You need to provide JViews Maps with a way of knowing where the resulting image is placed. This is done through two methods that return the transformation and coordinate system used in the raster property boundaries. For example, assuming the bounds are given in degrees:

private static IlvCoordinateTransformation INTERNAL =
IlvCoordinateTransformation.CreateTransformation
   (IlvGeographicCoordinateSystem.KERNEL, 
      IlvGeographicCoordinateSystem.WGS84);
public IlvCoordinateSystem getCoordinateSystem() {
   return INTERNAL.getTargetCS();
   }
public IlvMathTransform getInternalTransformation(int imageIndex) {
   return INTERNAL.getTransform();
}