Package com.bbn.openmap.proj

Source Code of com.bbn.openmap.proj.UTMProjection

package com.bbn.openmap.proj;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.ArrayList;

import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.proj.coords.UTMPoint;

/**
* A OpenMap Projection class that uses the {@link UTMPoint} to do its calculation.
*/
public class UTMProjection extends Proj {

    /**
     * Center of view as xy coordinates relative to the underlying projection
     */
    // TODO: find a better name?
    protected Point2D.Double xycenter = new Point2D.Double();

    protected int hy, wx;

    /**
     * Pixel per map unit. this is for a projection with a quadratic grid like
     * utm
     */
    protected float ppu;

    // used for calculating wrapping of ArrayList graphics
    // TODO: copied from Cylindrical. may need to change.
    protected Point world; // world width in pixels.

    protected int half_world; // world.x / 2

    private int zone_number;

    private boolean isnorthern;
   
    private Ellipsoid ellps;
   
    /**
     * The UTMType number. Just a random int not used by any other.
     */
    public final static transient int UTMType = 993387;

    public UTMProjection(LatLonPoint center, float s, int w, int h, int type, int zone_number,
            boolean isnorthern, Ellipsoid ellps) {
        super(center, s, w, h, type);

        this.zone_number = zone_number;
        this.isnorthern = isnorthern;
        this.ellps = ellps;
    }

    protected void computeParameters() {
        // super.computeParameters();

        hy = height / 2;
        wx = width / 2;

        if (xycenter != null) {
            UTMPoint c = UTMPoint.LLtoUTM(getCenter(), ellps, new UTMPoint(), zone_number, isnorthern);
            xycenter.setLocation(c.easting, c.northing);
        }

        // width of the world in pixels at current scale
        // TODO: copied from Cylindrical. may need to change
        if (world == null) {
            world = new Point();
        }
        world.x = (int) (planetPixelCircumference / scale);
        half_world = world.x / 2;

        ppu = (((float) pixelsPerMeter) / getScale());
    }

    public float normalize_latitude(float lat) {
        if (lat > NORTH_POLE) {
            return NORTH_POLE;
        } else if (lat < SOUTH_POLE) {
            return SOUTH_POLE;
        }
        return lat;
    }

    public Point forward(LatLonPoint llp, Point pt) {
        return forward(llp, pt, new UTMPoint());
    }
   
    private Point forward(LatLonPoint llp, Point pt, UTMPoint utmPoint) {
        utmPoint = UTMPoint.LLtoUTM(llp, ellps, utmPoint, zone_number, isnorthern);

        pt.x = (int) (wx + Math.round(ppu * (utmPoint.easting - xycenter.getX())));
        pt.y = (int) (hy - Math.round(ppu * (utmPoint.northing - xycenter.getY())));

        return pt;
    }

    public Point forward(float lat, float lon, Point pt) {
        return forward(new LatLonPoint(lat, lon), pt);
    }

    public Point forward(float lat, float lon, Point pt, boolean isRadian) {
        LatLonPoint ll = new LatLonPoint();
        ll.setLatLon(lat, lon, isRadian);
        return forward(ll, pt);
    }

    public LatLonPoint inverse(Point point, LatLonPoint llpt) {
        return inverse(point.x, point.y, llpt);
    }
   
    public LatLonPoint inverse(int x, int y, LatLonPoint llpt) {

        double northing = xycenter.getY() + ((hy - y) / ppu);
        double easting = xycenter.getX() + ((x - wx) / ppu);

        llpt = UTMPoint.UTMtoLL(ellps, (float) northing, (float) easting, zone_number,
                isnorthern, llpt);

        return llpt;
    }

    /**
     * Given a couple of points representing a bounding box, find out what the
     * scale should be in order to make those points appear at the corners of
     * the projection.
     *
     * @param ll1
     *            the upper left coordinates of the bounding box.
     * @param ll2
     *            the lower right coordinates of the bounding box.
     * @param point1
     *            a java.awt.Point reflecting a pixel spot on the projection
     *            that matches the ll1 coordinate, the upper left corner of the
     *            area of interest.
     * @param point2
     *            a java.awt.Point reflecting a pixel spot on the projection
     *            that matches the ll2 coordinate, usually the lower right
     *            corner of the area of interest.
     */
    public float getScale(LatLonPoint ll1, LatLonPoint ll2, Point point1, Point point2) {

        // super does not calculate scale correct for projections that does use
        // the same earth radius up north..

        float widthPX = point2.x - point1.x;
        float heightPX = point2.y - point1.y;
       
        UTMPoint xx1 = UTMPoint.LLtoUTM(ll1, ellps, new UTMPoint(), zone_number, isnorthern);
        UTMPoint xx2 = UTMPoint.LLtoUTM(ll2, ellps, new UTMPoint(), zone_number, isnorthern);

        float widthMap = (xx2.easting - xx1.easting);
        float widthScale = (float) (((double) getPPM()) * (widthMap / widthPX));

        float heightMap = (xx2.northing - xx1.northing);
        float heightScale = (float) (((double) getPPM()) * (heightMap / heightPX));
       
        // TODO: use width-, height- or medium scale? I guess width- and height scale should be
        // equal as the grid inside a single UTM zone is quadratic.

        return widthScale;
    }

    public boolean isPlotable(float lat, float lon) {
        return true;
    }

    protected ArrayList _forwardPoly(float[] rawllpts, int ltype, int nsegs, boolean isFilled) {
        // TODO: copied from Cylindrical. may need to change.
        int n, k, flag = 0, min = 0, max = 0, xp, xadj = 0;

        // determine length of pairs list
        int len = rawllpts.length >> 1; // len/2, chop off extra
        if (len < 2)
            return new ArrayList(0);

        // handle complicated line in specific routines
        if (isComplicatedLineType(ltype)) {
            return doPolyDispatch(rawllpts, ltype, nsegs, isFilled);
        }

        // determine when to stop
        Point temp = new Point(0, 0);
        int[] xs = new int[len];
        int[] ys = new int[len];
       
        // more temp objects to limit number of new objects that needs to be created
        UTMPoint tempUtm = new UTMPoint();
        LatLonPoint tempLL = new LatLonPoint();

        // forward project the first point
        tempLL.setLatLon(rawllpts[0], rawllpts[1], true);
        forward(tempLL, temp, tempUtm);
        //forward(rawllpts[0], rawllpts[1], temp, true, tempUtm);
        xp = temp.x;
        xs[0] = temp.x;
        ys[0] = temp.y;
        // forward project the other points
        for (n = 1, k = 2; n < len; n++, k += 2) {
            tempLL.setLatLon(rawllpts[k], rawllpts[k + 1], true);
            forward(tempLL, temp, tempUtm);
            //forward(rawllpts[k], rawllpts[k + 1], temp, true, tempUtm);
            xs[n] = temp.x;
            ys[n] = temp.y;
            // segment crosses longitude along screen edge
            if (Math.abs(xp - xs[n]) >= half_world) {
                flag += (xp < xs[n]) ? -1 : 1;// inc/dec the wrap
                // count
                min = (flag < min) ? flag : min;// left wrap count
                max = (flag > max) ? flag : max;// right wrap count
                xadj = flag * world.x;// adjustment to x coordinates
                // Debug.output("flag=" + flag + " xadj=" + xadj);
            }
            xp = temp.x;// save previous unshifted x coordinate
            if (flag != 0) {
                xs[n] += xadj;// adjust x coordinates
            }
        }
        min *= -1;// positive magnitude

        // now create the return list
        ArrayList ret_val = null;
        ret_val = new ArrayList(2 + 2 * (max + min));
        ret_val.add(xs);
        ret_val.add(ys);
        int[] altx = null;

        /*
         * if (Debug.debugging("proj")) { dumpPoly(rawllpts, xs, ys); }
         */

        // add the extra left-wrap polys
        for (int i = 1; i <= min; i++) {
            altx = new int[xs.length];
            xadj = i * world.x;// shift opposite
            for (int j = 0; j < altx.length; j++) {
                altx[j] = xs[j] + xadj;
            }
            ret_val.add(altx);
            ret_val.add(ys);
            /*
             * if (Debug.debugging("proj")) { dumpPoly(rawllpts, altx, ys); }
             */
        }

        // add the extra right-wrap polys
        for (int i = 1; i <= max; i++) {
            altx = new int[xs.length];
            xadj = -i * world.x;// shift opposite
            for (int j = 0; j < altx.length; j++) {
                altx[j] = xs[j] + xadj;
            }
            ret_val.add(altx);
            ret_val.add(ys);
            /*
             * if (Debug.debugging("proj")) { dumpPoly(rawllpts, altx, ys); }
             */
        }

        return ret_val;
    }// _forwardPoly()

    /**
     * Draw the background for the projection.
     *
     * @param g
     *            Graphics2D
     * @param paint
     *            java.awt.Paint to use for the background
     */
    public void drawBackground(Graphics2D g, java.awt.Paint paint) {
        g.setPaint(paint);
        drawBackground(g);
    }

    /**
     * Assume that the Graphics has been set with the Paint/Color needed, just
     * render the shape of the background.
     */
    public void drawBackground(Graphics g) {
        g.fillRect(0, 0, getWidth(), getHeight());
    }

    public boolean forwardRaw(float[] rawllpts, int rawoff, int[] xcoords, int[] ycoords,
            boolean[] visible, int copyoff, int copylen) {
        // TODO: copied from Cylindrical. may need a change
        Point temp = new Point();
        UTMPoint tempUtm = new UTMPoint();
        LatLonPoint tempLL = new LatLonPoint();
        int end = copylen + copyoff;
        for (int i = copyoff, j = rawoff; i < end; i++, j += 2) {
            tempLL.setLatLon(rawllpts[j], rawllpts[j + 1], true);
            forward(tempLL, temp, tempUtm);
            //forward(rawllpts[j], rawllpts[j + 1], temp, true, tempUtm);
            xcoords[i] = temp.x;
            ycoords[i] = temp.y;
            visible[i] = true;
        }
        // everything is visible
        return true;
    }

    public LatLonPoint getLowerRight() {
        return inverse(width - 1, height - 1);
    }

    public LatLonPoint getUpperLeft() {
        return inverse(0, 0);
    }

}
TOP

Related Classes of com.bbn.openmap.proj.UTMProjection

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.