com.vividsolutions.jtstest.testbuilder.topostretch.StretchedVertexFinder Maven / Gradle / Ivy
The newest version!
package com.vividsolutions.jtstest.testbuilder.topostretch;
import java.util.*;
import com.vividsolutions.jts.algorithm.*;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.geom.util.*;
class StretchedVertexFinder
{
public static List findNear(Collection linestrings, double tolerance, Envelope mask)
{
StretchedVertexFinder finder = new StretchedVertexFinder(linestrings, tolerance, mask);
return finder.getNearVertices();
}
private Collection linestrings;
private double tolerance = 0.0;
private Envelope limitEnv = null;
private List nearVerts = new ArrayList();
public StretchedVertexFinder(Collection linestrings, double tolerance)
{
this.linestrings = linestrings;
this.tolerance = tolerance;
}
public StretchedVertexFinder(Collection linestrings, double tolerance, Envelope limitEnv)
{
this(linestrings, tolerance);
this.limitEnv = limitEnv;
}
public List getNearVertices()
{
findNearVertices();
return nearVerts;
}
private void findNearVertices()
{
for (Iterator i = linestrings.iterator(); i.hasNext(); ) {
LineString line = (LineString) i.next();
findNearVertices(line);
}
}
private static int geomPointsLen(Coordinate[] pts)
{
int n = pts.length;
// don't process the last point of a ring twice
if (CoordinateArrays.isRing(pts))
n = pts.length - 1;
return n;
}
private void findNearVertices(LineString targetLine)
{
Coordinate[] pts = targetLine.getCoordinates();
// don't process the last point of a ring twice
int n = geomPointsLen(pts);
for (int i = 0; i < n; i++) {
if (limitEnv.intersects(pts[i]))
findNearVertex(pts, i);
}
}
private void findNearVertex(Coordinate[] linePts, int index)
{
for (Iterator i = linestrings.iterator(); i.hasNext(); ) {
LineString testLine = (LineString) i.next();
findNearVertex(linePts, index, testLine);
}
}
/**
* Finds a single near vertex.
* This is simply the first one found, not necessarily
* the nearest.
* This choice may sub-optimal, resulting
* in odd result geometry.
* It's not clear that this can be done better, however.
* If there are several near points, the stretched
* geometry is likely to be distorted anyway.
*
* @param targetPts
* @param index
* @param testLine
*/
private void findNearVertex(Coordinate[] targetPts, int index, LineString testLine)
{
Coordinate targetPt = targetPts[index];
Coordinate[] testPts = testLine.getCoordinates();
// don't process the last point of a ring twice
int n = geomPointsLen(testPts);
for (int i = 0; i < n; i++) {
Coordinate testPt = testPts[i];
StretchedVertex stretchVert = null;
// is near to vertex?
double dist = testPt.distance(targetPt);
if (dist <= tolerance && dist != 0.0) {
stretchVert = new StretchedVertex(targetPt, targetPts, index, testPt, testPts, i);
}
// is near segment?
else if (i < testPts.length - 1) {
Coordinate segEndPt = testPts[i + 1];
/**
* Check whether pt is near or equal to other segment endpoint.
* If near, it will be handled by the near vertex case code.
* If equal, don't record it at all
*/
double distToOther = segEndPt.distance(targetPt);
if (distToOther <= tolerance)
// will be handled as a point-vertex case
continue;
// Here we know point is not near the segment endpoints.
// Check if it is near the segment at all.
if (isPointNearButNotOnSeg(targetPt, testPt, segEndPt, tolerance)) {
stretchVert = new StretchedVertex(targetPt, targetPts, i, new LineSegment(testPt, testPts[i + 1]));
}
}
if (stretchVert != null)
nearVerts.add(stretchVert);
}
}
private static boolean contains(Envelope env, Coordinate p0, Coordinate p1)
{
if (! env.contains(p0)) return false;
if (! env.contains(p1)) return false;
return true;
}
private static boolean isPointNearButNotOnSeg(Coordinate p, Coordinate p0, Coordinate p1, double distTol)
{
// don't rely on segment distance algorithm to correctly compute zero distance
// on segment
if (CGAlgorithms.computeOrientation(p0, p1, p) == CGAlgorithms.COLLINEAR)
return false;
// compute actual distance
distSeg.p0 = p0;
distSeg.p1 = p1;
double segDist = distSeg.distance(p);
if (segDist > distTol)
return false;
return true;
}
private static LineSegment distSeg = new LineSegment();
private static double distanceToSeg(Coordinate p, Coordinate p0, Coordinate p1)
{
distSeg.p0 = p0;
distSeg.p1 = p1;
double segDist = distSeg.distance(p);
// robust calculation of zero distance
if (CGAlgorithms.computeOrientation(p0, p1, p) == CGAlgorithms.COLLINEAR)
segDist = 0.0;
return segDist;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy