// ********************************************************************** // // <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/ShapeUtils.java,v $ // $RCSfile: ShapeUtils.java,v $ // $Revision: 1.5 $ // $Date: 2005/12/09 21:09:09 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.dataAccess.shape; import java.io.EOFException; import java.io.IOException; import com.bbn.openmap.io.BinaryBufferedFile; import com.bbn.openmap.layer.shape.ESRIBoundingBox; import com.bbn.openmap.layer.shape.ESRIPoint; /** * Utilities for reading and writing the components of shape files. * * @author Tom Mitchell * @version $Revision: 1.5 $ $Date: 2005/12/09 21:09:09 $ */ public class ShapeUtils implements ShapeConstants { /** A buffer for reading/writing little endian ints. */ private static byte leiBuffer[] = new byte[4]; /** * Reads a big endian integer. * * @param b the raw data buffer * @param off the offset into the buffer where the int resides * @return the int read from the buffer at the offset location */ public static int readBEInt(byte[] b, int off) { return (((b[off + 0] & 0xff) << 24) | ((b[off + 1] & 0xff) << 16) | ((b[off + 2] & 0xff) << 8) | ((b[off + 3] & 0xff))); } /** * Reads a little endian integer. * * @param b the raw data buffer * @param off the offset into the buffer where the int resides * @return the int read from the buffer at the offset location */ public static int readLEInt(byte[] b, int off) { return (((b[off + 3] & 0xff) << 24) | ((b[off + 2] & 0xff) << 16) | ((b[off + 1] & 0xff) << 8) | ((b[off + 0] & 0xff))); } /** * Reads a little endian int from the current location of the given file. * Synchronized for thread-safe access to leiBuffer. * * @param in an input file * @return the int read from the file */ public static synchronized int readLEInt(BinaryBufferedFile in) throws IOException { int result = in.read(leiBuffer, 0, 4); if (result < 4) { throw new EOFException(); } else { return readLEInt(leiBuffer, 0); } } /** * Reads a little endian 8 byte integer. * * @param b the raw data buffer * @param off the offset into the buffer where the long resides * @return the long read from the buffer at the offset location */ public static long readLELong(byte[] b, int off) { return (((b[off + 0] & 0xffL)) | ((b[off + 1] & 0xffL) << 8) | ((b[off + 2] & 0xffL) << 16) | ((b[off + 3] & 0xffL) << 24) | ((b[off + 4] & 0xffL) << 32) | ((b[off + 5] & 0xffL) << 40) | ((b[off + 6] & 0xffL) << 48) | ((b[off + 7] & 0xffL) << 56)); } /** * Reads a little endian double. * * @param b the raw data buffer * @param off the offset into the buffer where the double resides * @return the double read from the buffer at the offset location */ public static double readLEDouble(byte[] b, int off) { double result = Double.longBitsToDouble(readLELong(b, off)); return result; } /** * Reads a point record. A point record is a double representing the x value * and a double representing a y value. * * @param b the raw data buffer * @param off the offset into the buffer where the int resides * @return the point read from the buffer at the offset location */ public static ESRIPoint readPoint(byte[] b, int off) { ESRIPoint point = new ESRIPoint(); point.x = readLEDouble(b, off); point.y = readLEDouble(b, off + 8); return point; } /** * Reads a bounding box record. A bounding box is four double representing, * in order, xmin, ymin, xmax, ymax. * * @param b the raw data buffer * @param off the offset into the buffer where the int resides * @return the point read from the buffer at the offset location */ public static ESRIBoundingBox readBox(byte[] b, int off) { ESRIBoundingBox bb = new ESRIBoundingBox(); bb.min = readPoint(b, off); bb.max = readPoint(b, off + 16); return bb; } /** * Writes the given integer to the given buffer at the given location in big * endian format. * * @param b the data buffer * @param off the offset into the buffer where writing should occur * @param val the integer to write * @return the number of bytes written */ public static int writeBEInt(byte[] b, int off, int val) { b[off + 0] = (byte) ((val >> 24) & 0xff); b[off + 1] = (byte) ((val >> 16) & 0xff); b[off + 2] = (byte) ((val >> 8) & 0xff); b[off + 3] = (byte) ((val) & 0xff); return 4; } /** * Writes the given integer to the given buffer at the given location in * little endian format. * * @param b the data buffer * @param off the offset into the buffer where writing should occur * @param val the integer to write * @return the number of bytes written */ public static int writeLEInt(byte[] b, int off, int val) { b[off + 0] = (byte) ((val) & 0xff); b[off + 1] = (byte) ((val >> 8) & 0xff); b[off + 2] = (byte) ((val >> 16) & 0xff); b[off + 3] = (byte) ((val >> 24) & 0xff); return 4; } /** * Writes the given long to the given buffer at the given location in little * endian format. * * @param b the data buffer * @param off the offset into the buffer where writing should occur * @param val the long to write * @return the number of bytes written */ public static int writeLELong(byte[] b, int off, long val) { b[off + 0] = (byte) ((val) & 0xff); b[off + 1] = (byte) ((val >> 8) & 0xff); b[off + 2] = (byte) ((val >> 16) & 0xff); b[off + 3] = (byte) ((val >> 24) & 0xff); b[off + 4] = (byte) ((val >> 32) & 0xff); b[off + 5] = (byte) ((val >> 40) & 0xff); b[off + 6] = (byte) ((val >> 48) & 0xff); b[off + 7] = (byte) ((val >> 56) & 0xff); return 8; } /** * Writes the given double to the given buffer at the given location in * little endian format. * * @param b the data buffer * @param off the offset into the buffer where writing should occur * @param val the double to write * @return the number of bytes written */ public static int writeLEDouble(byte[] b, int off, double val) { return writeLELong(b, off, Double.doubleToLongBits(val)); } /** * Writes the given point to the given buffer at the given location. The * point is written as a double representing x followed by a double * representing y. * * @param b the data buffer * @param off the offset into the buffer where writing should occur * @param point the point to write * @return the number of bytes written */ public static int writePoint(byte[] b, int off, ESRIPoint point) { int nBytes = writeLEDouble(b, off, point.x); nBytes += writeLEDouble(b, off + nBytes, point.y); return nBytes; } /** * Writes the given bounding box to the given buffer at the given location. * The bounding box is written as four doubles representing, in order, xmin, * ymin, xmax, ymax. * * @param b the data buffer * @param off the offset into the buffer where writing should occur * @param box the bounding box to write * @return the number of bytes written */ public static int writeBox(byte[] b, int off, ESRIBoundingBox box) { int nBytes = writePoint(b, off, box.min); nBytes += writePoint(b, off + nBytes, box.max); return nBytes; } /** * Return a readable string for a shape int type. * @param shapeType * @return String */ public static String getStringForType(int shapeType) { switch (shapeType) { case SHAPE_TYPE_NULL: return "NULL"; case SHAPE_TYPE_POINT: return "POINT"; case SHAPE_TYPE_POLYLINE: return "POLYLINE"; case SHAPE_TYPE_POLYGON: return "POLYGON"; case SHAPE_TYPE_MULTIPOINT: return "MULTIPOINT"; case SHAPE_TYPE_POINTZ: return "POINTZ"; case SHAPE_TYPE_POLYLINEZ: return "POLYLINEZ"; case SHAPE_TYPE_POLYGONZ: return "POLYGONZ"; case SHAPE_TYPE_MULTIPOINTZ: return "MULTIPOINTZ"; case SHAPE_TYPE_POINTM: return "POINTM"; case SHAPE_TYPE_POLYLINEM: return "POLYLINEM"; case SHAPE_TYPE_POLYGONM: return "POLYGONM"; case SHAPE_TYPE_MULTIPOINTM: return "MULTIPOINTM"; case SHAPE_TYPE_MULTIPATCH: return "MULTIPATCH"; default: return "UNKNOWN"; } } }