spatialindex.java
来自「OpenMap是一个基于JavaBeansTM的开发工具包。利用OpenMap你」· Java 代码 · 共 1,278 行 · 第 1/3 页
JAVA
1,278 行
shp.close(); ESRIRecord result[] = new ESRIRecord[nRecords]; v.copyInto(result); return result; } /** * The factory is used to filter and create OMGraphics from a shape file. * This accessor is provided in order to allow you to modify the data * projection it uses, or the line type. * * @return */ public EsriGraphicFactory getFactory() { if (factory == null) { factory = new EsriGraphicFactory(); } return factory; } public void setFactory(EsriGraphicFactory factory) { this.factory = factory; } /** * Locates OMGraphics in the shape file that intersect with the given * rectangle. The spatial index is searched for intersections and the * appropriate OMGraphics are created 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 * @param list OMGraphicList to add OMGraphics to and return, if null one * will be created. * @param drawingAttributes DrawingAttributes to set on the OMGraphics. * @param mapProj the Map Projection for the OMGraphics so they can be * generated right after creation. * @param dataProj for preprojected data, a coordinate translator for the * data's projection to use to translate the coordinates to decimal * degree lat/lon. Can be null to leave the coordinates untouched. * @return an OMGraphicList containing OMGraphics that intersect the given * rectangle * @exception IOException if something goes wrong reading the files */ public OMGraphicList getOMGraphics(double xmin, double ymin, double xmax, double ymax, OMGraphicList list, DrawingAttributes drawingAttributes, Projection mapProj, GeoCoordTransformation dataProj) throws IOException, FormatException { if (Debug.debugging("spatialindex")) { Debug.output("locateRecords:"); Debug.output("\txmin: " + xmin + "; ymin: " + ymin); Debug.output("\txmax: " + xmax + "; ymax: " + ymax); } if (list == null) { list = new OMGraphicList(); } if (shp == null) { shp = new BinaryBufferedFile(shpFileName); } if (shp == null) { return list; } EsriGraphicFactory.ReadByteTracker byteTracker = new EsriGraphicFactory.ReadByteTracker(); EsriGraphicFactory factory = getFactory(); factory.setDataCoordTransformation(dataProj); OMGraphicList labels = new OMGraphicList(); list.add(labels); for (Iterator it = entryIterator(dataProj); it.hasNext();) { Entry entry = (Entry) it.next(); if (entry.intersects(xmin, ymin, xmax, ymax)) { try { OMGraphic omg = (OMGraphic) factory.makeEsriGraphicFromRecord(entry.getByteOffset(), shp, drawingAttributes, pointIcon, byteTracker); if (dbf != null) { omg = dbf.evaluate(omg, labels, mapProj); } if (omg != null) { omg.generate(mapProj); list.add(omg); } } catch (IOException ioe) { Debug.error("SpatialIndex.locateRecords: IOException. "); ioe.printStackTrace(); break; } } } if (shp != null) { shp.close(); } return list; } /** * Skips the BinaryFile for the shp data to the offset and reads the record * data there, creating an OMGraphic from that data. * * @param byteOffset, usually gotten from an Entry object. * @param drawingAttributes * @return * @throws IOException * @throws FormatException */ public OMGraphic getOMGraphicAtOffset(int byteOffset, DrawingAttributes drawingAttributes) throws IOException, FormatException { return (OMGraphic) getFactory().makeEsriGraphicFromRecord(byteOffset, shp, drawingAttributes, pointIcon, new EsriGraphicFactory.ReadByteTracker()); } /** * Provides an iterator over the SpatialIndex entries. * * @return * @throws IOException * @throws FormatException */ public Iterator entryIterator() throws IOException, FormatException { return entryIterator(null); } /** * Provides an iterator over the SpatialIndex entries. * * @param dataTransform GeoCoordTransform for pre-projected data. * @return * @throws IOException * @throws FormatException */ public Iterator entryIterator(GeoCoordTransformation dataTransform) throws IOException, FormatException { if (entries == null) { boolean gatherBounds = false; if (bounds == null) { bounds = new ESRIBoundingBox(); gatherBounds = true; } entries = readIndexFile(gatherBounds ? bounds : null, dataTransform); } return entries.iterator(); } /** * * @param bounds if not null, add min/max values to them. * @return * @throws IOException * @throws FormatException */ protected List readIndexFile(ESRIBoundingBox bounds) throws IOException, FormatException { return readIndexFile(bounds, null); } /** * * @param bounds if not null, add min/max values to them. * @param dataTransform GeoCoordTransform for pre-projected data. * @return * @throws IOException * @throws FormatException */ protected List readIndexFile(ESRIBoundingBox bounds, GeoCoordTransformation dataTransform) throws IOException, FormatException { entries = new ArrayList(); byte ixRecord[] = new byte[SPATIAL_INDEX_RECORD_LENGTH]; if (ssx == null) { ssx = new BinaryBufferedFile(ssxFileName); ssx.byteOrder(false); } ssx.seek(100); // skip the file header LatLonPoint llp = null; if (dataTransform != null) { llp = new LatLonPoint(); } while (true) { int result = ssx.read(ixRecord, 0, SPATIAL_INDEX_RECORD_LENGTH); if (result <= 0) { break;// EOF } else { double xmin = readLEDouble(ixRecord, 8); double ymin = readLEDouble(ixRecord, 16); double xmax = readLEDouble(ixRecord, 24); double ymax = readLEDouble(ixRecord, 32); int byteOffset = readBEInt(ixRecord, 0) * 2; if (dataTransform != null) { dataTransform.inverse(xmin, ymin, llp); xmin = llp.getLongitude(); ymin = llp.getLatitude(); dataTransform.inverse(xmax, ymax, llp); xmax = llp.getLongitude(); ymax = llp.getLatitude(); } if (Debug.debugging("spatialindexdetail")) { Debug.output(" " + xmin + ", " + ymin + "\n " + xmax + ", " + ymax); } Entry entry = new Entry(xmin, ymin, xmax, ymax, byteOffset); entries.add(entry); if (bounds != null) { bounds.addPoint(xmin, ymin); bounds.addPoint(xmax, ymax); } } } ssx.close(); return entries; } /** * Determines if two rectangles intersect. Actually, this method determines * if two rectangles don't intersect, and then returns a negation of that * result. But the bottom line is the same. * * @param xmin1 the small x of rectangle 1 * @param ymin1 the small y of rectangle 1 * @param xmax1 the big x of rectangle 1 * @param ymax1 the big y of rectangle 1 * @param xmin2 the small x of rectangle 2 * @param ymin2 the small y of rectangle 2 * @param xmax2 the big x of rectangle 2 * @param ymax2 the big y of rectangle 2 * @return <code>true</code> if the rectangles intersect, * <code>false</code> if they do not */ protected static final boolean intersects(double xmin1, double ymin1, double xmax1, double ymax1, double xmin2, double ymin2, double xmax2, double ymax2) { return !((xmax1 <= xmin2) || (ymax1 <= ymin2) || (xmin1 >= xmax2) || (ymin1 >= ymax2)); } /** * Displays the contents of this index. * * @param showBounds true to show bounding box, false to skip it * @exception IOException if something goes wrong reading the file */ public void dumpIndex(boolean showBounds) throws IOException { byte ixRecord[] = new byte[SPATIAL_INDEX_RECORD_LENGTH]; int recNum = 0; 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) { // Debug.output("Processed " + recNum + " records"); break;// EOF } else { recNum++; int offset = readBEInt(ixRecord, 0); int length = readBEInt(ixRecord, 4); Debug.output("Record " + recNum + ": " + offset + ", " + length + (showBounds ? ("; " + readLEDouble(ixRecord, 8) + ", " + readLEDouble(ixRecord, 16) + ", " + readLEDouble(ixRecord, 24) + ", " + readLEDouble(ixRecord, 32)) : "")); } } } /** * Writes the spatial index for a polygon shape file. * * @param is the shape file input stream * @param ptr the current position in the file * @param os the spatial index file output stream */ protected static void indexPolygons(InputStream is, long ptr, OutputStream os) { boolean moreRecords = true; byte rHdr[] = new byte[SHAPE_RECORD_HEADER_LENGTH]; byte outBuf[] = new byte[SPATIAL_INDEX_RECORD_LENGTH]; int result; int shapeType; int nRecords = 0; int recLengthWords, recLengthBytes /* , recNumber */; long recOffset; int recBufSize = 100000; byte recBuf[] = new byte[recBufSize]; ESRIBoundingBox polyBounds; try { while (moreRecords) { result = is.read(rHdr, 0, SHAPE_RECORD_HEADER_LENGTH); if (result < 0) { moreRecords = false; Debug.output("Shapefile SpatialIndex Found " + nRecords + " records"); Debug.output("Shapefile SpatialIndex recBufSize = " + recBufSize); } else { nRecords++; recOffset = ptr; /* recNumber = */readBEInt(rHdr, 0); recLengthWords = readBEInt(rHdr, 4); recLengthBytes = recLengthWords * 2; if (recLengthBytes > recBufSize) { Debug.output("Shapefile SpatialIndex increasing recBufSize to " + recLengthBytes); recBufSize = recLengthBytes; recBuf = new byte[recBufSize]; } result = is.read(recBuf, 0, recLengthBytes); // Null shapes are allowed in any shape file, at any time. shapeType = readLEInt(recBuf, 0); if (shapeType != SHAPE_TYPE_NULL) { polyBounds = readBox(recBuf, 4); } else { polyBounds = new ESRIBoundingBox(); } ptr += recLengthBytes + 8; writeBEInt(outBuf, 0, (int) (recOffset / 2)); writeBEInt(outBuf, 4, recLengthWords); writeLEDouble(outBuf, 8, polyBounds.min.x); writeLEDouble(outBuf, 16, polyBounds.min.y); writeLEDouble(outBuf, 24, polyBounds.max.x); writeLEDouble(outBuf, 32, polyBounds.max.y); os.write(outBuf, 0, SPATIAL_INDEX_RECORD_LENGTH); } } } catch (java.io.IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (java.io.IOException e) { } } } /** * Writes the spatial index for a point shape file. * * @param is the shape file input stream * @param ptr the current position in the file * @param os the spatial index file output stream */ protected static void indexPoints(InputStream is, long ptr, OutputStream os) { boolean moreRecords = true; byte rHdr[] = new byte[SHAPE_RECORD_HEADER_LENGTH]; byte outBuf[] = new byte[SPATIAL_INDEX_RECORD_LENGTH]; int result; int nRecords = 0; int recLengthWords, recLengthBytes/* , recNumber */; long recOffset; int shapeType; int recBufSize = 20; byte recBuf[] = new byte[recBufSize]; double x = 0; double y = 0; try { while (moreRecords) { result = is.read(rHdr, 0, SHAPE_RECORD_HEADER_LENGTH); if (result < 0) { moreRecords = false; Debug.output("Found " + nRecords + " records"); Debug.output("recBufSize = " + recBufSize); } else { nRecords++; recOffset = ptr; /* recNumber = */readBEInt(rHdr, 0); recLengthWords = readBEInt(rHdr, 4); recLengthBytes = recLengthWords * 2; if (recLengthBytes > recBufSize) { Debug.output("Shapefile SpatialIndex increasing recBufSize to " + recLengthBytes); recBufSize = recLengthBytes; recBuf = new byte[recBufSize]; } result = is.read(recBuf, 0, recLengthBytes); // Null shapes are allowed in any shape file, at any time. shapeType = readLEInt(recBuf, 0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?