Package com.bbn.openmap.layer.vpf

Source Code of com.bbn.openmap.layer.vpf.VMAP2Shape

// **********************************************************************
//
// <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/vpf/VMAP2Shape.java,v $
// $RCSfile: VMAP2Shape.java,v $
// $Revision: 1.2.2.5 $
// $Date: 2005/09/09 21:23:07 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.layer.vpf;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.MoreMath;
import com.bbn.openmap.dataAccess.shape.EsriShapeExport;
import com.bbn.openmap.layer.shape.ShapeFile;
import com.bbn.openmap.layer.shape.ShapeUtils;
import com.bbn.openmap.omGraphics.OMGraphic;
import com.bbn.openmap.omGraphics.OMGraphicList;
import com.bbn.openmap.omGraphics.OMPoly;
import com.bbn.openmap.omGraphics.SinkGraphic;
import com.bbn.openmap.proj.DrawUtil;
import com.bbn.openmap.proj.ProjMath;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.util.PropUtils;

/**
* Convert NIMA VMAP geospatial data into ESRI shapefile format.
*/
public class VMAP2Shape {

    protected static final String DEF_VMAP_TYPE = "bnd";
    protected static final String DEF_PROPS_FILE_NAME = System.getProperty("user.home")
            + System.getProperty("file.separator") + "openmap.properties";
    protected static final String DEF_PREFIX = "vmapref";
    protected static final boolean DEF_DO_THINNING = false;
    protected static final float DEF_FAN_EPS = 0.1f;
    protected static final float DEF_ZERO_EPS = 0.0001f;
    protected static final float DEF_THRESHOLD = 0.5f;

    protected String vmaptype = DEF_VMAP_TYPE;
    protected String propsFileName = DEF_PROPS_FILE_NAME;
    protected String prefix = DEF_PREFIX;
    protected boolean doThinning = DEF_DO_THINNING;
    protected float fan_eps = DEF_FAN_EPS;
    protected float zero_eps = DEF_ZERO_EPS;
    protected float threshold = DEF_THRESHOLD;

    protected LibrarySelectionTable lst;
    protected transient LayerGraphicWarehouseSupport warehouse;

    public VMAP2Shape() {}

    /**
     * Will load the properties set in the VPF2Shape object, fetch the
     * OMGraphics from the VPF database, and write the shape file.
     *
     * @param shapeFileName
     */
    public void writeShapeFile(String shapeFileName) {
        setProperties(prefix, loadProperties());
        writeShapeFile(shapeFileName, getRectangle());
    }

    /**
     * Write the shape file, assumes that the properties have been
     * loaded and the graphics fetched from the VPF database.
     *
     * @param shapeFileName the file name to write the shapes into.
     * @param graphics OMGraphics from VPF database to write to shape
     *        file.
     */
    public void writeShapeFile(String shapeFileName, OMGraphicList graphics) {
        try {
            ShapeFile s = new ShapeFile(shapeFileName);
            int nGraphics = graphics.size();
            if (nGraphics > 0) {
                OMGraphic omg = graphics.getOMGraphicAt(0);
                if ((omg instanceof OMPoly)
                        && (omg.getRenderType() == OMGraphic.RENDERTYPE_LATLON)) {
                    int shapeType = ((OMPoly) omg).isPolygon() ? ShapeUtils.SHAPE_TYPE_POLYGON
                            : ShapeUtils.SHAPE_TYPE_ARC;
                    System.out.println("shapeType=" + shapeType);
                    s.setShapeType(shapeType);
                }
            }

            System.out.println(nGraphics + " candidates.");

            if (doThinning) {
                OMGraphicList saveGraphics = new OMGraphicList();
                for (int i = 0; i < nGraphics; i++) {
                    OMGraphic omg = graphics.getOMGraphicAt(i);
                    if ((omg instanceof OMPoly)
                            && (omg.getRenderType() == OMGraphic.RENDERTYPE_LATLON)) {
                        OMPoly poly = (OMPoly) omg;

                        if (maybeThrowAwayPoly(poly)) {
                            continue;
                        }

                        saveGraphics.addOMGraphic(poly);
                    } else {
                        System.out.println("Skipping candidate: "
                                + omg.getClass().toString() + ", "
                                + omg.getRenderType());
                    }
                }
               
                graphics = saveGraphics;

                // join polylines
                if (false) {
                    nGraphics = graphics.size();
                    System.out.println("Joining " + nGraphics + " polyline candidates.");
                    graphics = joinCommonLines(graphics, zero_eps);
                }
            }

            // Using com.bbn.openmap.dataAccess.shape package to write
            // shape file:
            EsriShapeExport ese = new EsriShapeExport(graphics, (Projection) null, shapeFileName);
            ese.export();

            // Instead of using com.bbn.openmap.layer.shape package to
            // write shape file:

            // int nDumped = 0;
            // nGraphics = graphics.size();
            // System.out.println("Dumping " + nGraphics + "
            // graphics.");
            // for (int i = 0; i < nGraphics; i++) {
            // OMPoly poly = (OMPoly) graphics.getOMGraphicAt(i);
            // float[] radians = poly.getLatLonArray();
            // ESRIPolygonRecord epr = new ESRIPolygonRecord();
            // epr.add(radians);
            // epr.setPolygon(poly.isPolygon());//set POLYGON vs ARC
            // s.add(epr);
            // ++nDumped;
            // }
            //
            // s.verify(true, true);
            // s.verify(true, true);
            // s.close();
            // System.out.println("Wrote " + nDumped + " Graphics.");

        } catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Iterates through graphic list finding non-connected polylines.
     * iterates over these to find lines with common endpoints and
     * joining them.
     *
     * @param list
     * @param zero_eps
     * @return
     */
    protected static OMGraphicList joinCommonLines(OMGraphicList list,
                                                   float zero_eps) {
        int size = list.size();
        int len1, len2;
        float lat1, lon1, lat2, lon2;
        OMGraphic obj;
        OMGraphicList newGraphics = new OMGraphicList();
        OMGraphicList plineGraphics = new OMGraphicList();

        // check for non-connected polylines
        System.out.println("finding polylines...");
        for (int i = 0; i < size; i++) {
            obj = list.getOMGraphicAt(i);
            if ((obj instanceof OMPoly) && !((OMPoly) obj).isPolygon()) {
                plineGraphics.addOMGraphic(obj);
            } else {
                newGraphics.addOMGraphic(obj);
            }
        }

        // iterate through the polylines and join lines with common
        // endpoints
        size = plineGraphics.size();
        OMPoly poly1, poly2;
        float[] rads1, rads2, radians;
        System.out.println("maybe joining " + size + " polylines...");
        // nasty!: > O(n^2)
        for (int i = 0; i < size; i++) {
            if (i % 500 == 0) {
                System.out.println("checking pline i=" + i);
            }
            for (int j = 0; j < size; j++) {
                if (i == j) {
                    continue;
                }
                obj = plineGraphics.getOMGraphicAt(i);
                if (obj instanceof SinkGraphic) {
                    continue;
                }
                poly1 = (OMPoly) obj;
                rads1 = poly1.getLatLonArray();
                len1 = rads1.length;
                lat1 = ProjMath.radToDeg(rads1[len1 - 2]);
                lon1 = ProjMath.radToDeg(rads1[len1 - 1]);

                obj = plineGraphics.getOMGraphicAt(j);
                if (obj instanceof SinkGraphic) {
                    continue;
                }
                poly2 = (OMPoly) obj;
                rads2 = poly2.getLatLonArray();
                len2 = rads2.length;
                lat2 = ProjMath.radToDeg(rads2[0]);
                lon2 = ProjMath.radToDeg(rads2[1]);

                if (MoreMath.approximately_equal(lat1, lat2, zero_eps)
                        && MoreMath.approximately_equal(lon1, lon2, zero_eps)) {
                    // System.out.println("joining...");
                    radians = new float[len1 + len2 - 2];
                    System.arraycopy(rads1, 0, radians, 0, len1);
                    System.arraycopy(rads2, 0, radians, len1 - 2, len2);
                    poly1.setLocation(radians, OMGraphic.RADIANS);
                    plineGraphics.setOMGraphicAt(SinkGraphic.getSharedInstance(),
                            j);
                    j = -1;// redo search
                }
            }
        }

        // add the joined lines back to the data set
        size = plineGraphics.size();
        for (int i = 0; i < size; i++) {
            obj = plineGraphics.getOMGraphicAt(i);
            if (obj instanceof OMPoly) {
                newGraphics.addOMGraphic(obj);
            }
        }
        return newGraphics;
    }

    /** traverse array and coalesce adjacent points which are the same */
    public static float[] coalesce_points(float[] radians, float eps,
                                          boolean ispolyg) {
        int write = 2;
        int len = radians.length;
        for (int i = write - 2, j = write; j < len; j += 2) {
            float lat1 = ProjMath.radToDeg(radians[i]);
            float lon1 = ProjMath.radToDeg(radians[i + 1]);
            float lat2 = ProjMath.radToDeg(radians[j]);
            float lon2 = ProjMath.radToDeg(radians[j + 1]);
            if (MoreMath.approximately_equal(lat1, lat2, eps)
                    && MoreMath.approximately_equal(lon1, lon2, eps)) {
                continue;
            }
            i = write;
            radians[write++] = radians[j];
            radians[write++] = radians[j + 1];
        }
        // check for mid-phase line
        if (ispolyg && (write == 6)
                && MoreMath.approximately_equal(radians[0], radians[4], eps)
                && MoreMath.approximately_equal(radians[1], radians[5], eps)) {
            write -= 2;// eliminate wrapped vertex
        }
        float[] newrads = new float[write];
        System.arraycopy(radians, 0, newrads, 0, write);
        return newrads;
    }

    /** return true if we should throw away the poly */
    protected boolean maybeThrowAwayPoly(OMPoly poly) {
        float[] radians = poly.getLatLonArray();
        float lat, lon, thresh = ProjMath.degToRad(threshold);
        radians = coalesce_points(radians, 0.0001f, poly.isPolygon());
        poly.setLocation(radians, OMGraphic.RADIANS);// install new
        if (radians.length < 4) {
            return true;// throw away
        }
        if (poly.isPolygon() && (radians.length < 6)) {
            return true;
        }
        int len = radians.length;
        float d;
        for (int i = 0; i < len; i += 2) {
            // test for proximity to 1-degree marks. this hopefully
            // avoids the problem of throwing away tiled slivers.
            // (don't throw away poly)
            lat = ProjMath.radToDeg(radians[i]);
            lon = ProjMath.radToDeg(radians[i + 1]);
            if (MoreMath.approximately_equal(lat,
                    (float) (Math.round(lat)),
                    zero_eps)) {
                return false;
            }
            if (MoreMath.approximately_equal(lon,
                    (float) (Math.round(lon)),
                    zero_eps)) {
                return false;
            }

            // check to see if all points fit within a certain
            // threshold. this should eliminate small islands and
            // countries like Luxembourg. sorry.
            for (int j = i + 2; j < radians.length; j += 2) {
                d = DrawUtil.distance(radians[i],
                        radians[i + 1],
                        radians[j],
                        radians[j + 1]);
                // outside threshold, don't throw away
                if (!MoreMath.approximately_equal(d, 0f, thresh)) {
                    return false;
                }
            }
        }

        if (poly.isPolygon()) {
            return true;// throw away
        }

        // throw away polyline if it's connected (island)
        return (MoreMath.approximately_equal(ProjMath.radToDeg(radians[0]),
                ProjMath.radToDeg(radians[radians.length - 2]),
                zero_eps) && MoreMath.approximately_equal(ProjMath.radToDeg(radians[1]),
                ProjMath.radToDeg(radians[radians.length - 1]),
                zero_eps));
    }

    protected Properties loadProperties() {
        Properties props = new Properties();
        try {
            props.load(new FileInputStream(propsFileName));
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
        return props;
    }

    protected void setProperties(String prefix, Properties props) {

        String realPrefix = PropUtils.getScopedPropertyPrefix(prefix);

        String[] paths = PropUtils.initPathsFromProperties(props, realPrefix
                + VPFLayer.pathProperty);

        String defaultProperty = props.getProperty(realPrefix
                + VPFLayer.defaultLayerProperty);

        if (defaultProperty != null) {
            System.out.println("defaultProperty=" + defaultProperty);
            realPrefix = defaultProperty + ".";
            props = VPFLayer.getDefaultProperties();
        }

        String coverage = props.getProperty(realPrefix
                + VPFLayer.coverageTypeProperty);
        if (coverage != null) {
            vmaptype = coverage;
            System.out.println("vmaptype=" + vmaptype);
        }
        initLST(paths);
        if (lst.getDatabaseName().equals("DCW")) {
            System.out.println("creating VPFLayerDCWWarehouse");
            warehouse = new VPFLayerDCWWarehouse();
        } else {
            System.out.println("creating VPFLayerGraphicWarehouse");
            warehouse = new VPFLayerGraphicWarehouse();
        }

        LayerGraphicWarehouseSupport.setDoThinning(doThinning);
        LayerGraphicWarehouseSupport.setFanEpsilon(fan_eps);
        warehouse.setProperties(realPrefix, props);
    }

    protected void initLST(String[] paths) {
        try {
            if (lst == null) {
                lst = new LibrarySelectionTable(paths);
            }
        } catch (com.bbn.openmap.io.FormatException f) {
            throw new java.lang.IllegalArgumentException(f.getMessage());
        }
    }

    public OMGraphicList getRectangle() {
        int scale = 30000000;
        int width = 640;
        int height = 480;
        LatLonPoint upperLeft = new LatLonPoint(90.0f, -180.0f);
        LatLonPoint lowerRight = new LatLonPoint(-90.0f, 180.0f);

        warehouse.clear();

        System.out.println("VMAP2Shape.getRectangle(): "
                + "calling drawTile with boundaries: " + upperLeft + lowerRight);
        long start = System.currentTimeMillis();
        lst.drawTile(scale,
                width,
                height,
                vmaptype,
                warehouse,
                upperLeft,
                lowerRight);
        long stop = System.currentTimeMillis();
        System.out.println("VMAP2Shape.getRectangle(): read time: "
                + ((stop - start) / 1000d) + " seconds");

        return warehouse.getGraphics();
    }

    public boolean isDoThinning() {
        return doThinning;
    }

    public void setDoThinning(boolean doThinning) {
        this.doThinning = doThinning;
    }

    public float getFan_eps() {
        return fan_eps;
    }

    public void setFan_eps(float fan_eps) {
        this.fan_eps = fan_eps;
    }

    public LibrarySelectionTable getLst() {
        return lst;
    }

    public void setLst(LibrarySelectionTable lst) {
        this.lst = lst;
    }

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getPropsFileName() {
        return propsFileName;
    }

    public void setPropsFileName(String propsFileName) {
        this.propsFileName = propsFileName;
    }

    public float getThreshold() {
        return threshold;
    }

    public void setThreshold(float threshold) {
        this.threshold = threshold;
    }

    public String getVmaptype() {
        return vmaptype;
    }

    public void setVmaptype(String vmaptype) {
        this.vmaptype = vmaptype;
    }

    public LayerGraphicWarehouseSupport getWarehouse() {
        return warehouse;
    }

    public void setWarehouse(LayerGraphicWarehouseSupport warehouse) {
        this.warehouse = warehouse;
    }

    public float getZero_eps() {
        return zero_eps;
    }

    public void setZero_eps(float zero_eps) {
        this.zero_eps = zero_eps;
    }

    public static void usage() {
        System.out.println("Usage: java VMAP2Shape [args] <outfile.shp>");
        System.out.println("Arguments:");
        System.out.println("\t-props <path>             path to properties file");
        System.out.println("                            default: "
                + DEF_PROPS_FILE_NAME);
        System.out.println("\t-prefix <identifier>      vmap properties prefix");
        System.out.println("                            default: " + DEF_PREFIX);
        System.out.println("\t-thin <eps> <thresh>      do thinning");
        System.out.println("                            default eps="
                + DEF_FAN_EPS + " thresh=" + DEF_THRESHOLD);
        System.exit(1);
    }

    public static void main(String args[]) {
        if ((args.length == 0)
                || ((args.length == 1) && (args[0].startsWith("-")))) {
            usage();
        }

        com.bbn.openmap.util.Debug.init(System.getProperties());

        VMAP2Shape c = new VMAP2Shape();

        for (int i = 0; i < args.length - 1; i++) {
            if (args[i].equalsIgnoreCase("-props")) {
                c.setPropsFileName(args[++i]);
            } else if (args[i].equalsIgnoreCase("-prefix")) {
                c.setPrefix(args[++i]);
            } else if (args[i].equalsIgnoreCase("-thin")) {
                c.setDoThinning(true);
                c.setFan_eps(Float.valueOf(args[++i]).floatValue());
                c.setThreshold(Float.valueOf(args[++i]).floatValue());
            } else {
                usage();
            }
        }

        c.writeShapeFile(args[args.length - 1]);

    }
}
TOP

Related Classes of com.bbn.openmap.layer.vpf.VMAP2Shape

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.