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