开源社区里利用JTS库进行空间处理的代码参考
2012-05-11 02:43
483 查看
开源社区里对于JTS库的使用还是比较广泛的。 下面是一段引自网上的代码工具类,可以帮助大家理解JTS的各个功能操作。
http://rsiaf.googlecode.com/svn/rs-gis-core/trunk/src/main/java/com/revolsys/gis/jts/JtsGeometryUtil.java
http://rsiaf.googlecode.com/svn/rs-gis-core/trunk/src/main/java/com/revolsys/gis/jts/JtsGeometryUtil.java
package com.revolsys.gis.jts; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.TreeMap; import com.revolsys.gis.data.model.DataObject; import com.vividsolutions.jts.algorithm.Angle; import com.vividsolutions.jts.algorithm.CGAlgorithms; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateSequence; import com.vividsolutions.jts.geom.CoordinateSequenceFactory; import com.vividsolutions.jts.geom.CoordinateSequenceFilter; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineSegment; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.PrecisionModel; import com.vividsolutions.jts.geom.impl.CoordinateArraySequenceFactory; import com.vividsolutions.jts.geom.impl.PackedCoordinateSequenceFactory; import com.vividsolutions.jts.operation.linemerge.LineMerger; public final class JtsGeometryUtil { public static final String FEATURE_PROPERTY = "feature"; private JtsGeometryUtil() { } public static DataObject getGeometryFeature(final Geometry geometry) { return (DataObject)getGeometryProperty(geometry, FEATURE_PROPERTY); } public static void setGeometryFeature(final Geometry geometry, final DataObject feature) { setGeometryProperty(geometry, FEATURE_PROPERTY, feature); } @SuppressWarnings("unchecked") public static <T extends Object> T getGeometryProperty( final Geometry geometry, final String name) { Map<String, Object> map = getGeometryProperties(geometry); return (T)map.get(name); } @SuppressWarnings("unchecked") public static Map<String, Object> getGeometryProperties( final Geometry geometry) { Object userData = geometry.getUserData(); if (userData instanceof Map) { Map<String, Object> map = (Map<String, Object>)userData; return map; } return Collections.emptyMap(); } @SuppressWarnings("unchecked") public static void setGeometryProperty(final Geometry geometry, final String name, final Object value) { Object userData = geometry.getUserData(); if (!(userData instanceof Map)) { userData = new TreeMap<Object, Object>(); geometry.setUserData(userData); } Map<Object, Object> map = (Map<Object, Object>)userData; map.put(name, value); } public static Polygon createPolygon(final MultiLineString multiLine) { GeometryFactory factory = multiLine.getFactory(); Coordinate[] coordinates = getMergeLine(multiLine).getCoordinates(); LinearRing linearRing = factory.createLinearRing(coordinates); Polygon polygon = factory.createPolygon(linearRing, null); return polygon; } public static LineString getMergeLine(final MultiLineString multiLineString) { Collection<LineString> lineStrings = getMergedLines(multiLineString); int numLines = lineStrings.size(); if (numLines == 1) { return (LineString)lineStrings.iterator().next(); } else { return null; } } @SuppressWarnings("unchecked") public static Collection<LineString> getMergedLines( final MultiLineString multiLineString) { LineMerger merger = new LineMerger(); merger.add(multiLineString); Collection<LineString> lineStrings = merger.getMergedLineStrings(); return lineStrings; } /** * Merge two lines that share common coordinates at either the start or end. * If the lines touch only at their start coordinates, the line2 will be * reversed and joined before the start of line1. If the tow lines ouch only * at their end coordinates, the line2 will be reversed and joined after the * end of line1. * * @param line1 The first line. * @param line2 The second line. * @return The new line string */ public static LineString merge(final LineString line1, final LineString line2) { CoordinateSequence coordinates = merge(line1.getCoordinateSequence(), line2.getCoordinateSequence()); GeometryFactory factory = line1.getFactory(); LineString line = factory.createLineString(coordinates); line.setUserData(line1.getUserData()); return line; } private static CoordinateSequence merge(final CoordinateSequence coordinates1, final CoordinateSequence coordinates2) { Coordinate[] coordinates = new Coordinate[coordinates1.size() + coordinates2.size() - 1]; int numCoords = 0; Coordinate coordinates1Start = coordinates1.getCoordinate(0); Coordinate coordinates1End = coordinates1.getCoordinate(coordinates1.size() - 1); Coordinate coordinates2Start = coordinates2.getCoordinate(0); Coordinate coordinates2End = coordinates2.getCoordinate(coordinates2.size() - 1); if (coordinates1Start.equals(coordinates2End)) { numCoords = addCoordinates(coordinates2, coordinates, numCoords, null); numCoords = addCoordinates(coordinates1, coordinates, numCoords, coordinates[numCoords - 1]); } else if (coordinates2Start.equals(coordinates1End)) { numCoords = addCoordinates(coordinates1, coordinates, numCoords, null); numCoords = addCoordinates(coordinates2, coordinates, numCoords, coordinates[numCoords - 1]); } else if (coordinates1Start.equals(coordinates2Start)) { numCoords = addReversedCoordinates(coordinates2, coordinates, numCoords, null); numCoords = addCoordinates(coordinates1, coordinates, numCoords, coordinates[numCoords - 1]); } else if (coordinates1End.equals(coordinates2End)) { numCoords = addCoordinates(coordinates1, coordinates, numCoords, null); numCoords = addReversedCoordinates(coordinates2, coordinates, numCoords, coordinates[numCoords - 1]); } else { throw new IllegalArgumentException("lines don't touch"); } if (numCoords != coordinates.length) { Coordinate[] newCoordinates = new Coordinate[numCoords]; System.arraycopy(coordinates, 0, newCoordinates, 0, numCoords); coordinates = newCoordinates; } return CoordinateArraySequenceFactory.instance().create(coordinates); } public static int addCoordinates(final CoordinateSequence src, final Coordinate[] dest, final int startIndex, final Coordinate lastCoordinate) { Coordinate previousCoordinate = lastCoordinate; int coordIndex = startIndex; try { for (int i = 0; i < src.size(); i++) { Coordinate coordinate = src.getCoordinate(i); if (!coordinate.equals(previousCoordinate)) { dest[coordIndex++] = coordinate; } previousCoordinate = coordinate; } } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } return coordIndex; } public static int addReversedCoordinates(final CoordinateSequence src, final Coordinate[] dest, final int startIndex, final Coordinate lastCoordinate) { Coordinate endCoordinate = lastCoordinate; int coordIndex = startIndex; try { for (int i = src.size() - 1; i > -1; i--) { Coordinate coordinate = src.getCoordinate(i); if (!coordinate.equals(endCoordinate)) { dest[coordIndex++] = coordinate; } endCoordinate = coordinate; } } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } return coordIndex; } public static boolean equalsExact3D(final LineString line1, final LineString line2) { if (line1.getNumPoints() != line2.getNumPoints()) { return false; } for (int i = 0; i < line1.getNumPoints(); i++) { line1.getCoordinateN(i); Coordinate coordinate1 = line1.getCoordinateN(i); Coordinate coordinate2 = line2.getCoordinateN(i); if (!coordinate1.equals3D(coordinate2)) { return false; } } return true; } public static boolean equalsExact3D(final Point point1, final Point point2) { Coordinate coordinate1 = point1.getCoordinate(); Coordinate coordinate2 = point2.getCoordinate(); return (coordinate1.x == coordinate2.x) && (coordinate1.y == coordinate2.y) && equalsZ(coordinate1.z, coordinate2.z); } public static boolean equalsZ(final double z1, final double z2) { if (z1 == z2) { return true; } else if (Double.isNaN(z1)) { return (Double.isNaN(z2) || z2 == 0); } else if (z1 == 0 && Double.isNaN(z2)) { return true; } else { return false; } } public static boolean equalsExact3D(final Geometry geometry1, final Geometry geometry2) { if ((geometry1 instanceof LineString) && (geometry2 instanceof LineString)) { LineString line1 = (LineString)geometry1; LineString line2 = (LineString)geometry2; return equalsExact3D(line1, line2); } else if ((geometry1 instanceof Point) && (geometry2 instanceof Point)) { Point point1 = (Point)geometry1; Point point2 = (Point)geometry2; return equalsExact3D(point1, point2); } else if ((geometry1 instanceof MultiPoint) && (geometry2 instanceof MultiPoint)) { MultiPoint multiPoint1 = (MultiPoint)geometry1; MultiPoint multiPoint2 = (MultiPoint)geometry2; return equalsExact3D(multiPoint1, multiPoint2); } return false; } public static boolean equalsExact3D(final GeometryCollection collection1, final GeometryCollection collection2) { if (collection1.getNumGeometries() != collection2.getNumGeometries()) { return false; } else { for (int i = 0; i < collection1.getNumGeometries(); i++) { Geometry geometry1 = collection1.getGeometryN(i); Geometry geometry2 = collection2.getGeometryN(i); if (!equalsExact3D(geometry1, geometry2)) { return false; } } } return true; } public static double distance(final Coordinate coordinate, final Geometry geometry) { GeometryFactory factory = geometry.getFactory(); Point point = factory.createPoint(coordinate); return point.distance(geometry); } public static void applyPrecisionModel(final Geometry geometry) { PrecisionModel precisionModel = geometry.getPrecisionModel(); Coordinate[] coordinates = geometry.getCoordinates(); for (int i = 0; i < coordinates.length; i++) { Coordinate coordinate = coordinates[i]; precisionModel.makePrecise(coordinate); } } public static double getMiddleAngle(final double lastAngle, final double angle, final int orientation) { if (orientation == Angle.COUNTERCLOCKWISE) { if (Double.isNaN(lastAngle)) { return angle + Angle.PI_OVER_2; } else if (Double.isNaN(angle)) { return lastAngle + Angle.PI_OVER_2; } else { int turn = Angle.getTurn(lastAngle, angle); double angleDiff = angle - lastAngle; if (turn == Angle.CLOCKWISE) { return lastAngle - (Angle.PI_TIMES_2 - (Math.PI - Math.abs(angleDiff)) / 2); } else { return angle + (Math.PI - Math.abs(angleDiff)) / 2; } } } else { if (Double.isNaN(lastAngle)) { return angle - Angle.PI_OVER_2; } else if (Double.isNaN(angle)) { return lastAngle - Angle.PI_OVER_2; } else { int turn = Angle.getTurn(lastAngle, angle); double angleDiff = angle - lastAngle; if (turn == Angle.CLOCKWISE) { return angle - (Math.PI - Math.abs(angleDiff)) / 2; } else { return lastAngle + (Angle.PI_TIMES_2 - (Math.PI - Math.abs(angleDiff)) / 2); } } } } public static LineString subLineString(final LineString line, final int length) { CoordinateSequence coords = line.getCoordinateSequence(); CoordinateSequence newCoords = subSequence(coords, 0, length); GeometryFactory factory = line.getFactory(); return factory.createLineString(newCoords); } public static LineString subLineString(final LineString line, final Coordinate fromCoordinate, final int fromIndex, final int toIndex, final Coordinate toCoordinate) { int numCoords = toIndex - fromIndex + 1; int length = numCoords; int offset = 0; if (fromCoordinate != null) { length++; offset = 1; } if (toCoordinate != null) { length++; } CoordinateSequence coords = line.getCoordinateSequence(); int dimension = coords.getDimension(); PackedCoordinateSequenceFactory doubleFactory = PackedCoordinateSequenceFactory.DOUBLE_FACTORY; try { CoordinateSequence newCoords = doubleFactory.create(length, dimension); if (fromCoordinate != null) { setCoordinate(newCoords, 0, fromCoordinate); } copyCoords(coords, fromIndex, newCoords, offset, numCoords); if (toCoordinate != null) { try { setCoordinate(newCoords, length - 1, toCoordinate); } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } } GeometryFactory factory = line.getFactory(); return factory.createLineString(newCoords); } catch (NegativeArraySizeException e) { e.printStackTrace(); throw e; } } public static LineString subLineString(final LineString line, final int length, final Coordinate coordinate) { CoordinateSequence coords = line.getCoordinateSequence(); int dimension = coords.getDimension(); PackedCoordinateSequenceFactory doubleFactory = PackedCoordinateSequenceFactory.DOUBLE_FACTORY; CoordinateSequence newCoords = doubleFactory.create(length + 1, dimension); copyCoords(coords, 0, newCoords, 0, length); setCoordinate(newCoords, length, coordinate); GeometryFactory factory = line.getFactory(); return factory.createLineString(newCoords); } public static LineString createLineString(final GeometryFactory factory, final Coordinate coordinate, final double angle, final double lengthBackward, final double lengthForward) { Coordinate c1 = new Coordinate(coordinate.x - lengthBackward * Math.cos(angle), coordinate.y - lengthBackward * Math.sin(angle)); Coordinate c2 = new Coordinate(coordinate.x + lengthForward * Math.cos(angle), coordinate.y + lengthForward * Math.sin(angle)); LineString line = factory.createLineString(new Coordinate[] { c1, c2 }); return line; } public static LineString createParallelLineString(final LineString line, final int orientation, final double distance) { GeometryFactory factory = line.getFactory(); CoordinateSequence coordinates = line.getCoordinateSequence(); List<Coordinate> newCoordinates = new ArrayList<Coordinate>(); Coordinate coordinate = coordinates.getCoordinate(0); LineSegment lastLineSegment = null; int coordinateCount = coordinates.size(); for (int i = 0; i < coordinateCount; i++) { Coordinate nextCoordinate = null; LineSegment lineSegment = null; if (i < coordinateCount - 1) { nextCoordinate = coordinates.getCoordinate(i + 1); lineSegment = new LineSegment(coordinate, nextCoordinate); lineSegment = offset(lineSegment, distance, orientation); // if (lastLineSegment == null) { // lineSegment = addLength(lineSegment, 0, distance*2); // } else if (i == coordinateCount - 2) { // lineSegment = addLength(lineSegment, distance*2, 0); // } else { // lineSegment = addLength(lineSegment, distance*2, distance*2); // } } if (lineSegment == null) { newCoordinates.add(lastLineSegment.p1); } else if (lastLineSegment == null) { newCoordinates.add(lineSegment.p0); } else { Coordinate intersection = lastLineSegment.intersection(lineSegment); if (intersection != null) { newCoordinates.add(intersection); } else { // newCoordinates.add(lastLineSegment.p1); newCoordinates.add(lineSegment.p0); } } coordinate = nextCoordinate; lastLineSegment = lineSegment; } CoordinateSequence newCoords = PackedCoordinateSequenceFactory.DOUBLE_FACTORY.create(newCoordinates.toArray(new Coordinate[0])); return factory.createLineString(newCoords); } public static LineSegment offset(final LineSegment line, final double distance, final int orientation) { double angle = line.angle(); if (orientation == Angle.CLOCKWISE) { angle -= Angle.PI_OVER_2; } else { angle += Angle.PI_OVER_2; } Coordinate c1 = offset(line.p0, angle, distance); Coordinate c2 = offset(line.p1, angle, distance); return new LineSegment(c1, c2); } public static Coordinate offset(final Coordinate coordinate, final double angle, final double distance) { double newX = coordinate.x + distance * Math.cos(angle); double newY = coordinate.y + distance * Math.sin(angle); Coordinate newCoordinate = new Coordinate(newX, newY); return newCoordinate; } public static LineSegment addLength(final LineSegment line, final double startDistance, final double endDistance) { double angle = line.angle(); Coordinate c1 = offset(line.p0, angle, -startDistance); Coordinate c2 = offset(line.p1, angle, endDistance); return new LineSegment(c1, c2); } /** * Add a evelation (z) value for a coordinate that is on a line segment. * * @param coordinate The Coordinate. * @param line The line segment the coordinate is on. */ public static void addElevation(final Coordinate coordinate, final LineSegment line) { double z = getElevation(line, coordinate); coordinate.z = z; } public static double getElevation(final LineSegment line, final Coordinate coordinate) { Coordinate c0 = line.p0; Coordinate c1 = line.p1; double fraction = coordinate.distance(c0) / line.getLength(); double z = c0.z + (c1.z - c0.z) * (fraction); return z; } public static CoordinateSequence subSequence(final CoordinateSequence coords, final int start, final int length) { int dimension = coords.getDimension(); PackedCoordinateSequenceFactory factory = PackedCoordinateSequenceFactory.DOUBLE_FACTORY; CoordinateSequence newCoords = factory.create(length, dimension); copyCoords(coords, start, newCoords, 0, length); return newCoords; } public static void visitLineSegments(final CoordinateSequence coords, final LineSegmentVistor visitor) { Coordinate previousCoordinate = coords.getCoordinate(0); for (int i = 1; i < coords.size(); i++) { Coordinate coordinate = coords.getCoordinate(i); LineSegment segment = new LineSegment(previousCoordinate, coordinate); if (segment.getLength() > 0) { if (!visitor.visit(segment)) { return; } } previousCoordinate = coordinate; } } public static void addElevation(final PrecisionModel precisionModel, final Coordinate coordinate, final LineSegment3D line) { addElevation(coordinate, line); coordinate.z = precisionModel.makePrecise(coordinate.z); } public static void makePrecise(final PrecisionModel precision, final Geometry geometry) { geometry.apply(new CoordinateSequenceFilter() { public void filter(final CoordinateSequence coordinates, final int index) { for (int i = 0; i < coordinates.getDimension(); i++) { double ordinate = coordinates.getOrdinate(index, i); double preciseOrdinate = precision.makePrecise(ordinate); coordinates.setOrdinate(index, i, preciseOrdinate); } } public boolean isDone() { return false; } public boolean isGeometryChanged() { return true; } }); } public static Envelope buffer(final Envelope envelope, final int i) { // TODO Auto-generated method stub return new Envelope(envelope.getMinX() - i, envelope.getMaxX() + i, envelope.getMinY() - i, envelope.getMaxY() + i); } /** * Computes whether a ring defined by an array of {@link Coordinate} is * oriented counter-clockwise. * <ul> * <li>The list of points is assumed to have the first and last points equal. * <li>This will handle coordinate lists which contain repeated points. * </ul> * This algorithm is <b>only</b> guaranteed to work with valid rings. If the * ring is invalid (e.g. self-crosses or touches), the computed result <b>may</b> * not be correct. * * @param ring an array of coordinates forming a ring * @return <code>true</code> if the ring is oriented counter-clockwise. */ public static boolean isCCW(final CoordinateSequence ring) { // # of points without closing endpoint int nPts = ring.size() - 1; // find highest point Coordinate hiPt = ring.getCoordinate(0); int hiIndex = 0; for (int i = 1; i <= nPts; i++) { Coordinate p = ring.getCoordinate(i); if (p.y > hiPt.y) { hiPt = p; hiIndex = i; } } // find distinct point before highest point int iPrev = hiIndex; do { iPrev = iPrev - 1; if (iPrev < 0) { iPrev = nPts; } } while (ring.getCoordinate(iPrev).equals2D(hiPt) && iPrev != hiIndex); // find distinct point after highest point int iNext = hiIndex; do { iNext = (iNext + 1) % nPts; } while (ring.getCoordinate(iNext).equals2D(hiPt) && iNext != hiIndex); Coordinate prev = ring.getCoordinate(iPrev); Coordinate next = ring.getCoordinate(iNext); /** * This check catches cases where the ring contains an A-B-A configuration * of points. This can happen if the ring does not contain 3 distinct points * (including the case where the input array has fewer than 4 elements), or * it contains coincident line segments. */ if (prev.equals2D(hiPt) || next.equals2D(hiPt) || prev.equals2D(next)) { return false; } int disc = CGAlgorithms.computeOrientation(prev, hiPt, next); /** * If disc is exactly 0, lines are collinear. There are two possible cases: * (1) the lines lie along the x axis in opposite directions (2) the lines * lie on top of one another (1) is handled by checking if next is left of * prev ==> CCW (2) will never happen if the ring is valid, so don't check * for it (Might want to assert this) */ boolean isCCW = false; if (disc == 0) { // poly is CCW if prev x is right of next x isCCW = (prev.x > next.x); } else { // if area is positive, points are ordered CCW isCCW = (disc > 0); } return isCCW; } public static void addElevation(final Coordinate coordinate, final LineString line) { CoordinateSequence coordinates = line.getCoordinateSequence(); Coordinate previousCoordinate = coordinates.getCoordinate(0); for (int i = 1; i < coordinates.size(); i++) { Coordinate currentCoordinate = coordinates.getCoordinate(i); LineSegment3D segment = new LineSegment3D(previousCoordinate, currentCoordinate); if (segment.distance(coordinate) < 1) { PrecisionModel precisionModel = line.getFactory().getPrecisionModel(); addElevation(precisionModel, coordinate, segment); return; } previousCoordinate = currentCoordinate; } } public static Geometry difference2DZ(final LineString line, final Geometry geometry) { Geometry difference = line.difference(geometry); if (difference instanceof LineString) { LineString lineDiff = (LineString)difference; Coordinate c0 = lineDiff.getCoordinateN(0); if (Double.isNaN(c0.z)) { addElevation(c0, line); } Coordinate cN = lineDiff.getCoordinateN(lineDiff.getNumPoints() - 1); if (Double.isNaN(cN.z)) { addElevation(cN, line); } } difference.setUserData(line.getUserData()); return difference; } /** * Change to a floating precision model to calculate the intersection. This * reduces the chance of lines being returned instead of points where there is * a sharp angle * * @param line1 * @param line2 * @return */ public static Geometry intersection2DZFloating(final LineString line1, final LineString line2) { GeometryFactory factory = new GeometryFactory(); CoordinateSequence coordinates1 = line1.getCoordinateSequence(); LineString line1Floating = factory.createLineString(coordinates1); CoordinateSequence coordinates2 = line2.getCoordinateSequence(); LineString line2Floating = factory.createLineString(coordinates2); return JtsGeometryUtil.intersection2DZ(line1Floating, line2Floating); } public static Geometry intersection2DZ(final LineString line, final Geometry geometry) { Geometry intersection = line.intersection(geometry); if (intersection instanceof LineString) { LineString lineDiff = (LineString)intersection; addElevation(line, lineDiff); } else { if (intersection instanceof MultiLineString) { for (int i = 0; i < intersection.getNumGeometries(); i++) { LineString lineDiff = (LineString)intersection.getGeometryN(i); addElevation(line, lineDiff); } } } intersection.setUserData(line.getUserData()); return intersection; } private static void addElevation(final LineString original, final LineString update) { Coordinate c0 = update.getCoordinateN(0); if (Double.isNaN(c0.z)) { addElevation(c0, original); } Coordinate cN = update.getCoordinateN(update.getNumPoints() - 1); if (Double.isNaN(cN.z)) { addElevation(cN, original); } } public static Polygon getMitredBuffer(final Polygon polygon, final double distance) { Geometry buffer = polygon; LineString exteriorRing = polygon.getExteriorRing(); Geometry exteriorBuffer = getMitredBuffer(exteriorRing, distance); buffer = buffer.union(exteriorBuffer); for (int i = 0; i < polygon.getNumInteriorRing(); i++) { LineString ring = polygon.getInteriorRingN(i); Geometry bufferedRing = getMitredBuffer(ring, distance); buffer = buffer.union(bufferedRing); } return (Polygon)buffer; } public static Polygon getMitredBuffer(final LineString lineString, final double distance) { LineStringMitredBuffer visitor = new LineStringMitredBuffer(distance); visitLineSegments(lineString.getCoordinateSequence(), visitor); return visitor.getBuffer(); } public static Polygon getMitredBuffer(final LineSegment segment, final double distance) { LineSegment extendedSegment = addLength(segment, distance, distance); LineSegment clockwiseSegment = offset(extendedSegment, distance, Angle.CLOCKWISE); LineSegment counterClockwiseSegment = offset(extendedSegment, distance, Angle.COUNTERCLOCKWISE); Coordinate[] coords = new Coordinate[] { clockwiseSegment.p0, clockwiseSegment.p1, counterClockwiseSegment.p1, counterClockwiseSegment.p0, clockwiseSegment.p0 }; GeometryFactory factory = new GeometryFactory(); LinearRing exteriorRing = factory.createLinearRing(coords); return factory.createPolygon(exteriorRing, null); } /** * @param line1 The line to match * @param line2 The line to compare the start of with the other line * @return */ public static boolean touchesAtStart(final LineString line1, final LineString line2) { Coordinate l1c0 = line1.getCoordinateN(0); Coordinate l1cN = line1.getCoordinateN(line1.getNumPoints() - 1); Coordinate l2c0 = line2.getCoordinateN(0); if (l2c0.equals2D(l1c0)) { return true; } else { return l2c0.equals2D(l1cN); } } /** * @param line1 The line to match * @param line2 The line to compare the start of with the other line * @return */ public static boolean touchesAtEnd(final LineString line1, final LineString line2) { Coordinate l1c0 = line1.getCoordinateN(0); Coordinate l1cN = line1.getCoordinateN(line1.getNumPoints() - 1); Coordinate l2cN = line2.getCoordinateN(line2.getNumPoints() - 1); if (l2cN.equals2D(l1c0)) { return true; } else { return l2cN.equals2D(l1cN); } } public static boolean startAndEndEqual(final LineString geometry1, final LineString geometry2) { Coordinate g1c0 = geometry1.getCoordinateN(0); Coordinate g1cN = geometry1.getCoordinateN(geometry1.getNumPoints() - 1); Coordinate g2c0 = geometry2.getCoordinateN(0); Coordinate g2cN = geometry2.getCoordinateN(geometry2.getNumPoints() - 1); if (g1c0.equals2D(g2c0)) { return g1cN.equals2D(g2cN); } else if (g1c0.equals2D(g2cN)) { return g1cN.equals2D(g2c0); } else { return false; } } public static boolean isBothWithinDistance(final LineString line1, final LineString line2, final double maxDistance) { if (isWithinDistance(line1, line2, maxDistance)) { return isWithinDistance(line2, line1, maxDistance); } else { return false; } } public static boolean isWithinDistance(final LineString line1, final LineString line2, final double maxDistance) { CoordinateSequence coordinates1 = line1.getCoordinateSequence(); for (int i = 0; i < coordinates1.size(); i++) { Coordinate coordinate = coordinates1.getCoordinate(i); if (!isWithinDistance(coordinate, line2, maxDistance)) { return false; } } return true; } public static boolean isWithinDistance(final Coordinate coordinate, final LineString line, final double maxDistance) { GeometryFactory factory = line.getFactory(); Point point = factory.createPoint(coordinate); double distance = line.distance(point); return distance <= maxDistance; } public static Polygon reversePolygon(final Polygon polygon) { GeometryFactory factory = polygon.getFactory(); LineString exteriorRing = polygon.getExteriorRing(); CoordinateSequence oldCoordinates = exteriorRing.getCoordinateSequence(); ReverseCoordinateSequence newCoordinates = new ReverseCoordinateSequence( oldCoordinates); LinearRing shell = factory.createLinearRing(newCoordinates); return factory.createPolygon(shell, null); } public static Geometry get2DGeometry(final Geometry geometry) { GeometryFactory factory = geometry.getFactory(); if (geometry instanceof Point) { Point point = (Point)geometry; return factory.createPoint(get2DCoordinates(point.getCoordinateSequence())); } else if (geometry instanceof LineString) { LineString line = (LineString)geometry; return factory.createLineString(get2DCoordinates(line.getCoordinateSequence())); } else if (geometry instanceof Polygon) { Polygon polygon = (Polygon)geometry; LinearRing shell = (LinearRing)polygon.getExteriorRing(); LinearRing shell2d = get2DGeometry(shell); LinearRing[] holes2d = new LinearRing[polygon.getNumInteriorRing()]; for (int i = 0; i < polygon.getNumInteriorRing(); i++) { LinearRing hole = (LinearRing)polygon.getInteriorRingN(i); holes2d[i] = get2DGeometry(hole); } return factory.createPolygon(shell2d, holes2d); } return null; } public static LinearRing get2DGeometry(final LinearRing ring) { CoordinateSequence coordinates = ring.getCoordinateSequence(); CoordinateSequence coordinates2d = get2DCoordinates(coordinates); GeometryFactory factory = ring.getFactory(); return factory.createLinearRing(coordinates2d); } private static CoordinateSequence get2DCoordinates( final CoordinateSequence coordinateSequence) { CoordinateSequenceFactory coordFactory = PackedCoordinateSequenceFactory.DOUBLE_FACTORY; int numCoords = coordinateSequence.size(); CoordinateSequence coordinates = coordFactory.create(numCoords, 2); for (int i = 0; i < numCoords; i++) { double x = coordinateSequence.getX(i); double y = coordinateSequence.getY(i); coordinates.setOrdinate(i, 0, x); coordinates.setOrdinate(i, 1, y); } return coordinates; } /** * Insert the coordinate at the specified index into the line, returning the * new line. * * @param line The line. * @param index The index to insert the coordinate. * @param coordinate The coordinate. */ public static LineString insert(final LineString line, final int index, final Coordinate coordinate) { CoordinateSequence coords = line.getCoordinateSequence(); CoordinateSequence newCoords = PackedCoordinateSequenceFactory.DOUBLE_FACTORY.create( coords.size() + 1, coords.getDimension()); int j = 0; for (int i = 0; i < newCoords.size(); i++) { if (i == index) { newCoords.setOrdinate(i, 0, coordinate.x); newCoords.setOrdinate(i, 1, coordinate.y); if (newCoords.getDimension() > 2) { newCoords.setOrdinate(i, 2, coordinate.z); } } else { for (int o = 0; o < newCoords.getDimension(); o++) { newCoords.setOrdinate(i, o, coords.getOrdinate(j, o)); } j++; } } GeometryFactory factory = line.getFactory(); LineString newLine = factory.createLineString(newCoords); return newLine; } public static List<LineString> split(final LineString line, final int index, final Coordinate coordinate) { List<LineString> lines = new ArrayList<LineString>(); boolean containsCoordinate = coordinate.equals(line.getCoordinateN(index)); CoordinateSequence coords = line.getCoordinateSequence(); int dimension = coords.getDimension(); int coords1Size; int coords2Size = coords.size() - index; if (containsCoordinate) { coords1Size = index + 1; coords2Size = coords.size() - index; } else { coords1Size = index + 2; coords2Size = coords.size() - index; } CoordinateSequence coords1 = PackedCoordinateSequenceFactory.DOUBLE_FACTORY.create( coords1Size, dimension); copyCoords(coords, 0, coords1, 0, index + 1); if (!containsCoordinate) { setCoordinate(coords1, coords1Size - 1, coordinate); } CoordinateSequence coords2 = PackedCoordinateSequenceFactory.DOUBLE_FACTORY.create( coords2Size, dimension); if (!containsCoordinate) { setCoordinate(coords2, 0, coordinate); copyCoords(coords, index + 1, coords2, 1, coords2.size() - 1); } else { copyCoords(coords, index, coords2, 0, coords2.size()); } GeometryFactory geometryFactory = line.getFactory(); if (coords1Size > 1) { LineString line1 = geometryFactory.createLineString(coords1); if (line1.getLength() > 0) { lines.add(line1); } } if (coords2Size > 1) { LineString line2 = geometryFactory.createLineString(coords2); if (line2.getLength() > 0) { lines.add(line2); } } return lines; } public static void copyCoords(final CoordinateSequence src, final int srcPos, final CoordinateSequence dest, final int destPos, final int length) { int dimension = Math.min(src.getDimension(), dest.getDimension()); for (int i = 0; i < length; i++) { for (int j = 0; j < dimension; j++) { double ordinate = src.getOrdinate(srcPos + i, j); dest.setOrdinate(destPos + i, j, ordinate); } } } public static void setCoordinate(final CoordinateSequence coordinates, final int i, final Coordinate coordinate) { coordinates.setOrdinate(i, 0, coordinate.x); coordinates.setOrdinate(i, 1, coordinate.y); if (coordinates.getDimension() > 2) { coordinates.setOrdinate(i, 2, coordinate.z); } } public static boolean isAlmostParallel(final LineString line, final LineString matchLine, final double maxDistance) { CoordinateSequence coords = line.getCoordinateSequence(); CoordinateSequence matchCoords = line.getCoordinateSequence(); Coordinate previousCoordinate = coords.getCoordinate(0); for (int i = 1; i < coords.size(); i++) { Coordinate coordinate = coords.getCoordinate(i); Coordinate previousMatchCoordinate = matchCoords.getCoordinate(0); for (int j = 1; j < coords.size(); j++) { Coordinate matchCoordinate = matchCoords.getCoordinate(i); double distance = CGAlgorithms.distanceLineLine(previousCoordinate, coordinate, previousMatchCoordinate, matchCoordinate); if (distance <= maxDistance) { double angle1 = Angle.normalizePositive(Angle.angle( previousCoordinate, coordinate)); double angle2 = Angle.normalizePositive(Angle.angle( previousMatchCoordinate, matchCoordinate)); double angleDiff = Math.abs(angle1 - angle2); if (angleDiff <= Math.PI / 6) { return true; } } previousMatchCoordinate = matchCoordinate; } previousCoordinate = coordinate; } return false; } public static LineString getMatchingLines(final LineString line1, final LineString line2, final double maxDistance) { List<Coordinate> newCoords = new ArrayList<Coordinate>(); CoordinateSequence coords1 = line1.getCoordinateSequence(); CoordinateSequence coords2 = line1.getCoordinateSequence(); Coordinate previousCoordinate = coords1.getCoordinate(0); boolean finish = false; for (int i = 1; i < coords1.size() && !finish; i++) { Coordinate coordinate = coords1.getCoordinate(i); Coordinate previousCoordinate2 = coords2.getCoordinate(0); for (int j = 1; j < coords1.size() && !finish; j++) { Coordinate coordinate2 = coords2.getCoordinate(i); double distance = CGAlgorithms.distanceLineLine(previousCoordinate, coordinate, previousCoordinate2, coordinate2); if (distance > maxDistance) { finish = true; } previousCoordinate2 = coordinate2; } previousCoordinate = coordinate; } if (newCoords.size() > 1) { return createLineString(line1.getFactory(), newCoords); } else { return null; } } public static LineString createLineString(final GeometryFactory factory, final List<Coordinate> coordinates) { Coordinate[] coords = new Coordinate[coordinates.size()]; coordinates.toArray(coords); return factory.createLineString(coords); } public static int[] findClosestSegmentAndCoordinate(final LineString line, final Coordinate coordinate) { int[] closest = new int[] { -1, -1, 0 }; double closestDistance = Double.MAX_VALUE; CoordinateSequence coordinates = line.getCoordinateSequence(); Coordinate previousCoord = coordinates.getCoordinate(0); double previousCoordinateDistance = previousCoord.distance(coordinate); if (previousCoordinateDistance == 0) { closest[0] = 0; closest[1] = 0; closest[2] = 1; } else { for (int i = 1; i < coordinates.size(); i++) { Coordinate currentCoordinate = coordinates.getCoordinate(i); double currentCoordinateDistance = currentCoordinate.distance(coordinate); if (currentCoordinateDistance == 0) { closest[0] = i; closest[1] = i; closest[2] = 1; return closest; } LineSegment lineSegment = new LineSegment(previousCoord, currentCoordinate); double distance = lineSegment.distance(coordinate); if (distance == 0) { closest[0] = i - 1; if (previousCoordinateDistance < currentCoordinateDistance) { closest[1] = i - 1; } else { closest[1] = i; } return closest; } else if (distance < closestDistance) { closestDistance = distance; closest[0] = i - 1; if (previousCoordinateDistance < currentCoordinateDistance) { closest[1] = i - 1; } else { closest[1] = i; } } previousCoord = currentCoordinate; } } return closest; } public static List<LineString> splitLineString(final LineString line, final Coordinate coordinate) { int[] indexes = findClosestSegmentAndCoordinate(line, coordinate); int segmentIndex = indexes[0]; if (segmentIndex != -1) { int coordinateIndex = indexes[1]; boolean exactMatch = coordinateIndex == 1; if (coordinateIndex == 0) { if (exactMatch) { return Collections.singletonList(line); } else { Coordinate c0 = line.getCoordinateN(0); Coordinate c1; int i = 1; do { c1 = line.getCoordinateN(i); i++; } while (c1.equals(c0)); if (Angle.isAcute(c1, c0, coordinate)) { Coordinate projectedCoordinate = new LineSegment(c0, c1).project(coordinate); return split(line, 1, projectedCoordinate); } else { return Collections.singletonList(line); } } } else if (coordinateIndex == line.getNumPoints() - 1) { if (exactMatch) { return Collections.singletonList(line); } else { Coordinate cn = line.getCoordinateN(line.getNumPoints() - 1); Coordinate cn1; int i = line.getNumPoints() - 2; do { cn1 = line.getCoordinateN(i); i++; } while (cn1.equals(cn)); if (Angle.isAcute(cn1, cn, coordinate)) { Coordinate projectedCoordinate = new LineSegment(cn, cn1).project(coordinate); return split(line, line.getNumPoints() - 1, projectedCoordinate); } else { return Collections.singletonList(line); } } } else { Coordinate c = line.getCoordinateN(segmentIndex); Coordinate c1; int i = segmentIndex + 1; do { c1 = line.getCoordinateN(i); i++; } while (c.equals(c1)); Coordinate projectedCoordinate = new LineSegment(c, c1).project(coordinate); return split(line, segmentIndex, projectedCoordinate); } } else { return Collections.emptyList(); } } }
相关文章推荐
- 分享(非充分)利用NIO2进行压缩处理的代码
- 利用正则表达式获取特定文件(如java class)并对其进行处理(如代码统计)
- 利用中断向量(IDT)进行代码的防御和攻击
- 无需进行滤波后处理,利用循环推断算法实现歌唱语音分离
- System.Resources.MissingManifestResourceException”类型的异常在 mscorlib.dll 中发生,但未在用户代码中进行处理
- 利用 Python 进行数据分析(二)尝试处理一份 JSON 数据并生成条形图
- 利用Rational Rose进行C++代码和数据库逆向工程 结构分析
- 使用highlight.js 对代码进行语法高亮处理
- 利用PCL处理Realsense点云数据-使用VoxelGrid滤波器对点云进行下采样
- 对比使用C# unsafe代码和OpenCV进行图像处理的效率(上)
- 怎么对代码中的大量的NSLog( )打印函数进行统一处理
- 利用CreateRemoteThread进行远程代码注入的技术在64位机上可能遇到的问题
- 如何在Delphi里面利用Word的VBA代码进行一些总结
- 利用单元测试在每个层上对PHP代码进行检查
- 利用XPerf进行代码性能分析
- 利用JMeter的beanshell进行接口的加密处理
- php利用pdo进行mysql的事务处理机制
- 利用Eclipse处理臃肿代码的方法
- C#对图片进行马赛克处理可控制模糊程度的实现代码
- 利用 .NET Printing 命名空间从 Windows 窗体应用程序中进行预览和打印