package com.vividsolutions.jts.noding.snapround;
import java.util.*;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.noding.*;
import com.vividsolutions.jts.algorithm.LineIntersector;
import com.vividsolutions.jts.index.chain.*;
import com.vividsolutions.jts.index.*;
import com.vividsolutions.jts.index.strtree.STRtree;
import com.vividsolutions.jts.index.quadtree.Quadtree;
/**
* "Snaps" all {@link SegmentString}s in a {@link SpatialIndex} containing
* {@link MonotoneChain}s to a given {@link HotPixel}.
*
* @version 1.7
*/
public class MCIndexPointSnapper
{
public static int nSnaps = 0;
private STRtree index;
public MCIndexPointSnapper(SpatialIndex index) {
this.index = (STRtree) index;
}
/**
* Snaps (nodes) all interacting segments to this hot pixel.
* The hot pixel may represent a vertex of an edge,
* in which case this routine uses the optimization
* of not noding the vertex itself
*
* @param hotPixel the hot pixel to snap to
* @param parentEdge the edge containing the vertex, if applicable, or <code>null</code>
* @param hotPixelVertexIndex the index of the hotPixel vertex, if applicable, or -1
* @return <code>true</code> if a node was added for this pixel
*/
public boolean snap(HotPixel hotPixel, SegmentString parentEdge, int hotPixelVertexIndex)
{
final Envelope pixelEnv = hotPixel.getSafeEnvelope();
final HotPixelSnapAction hotPixelSnapAction = new HotPixelSnapAction(hotPixel, parentEdge, hotPixelVertexIndex);
index.query(pixelEnv, new ItemVisitor() {
public void visitItem(Object item) {
MonotoneChain testChain = (MonotoneChain) item;
testChain.select(pixelEnv, hotPixelSnapAction);
}
}
);
return hotPixelSnapAction.isNodeAdded();
}
public boolean snap(HotPixel hotPixel)
{
return snap(hotPixel, null, -1);
}
public class HotPixelSnapAction
extends MonotoneChainSelectAction
{
private HotPixel hotPixel;
private SegmentString parentEdge;
// is -1 if hotPixel is not a vertex
private int hotPixelVertexIndex;
private boolean isNodeAdded = false;
public HotPixelSnapAction(HotPixel hotPixel, SegmentString parentEdge, int hotPixelVertexIndex)
{
this.hotPixel = hotPixel;
this.parentEdge = parentEdge;
this.hotPixelVertexIndex = hotPixelVertexIndex;
}
public boolean isNodeAdded() { return isNodeAdded; }
public void select(MonotoneChain mc, int startIndex)
{
NodedSegmentString ss = (NodedSegmentString) mc.getContext();
/**
* Check to avoid snapping a hotPixel vertex to the same vertex.
* This method is called for segments which intersects the
* hot pixel,
* so need to check if either end of the segment is equal to the hot pixel
* and if so, do not snap.
*
* Sep 22 2012 - MD - currently do need to snap to every vertex,
* since otherwise the testCollapse1 test in SnapRoundingTest fails.
*/
if (parentEdge != null) {
if (ss == parentEdge &&
(startIndex == hotPixelVertexIndex
|| startIndex+1 == hotPixelVertexIndex
))
return;
}
isNodeAdded = isNodeAdded || hotPixel.addSnappedNode(ss, startIndex);
}
}
}