spatialindex.java

来自「OpenMap是一个基于JavaBeansTM的开发工具包。利用OpenMap你」· Java 代码 · 共 1,278 行 · 第 1/3 页

JAVA
1,278
字号
// **********************************************************************// // <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/SpatialIndex.java,v $// $RCSfile: SpatialIndex.java,v $// $Revision: 1.6.2.6 $// $Date: 2007/06/21 21:41:38 $// $Author: dietrick $// // **********************************************************************package com.bbn.openmap.layer.shape;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.PrintStream;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Vector;import javax.swing.ImageIcon;import com.bbn.openmap.LatLonPoint;import com.bbn.openmap.dataAccess.shape.DbfHandler;import com.bbn.openmap.dataAccess.shape.EsriGraphicFactory;import com.bbn.openmap.io.BinaryBufferedFile;import com.bbn.openmap.io.BinaryFile;import com.bbn.openmap.io.FormatException;import com.bbn.openmap.omGraphics.DrawingAttributes;import com.bbn.openmap.omGraphics.OMGraphic;import com.bbn.openmap.omGraphics.OMGraphicList;import com.bbn.openmap.proj.Projection;import com.bbn.openmap.proj.coords.GeoCoordTransformation;import com.bbn.openmap.util.Debug;/** * A Spatial Index is a variation on a Shape Index, adding the bounding box of * the shape to the index. * <p> * The file has a 100 byte header identical to a Shape Index followed by <i>n * </i> records. * <p> * The record layout of the spatial index is as follows: * <p> * <TABLE BORDER COLS=5 WIDTH="100%" > * <TR> * <TD ALIGN=CENTER><b><i>Position </i> </b></TD> * <TD ALIGN=CENTER><b><i>Field </i> </b></TD> * <TD ALIGN=CENTER><b><i>Value </i> </b></TD> * <TD ALIGN=CENTER><b><i>Type </i> </b></TD> * <TD ALIGN=CENTER><b><i>Byte Order </i> </b></TD> * </TR> * <TR> * <TD ALIGN=CENTER>Byte 0</TD> * <TD ALIGN=CENTER>Offset</TD> * <TD ALIGN=CENTER>Offset</TD> * <TD ALIGN=CENTER>Integer</TD> * <TD ALIGN=CENTER>Big</TD> * </TR> * <TR> * <TD ALIGN=CENTER>Byte 4</TD> * <TD ALIGN=CENTER>Content Length</TD> * <TD ALIGN=CENTER>Content Length</TD> * <TD ALIGN=CENTER>Integer</TD> * <TD ALIGN=CENTER>Big</TD> * </TR> * <TR> * <TD ALIGN=CENTER>Byte 8</TD> * <TD ALIGN=CENTER>Bounding Box</TD> * <TD ALIGN=CENTER>Xmin</TD> * <TD ALIGN=CENTER>Double</TD> * <TD ALIGN=CENTER>Little</TD> * </TR> * <TR> * <TD ALIGN=CENTER>Byte 16</TD> * <TD ALIGN=CENTER>Bounding Box</TD> * <TD ALIGN=CENTER>Ymin</TD> * <TD ALIGN=CENTER>Double</TD> * <TD ALIGN=CENTER>Little</TD> * </TR> * <TR> * <TD ALIGN=CENTER>Byte 24</TD> * <TD ALIGN=CENTER>Bounding Box</TD> * <TD ALIGN=CENTER>Xmax</TD> * <TD ALIGN=CENTER>Double</TD> * <TD ALIGN=CENTER>Little</TD> * </TR> * <TR> * <TD ALIGN=CENTER>Byte 32</TD> * <TD ALIGN=CENTER>Bounding Box</TD> * <TD ALIGN=CENTER>Ymax</TD> * <TD ALIGN=CENTER>Double</TD> * <TD ALIGN=CENTER>Little</TD> * </TR> * </TABLE> *  * <H2>Usage</H2> * <DT>java com.bbn.openmap.layer.shape.SpatialIndex -d file.ssx </DT> * <DD><i>Dumps spatial index information, excluding bounding boxes to stdout. * Useful for comparing to a shape index. </i></DD> * <p> * <DT>java com.bbn.openmap.layer.shape.SpatialIndex -d -b file.ssx </DT> * <DD><i>Dumps spatial index information including bounding boxes to stdout. * </i></DD> * <p> * <DT>java com.bbn.openmap.layer.shape.SpatialIndex -c file.ssx file.shp</DT> * <DD><i>Creates spatial index <code>file.ssx</code> from shape file * <code>file.shp</code>. </i></DD> * <p> *  * <H2>Notes</H2> * When reading the Shape file, the content length is the length of the record's * contents, exclusive of the record header (8 bytes). So the size that we need * to read in from the Shape file is actually denoted as ((contentLength * 2) + * 8). This converts from 16bit units to 8 bit bytes and adds the 8 bytes for * the record header. *  * <H2>To Do</H2> * <UL> * <LI>index arcs</LI> * <LI>index multipoints</LI> * </UL> *  * @author Tom Mitchell <tmitchell@bbn.com> * @version $Revision: 1.6.2.6 $ $Date: 2007/06/21 21:41:38 $ * @see ShapeIndex */public class SpatialIndex extends ShapeUtils {    /** Size of a shape file header in bytes. */    public final static int SHAPE_FILE_HEADER_LENGTH = 100;    /** Size of a shape file record header in bytes. */    public final static int SHAPE_RECORD_HEADER_LENGTH = 8;    /** Size of the spatial index header in bytes. */    public final static int SPATIAL_INDEX_HEADER_LENGTH = 100;    /** Size of the spatial index record in bytes. */    public final static int SPATIAL_INDEX_RECORD_LENGTH = 40;    /** Default size for shape record buffer. */    public final static int DEFAULT_SHAPE_RECORD_SIZE = 50000;    /** The spatial index file. */    protected BinaryBufferedFile ssx;    /** The shape file. */    protected BinaryBufferedFile shp;    /**     * The handler for dbf file information.     */    protected DbfHandler dbf;    /** The icon to use for point objects. */    protected ImageIcon pointIcon;    /** The bounds of all the shapes in the shape file. */    protected ESRIBoundingBox bounds = null;    /**     * The file name for the shape file, for opening/reopening.     */    protected String shpFileName;    /**     * The file name for the spatial index file, for opening/reopening.     */    protected String ssxFileName;    /**     * A cached list of the SpatialIndex file entries, for repeated reference.     */    protected List entries;    /**     * A factory object to use to create OMGraphics from the shp file.     */    EsriGraphicFactory factory = new EsriGraphicFactory();    /**     * Opens a spatial index file for reading.     *      * @param ssxFilename the name of the spatial index file     * @exception IOException if something goes wrong opening the file     */    public SpatialIndex(String ssxFilename) throws IOException {        this.ssxFileName = ssxFilename;        // ssx = new BinaryBufferedFile(ssxFilename);    }    /**     * Opens a spatial index file and it's associated shape file.     *      * @param ssxFilename the name of the spatial index file     * @param shpFilename the name of the shape file     * @exception IOException if something goes wrong opening the files     */    public SpatialIndex(String ssxFilename, String shpFilename)            throws IOException {        if (Debug.debugging("spatialindex")) {            Debug.output("SpatialIndex(" + ssxFilename + ", " + shpFilename                    + ");");        }        this.shpFileName = shpFilename;        this.ssxFileName = ssxFilename;        // ssx = new BinaryBufferedFile(ssxFilename);        // shp = new BinaryBufferedFile(shpFilename);    }    /**     * Get the box boundary containing all the shapes.     */    public ESRIBoundingBox getBounds() {        if (bounds == null) {            try {                locateRecords(-180, -90, 180, 90);            } catch (IOException ioe) {                bounds = null;            } catch (FormatException fe) {                bounds = null;            }        }        return bounds;    }    /**     * Reset the bounds so they will be recalculated the next time a file is     * read.     */    public void resetBounds() {        bounds = null;    }    /**     * Creates a record instance from the shape file data. Calls the appropriate     * record constructor based on the shapeType, and passes the buffer and     * offset to that constructor.     *      * @param shapeType the shape file's shape type, enumerated in     *        <code>ShapeUtils</code>     * @param b the buffer pointing to the raw record data     * @param off the offset of the data starting point in the buffer     * @exception IOException if something goes wrong reading the file     * @see ShapeUtils     */    public ESRIRecord makeESRIRecord(int shapeType, byte[] b, int off)            throws IOException {        switch (shapeType) {        case SHAPE_TYPE_NULL:            return null;        case SHAPE_TYPE_POINT:            // return new ESRIPointRecord(b, off);            return new ESRIPointRecord(b, off, pointIcon);        case SHAPE_TYPE_POLYGON:        case SHAPE_TYPE_ARC:            // case SHAPE_TYPE_POLYLINE:            return new ESRIPolygonRecord(b, off);        case SHAPE_TYPE_MULTIPOINT:            Debug.output("SpatialIndex.makeESRIRecord: Arc NYI");            return null;            // return new ESRIMultipointRecord(b, off);        default:            return null;        }    }    /**     * Locates records in the shape file that intersect with the given     * rectangle. The spatial index is searched for intersections and the     * appropriate records are read from the shape file.     *      * @param xmin the smaller of the x coordinates     * @param ymin the smaller of the y coordinates     * @param xmax the larger of the x coordinates     * @param ymax the larger of the y coordinates     * @return an array of records that intersect the given rectangle     * @exception IOException if something goes wrong reading the files     */    public ESRIRecord[] locateRecords(double xmin, double ymin, double xmax,                                      double ymax) throws IOException,            FormatException {        boolean gatherBounds = false;        if (bounds == null) {            bounds = new ESRIBoundingBox();            gatherBounds = true;        }        if (Debug.debugging("spatialindex")) {            Debug.output("locateRecords:");            Debug.output("\txmin: " + xmin + "; ymin: " + ymin);            Debug.output("\txmax: " + xmax + "; ymax: " + ymax);        }        byte ixRecord[] = new byte[SPATIAL_INDEX_RECORD_LENGTH];        int recNum = 0;        Vector v = new Vector();        int sRecordSize = DEFAULT_SHAPE_RECORD_SIZE;        byte sRecord[] = new byte[sRecordSize];        if (ssxFileName == null || shpFileName == null) {            return null;        }        ssx = new BinaryBufferedFile(ssxFileName);        shp = new BinaryBufferedFile(shpFileName);        // Need to figure out what the shape type is...        ssx.seek(32);        // int shapeType = readLEInt(ssx);        // /        ssx.byteOrder(false);        int shapeType = ssx.readInteger();        // /        ssx.seek(100); // skip the file header        while (true) {            int result = ssx.read(ixRecord, 0, SPATIAL_INDEX_RECORD_LENGTH);            // if (result == -1) {            if (result <= 0) {                break;// EOF            } else {                recNum++;                double xmin2 = readLEDouble(ixRecord, 8);                double ymin2 = readLEDouble(ixRecord, 16);                double xmax2 = readLEDouble(ixRecord, 24);                double ymax2 = readLEDouble(ixRecord, 32);                if (Debug.debugging("spatialindexdetail")) {                    Debug.output("Looking at rec num " + recNum);                    Debug.output("  " + xmin2 + ", " + ymin2 + "\n  " + xmax2                            + ", " + ymax2);                }                if (gatherBounds) {                    bounds.addPoint(xmin2, ymin2);                    bounds.addPoint(xmax2, ymax2);                }                if (intersects(xmin,                        ymin,                        xmax,                        ymax,                        xmin2,                        ymin2,                        xmax2,                        ymax2)) {                    int offset = readBEInt(ixRecord, 0);                    int byteOffset = offset * 2;                    int contentLength = readBEInt(ixRecord, 4);                    int recordSize = (contentLength * 2) + 8;                    // System.out.print(".");                    // System.out.flush();                    if (recordSize < 0) {                        Debug.error("SpatialIndex: supposed to read record size of "                                + recordSize);                        break;                    }                    if (recordSize > sRecordSize) {                        sRecordSize = recordSize;                        if (Debug.debugging("spatialindexdetail")) {                            Debug.output("Shapefile SpatialIndex record size: "                                    + sRecordSize);                        }                        sRecord = new byte[sRecordSize];                    }                    if (Debug.debugging("spatialindex")) {                        Debug.output("going to shp byteOffset = " + byteOffset                                + " for record size = " + recordSize                                + ", offset = " + offset + ", shape type = "                                + shapeType);                    }                    try {                        shp.seek(byteOffset);                        int nBytes = shp.read(sRecord, 0, recordSize);                        if (nBytes < recordSize) {                            Debug.error("Shapefile SpatialIndex expected "                                    + recordSize + " bytes, but got " + nBytes                                    + " bytes instead.");                        }                        ESRIRecord record = makeESRIRecord(shapeType,                                sRecord,                                0);                        v.addElement(record);                    } catch (IOException ioe) {                        Debug.error("SpatialIndex.locateRecords: IOException. ");                        ioe.printStackTrace();                        break;                    }                }            }        }        if (Debug.debugging("spatialindex")) {            Debug.output("Processed " + recNum + " records");            Debug.output("Selected " + v.size() + " records");        }        int nRecords = v.size();        ssx.close();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?