Package com.bbn.openmap.layer.etopo

Source Code of com.bbn.openmap.layer.etopo.ETOPOJarLayer

// **********************************************************************
//
// <copyright>
//
//  BBN Technologies
//  10 Moulton Street
//  Cambridge, MA 02138
//  (617) 873-8000
//
//  Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/layer/etopo/ETOPOJarLayer.java,v $
// $RCSfile: ETOPOJarLayer.java,v $
// $Revision: 1.4.2.2 $
// $Date: 2008/02/27 01:53:54 $
// $Author: dietrick $
//
// **********************************************************************


package com.bbn.openmap.layer.etopo;

/**
* Creation date: (1/12/2001 9:41:59 PM)
* @author John Watts from nextjet.com:
*/
import java.awt.Color;
import java.awt.Point;
import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;

import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.MoreMath;
import com.bbn.openmap.omGraphics.OMRaster;
import com.bbn.openmap.proj.CADRG;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.util.Debug;

/**
* This subclass of ETOPOLayer reads data from jar files and *
* interpolates elevations to provide more smoothe color transitions
* using * low resolution data. 
*/
public class ETOPOJarLayer extends ETOPOLayer {

    /**
     * ETOPOJarLayer constructor comment.
     */
    public ETOPOJarLayer() {
        super();
    }     

    /**
     * ETOPOJarLayer constructor comment.
     * @param pathToETOPODir java.lang.String
     */
    public ETOPOJarLayer(String pathToETOPODir) {
        super(pathToETOPODir);
    }  

    /**
     * Loads the database from the appropriate file based on the
     * current resolution. The data files are in INTEL format (must call
     * BinaryBufferedFile.byteOrder(true)).
     */
    protected void loadBuffer() {

        // get the resolution index
        int resIdx = minuteSpacing / 5 - 1;
        if (resIdx < 0)
            resIdx = 0;
        else if (resIdx > 2)
            resIdx = 2;

        // build file name
        String fileName = path + etopoFileNames[resIdx];

        try {

            // open etopo file as resource stream
            BufferedInputStream bis =
                new BufferedInputStream(ClassLoader.getSystemResourceAsStream(fileName));

            // set width/height
            bufferWidth = etopoWidths[resIdx];
            bufferHeight = etopoHeights[resIdx];

            int spacer = 1;
            // don't know why I have to do this, but there seems to be
            // a wrapping thing going on with different data sets.
            switch (minuteSpacing) {
            case (2):
                spacer = 1 + this.spacer;
                break;
            case (5):
                spacer = 0 + this.spacer;
                break;
            default:
                spacer = 1 + this.spacer;
            }
           
            int numberOfWords = (bufferWidth + spacer) * bufferHeight;

            // allocate storage
            dataBuffer = new short[numberOfWords];

            // read data
            iv_buffer = new byte[2 * numberOfWords];

            iv_bytesinbuffer = bis.read(iv_buffer,0,2*numberOfWords);
            iv_curptr = 0;

            for (int i = 0; i < bufferWidth * bufferHeight; i++)
                dataBuffer[i] = readShort();

            // done
            bis.close();

            // don't know why I have to do this, but...
            bufferWidth = bufferWidth + spacer;

        } catch (FileNotFoundException e) {
            Debug.error("ETOPOLayer loadBuffer(): file " +
                        fileName + " not found");
        } catch (IOException e) {
            Debug.error("ETOPOLayer loadBuffer(): File IO Error!\n" +
                        e.toString());
        }
       
    }                    
   
    byte  iv_buffer[];
    int   iv_bytesinbuffer;
    int   iv_curptr;
   
    /**
     * Reads and returns a short
     * @return the 2 bytes merged into a short, according to the
     * current byte ordering
     * @exception EOFException there were less than 2 bytes left in
     * the file
     */
    public short readShort() throws EOFException {
        //MSBFirst must be set when we are called
        if (iv_bytesinbuffer < 2) {
            throw new EOFException();
        }
        iv_curptr += 2;
        iv_bytesinbuffer -= 2;
        return MoreMath.BuildShort(iv_buffer, iv_curptr - 2, true);
    }

    /*
     *  Builds the raster image that has the dimensions of the current
     *  projection.  The alogorithm is is follows:
     *
     *    allocate storage the size of the projection (use ints for RGBA)
     *
     *    for each screen point
     *  
     *      inverse project screen point to get lat/lon (world coords)
     *      get altitude and/or slope at the world coord
     *      compute (lookup) color at the world coord
     *      set color value into screen coord location
     *
     *    end
     *
     *    create OMRaster from the int array data.
     *
     *  The code contains a HACK (primarily for the Orthographic
     *  projection) since * x/y values which would return an "Outer
     *  Space" value actually return lat/lon values for the center of
     *  the projection (see Orthographic.inverse(...)). This resulted
     *  in the "Outer Space" being painted the color of whatever the
     *  center lat/lon was. The HACK turns any center lat/lon value
     *  into black. Of course, this causes valid center lat/lon values
     *  to be painted black, but the trade off is worth it
     *  visually. The appropriate method may be to have
     *  Projection.inverse and its variants raise an exception for
     *  "Outer Space" values.
     *
     */
    protected OMRaster buildRaster() {
        // initialize the return
        OMRaster ret = null;
        Projection projection = getProjection();
        // work with the slopeMap
        if (slopeMap != null) {
           
            // compute our deltas
            int pixelColumns = projection.getWidth();
            int pixelRows = projection.getHeight();

            // create int array to hold colors
            int[] colors = new int[pixelColumns * pixelRows];

            // compute scalers for lat/lon indicies
            float yPixPerDataPt = (float) bufferHeight / 180F;
            float xPixPerDataPt = (float) bufferWidth / 360F;

            // starting and ending indices
            int sx = 0, sy = 0, ex = pixelColumns, ey = pixelRows;

            // handle CADRG
            if (projection instanceof CADRG) {

                                // get corners
                LatLonPoint ul = projection.getUpperLeft();
                LatLonPoint lr = projection.getLowerRight();

                                // set start/end indicies
                Point ulp = projection.forward(ul);
                Point lrp = projection.forward(lr);
                sx = (int) ulp.getX();
                ex = (int) lrp.getX();
                sy = (int) ulp.getY();
                ey = (int) lrp.getY();

            }

            // get the center lat/lon (used by the HACK, see above in
            // method description)
            LatLonPoint center = projection.getCenter();
            LatLonPoint llp = new LatLonPoint();

            // build array
            float lat;
            float lon;
            int lat_idx;
            int lon_idx;
            float latWt;
            float lonWt;

            // offset
            int ofs;
            int ofsRight;
            int ofsDown;
            int ofsDownRight;

            for (int y = sy; y < ey; y++) {


                                // process each column
                for (int x = sx; x < ex; x++) {

                    // inverse project x,y to lon,lat
                    projection.inverse(x, y, llp);

                    // get point values
                    lat = llp.getLatitude();
                    lon = llp.getLongitude();

                    // check
                    if (lon < 0.) {
                        lon += 360.;
                    }

                    // find indicies
                    lat_idx = (int) ((90. - lat) * yPixPerDataPt);
                    lon_idx = (int) (lon * xPixPerDataPt);

                    // most pixels fall between data points. The data
                    // point originally used is the one immediately
                    // above and to the left of the pixel. The amount
                    // by which the pixel is offset from the data
                    // point can be used to weight the elevation
                    // contribution of the four data points
                    // surrounding the pixel ie. the weights. The
                    // truncated decimal part of the index computation
                    // is the weight.
                    latWt = ((90f - lat) * yPixPerDataPt) - (float) lat_idx;
                    lonWt = (lon * xPixPerDataPt) - (float) lon_idx;

                    // offsets of the four surrounding data points.
                    ofs = lon_idx + lat_idx * bufferWidth;
                    ofsRight = ofs + 1;
                    if (lat_idx+1 < bufferHeight) {
                        ofsDown = lon_idx + (1 + lat_idx) * bufferWidth;
                    } else {
                        ofsDown = ofs;
                    }
                    ofsDownRight = ofsDown + 1;

                    // make a color
                    int idx = 0;
                    int gray = 0;
                    short el = 0;
                    byte sl = 0;

                    try {

                        try {
                            float ulwt = (1f - lonWt + 1f - latWt);
                            float urwt = (lonWt + 1f - latWt);
                            float llwt = (1f - lonWt + latWt);
                            float lrwt = (lonWt + latWt);
                            // get elevation
                            el =
                                (short) ((float) dataBuffer[ofs] * ulwt
                                         + (float) dataBuffer[ofsRight] * urwt
                                         + (float) dataBuffer[ofsDown] * llwt
                                         + (float) dataBuffer[ofsDownRight] * lrwt);

                            // slope
                            sl =
                                (byte) ((float) slopeMap[ofs] * ulwt
                                        + (float) slopeMap[ofsRight] * urwt
                                        + (float) slopeMap[ofsDown] * llwt
                                        + (float) slopeMap[ofsDownRight] * lrwt);
                            float exagFactor = 1f/ (el > 0?1.5f:3f);
                            el = (short)((float)el * exagFactor);
                            sl = (byte)((float)sl * exagFactor);

                            // bad index
                        } catch (ArrayIndexOutOfBoundsException e) {
                            Debug.error(e.toString() + ":" +
                                        ofs + " limit=" +
                                        dataBuffer.length);
                        }
                        // our index
                        idx = y * pixelColumns + x;

                        // create a color
                        Color pix = null;
                        if (viewType == SLOPESHADING) {
                            // HACK (see method description above)
                            if ((llp.getLatitude() == center.getLatitude())
                                && (llp.getLongitude() == center.getLongitude()))
                                gray = 0;
                            else
                                gray = 127 + sl;
                            pix = new Color(gray, gray, gray, opaqueness);
                        } else if (viewType == COLOREDSHADING) {
                            // HACK (see method description above)
                            if ((llp.getLatitude() == center.getLatitude())
                                && (llp.getLongitude() == center.getLongitude()))
                                pix = new Color(0, 0, 0, opaqueness);
                            else
                                pix = getColor(el, sl);
                        }

                        // set
                        colors[idx] = pix.getRGB();
                       
                    }
                   
                    // tried to set a bad color level
                    catch (IllegalArgumentException e) {
                        Debug.error(e.toString() + ":" + gray);
                    }
                   
                    // bad index
                    catch (ArrayIndexOutOfBoundsException e) {
                        Debug.error(e.toString() + ":" + idx);
                    }
                }
            }

            // create the raster
            ret = new OMRaster(0, 0, pixelColumns, pixelRows, colors);

        }

        // return or raster
        return ret;

    }

    protected Color getColor(short elevation,byte slopeVal) {
        // build first time
        if (slopeColors==null){// || slopeColors[0][0].getAlpha() != opaqueness) {
            System.out.println("loading colors");
            // allocate storage for elevation bands, 8 slope bands
            slopeColors = new Color[elevLimitCnt][8];
           
            // process each elevation band
            for (int i=0;i<elevLimitCnt;i++) {
               
                // get base color (0 slope color)
                Color base = new Color(redElev[i],greenElev[i],blueElev[i],opaqueness);
               
                // call the "brighter" method on the base color for
                // positive slope
                for (int j=4;j<8;j++) {
                   
                    // set
                    if ( j==4 )
                        slopeColors[i][j] = base;
                    else
                        slopeColors[i][j] = slopeColors[i][j-1].brighter();
                }

                                // call the "darker" method on the base color for negative slopes
                for (int k=3;k>=0;k--) {
                    // set
                    slopeColors[i][k] = slopeColors[i][k+1].darker();
                }
            }
        }

        // get the elevation band index
        int elIdx = getElevIndex(elevation);

        // compute slope idx
        int slopeIdx = ((int)slopeVal+127)>>5;
        //int slopeIdx = ((int)slopeVal+127)/32;

        // return color
        return slopeColors[elIdx][slopeIdx];
        //Color norm = slopeColors[elIdx][slopeIdx];

        // set alpha
        //return new Color(norm.getRed(),norm.getGreen(),norm.getBlue(),opaqueness);

    }
}
TOP

Related Classes of com.bbn.openmap.layer.etopo.ETOPOJarLayer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.