Package com.bbn.openmap.dataAccess.asrp

Source Code of com.bbn.openmap.dataAccess.asrp.ASRPDirectory

// **********************************************************************
//
// <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/dataAccess/asrp/ASRPDirectory.java,v $
// $RCSfile: ASRPDirectory.java,v $
// $Revision: 1.1.2.7 $
// $Date: 2005/08/11 21:03:20 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.dataAccess.asrp;

import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.dataAccess.iso8211.*;
import com.bbn.openmap.layer.util.cacheHandler.*;
import com.bbn.openmap.omGraphics.OMGraphic;
import com.bbn.openmap.omGraphics.OMGraphicList;
import com.bbn.openmap.omGraphics.OMRect;
import com.bbn.openmap.omGraphics.OMScalingRaster;
import com.bbn.openmap.proj.EqualArc;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.util.Debug;

import java.awt.Color;
import java.awt.Rectangle;
import java.awt.Shape;
import java.io.File;
import java.io.IOException;
import java.util.List;

/**
* An ASRP directory contains information needed to view images. It
* contains multiple files, each containing complementary information
* about the image. The GeneralInformationFile (GEN) contains
* information about the image such as coverage and location. The
* QualityFile (QAL) contains accuracy and color information. The
* GeoReferenceFile (GER) contains projection information, the
* SourceFile (SOU) contains information about the map that was used
* to create the images. The RasterGeoDataFile (IMG) contains the
* actual pixel information.
* <P>
*
* This class knows how to use all of these files to create images,
* which are made up of subframe tiles called blocks.
*/
public class ASRPDirectory extends CacheHandler implements ASRPConstants {

    protected GeneralInformationFile gen;
    protected QualityFile qal;
    protected RasterGeoDataFile img;
    protected GeoReferenceFile ger;
    protected SourceFile sou;

    /** List of tile indexes. */
    protected List tsi;
    /** Number of horizontal blocks. */
    protected int numHorBlocks_N;
    /** Number of vertical blocks. */
    protected int numVerBlocks_M;
    /** Number of horizontal pixels per block. */
    protected int numHorPixels_Q;
    /** Number of vertical pixels per block. */
    protected int numVerPixels_P;
    /**
     * When reading image bytes, the number of bits that represent the
     * number of pixels the next color index stands for.
     */
    protected int pixelCountBits;
    /**
     * When reading image bytes, the number of bits that represent the
     * color index.
     */
    protected int pixelValueBits;

    /* Bounding coordinates for coverage. */
    protected float swo, nea, neo, swa; // west lon, north lat, east
                                        // lon, south lat
    /* Upper left latitude/longitude for top left tile. */
    protected float lso, pso; // padded longitude, latitude of upper
                              // left image corner
    /** Number of pixels 360 degrees east - west. */
    protected int arv;
    /** Number of pixels 360 degrees north - south. */
    protected int brv;
    /**
     * Calculated number of degrees per block in the horizontal
     * direction.
     */
    protected float degPerHorBlock;
    /**
     * Calculated number of degrees per block in the vertical
     * direction.
     */
    protected float degPerVerBlock;
    /** Byte offset into the IMG file where tile data starts. */
    protected int tileDataOffset;
    /** The colors from the QAL file. */
    protected Color[] colors;
    /** The OMRect used to track coverage boundaries. */
    protected OMRect bounds;

    protected File dir;

    /**
     * Protective mechanism, doesn't display data that has images with
     * a base scale that is more than a factor of the scaleFactor away
     * from the scale of the map.
     */
    protected double scaleFactor = 4;

    /**
     * Create a new ASRP directory for the given path. Calls
     * initialize() which will read in the different files to find out
     * the attribute information about the data.
     */
    public ASRPDirectory(String path) {

        dir = new File(path);

        if (dir.exists()) {
            try {
                initialize(dir.getPath(), dir.getName(), "01");
            } catch (IOException ioe) {
                Debug.error(ioe.getMessage());
                ioe.printStackTrace();
                return;
            }
        } else {
            Debug.error("ASRPDirectory (" + path + ") doesn't exist");
        }

    }

    public String getPath() {
        if (dir != null) {
            return dir.getPath();
        }
        return null;
    }

    /**
     * Get the OMRect used for calculating coverage area.
     */
    public OMRect getBounds() {
        if (bounds == null) {
            bounds = new OMRect(pso, lso, pso - degPerVerBlock * numVerBlocks_M, lso
                    + degPerHorBlock * numHorBlocks_N, OMGraphic.LINETYPE_GREATCIRCLE);
        }

        return bounds;
    }

    public void setScaleFactor(double scaleFactorIn) {
        scaleFactor = scaleFactorIn;
    }

    public double getScaleFactor() {
        return scaleFactor;
    }

    /**
     * Return true of current bounds covers the projection area.
     */
    public boolean isOnMap(Projection proj) {
        OMRect bds = getBounds();
        bds.generate(proj);
        Shape s = bds.getShape();
        return s.intersects(0, 0, proj.getWidth(), proj.getHeight());
    }

    public boolean validScale(Projection proj) {
        if (proj instanceof EqualArc) {
            EqualArc ea = (EqualArc) proj;
            double xPixConstant = ea.getXPixConstant();

            double scale = xPixConstant / arv;

            boolean result = (scale < scaleFactor) && (scale > 1 / scaleFactor);
            if (Debug.debugging("asrp")) {
                Debug.output("Scale comparing arv = " + arv + ", "
                        + xPixConstant + ", result: " + result);
            }
            return result;
        }
        return false;
    }

    /**
     * Get an OMGraphicList of files that cover the projection.
     * Returns an empty list if the coverage isn't over the map.
     */
    public OMGraphicList checkProjAndGetTiledImages(Projection proj)
            throws IOException {

        if (!isOnMap(proj) || !validScale(proj)) {
            // off the map
            return new OMGraphicList();
        }

        return getTiledImages(proj);
    }

    /**
     * Assumes that the projection checks have occured, have passed,
     * and just fetches the image tiles.
     */
    public OMGraphicList getTiledImages(Projection proj) throws IOException {

        float ullat = pso;
        float ullon = lso;
        float lrlat = ullat - (degPerVerBlock * numVerBlocks_M);
        float lrlon = ullon + (degPerHorBlock * numHorBlocks_N);

        LatLonPoint llp1 = proj.getUpperLeft();
        LatLonPoint llp2 = proj.getLowerRight();

        int startX = (int) Math.floor((llp1.getLongitude() - ullon)
                / degPerHorBlock);
        int startY = (int) Math.floor((ullat - llp1.getLatitude())
                / degPerVerBlock);

        int endX = numHorBlocks_N
                - (int) Math.floor((lrlon - llp2.getLongitude())
                        / degPerHorBlock);
        int endY = numVerBlocks_M
                - (int) Math.floor((llp2.getLatitude() - lrlat)
                        / degPerVerBlock);

        if (startX < 0)
            startX = 0;
        if (startY < 0)
            startY = 0;

        if (endX > numHorBlocks_N)
            endX = numHorBlocks_N;
        if (endY > numVerBlocks_M)
            endY = numVerBlocks_M;

        return getTiledImages(new Rectangle(startX, startY, endX - startX, endY
                - startY), proj);
    }

    /**
     * Provide an OMGraphicList containing the tile blocks described
     * by the rectangle.
     *
     * @param rect rectangle defining the tile blocks to get. rect.x
     *        and rect.y describe the starting upper left block to
     *        get, rect.getWidth and rect.getHeight describe the
     *        number of tiles to the right and down from the first
     *        block to collect.
     */
    protected OMGraphicList getTiledImages(Rectangle rect, Projection proj)
            throws IOException {

        if (Debug.debugging("asrp")) {
            Debug.output("ASRPDirectory: fielding request for " + rect);
        }

        OMGraphicList list = new OMGraphicList();

        int startX = (int) rect.getX();
        int startY = (int) rect.getY();
        int endX = startX + (int) rect.getWidth();
        int endY = startY + (int) rect.getHeight();

        for (int x = startX; x < endX; x++) {
            for (int y = startY; y < endY; y++) {
                OMGraphic omg = (OMGraphic) get(new String(x + "," + y).intern());
                if (omg != null) {
                    omg.generate(proj);
                    list.add(omg);
                }
            }
        }

        return list;
    }

    /**
     * Fetch the subframe tile block from the IMG file.
     */
    public OMScalingRaster getBlock(int x, int y) throws IOException {
        float ullat = pso - y * degPerVerBlock;
        float ullon = lso + x * degPerHorBlock;
        float lrlat = ullat - degPerVerBlock;
        float lrlon = ullon + degPerHorBlock;

        // Get image data.
        if (tsi != null) {

            int index = y * numHorBlocks_N + x;

            // Check for not blowing the list end...
            if (index >= tsi.size()) {
                return null;
            }

            // Subtracting one because the values look like they start
            // with 1.
            int blockOffset = ((DDFSubfield) tsi.get(index)).intValue() - 1;

            if (Debug.debugging("asrp")) {
                Debug.output("ASRPDirectory.getBlock: index of (" + x + ", "
                        + y + ") is " + blockOffset);
            }

            if (blockOffset < 0) {
                // Can't have a negative offset...
                if (Debug.debugging("asrp")) {
                    Debug.output("     skipping...");
                }

                return null;
            }

            DDFModule mod = img.getInfo();
            mod.seek(tileDataOffset + blockOffset);

            int byteCount = 0; // Which data byte is being set
            int numBlockPixels = numHorPixels_Q * numVerPixels_P;
            byte[] data = new byte[numBlockPixels]; // image byte data

            int rowCount = 0; // the per row count, should equal 128 (
                              // numHorPixels_Q) at the end of every
                              // row
            int cpc = 0; // current pixel count for file pointer
            int cpv = 0; // current pixel value for file pointer
            while (byteCount < numBlockPixels) {
                switch (pixelCountBits) {
                case 8:
                    cpc = mod.read();
                    break;
                case 4:
                    cpc = mod.read() >> 4;
                    // need to back pointer up 4 bits before reading
                    // cpv??
                    Debug.output("CAUTION:  4 bit count");
                    break;
                default:
                    cpc = 1;
                }

                cpv = mod.read();

                // OK, cpv has value, cpc says how many pixels that
                // goes in.

                try {
                    for (int c = 0; c < cpc; c++) {
                        rowCount++;
                        if (colors != null && cpv > colors.length) {
                            if (Debug.debugging("asrpdetail")) {
                                Debug.output("Got value that is too big for colortable");
                            }
                        }
                        data[byteCount + c] = (byte) cpv;
                    }
                } catch (ArrayIndexOutOfBoundsException aioobe) {
                    if (Debug.debugging("asrp")) {
                        Debug.output("ASRPDirectory.getBlock(): bad index for setting byte value: "
                                + aioobe.getMessage());
                    }
                    // This try/catch block is really for the data[]
                    // array indexing.

                    // if byteCount + x was greater than
                    // numBlockPixels,
                    // we should be at the end of the image bytes, so
                    // we
                    // shouldn't have to worry about rowCount not
                    // being
                    // properly updated.
                }

                byteCount += cpc;
                if (rowCount == numHorPixels_Q) {
                    rowCount = 0;
                }
            }

            if (Debug.debugging("asrpdetail")) {
                Debug.output("ASRPDirectory creating image covering (" + ullat
                        + ", " + ullon + "), (" + lrlat + ", " + lrlon + ")");
            }

            return new OMScalingRaster(ullat, ullon, lrlat, lrlon, numHorPixels_Q, numVerPixels_P, data, getColors(), 255);
        }

        return null;
    }

    /**
     * Get the colors from the QAL file.
     */
    protected Color[] getColors() {
        if (colors == null) {
            DDFField col = qal.getField(QualityFile.COLOUR_CODE_ID);

            List reds = col.getSubfields("NSR");
            List greens = col.getSubfields("NSG");
            List blues = col.getSubfields("NSB");

            int numColors = reds.size();
            colors = new Color[numColors];

            for (int count = 0; count < numColors; count++) {
                int red = ((DDFSubfield) reds.get(count)).intValue();
                int green = ((DDFSubfield) greens.get(count)).intValue();
                int blue = ((DDFSubfield) blues.get(count)).intValue();
                //                 Debug.output("Created color " + count + " with " +
                // red + ", " + green + ", " + blue);
                // The zero color is supposed to tbe null color, and
                // clear. Doesn't seem to be working.
                colors[count] = new Color(red, green, blue, (count == 0 ? 0
                        : 255));
            }

        }
        return colors;
    }

    /**
     * Read in the attribute information about the data.
     *
     * @param dirPath path to the ASRP directory.
     * @param root name of all of the files, usually the same as the
     *        ASRP directory itself.
     * @param DD the occurance number, usually '01' of the files.
     */
    protected void initialize(String dirPath, String root, String DD)
            throws IOException {
        String rootPath = dirPath + "/" + root + DD + ".";

        gen = new GeneralInformationFile(rootPath + GEN_NAME);
        ger = new GeoReferenceFile(rootPath + GER_NAME);
        qal = new QualityFile(rootPath + QAL_NAME);
        sou = new SourceFile(rootPath + SOURCE_NAME);
        img = new RasterGeoDataFile(rootPath + IMAGE_NAME);

        DDFField sprInfo = gen.getField(GeneralInformationFile.DATA_SET_PARAMETERS);
        numHorBlocks_N = sprInfo.getSubfield("NFC").intValue();
        numVerBlocks_M = sprInfo.getSubfield("NFL").intValue();
        numHorPixels_Q = sprInfo.getSubfield("PNC").intValue();
        numVerPixels_P = sprInfo.getSubfield("PNL").intValue();
        pixelCountBits = sprInfo.getSubfield("PCB").intValue();
        pixelValueBits = sprInfo.getSubfield("PVB").intValue();

        //assume there is a tile index map

        DDFField genInfo = gen.getField(GeneralInformationFile.GENERAL_INFORMATION);
        swo = genInfo.getSubfield("SWO").floatValue() / 3600f;
        neo = genInfo.getSubfield("NEO").floatValue() / 3600f;
        nea = genInfo.getSubfield("NEA").floatValue() / 3600f;
        swa = genInfo.getSubfield("SWA").floatValue() / 3600f;
        lso = genInfo.getSubfield("LSO").floatValue() / 3600f;
        pso = genInfo.getSubfield("PSO").floatValue() / 3600f;

        arv = genInfo.getSubfield("ARV").intValue();
        brv = genInfo.getSubfield("BRV").intValue();

        DDFField timInfo = gen.getField(GeneralInformationFile.TILE_INDEX_MAP);
        tsi = timInfo.getSubfields("TSI");

        DDFField pixelInfo = img.getField(RasterGeoDataFile.PIXEL);
        // Finding this out lets you use the tile index map to access
        // pixel data. This offset points to the start of the tile
        // data.
        tileDataOffset = pixelInfo.getHeaderOffset()
                + pixelInfo.getDataPosition();

        degPerHorBlock = 360f / (float) arv * (float) numHorPixels_Q;
        degPerVerBlock = 360f / (float) brv * (float) numVerPixels_P;

        if (Debug.debugging("asrp")) {
            Debug.output("For " + rootPath + "\n\thave blocks ("
                    + numHorBlocks_N + ", " + numVerBlocks_M
                    + ")\n\twith pixels (" + numHorPixels_Q + ", "
                    + numVerPixels_P + ")");
            Debug.output("\tCoverage from (" + nea + ", " + swo + ") to ("
                    + swa + ", " + neo + ")");
            Debug.output("\tPadded coverage starting at (" + pso + ", " + lso
                    + ")");
            Debug.output("\tNumber of pixels 360 e-w (" + arv + ") , n-s ("
                    + brv + ")");
            Debug.output("\tdegrees per horizontal block: " + degPerHorBlock
                    + ", vertical: " + degPerVerBlock);
            Debug.output("\tImage Data made up of count bits: "
                    + pixelCountBits + ", value bits: " + pixelValueBits);

            if (Debug.debugging("asrpdetail")) {
                Debug.output("Checking...");

                float latdiff = nea - swa;
                float londiff = neo - swo;

                float horPixels = arv * (londiff / 360f);
                float verPixels = brv * (latdiff / 360f);

                Debug.output("\tCalculating " + (horPixels / numHorPixels_Q)
                        + " hor blocks");
                Debug.output("\tCalculating " + (verPixels / numVerPixels_P)
                        + " hor blocks");
                Debug.output("\tCalculating "
                        + (lso + degPerHorBlock * numHorBlocks_N)
                        + " end latitude");
                Debug.output("\tCalculating "
                        + (pso - degPerVerBlock * numVerBlocks_M)
                        + " end latitude");
            }

        }

        getColors();

        gen.close();
        ger.close();
        qal.close();
        sou.close();
        img.close();
    }

    /**
     * A private class to store cached images.
     */
    private static class ASRPBlockCacheObject extends CacheObject {
        /**
         * @param id passed to superclass
         * @param obj passed to superclass
         */
        public ASRPBlockCacheObject(String id, OMGraphic obj) {
            super(id, obj);
        }

        /**
         * Calls dispose() on the contained frame, to make it eligible
         * for garbage collection.
         */
        public void finalize() {}
    }

    /**
     * Load a block image into the cache, based on the relative
     * coordintes of the block as a key.
     *
     * @param xAndY String of form 'x,y' identifying the relative location
     *        of the subframe image.
     * @return Block image, hidden as a CacheObject.
     */
    public CacheObject load(String xAndY) {
        if (xAndY != null) {

            int commaIndex = xAndY.indexOf(',');
            int x = Integer.parseInt(xAndY.substring(0, commaIndex));
            int y = Integer.parseInt(xAndY.substring(commaIndex + 1));

            if (Debug.debugging("asrpdetail")) {
                Debug.output("Getting tiled image " + x + ", " + y + " (from "
                        + xAndY + ")");
            }

            try {
                OMGraphic block = getBlock(x, y);
                if (block != null) {
                    return new ASRPBlockCacheObject(xAndY.intern(), block);
                }
            } catch (IOException ioe) {
                Debug.error("ASRPDirectory caught exception creating tiled image for "
                        + xAndY);
            }
        }
        return null;
    }

    public static void main(String[] argv) {
        Debug.init();

        if (argv.length < 1) {
            Debug.output("Usage: ASRPDirectory dir_pathname");
        } else {
            new ASRPDirectory(argv[0]);
        }

        System.exit(0);
    }

}
TOP

Related Classes of com.bbn.openmap.dataAccess.asrp.ASRPDirectory

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.