| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 12 |
|
| 13 |
package org.locationtech.jts.operation.overlay.validate; |
| 14 |
|
| 15 |
import java.util.ArrayList; |
| 16 |
import java.util.Iterator; |
| 17 |
import java.util.List; |
| 18 |
|
| 19 |
import org.locationtech.jts.geom.Coordinate; |
| 20 |
import org.locationtech.jts.geom.Geometry; |
| 21 |
import org.locationtech.jts.geom.LineString; |
| 22 |
import org.locationtech.jts.geom.util.LinearComponentExtracter; |
| 23 |
|
| 24 |
/** |
| 25 |
* Generates points offset by a given distance |
| 26 |
* from both sides of the midpoint of |
| 27 |
* all segments in a {@link Geometry}. |
| 28 |
* Can be used to generate probe points for |
| 29 |
* determining whether a polygonal overlay result |
| 30 |
* is incorrect. |
| 31 |
* The input geometry may have any orientation for its rings, |
| 32 |
* but {@link #setSidesToGenerate(boolean, boolean)} is |
| 33 |
* only meaningful if the orientation is known. |
| 34 |
* |
| 35 |
* @author Martin Davis |
| 36 |
* @version 1.7 |
| 37 |
*/ |
| 38 |
public class OffsetPointGenerator |
| 39 |
{ |
| 40 |
private Geometry g; |
| 41 |
private boolean doLeft = true; |
| 42 |
private boolean doRight = true; |
| 43 |
|
| 44 |
public OffsetPointGenerator(Geometry g) |
| 45 |
{ |
| 46 |
this.g = g; |
| 47 |
} |
| 48 |
|
| 49 |
/** |
| 50 |
* Set the sides on which to generate offset points. |
| 51 |
* |
| 52 |
* @param doLeft |
| 53 |
* @param doRight |
| 54 |
*/ |
| 55 |
public void setSidesToGenerate(boolean doLeft, boolean doRight) |
| 56 |
{ |
| 57 |
this.doLeft = doLeft; |
| 58 |
this.doRight = doRight; |
| 59 |
} |
| 60 |
|
| 61 |
/** |
| 62 |
* Gets the computed offset points. |
| 63 |
* |
| 64 |
* @return List<Coordinate> |
| 65 |
*/ |
| 66 |
public List getPoints(double offsetDistance) |
| 67 |
{ |
| 68 |
List offsetPts = new ArrayList(); |
| 69 |
List lines = LinearComponentExtracter.getLines(g); |
| 70 |
for (Iterator i = lines.iterator(); i.hasNext(); ) { |
| 71 |
LineString line = (LineString) i.next(); |
| 72 |
extractPoints(line, offsetDistance, offsetPts); |
| 73 |
} |
| 74 |
|
| 75 |
return offsetPts; |
| 76 |
} |
| 77 |
|
| 78 |
private void extractPoints(LineString line, double offsetDistance, List offsetPts) |
| 79 |
{ |
| 80 |
Coordinate[] pts = line.getCoordinates(); |
| 81 |
for (int i = 0; i < pts.length - 1; i++) { |
| 82 |
computeOffsetPoints(pts[i], pts[i + 1], offsetDistance, offsetPts); |
| 83 |
} |
| 84 |
} |
| 85 |
|
| 86 |
/** |
| 87 |
* Generates the two points which are offset from the |
| 88 |
* midpoint of the segment <tt>(p0, p1)</tt> by the |
| 89 |
* <tt>offsetDistance</tt>. |
| 90 |
* |
| 91 |
* @param p0 the first point of the segment to offset from |
| 92 |
* @param p1 the second point of the segment to offset from |
| 93 |
*/ |
| 94 |
private void computeOffsetPoints(Coordinate p0, Coordinate p1, double offsetDistance, List offsetPts) |
| 95 |
{ |
| 96 |
double dx = p1.x - p0.x; |
| 97 |
double dy = p1.y - p0.y; |
| 98 |
double len = Math.sqrt(dx * dx + dy * dy); |
| 99 |
|
| 100 |
double ux = offsetDistance * dx / len; |
| 101 |
double uy = offsetDistance * dy / len; |
| 102 |
|
| 103 |
double midX = (p1.x + p0.x) / 2; |
| 104 |
double midY = (p1.y + p0.y) / 2; |
| 105 |
|
| 106 |
if (doLeft) { |
| 107 |
Coordinate offsetLeft = new Coordinate(midX - uy, midY + ux); |
| 108 |
offsetPts.add(offsetLeft); |
| 109 |
} |
| 110 |
|
| 111 |
if (doRight) { |
| 112 |
Coordinate offsetRight = new Coordinate(midX + uy, midY - ux); |
| 113 |
offsetPts.add(offsetRight); |
| 114 |
} |
| 115 |
} |
| 116 |
|
| 117 |
} |
| 118 |
|