📄 polygonhandler.java
字号:
/*
* 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 + -