package com.bbn.openmap.proj; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.geom.Point2D; import java.util.ArrayList; import com.bbn.openmap.proj.coords.DatumShiftGCT; import com.bbn.openmap.proj.coords.LatLonPoint; /** * This projection wraps another projection and adds datum handling. The * motivation for this projection is to be able to serve wms clients requesting * maps in a datum different from wgs84. * <p> * The underlying data is supposed to be wgs4. The given {@link DatumShiftGCT} * convert this to another datum before using the wrapped projection to * calculate the screen coordinates. * <p> * {@link LatLonPoint} as input or output of any of the methods in this class is * in wgs84. Internally, each method will convert datums as needed. * <p> * A user (like wms) of this projection will use a * {@link com.bbn.openmap.proj.coords.CoordinateReferenceSystem} to convert coordinates to wgs84 before * using this method. */ public class DatumShiftProjection extends GeoProj { private GeoProj wrappedProjection; private DatumShiftGCT datum; public DatumShiftProjection(GeoProj proj, DatumShiftGCT datum) { super(proj.getCenter(), proj.getScale(), proj.getWidth(), proj.getHeight()); this.datum = datum; this.wrappedProjection = proj; setCenter(proj.getCenter()); } @Override public void setCenter(double lat, double lon) { super.setCenter(lat, lon); Point2D centerInDifferentDatum = datum.forward(lat, lon, new Point2D.Double()); wrappedProjection.setCenter((float) centerInDifferentDatum.getY(), (float) centerInDifferentDatum.getX()); } public ArrayList<float[]> _forwardPoly(float[] rawllpts, int ltype, int nsegs, boolean isFilled) { float[] rawllptsInDifferentDatum = new float[rawllpts.length]; Point2D tmpll = new Point2D.Double(); for (int i = 0; i < rawllpts.length; i += 2) { tmpll = datum.forward(Math.toDegrees(rawllpts[i]), Math.toDegrees(rawllpts[i + 1]), tmpll); rawllptsInDifferentDatum[i] = (float) Math.toRadians(tmpll.getY()); rawllptsInDifferentDatum[i + 1] = (float) Math.toRadians(tmpll.getX()); } return wrappedProjection._forwardPoly(rawllptsInDifferentDatum, ltype, nsegs, isFilled); } protected ArrayList<float[]> _forwardPoly(double[] rawllpts, int ltype, int nsegs, boolean isFilled) { double[] rawllptsInDifferentDatum = new double[rawllpts.length]; Point2D tmpll = new Point2D.Double(); for (int i = 0; i < rawllpts.length; i += 2) { tmpll = datum.forward(Math.toDegrees(rawllpts[i]), Math.toDegrees(rawllpts[i + 1]), tmpll); rawllptsInDifferentDatum[i] = Math.toRadians(tmpll.getY()); rawllptsInDifferentDatum[i + 1] = Math.toRadians(tmpll.getX()); } return wrappedProjection._forwardPoly(rawllptsInDifferentDatum, ltype, nsegs, isFilled); } protected void computeParameters() { if (wrappedProjection != null) { wrappedProjection.width = width; wrappedProjection.height = height; wrappedProjection.scale = scale; // wrappedProjection.ctrLat = ctrLat; // wrappedProjection.ctrLon = ctrLon; wrappedProjection.computeParameters(); } } public void drawBackground(Graphics2D g, Paint p) { wrappedProjection.drawBackground(g, p); } public void drawBackground(Graphics g) { wrappedProjection.drawBackground(g); } public double normalizeLatitude(double lat) { if (lat > NORTH_POLE) { return NORTH_POLE; } else if (lat < SOUTH_POLE) { return SOUTH_POLE; } return lat; } public Point2D forward(double lat, double lon, Point2D pt, boolean isRadian) { Point2D t; if (isRadian) { t = datum.forward(Math.toDegrees(lat), Math.toDegrees(lon)); } else { t = datum.forward(lat, lon); } return wrappedProjection.forward((float) t.getY(), (float) t.getX(), pt); } public boolean forwardRaw(float[] rawllpts, int rawoff, float[] xcoords, float[] ycoords, boolean[] visible, int copyoff, int copylen) { float[] rawllptsInDifferentDatum = new float[rawllpts.length]; Point2D tmpll = new Point2D.Double(); int end = copylen + copyoff; for (int i = copyoff, j = rawoff; i < end; i++, j += 2) { tmpll = datum.forward(Math.toDegrees(rawllpts[j]), Math.toDegrees(rawllpts[j + 1]), tmpll); rawllptsInDifferentDatum[j] = (float) Math.toRadians(tmpll.getY()); rawllptsInDifferentDatum[j + 1] = (float) Math.toRadians(tmpll.getX()); } return wrappedProjection.forwardRaw(rawllptsInDifferentDatum, rawoff, xcoords, ycoords, visible, copyoff, copylen); } public LatLonPoint getLowerRight() { Point2D llp = wrappedProjection.getLowerRight(); return datum.inverse(llp.getX(), llp.getY()); } public LatLonPoint getUpperLeft() { Point2D llp = wrappedProjection.getUpperLeft(); return datum.inverse(llp.getX(), llp.getY()); } public LatLonPoint inverse(double x, double y, Point2D pt) { LatLonPoint llpt = assertLatLonPoint(pt); llpt = (LatLonPoint) wrappedProjection.inverse(x, y, llpt); return datum.inverse(llpt.getX(), llpt.getY(), llpt); } public boolean isPlotable(double lat, double lon) { Point2D t = datum.forward(lat, lon); return wrappedProjection.isPlotable(t.getY(), t.getX()); } @Override public float getScale(Point2D ll1, Point2D ll2, Point2D point1, Point2D point2) { return wrappedProjection.getScale(ll1, ll2, point1, point2); } }