// **********************************************************************
//
// <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/dataAccess/shape/input/ShpInputStream.java,v $
// $RCSfile: ShpInputStream.java,v $
// $Revision: 1.10 $
// $Date: 2009/01/21 01:24:42 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.dataAccess.shape.input;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import com.bbn.openmap.dataAccess.shape.EsriGraphic;
import com.bbn.openmap.dataAccess.shape.EsriGraphicFactory;
import com.bbn.openmap.dataAccess.shape.EsriGraphicList;
import com.bbn.openmap.dataAccess.shape.EsriPoint;
import com.bbn.openmap.dataAccess.shape.EsriPointList;
import com.bbn.openmap.dataAccess.shape.EsriPolygon;
import com.bbn.openmap.dataAccess.shape.EsriPolygonList;
import com.bbn.openmap.dataAccess.shape.EsriPolyline;
import com.bbn.openmap.dataAccess.shape.EsriPolylineList;
import com.bbn.openmap.dataAccess.shape.ShapeConstants;
import com.bbn.openmap.omGraphics.DrawingAttributes;
import com.bbn.openmap.omGraphics.OMColor;
import com.bbn.openmap.omGraphics.OMGraphic;
import com.bbn.openmap.omGraphics.OMGraphicList;
import com.bbn.openmap.omGraphics.OMPoly;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.util.Debug;
/**
* Reads geometry data from a .shp file.
*
* @author Doug Van Auken
*/
public class ShpInputStream
implements ShapeConstants {
/**
* An input stream to process primitives in Little Endian or Big Endian
*/
private LittleEndianInputStream _leis = null;
protected DrawingAttributes drawingAttributes = DrawingAttributes.getDefaultClone();
/**
* Constructor
*
* @param is An inputstream to chain with LittleEndianInputStream
*/
public ShpInputStream(InputStream is) {
BufferedInputStream bis = new BufferedInputStream(is);
_leis = new LittleEndianInputStream(bis);
}
/**
* Set the DrawingAttributes to use for drawing the graphics.
*/
public void setDrawingAttributes(DrawingAttributes da) {
drawingAttributes = da;
}
/**
* Get the DrawingAttributes used for drawing the graphics.
*/
public DrawingAttributes getDrawingAttributes() {
return drawingAttributes;
}
/**
* Reads geometry from a .shp file
*
* @param indexData The index data retrieved from the .shx file
* @return EsriGraphicList A list of geometry
* @deprecated use getGeometry() instead, indexData isn't used.
*/
public EsriGraphicList getGeometry(int[][] indexData)
throws Exception {
return getGeometry();
}
/**
* Reads geometry from a .shp file. This method will create an
* EsriGraphicFactory with the default settings (LINETYPE_STRAIGHT and no
* data projection available).
*
* @return EsriGraphicList A list of geometry
*/
public EsriGraphicList getGeometry()
throws Exception {
return getGeometry(new EsriGraphicFactory());
}
/**
* Reads geometry from a .shp file. This method will use the provided
* EsriGraphicFactory.
*
* @param factory an EsriGraphicFactory to be used to read from the internal
* stream.
* @return EsriGraphicList A list of geometry
*/
public EsriGraphicList getGeometry(EsriGraphicFactory factory)
throws Exception {
return (EsriGraphicList) factory.getEsriGraphics(_leis, drawingAttributes, (Object) null, (Projection) null,
(OMGraphicList) null);
}
/**
* Creates an array that specifies at what index a parts geometry begins with
*
* @return An array whose elements denote the position where a part begins
* witin an array of point data for a given shape
* @deprecated not used.
*/
protected int[] getPartOffsets(OMGraphicList sublist) {
int pos = 0;
int[] offsets = new int[sublist.size()];
for (int j = 0; j < sublist.size(); j++) {
OMPoly poly = (OMPoly) sublist.getOMGraphicAt(j);
double[] data = poly.getLatLonArray();
offsets[j] = pos / 2;
pos += data.length;
}
return offsets;
}
/**
* Iterates through the given input stream to construct geometry objects
*
* @param indexData A list of offsets obtained by iterating through the
* associated SHX file
* @return list An OMGraphicList that contains the collection of objects
* created by iterating through this input stream *
* @deprecated not used.
*/
public EsriGraphicList getPointGeometry(int[][] indexData)
throws Exception {
EsriGraphicList list = new EsriPointList();
int numShapes = indexData[1].length;
EsriPoint point;
for (int i = 0; i < numShapes; i++) {
int shpRecord = _leis.readInt();
/* int shpContentLength = */_leis.readInt();
int shpType = _leis.readLEInt();
if (shpType != SHAPE_TYPE_NULL) {
double lambda = _leis.readLEDouble();
double phi = _leis.readLEDouble();
float f1 = (float) lambda;
float f2 = (float) phi;
point = new EsriPoint(f2, f1);
// We reset the index to be based at 0 instead of 1, following Java
// convention.
point.putAttribute(SHAPE_INDEX_ATTRIBUTE, new Integer(shpRecord - 1));
if (drawingAttributes != null) {
drawingAttributes.setTo(point);
} else {
DrawingAttributes.DEFAULT.setTo(point);
}
list.add(point);
}
}
return list;
}
/**
* Iterates through each part of shape to obtain the total number of points
*
* @param sublist A list that contains multiple parts
* @return The total number of points for a given shape
* @deprecated not used.
*/
protected int getPointsPerShape(OMGraphicList sublist) {
int numPoints = 0;
for (int i = 0; i < sublist.size(); i++) {
OMPoly poly = (OMPoly) sublist.getOMGraphicAt(i);
double[] data = poly.getLatLonArray();
numPoints += data.length;
}
numPoints /= 2;
return numPoints;
}
/**
* Iterates through the given input stream to construct geometry objects
*
* @param shapeType the type of shape to read
* @param indexData A list of offsets obtained by iterating through the
* associated SHX file
* @return list An OMGraphicList that contains the collection of objects
* created by iterating through this input stream *
* @deprecated not used.
*/
public EsriGraphicList getPolyGeometry(int[][] indexData, int shapeType)
throws Exception {
EsriGraphicList list = null;
if (shapeType == SHAPE_TYPE_POLYLINE) {
list = new EsriPolylineList();
} else if (shapeType == SHAPE_TYPE_POLYGON) {
list = new EsriPolygonList();
}
int numVertices;
int numShapes = indexData[1].length;
for (int t = 0; t < numShapes; t++) {
// Resetting the index to be based on 0 instead of 1, following Java
// convention.
Integer shpRecordIndex = new Integer(_leis.readInt() - 1);
/* int shpContentLength = */_leis.readInt();
int shpType = _leis.readLEInt();
if (shpType != SHAPE_TYPE_NULL) {
/* double xLeft = */_leis.readLEDouble();
/* double xBottom = */_leis.readLEDouble();
/* double xRight = */_leis.readLEDouble();
/* double xTop = */_leis.readLEDouble();
int numParts = _leis.readLEInt();
int numPoints = _leis.readLEInt();
int[] offsets = new int[numParts];
// OK, we don't want to create a sublist unless the poly
// has multiple parts. Remember that. sublist will only
// be created if there is more than one part.
for (int n = 0; n < numParts; n++) {
offsets[n] = _leis.readLEInt();
}
double[] points;
OMGraphic poly = null;
EsriGraphicList sublist = null;
if (numParts > 1) {
if (shapeType == SHAPE_TYPE_POLYLINE) {
sublist = new EsriPolylineList();
} else if (shapeType == SHAPE_TYPE_POLYGON) {
sublist = new EsriPolygonList();
}
if (sublist != null) {
sublist.setVague(true); // Treat sublist as one
// OMGraphic.
sublist.putAttribute(SHAPE_INDEX_ATTRIBUTE, shpRecordIndex);
}
}
for (int j = 0; j < numParts; j++) {
int i = 0;
if (j != numParts - 1) {
numVertices = (offsets[j + 1]) - offsets[j];
points = new double[numVertices * 2];
} else {
numVertices = (numPoints - offsets[j]);
points = new double[numVertices * 2];
}
for (int n = 0; n < numVertices; n++) {
double lambda = _leis.readLEDouble();
double phi = _leis.readLEDouble();
points[i++] = (float) Math.toRadians(phi);
points[i++] = (float) Math.toRadians(lambda);
}
if (shapeType == SHAPE_TYPE_POLYLINE) {
poly = new EsriPolyline(points, OMGraphic.RADIANS, OMGraphic.LINETYPE_GREATCIRCLE);
} else if (shapeType == SHAPE_TYPE_POLYGON) {
poly = new EsriPolygon(points, OMGraphic.RADIANS, OMGraphic.LINETYPE_GREATCIRCLE);
}
if (drawingAttributes != null) {
drawingAttributes.setTo(poly);
} else {
DrawingAttributes.DEFAULT.setTo(poly);
}
if (poly instanceof EsriPolyline) {
// Just to make sure it gets rendered as a
// polyline. The OMPoly code will render it as a
// polygon if the fill color is not clear.
poly.setFillPaint(OMColor.clear);
}
// sublist is null for non multi-part geometries.
if (sublist != null) {
sublist.addOMGraphic(poly);
} else if (poly != null) {
poly.putAttribute(SHAPE_INDEX_ATTRIBUTE, shpRecordIndex);
}
}
// sublist is null for non multi-part geometries.
if (list != null) {
if (sublist != null) {
list.add(sublist);
} else {
list.add(poly);
}
if (Debug.debugging("esri")) {
EsriGraphic eg = null;
if (sublist == null) {
eg = (EsriGraphic) poly;
} else {
eg = sublist;
}
if (eg != null) {
double[] ex1 = eg.getExtents();
Debug.output("extents of list: xmin=" + ex1[1] + ", ymin=" + ex1[0] + ", xmax=" + ex1[3] + ", ymax=" + ex1[2]);
Debug.output("list.size=" + list.size());
}
}
}
}
}
if (Debug.debugging("esri") && list != null) {
double[] ex = list.getExtents();
Debug.output("extents of list: xmin=" + ex[1] + ", ymin=" + ex[0] + ", xmax=" + ex[3] + ", ymax=" + ex[2]);
}
return list;
}
/**
* Reads the header section of a .shp file
*
* @return the shape type
* @deprecated not used.
*/
public int readHeader()
throws IOException {
/* int fileCode = */_leis.readInt();
_leis.skipBytes(20);
/* int fileLength = */_leis.readInt();
/* int version = */_leis.readLEInt();
int shapeType = _leis.readLEInt();
/* double xMin = */_leis.readLEDouble();
/* double yMin = */_leis.readLEDouble();
/* double xMax = */_leis.readLEDouble();
/* double yMax = */_leis.readLEDouble();
/* double zMin = */_leis.readLEDouble();
/* double zMax = */_leis.readLEDouble();
/* double mMin = */_leis.readLEDouble();
/* double mMax = */_leis.readLEDouble();
return shapeType;
}
}