⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 polygonhandler.java

📁 shape file read and write
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 *    GeoTools - OpenSource mapping toolkit
 *    http://geotools.org
 *    (C) 2002-2006, Geotools Project Managment Committee (PMC)
 *    (C) 2002, Centre for Computational Geography
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation; either
 *    version 2.1 of the License, or (at your option) any later version.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 */
package org.geotools.data.shapefile.shp;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import com.vividsolutions.jts.algorithm.CGAlgorithms;
import com.vividsolutions.jts.algorithm.RobustCGAlgorithms;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon;

/**
 * Wrapper for a Shapefile polygon.
 * 
 * @author aaime
 * @author Ian Schneider
 * @source $URL:
 *         http://svn.geotools.org/geotools/trunk/gt/modules/plugin/shapefile/src/main/java/org/geotools/data/shapefile/shp/PolygonHandler.java $
 * @version $Id: PolygonHandler.java 30011 2008-04-21 14:47:24Z groldan $
 */
public class PolygonHandler implements ShapeHandler {
    GeometryFactory geometryFactory = new GeometryFactory();
    RobustCGAlgorithms cga = new RobustCGAlgorithms();

    final ShapeType shapeType;

    public PolygonHandler() {
        shapeType = ShapeType.POLYGON;
    }

    public PolygonHandler(ShapeType type) throws ShapefileException {
        if ((type != ShapeType.POLYGON) && (type != ShapeType.POLYGONM)
                && (type != ShapeType.POLYGONZ)) {
            throw new ShapefileException(
                    "PolygonHandler constructor - expected type to be 5, 15, or 25.");
        }

        shapeType = type;
    }

    // returns true if testPoint is a point in the pointList list.
    boolean pointInList(Coordinate testPoint, Coordinate[] pointList) {
        Coordinate p;

        for (int t = pointList.length - 1; t >= 0; t--) {
            p = pointList[t];

            if ((testPoint.x == p.x)
                    && (testPoint.y == p.y)
                    && ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) // nan
                                                                                    // test;
                                                                                    // x!=x
                                                                                    // iff
                                                                                    // x is
                                                                                    // nan
            ) {
                return true;
            }
        }

        return false;
    }

    public ShapeType getShapeType() {
        return shapeType;
    }

    public int getLength(Object geometry) {
        MultiPolygon multi;

        if (geometry instanceof MultiPolygon) {
            multi = (MultiPolygon) geometry;
        } else {
            multi = geometryFactory
                    .createMultiPolygon(new Polygon[] { (Polygon) geometry });
        }

        int nrings = 0;

        for (int t = 0; t < multi.getNumGeometries(); t++) {
            Polygon p;
            p = (Polygon) multi.getGeometryN(t);
            nrings = nrings + 1 + p.getNumInteriorRing();
        }

        int npoints = multi.getNumPoints();
        int length;

        if (shapeType == ShapeType.POLYGONZ) {
            length = 44 + (4 * nrings) + (16 * npoints) + (8 * npoints) + 16
                    + (8 * npoints) + 16;
        } else if (shapeType == ShapeType.POLYGONM) {
            length = 44 + (4 * nrings) + (16 * npoints) + (8 * npoints) + 16;
        } else if (shapeType == ShapeType.POLYGON) {
            length = 44 + (4 * nrings) + (16 * npoints);
        } else {
            throw new IllegalStateException(
                    "Expected ShapeType of Polygon, got " + shapeType);
        }
        return length;
    }

    public Object read(ByteBuffer buffer, ShapeType type) {
        if (type == ShapeType.NULL) {
            return createNull();
        }
        // bounds
        buffer.position(buffer.position() + 4 * 8);

        int[] partOffsets;

        int numParts = buffer.getInt();
        int numPoints = buffer.getInt();

        partOffsets = new int[numParts];

        for (int i = 0; i < numParts; i++) {
            partOffsets[i] = buffer.getInt();
        }

        ArrayList shells = new ArrayList();
        ArrayList holes = new ArrayList();
        Coordinate[] coords = readCoordinates(buffer, numPoints);

        if (shapeType == ShapeType.POLYGONZ) {
            // z
            buffer.position(buffer.position() + 2 * 8);

            for (int t = 0; t < numPoints; t++) {
                coords[t].z = buffer.getDouble();
            }
        }

        int offset = 0;
        int start;
        int finish;
        int length;

        for (int part = 0; part < numParts; part++) {
            start = partOffsets[part];

            if (part == (numParts - 1)) {
                finish = numPoints;
            } else {
                finish = partOffsets[part + 1];
            }

            length = finish - start;

            // Use the progressive CCW algorithm.
            // basically the area algorithm for polygons
            // which also tells us vertex order based upon the
            // sign of the area.
            Coordinate[] points = new Coordinate[length];
            // double area = 0;
            // int sx = offset;
            for (int i = 0; i < length; i++) {
                points[i] = coords[offset++];
                // int j = sx + (i + 1) % length;
                // area += points[i].x * coords[j].y;
                // area -= points[i].y * coords[j].x;
            }
            // area = -area / 2;
            // REVISIT: polyons with only 1 or 2 points are not polygons -
            // geometryFactory will bomb so we skip if we find one.
            if (points.length == 0 || points.length > 3) {
                LinearRing ring = geometryFactory.createLinearRing(points);

                if (CGAlgorithms.isCCW(points)) {
                    // counter-clockwise
                    holes.add(ring);
                } else {
                    // clockwise
                    shells.add(ring);
                }
            }
        }

        // quick optimization: if there's only one shell no need to check
        // for holes inclusion
        if (shells.size() == 1) {
            return createMulti((LinearRing) shells.get(0), holes);
        }
        // if for some reason, there is only one hole, we just reverse it and
        // carry on.
        else if (holes.size() == 1 && shells.size() == 0) {
            org.geotools.util.logging.Logging.getLogger(
                    "org.geotools.data.shapefile").warning(
                    "only one hole in this polygon record");
            return createMulti(JTSUtilities.reverseRing((LinearRing) holes
                    .get(0)));
        } else {

            // build an association between shells and holes
            final ArrayList holesForShells = assignHolesToShells(shells, holes);

            Geometry g = buildGeometries(shells, holes, holesForShells);

            return g;
        }
    }

    /**
     * @param buffer
     * @param numPoints
     */
    private Coordinate[] readCoordinates(final ByteBuffer buffer,
            final int numPoints) {
        Coordinate[] coords = new Coordinate[numPoints];

        for (int t = 0; t < numPoints; t++) {
            coords[t] = new Coordinate(buffer.getDouble(), buffer.getDouble());
        }

        return coords;
    }

    /**
     * @param shells
     * @param holes
     * @param holesForShells
     */
    private Geometry buildGeometries(final List shells, final List holes,
            final List holesForShells) {
        Polygon[] polygons;

        // if we have shells, lets use them
        if (shells.size() > 0) {
            polygons = new Polygon[shells.size()];
            // oh, this is a bad record with only holes
        } else {
            polygons = new Polygon[holes.size()];
        }

        // this will do nothing for the "only holes case"
        for (int i = 0; i < shells.size(); i++) {
            polygons[i] = geometryFactory.createPolygon((LinearRing) shells
                    .get(i), (LinearRing[]) ((ArrayList) holesForShells.get(i))
                    .toArray(new LinearRing[0]));
        }

        // this will take care of the "only holes case"
        // we just reverse each hole
        if (shells.size() == 0) {
            for (int i = 0, ii = holes.size(); i < ii; i++) {
                LinearRing hole = (LinearRing) holes.get(i);
                polygons[i] = geometryFactory.createPolygon(JTSUtilities
                        .reverseRing(hole), new LinearRing[0]);
            }

⌨️ 快捷键说明

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