Package com.bbn.openmap.proj

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

// **********************************************************************
//
// <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/proj/CADRG.java,v $
// $RCSfile: CADRG.java,v $
// $Revision: 1.4.2.3 $
// $Date: 2005/08/09 21:17:54 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.proj;

import java.awt.Point;
import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.MoreMath;
import com.bbn.openmap.util.Debug;

/**
* Implements the CADRG projection. This is really an Equal Arc
* Projection with pixel spacings as dictated by the RPF
* specification.
*/
public class CADRG extends Cylindrical implements EqualArc {

    /**
     * The CADRG name.
     */
    public final static transient String CADRGName = "CADRG";

    /**
     * The CADRG type of projection.
     */
    public final static transient int CADRGType = 42;

    public final static transient float epsilon = 0.0001f;

    // HACK -degrees
    private static final float NORTH_LIMIT = ProjMath.degToRad(80.0f);
    private static final float SOUTH_LIMIT = -NORTH_LIMIT;

    private double spps_x, spps_y; // scaled pixels per SCoord
    private static final int CADRG_ARC_A[] = { 369664, 302592, 245760, 199168,
            163328, 137216, 110080, 82432 };
    private static final double CADRG_SCALE_LIMIT = 2000.0;
    private static final int CADRG_get_zone_old_extents[] = { 32, 48, 56, 64,
            68, 72, 76, 80, 90 };
    private int /* ox, */oy;
    private double x_pix_constant, y_pix_constant;
    private Point ul;//upper left

    private float[] lower_zone_extents;
    private float[] upper_zone_extents;

    private int zone;

    /**
     * Construct a CADRG projection.
     *
     * @param center LatLonPoint center of projection
     * @param scale float scale of projection
     * @param width width of screen
     * @param height height of screen
     */
    public CADRG(LatLonPoint center, float scale, int width, int height) {
        super(center, scale, width, height, CADRGType);
        minscale = (float) 1000000 / (float) CADRG_SCALE_LIMIT;
    }

    /**
     * Sets radian latitude to something sane. This is an abstract
     * function since some projections don't deal well with extreme
     * latitudes.
     *
     * @param lat float latitude in radians
     * @return float latitude (-PI/2 &lt;= y &lt;= PI/2)
     * @see com.bbn.openmap.LatLonPoint#normalize_latitude(float)
     * 
     */
    public float normalize_latitude(float lat) {
        if (lat > NORTH_LIMIT) {
            lat = NORTH_LIMIT;
        } else if (lat < SOUTH_LIMIT) {
            lat = SOUTH_LIMIT;
        }
        return lat;
    }

    //    protected void finalize() {
    //      Debug.message("proj", "CADRG finialized");
    //    }

    /**
     * Return stringified description of this projection.
     * <p>
     *
     * @return String
     * @see Projection#getProjectionID
     * 
     */
    public String toString() {
        return "CADRG[ spps_x=" + spps_x + " spps_y=" + spps_y + " x_pix="
                + x_pix_constant + " y_pix=" + y_pix_constant +
                /* " ox=" + ox + */" oy=" + oy + " ul(" + ul.x + "," + ul.y
                + ")" + super.toString();
    }

    /**
     * Returns the current zone of the projection. Zone number starts
     * at 1, goes to 8, per the RPF specification. We don't handle
     * zone 9 (polar).
     *
     * @return the zone of the projection.
     */
    public int getZone() {
        return zone;
    }

    /**
     * Given a letter for a zone, return the CADRG zone equivalent,
     */
    public static int getProjZone(char asciiZone) {
        int z = (int) asciiZone;

        if (z == 74)
            z--; // Fix J to a zone.
        if (z > 64)
            z -= 64; // Below the equator
        else
            z -= 48; // Above the equator

        // Now we should have a number, of a zone 1-9
        return z;
    }

    /**
     * Get the planet pixel circumference.
     *
     * @return float circumference of planet in pixels
     */
    public float getPlanetPixelCircumference() {
        // Why this algorithm? Well, the CADRG_ARC_A is a pixel count
        // that needs to be multiplied by 1000000 to normalize it
        // against the 1:1M factor reflected in the array values. The
        // 1.5 factor was tossed in there because it was showing up in
        // other calculations as that 100/150 thing. It works in
        // tests.

        return (1000000 * (float) CADRG_ARC_A[zone - 1]) / 1.5f;
        // These are the same things...
        //      return (float)getXPixConstant() * scale;

        // This is what the default return value is from the super
        // class.
        //      return planetPixelCircumference; // the standard return for
        // projections...
    }

    /**
     * Returns the zone based on the y_pix_constant and a latitude.
     * <p>
     * HACK: latitude in decimal degrees DO THE CONSTANTS DEPEND ON
     * THIS?!!
     * <p>
     *
     * @param lat latitude
     * @param y_pix_constant pixel constant
     * 
     */
    private int getZone(double lat, double y_pix_constant) {
        int NOT_SET = -1;
        int ret = NOT_SET;

        double delta;
        double upper_lat, lower_lat;
        int x;
        double pivot;
        /** Pixels per degree */
        double ppd = y_pix_constant / 90;

        if (upper_zone_extents == null) {
            upper_zone_extents = new float[CADRG_get_zone_old_extents.length];
        }
        if (lower_zone_extents == null) {
            lower_zone_extents = new float[CADRG_get_zone_old_extents.length + 1];
        }

        /**
         * Delta*2 is the number of degrees for the height of the
         * projection.
         */
        if (y_pix_constant == 0)
            delta = 0;
        else
            delta = height / 2.0 * 90.0 / y_pix_constant;
        Debug.message("proj", "height = " + height);

        upper_lat = Math.abs(Math.abs(lat) + delta);
        lower_lat = Math.abs(Math.abs(lat) - delta);

        Debug.message("proj", "upper_lat = " + upper_lat);
        Debug.message("proj", "lower_lat = " + lower_lat);

        lower_zone_extents[0] = 0f;
        lower_zone_extents[8] = 80f;
        upper_zone_extents[8] = 90f;

        // figure out new extents - from CADRG spec
        for (x = 0; x < CADRG_get_zone_old_extents.length - 1/* 8 */; x++) {
            pivot = ppd * CADRG_get_zone_old_extents[x] / 1536.0;
            pivot = Math.floor(pivot);
            Debug.message("proj", "pivot = " + pivot);
            lower_zone_extents[x + 1] = (float) (pivot * 1536.0 / ppd);
            // Can't go further than the equator.
            //          if (x == 0) lower_zone_extents[x] = 0;
            pivot++;
            upper_zone_extents[x] = (float) (pivot * 1536.0 / ppd);
            Debug.message("proj", "lower_zone_extents[" + x + "] = "
                    + lower_zone_extents[x]);
            Debug.message("proj", "upper_zone_extents[" + x + "] = "
                    + upper_zone_extents[x]);

            if ((lower_lat <= (double) upper_zone_extents[x])
                    && (upper_lat <= (double) upper_zone_extents[x])
                    && ret == NOT_SET)
                ret = x + 1;
        }
        if (ret == NOT_SET)
            ret = CADRG_get_zone_old_extents.length - 1;

        return ret;
    }

    /**
     * Returns the x pixel constant of the projection. This was
     * calcuated when the projection was created. Represents the
     * number of pixels around the earth (360 degrees).
     */
    public double getXPixConstant() {
        return x_pix_constant;
    }

    /**
     * Returns the y pixel constant of the projection. This was
     * calcuated when the projection was created. Represents the
     * number of pixels from 0 to 90 degrees.
     */
    public double getYPixConstant() {
        return y_pix_constant;
    }

    /**
     * Returns the upper zone extent for the given zone at the current
     * scale. This only makes sense if the projection is at the same
     * scale as the chart data you are interested in.
     */
    public float getUpperZoneExtent(int zone) {
        if (zone < 1)
            zone = 1;
        if (zone > 8)
            zone = 9;
        return upper_zone_extents[zone - 1];
    }

    /**
     * Returns the lower zone extent for the given zone at the current
     * scale. This only makes sense if the projection is at the same
     * scale as the chart data you are interested in.
     */
    public float getLowerZoneExtent(int zone) {
        if (zone < 1)
            zone = 1;
        if (zone > 8)
            zone = 9;
        return lower_zone_extents[zone - 1];
    }

    /**
     * Return the number of horizontal frame files that will fit
     * around the world in the current zone. This only makes sense if
     * the projection is at the same scale as the chart data you are
     * interested in.
     *
     * @return number of frame columes in the current zone, to go
     *         around the world.
     */
    public int numHorizontalFrames() {
        return (int) Math.ceil(x_pix_constant / (1536.0));
    }

    /**
     * Return the number of vertical frame files that will fit within
     * the current zone, overlaps included. This only makes sense if
     * the projection is at the same scale as the chart data you are
     * interested in.
     *
     * @return number of frame rows in the current zone.
     */
    public int numVerticalFrames() {
        return (int) Math.round((upper_zone_extents[zone - 1] - lower_zone_extents[zone - 1])
                * (y_pix_constant / 90.0) / (1536.0));
    }

    /**
     * Figures out the number of pixels around the earth, for 360
     * degrees.
     * <p>
     *
     * @param adrgscale The scale adjusted to 1:1M (1M/real scale)
     * @param zone ADRG zone
     * @return The number of pixels around the equator (360 degrees)
     */
    private double CADRG_x_pix_constant(double adrgscale, int zone) {
        // E-W pixel constant
        double x_pix = (double) adrgscale * CADRG_ARC_A[zone - 1] / 512.0;

        // Increase, if necessary, to the next highest integer value
        x_pix = Math.ceil(x_pix);
        x_pix = x_pix * 1.33333;//(512*100)/(150*256);

        // Round the final result.
        x_pix = Math.round(x_pix);

        return x_pix * 256.0;
    }

    /**
     * Calculate the maximum allowable scale.
     * <p>
     *
     * @return float maxscale
     * 
     */
    private float CADRG_calc_maxscale() {
        // Why 1.5? It was 150/100? Why?
        return (1000000 * (float) CADRG_ARC_A[0]) / (width * 1.5f);
    }

    /**
     * Returns the number of pixels from the equator to a pole.
     * <p>
     *
     * @param adrgscale scale adjusted to 1:1M (1M/real scale)
     * @return number of pixels from 0 to 90 degrees
     * 
     */
    private double CADRG_y_pix_constant(double adrgscale) {
        final int CADRG_ARC_B = 400384;

        double y_pix = (double) adrgscale * CADRG_ARC_B / 512.0;

        // Increase, if necessary, to the next highest integer value
        y_pix = Math.ceil(y_pix);

        y_pix = y_pix * 0.33333;//(512*100)/(4*150*256);

        // Round the final result.
        y_pix = Math.round(y_pix);

        return y_pix * 256.0;
    }

    /**
     * Checks if a LatLonPoint is plot-able.
     * <p>
     * A point is plot-able in the CADRG projection if it is within
     * the North and South zone limits.
     * <p>
     *
     * @param lat float latitude in decimal degrees
     * @param lon float longitude in decimal degrees
     * @return boolean
     */
    public boolean isPlotable(float lat, float lon) {
        lat = normalize_latitude(ProjMath.degToRad(lat));
        return ((lat - epsilon < NORTH_LIMIT) && (lat + epsilon > SOUTH_LIMIT));
    }

    /**
     * Projects a point from Lat/Lon space to X/Y space.
     * <p>
     *
     * @param pt LatLonPoint
     * @param ret_val Point retval
     * @return Point ret_val
     */
    public Point forward(LatLonPoint pt, Point ret_val) {
        float lon_ = wrap_longitude(pt.radlon_ - ctrLon);
        float lat_ = normalize_latitude(pt.radlat_);

        ret_val.x = (int) ProjMath.roundAdjust(spps_x * lon_) - ul.x;
        ret_val.y = (int) ProjMath.roundAdjust(-spps_y * lat_) + ul.y + oy;

        return ret_val;
    }

    /**
     * Forward projects lat,lon into XY space and returns a Point.
     *
     * @param lat float latitude in radians
     * @param lon float longitude in radians
     * @param ret_val Resulting XY Point
     * @return Point ret_val
     */
    public Point forward(float lat, float lon, Point ret_val, boolean b) {
        float lon_ = wrap_longitude(lon - ctrLon);
        float lat_ = normalize_latitude(lat);

        ret_val.x = (int) ProjMath.roundAdjust(spps_x * lon_) - ul.x;
        ret_val.y = (int) ProjMath.roundAdjust(-spps_y * lat_) + ul.y + oy;
        return ret_val;
    }

    /**
     * Forward projects lat,lon coordinates.
     * <p>
     *
     * @param lat raw latitude in decimal degrees
     * @param lon raw longitude in decimal degrees
     * @param ret_val Resulting XY Point
     * @return Point ret_val
     */
    public Point forward(float lat, float lon, Point ret_val) {
        float lon_ = wrap_longitude(ProjMath.degToRad(lon) - ctrLon);
        float lat_ = normalize_latitude(ProjMath.degToRad(lat));

        ret_val.x = (int) ProjMath.roundAdjust(spps_x * lon_) - ul.x;
        ret_val.y = (int) ProjMath.roundAdjust(-spps_y * lat_) + ul.y + oy;
        return ret_val;
    }

    /**
     * Inverse project a Point.
     *
     * @param pt x,y Point
     * @param ret_val resulting LatLonPoint
     * @return LatLonPoint ret_val
     * 
     */
    public LatLonPoint inverse(Point pt, LatLonPoint ret_val) {
        //Debug.output("CADRG.inverse");
        Point pixpoint = new Point(0, 0);

        /* offset back into pixel space from Drawable space */
        pixpoint.x = pt.x + ul.x/* - ox */;
        pixpoint.y = -pt.y + ul.y + oy;

        // Check bounds on the call (P Space). Mutate if needed.
        if (pixpoint.x > (int) ProjMath.roundAdjust(world.x / 2.0)) {
            pixpoint.x = (int) ProjMath.roundAdjust(world.x / 2.0);
        } else if (pixpoint.x < (int) ProjMath.roundAdjust(-world.x / 2.0)) {
            pixpoint.x = (int) ProjMath.roundAdjust(-world.x / 2.0);
        }
        if (pixpoint.y > (int) ProjMath.roundAdjust(world.y / 2.0)) {
            pixpoint.y = (int) ProjMath.roundAdjust(world.y / 2.0);
        } else if (pixpoint.y < (int) ProjMath.roundAdjust(-world.y / 2.0)) {
            pixpoint.y = (int) ProjMath.roundAdjust(-world.y / 2.0);
        }

        // normalize_latitude on the way out.
        float lat_ = normalize_latitude((float) ((double) pixpoint.y / (double) spps_y));
        ret_val.setLatitude(ProjMath.radToDeg(lat_));
        // longitude is wrapped as usual.
        ret_val.setLongitude(ProjMath.radToDeg((float) ((double) pixpoint.x / (double) spps_x)
                + ctrLon));

        //      // normalize_latitude on the way out.
        //      float lat_ =
        // normalize_latitude(degToRad(((float)MoreMath.SC_TO_DEG(
        //          (int)(ProjMath.roundAdjust((double)pixpoint.y/(double)spps_y))))));
        //      ret_val.setLatitude((float)ProjMath.radToDeg(lat_));

        //      // longitude is wrapped as usual.
        //      ret_val.setLongitude((float)MoreMath.SC_TO_DEG(
        //          (int)(ProjMath.roundAdjust((double)pixpoint.x/(double)spps_x)
        // +
        //                MoreMath.DEG_TO_SC(ProjMath.radToDeg(ctrLon)))));

        return ret_val;
    }

    /**
     * Inverse project x,y coordinates into a LatLonPoint.
     * <p>
     *
     * @param x integer x coordinate
     * @param y integer y coordinate
     * @param ret_val LatLonPoint
     * @return LatLonPoint ret_val
     * @see Proj#inverse(Point)
     * 
     */
    public LatLonPoint inverse(int x, int y, LatLonPoint ret_val) {
        //Debug.output("CADRG.inverse");
        Point pixpoint = new Point(0, 0);

        /* offset back into pixel space from Drawable space */
        pixpoint.x = x + ul.x/* - ox */;
        pixpoint.y = -y + ul.y + oy;

        // Check bounds on the call (P Space). Mutate if needed.
        if (pixpoint.x > (int) ProjMath.roundAdjust(world.x / 2.0)) {
            pixpoint.x = (int) ProjMath.roundAdjust(world.x / 2.0);
        } else if (pixpoint.x < (int) ProjMath.roundAdjust(-world.x / 2.0)) {
            pixpoint.x = (int) ProjMath.roundAdjust(-world.x / 2.0);
        }
        if (pixpoint.y > (int) ProjMath.roundAdjust(world.y / 2.0)) {
            pixpoint.y = (int) ProjMath.roundAdjust(world.y / 2.0);
        } else if (pixpoint.y < (int) ProjMath.roundAdjust(-world.y / 2.0)) {
            pixpoint.y = (int) ProjMath.roundAdjust(-world.y / 2.0);
        }

        // normalize_latitude on the way out.
        float lat_ = normalize_latitude((float) ((double) pixpoint.y / (double) spps_y));
        ret_val.setLatitude(ProjMath.radToDeg(lat_));
        // longitude is wrapped as usual.
        ret_val.setLongitude(ProjMath.radToDeg((float) ((double) pixpoint.x / (double) spps_x)
                + ctrLon));

        return ret_val;
    }

    /**
     * Called when some fundamental parameters change.
     * <p>
     * Each projection will decide how to respond to this change. For
     * instance, they may need to recalculate "constant" paramters
     * used in the forward() and inverse() calls.
     * <p>
    
     */
    protected void computeParameters() {
        int w, h;

        if (ul == null)
            ul = new Point(0, 0); //HACK

        // quick calculate the maxscale
        maxscale = CADRG_calc_maxscale();
        if (scale > maxscale)
            scale = maxscale;

        // Compute the "ADRG" scale, which gets used below.
        double adrgscale = 1000000.0 / scale; // 1 million (from ADRG
                                              // spec)
        if (adrgscale > CADRG_SCALE_LIMIT) {
            Debug.message("proj", "CADRG: adrgscale > CADRG_SCALE_LIMIT");
            adrgscale = CADRG_SCALE_LIMIT;
        }

        // Compute the y pixel constant based on scale.
        y_pix_constant = CADRG_y_pix_constant(adrgscale);
        if (Debug.debugging("proj")) {
            Debug.output("Y pix constant = " + y_pix_constant);
        }
        // What zone are we in?
        zone = getZone(ProjMath.radToDeg(ctrLat), y_pix_constant);
        if (Debug.debugging("proj")) {
            Debug.output("Zone = " + zone);
        }

        // Compute the x pixel constant, based on scale and zone.
        x_pix_constant = CADRG_x_pix_constant(adrgscale, zone);
        if (Debug.debugging("proj")) {
            Debug.output("x_pix_constant = " + x_pix_constant);
        }
        // Now I can compute the world coordinate.
        if (world == null)
            world = new Point(0, 0);
        world.x = (int) ProjMath.roundAdjust(x_pix_constant);
        world.y = (int) ProjMath.roundAdjust(y_pix_constant * 4.0 / 2.0);
        Debug.message("proj", "world = " + world.x + "," + world.y);

        // Compute scaled pixels per RADIAN, not SCOORD
        spps_x = (double) x_pix_constant / MoreMath.TWO_PI/* MoreMath.DEG_TO_SC(360) */;
        spps_y = (double) y_pix_constant / MoreMath.HALF_PI/* MoreMath.DEG_TO_SC(90) */;
        Debug.message("proj", "spps = " + spps_x + "," + spps_y);

        // Fix the "small world" situation, computing ox, oy.
        if (width > world.x) {
            Debug.message("proj", "CADRG: fixing small world");
            w = world.x;
            //          ox = (int) ProjMath.roundAdjust((width - w) / 2.0);
        } else {
            w = width;
            //          ox = 0;
        }
        if (height > world.y) {
            h = (int) world.y;
            oy = (int) ProjMath.roundAdjust((height - h) / 2.0);
        } else {
            h = height;
            oy = 0;
        }

        // compute the "upper left" adjustment.
        long temp = (long) ProjMath.roundAdjust(spps_y * ctrLat);
        if (Debug.debugging("proj")) {
            Debug.output("CADRG.temp = " + temp);
        }
        if (ul == null)
            ul = new Point(0, 0);
        ul.x = (int) ProjMath.roundAdjust(-w / 2.0);
        if ((temp != 0) && (oy != 0)) {
            ul.y = (int) ProjMath.roundAdjust(h / 2.0);
        } else {
            ul.y = (int) temp + (int) ProjMath.roundAdjust(h / 2.0);
        }

        if (Debug.debugging("proj")) {
            Debug.output("CADRG: ul = " + ul.x + "," + ul.y);
            Debug.output(/* "ox = " + ox + */" oy = " + oy);
        }

        // Finally compute some useful cylindrical projection
        // parameters
        //      maxscale = (CADRG_ARC_A[0] * (1000000/width));// HACK!!!
        half_world = world.x / 2;
        if (scale > maxscale) {
            scale = maxscale;
        }
        //      scaled_radius = planetPixelRadius/scale;
        Debug.message("proj", "CADRG.computeParameters(): maxscale: "
                + maxscale);
    }

    /**
     * Get the name string of the projection.
     */
    public String getName() {
        return CADRGName;
    }

    /**
     * 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) {
        return getScale(ll1, ll2, point1, point2, 0);
    }

    /**
     * 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.
     * @param recursiveCount a protective count to keep this method
     *        from getting in a recursive death spiral.
     */
    private float getScale(LatLonPoint ll1, LatLonPoint ll2, Point point1,
                           Point point2, int recursiveCount) {

        try {

            float deltaDegrees;
            float pixPerDegree;
            int deltaPix;
            float ret;
            float dx = Math.abs(point2.x - point1.x);
            float dy = Math.abs(point2.y - point1.y);

            float nCenterLat = Math.min(ll1.getLatitude(), ll2.getLatitude())
                    + Math.abs(ll1.getLatitude() - ll2.getLatitude()) / 2f;
            float nCenterLon = Math.min(ll1.getLongitude(), ll2.getLongitude())
                    + Math.abs(ll1.getLongitude() - ll2.getLongitude()) / 2f;

            if (dx < dy) {
                float dlat = Math.abs(ll1.getLatitude() - ll2.getLatitude());
                deltaDegrees = dlat;
                deltaPix = getHeight();
                pixPerDegree = getScale() * (float) getYPixConstant() / 90f;
            } else {
                float dlon;
                float lat1, lon1, lon2;

                // point1 is to the right of point2. switch the
                // LatLonPoints so that ll1 is west (left) of ll2.
                if (point1.x > point2.x) {
                    lat1 = ll1.getLatitude();
                    lon1 = ll1.getLongitude();
                    ll1.setLatLon(ll2);
                    ll2.setLatLon(lat1, lon1);
                }

                lon1 = ll1.getLongitude();
                lon2 = ll2.getLongitude();

                // allow for crossing dateline
                if (lon1 > lon2) {
                    dlon = (180 - lon1) + (180 + lon2);
                } else {
                    dlon = lon2 - lon1;
                }

                deltaDegrees = dlon;
                deltaPix = getWidth();
                pixPerDegree = getPlanetPixelCircumference() / 360f;
            }

            // The new scale...
            ret = pixPerDegree / (deltaPix / deltaDegrees);

            //OK, now given the new scale at the apparent new center
            //location, we need to test if the zone changes, because
            //if it does, the values don't work out right because the
            //pixel spacings are different. If the zones are
            //different, we need to recalculate the scale based on
            // the
            //new zone.
            CADRG newcadrg = new CADRG(new LatLonPoint(nCenterLat, nCenterLon), ret, getWidth(), getHeight());

            // Use the recursiveCount to prevent extended recalls. A
            // couple rounds should suffice.
            if (newcadrg.getZone() != zone && recursiveCount < 2) {
                ret = newcadrg.getScale(ll1,
                        ll2,
                        newcadrg.forward(ll1),
                        newcadrg.forward(ll2),
                        recursiveCount + 1);
            }

            return ret;
        } catch (NullPointerException npe) {
            Debug.error("ProjMath.getScale(): caught null pointer exception.");
            return Float.MAX_VALUE;
        }
    }

    /*
     * public static void main (String argv[]) { CADRG proj= new
     * CADRG(new LatLonPoint(42.0f, 0.0f), 18000000.0f, 620,480);
     *
     * Debug.output("---testing latitude"); proj.testPoint(0.0f,
     * 0.0f); proj.testPoint(10.0f, 0.0f); proj.testPoint(-10.0f,
     * 0.0f); proj.testPoint(23.1234f, 0.0f);
     * proj.testPoint(-23.1234f, 0.0f); proj.testPoint(90.0f, 0.0f);
     * proj.testPoint(-100.0f, 0.0f);
     *
     * Debug.output("---testing longitude"); proj.testPoint(0.0f,
     * 10.0f); proj.testPoint(0.0f, -10.0f); proj.testPoint(0.0f,
     * 86.45f); proj.testPoint(0.0f, -86.45f); proj.testPoint(0.0f,
     * 375.0f); proj.testPoint(0.0f, -375.0f); }
     *
     * private void testPoint(float lat, float lon) { LatLonPoint
     * llpoint = new LatLonPoint(ProjMath.radToDeg(
     * normalize_latitude(ProjMath.degToRad(lat))), lon); Point point =
     * forward(llpoint);
     *
     * Debug.output("(lon="+llpoint.getLongitude()+
     * ",lat="+llpoint.getLatitude()+ ") =
     * (x="+point.x+",y="+point.y+")");
     *
     * llpoint = inverse(point);
     *
     * Debug.output("(x="+point.x+",y="+point.y+") = (lon="+
     * llpoint.getLongitude()+",lat="+ llpoint.getLatitude()+")"); }
     */
}
TOP

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

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.