// **********************************************************************
//
// <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/shape/ESRIPoly.java,v $
// $RCSfile: ESRIPoly.java,v $
// $Revision: 1.5 $
// $Date: 2009/01/21 01:24:42 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.layer.shape;
import com.bbn.openmap.dataAccess.shape.ShapeUtils;
import com.bbn.openmap.proj.ProjMath;
import com.bbn.openmap.util.Debug;
/**
* A representation of a shape file polygon, subordinate to an
* <code>ESRIPolygonRecord</code>. This is an abstract class,
* please use one of the fully derived internal classes to do your
* bidding.
*
* <h3>TODO</h3>
* <ul>
* <li>Write double-floating point representation of an ESRIPoly.
* <li>Make sure to abstract float point vs double float in other
* objects of the ShapeFile reading code.
* </ul>
*
* @author Ray Tomlinson
* @author Tom Mitchell
* @author HACK-author blame it on aculline
* @version $Revision: 1.5 $ $Date: 2009/01/21 01:24:42 $
*/
public abstract class ESRIPoly extends ShapeUtils {
/**
* The number of (y,x) pairs of the ESRIPoly. This value should be
* the <code>points.length>>1</code>.
*/
public int nPoints;
/**
* Poly with data stored in floating point format. This ESRIPoly
* has been optimized for reading data in the OpenMap environment.
* By default, The internal points are stored in y,x,y,x
* (lat,lon,...) order as radian values. There have been
* allowances made to allow internal coordinates to be stored as
* decimal degree values, but this is not the best way to do
* things. The projection libraries are tuned for polygons holding
* radian point coordinates.
*/
public static class ESRIFloatPoly extends ESRIPoly {
/**
* A vector of vertices, stored as RADIAN y,x,y,x,
* (lat,lon,...). This is to allow for optimized processing by
* OpenMap.
*/
protected double[] radians;
/**
* Flag noting if the internal representation of coordinates
* is in RADIANS, or DECIMAL_DEGREES. By default, the
* coordinates are in radians. But, a constructor is available
* to let them be noted as DECIMAL_DEGREES. Also, if you ask
* for the coordinates as radians, they get converted to
* radians internally, and this flag gets set accordingly.
* Likewise, if you as for recimal degrees coordinates, the
* coordinates internally will be changed to reflect that.
*/
protected boolean isRadians = true;
/**
* Construct a poly with the given number of points. Remember
* to `+2' if you want all vertices for a polygon.
*
* @param nPts the number of (y,x) pairs
*/
public ESRIFloatPoly(int nPts) {
if (Debug.debugging("shape") && (nPts > 50000)) {
Debug.output("ESRIPoly w/" + nPts + " points");
}
nPoints = nPts;
radians = new double[nPoints * 2];
}
/**
* Construct an ESRIFloatPoly. Remember to `+2' if you want
* all vertices for a polygon.
*
* @param radians float[] coordinates: y,x,y,x,... (lat,lon)
* order in RADIANS!
*/
public ESRIFloatPoly(double[] radians) {
this.radians = radians;
this.isRadians = true;
nPoints = radians.length / 2;
}
/**
* Construct an ESRIFloatPoly. Remember to `+2' if you want
* all vertices for a polygon.
*
* @param radians float[] coordinates: y,x,y,x,... (lat,lon)
* order in RADIANS!
*/
public ESRIFloatPoly(double[] radians, boolean isRadians) {
this.radians = radians;
nPoints = radians.length / 2;
this.isRadians = isRadians;
}
/**
* Get the internal points array. If the internal points are
* not presently stored as radians, they will be permanently
* converted.
*
* @return float[] RADIAN y,x,y,x,... (lat,lon)
*/
public double[] getRadians() {
if (!isRadians) {
ProjMath.arrayDegToRad(radians);
isRadians = true;
}
return radians;
}
/**
* Get the internal points array. If the internal points are
* not presently stored as decimal degree values, the will be
* permanently.
*
* @return float[] DECIMAL_DEGREES y,x,y,x,... (lat,lon)
*/
public double[] getDecimalDegrees() {
if (isRadians) {
ProjMath.arrayRadToDeg(radians);
isRadians = false;
}
return radians;
}
/**
* Reads a polygon from the given buffer starting at the given
* offset.
*
* @param b the buffer
* @param off the offset
* @param connect connect the points (polygon)
* @return the number of bytes read
*/
public int read(byte b[], int off, boolean connect) {
int i, ptr = off;
int end = (connect) ? radians.length - 2 : radians.length;
for (i = 0; i < end; i += 2) {
// REMEMBER: y,x order (lat,lon order)
radians[i + 1] = ProjMath.degToRad((float) readLEDouble(b, ptr));//x
// (lon)
ptr += 8;
radians[i] = ProjMath.degToRad((float) readLEDouble(b, ptr));//y
// (lat)
ptr += 8;
}
// cap the points if polygon, assuming enough space in
// array...
if (connect) {
radians[i] = radians[0];
radians[i + 1] = radians[1];
}
return ptr - off;
}
/**
* Returns the x coordinate of the indicated vertex.
*
* @param index the ordinal of the vertex of interest
* @return the x (longitude) coordinate in decimal degrees
*/
public double getX(int index) {
// REMEMBER: y,x order (lat,lon order)
return ProjMath.radToDeg(radians[(index * 2) + 1]);//x
// (lon)
}
/**
* Returns the y coordinate of the indicated vertex.
*
* @param index the ordinal of the vertex of interest
* @return the y (latitude) coordinate in decimal degrees
*/
public double getY(int index) {
// REMEMBER: y,x order (lat,lon order)
return ProjMath.radToDeg(radians[(index * 2)]);//y (lat)
}
}
/**
* Reads a polygon from the given buffer starting at the given
* offset.
*
* @param b the buffer
* @param off the offset
* @return the number of bytes read
*/
public abstract int read(byte b[], int off, boolean connect);
}