com.vividsolutions.jtstest.testbuilder.topostretch.TopologyStretcher Maven / Gradle / Ivy
package com.vividsolutions.jtstest.testbuilder.topostretch;
import java.util.*;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.geom.util.*;
/**
* Stretches the vertices and segments of a @link Geometry}
* to make the topology more visible.
*
* @author Martin Davis
*
*/
public class TopologyStretcher
{
private double stretchDistance = 0.1;
private Geometry[] inputGeoms;
private List linestrings;
private List[] modifiedCoords;
public TopologyStretcher(Geometry g)
{
inputGeoms = new Geometry[1];
inputGeoms[0] = g;
}
public TopologyStretcher(Geometry g1, Geometry g2)
{
inputGeoms = new Geometry[2];
inputGeoms[0] = g1;
inputGeoms[1] = g2;
}
public int numVerticesInMask(Envelope mask)
{
VertexInMaskCountCoordinateFilter filter = new VertexInMaskCountCoordinateFilter(mask);
if (inputGeoms[0] != null) inputGeoms[0].apply(filter);
if (inputGeoms[1] != null) inputGeoms[1].apply(filter);
return filter.getCount();
}
public Geometry[] stretch(double nearnessTol, double stretchDistance)
{
return stretch(nearnessTol, stretchDistance, null);
}
public Geometry[] stretch(double nearnessTol, double stretchDistance, Envelope mask)
{
this.stretchDistance = stretchDistance;
linestrings = extractLineStrings(inputGeoms, mask);
List nearVerts = StretchedVertexFinder.findNear(linestrings, nearnessTol, mask);
Map coordinateMoves = getCoordinateMoves(nearVerts);
Geometry[] strGeoms = new Geometry[inputGeoms.length];
modifiedCoords = new List[inputGeoms.length];
for (int i = 0; i < inputGeoms.length; i++) {
Geometry geom = (Geometry) inputGeoms[i];
if (geom != null) {
GeometryVerticesMover mover = new GeometryVerticesMover(geom, coordinateMoves);
Geometry stretchedGeom = mover.move();
strGeoms[i] = stretchedGeom;
modifiedCoords[i] = mover.getModifiedCoordinates();
}
}
return strGeoms;
}
/**
* Gets the {@link Coordinate}s in each stretched geometry which were modified (if any).
*
* @return lists of Coordinates, one for each input geometry
*/
public List[] getModifiedCoordinates()
{
return modifiedCoords;
}
private List extractLineStrings(Geometry[] geom, Envelope mask)
{
List lines = new ArrayList();
LinearComponentExtracter lineExtracter = new LinearComponentExtracter(lines);
for (int i = 0; i < geom.length; i++ ) {
if (geom[i] == null) continue;
if (mask != null && ! mask.intersects(geom[i].getEnvelopeInternal()))
continue;
geom[i].apply(lineExtracter);
}
if (mask != null) {
List masked = new ArrayList();
for (Iterator i = lines.iterator(); i.hasNext(); ) {
LineString line = (LineString) i.next();
if (mask.intersects(line.getEnvelopeInternal()))
masked.add(line);
}
return masked;
}
return lines;
}
private Map getCoordinateMoves(List nearVerts)
{
Map moves = new TreeMap();
for (Iterator i = nearVerts.iterator(); i.hasNext(); ) {
StretchedVertex nv = (StretchedVertex) i.next();
// TODO: check if move would invalidate topology. If yes, don't move
Coordinate src = nv.getVertexCoordinate();
Coordinate moved = nv.getStretchedVertex(stretchDistance);
if (! moved.equals2D(src))
moves.put(src, moved);
}
return moves;
}
private static class VertexInMaskCountCoordinateFilter
implements CoordinateFilter
{
private Envelope mask;
private int count = 0;
public VertexInMaskCountCoordinateFilter(Envelope mask)
{
this.mask = mask;
}
public void filter(Coordinate coord)
{
if (mask.contains(coord))
count++;
}
public int getCount() { return count; }
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy