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 + -
显示快捷键?