package com.revolsys.geometry.graph.visitor;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import com.revolsys.geometry.graph.Edge;
import com.revolsys.geometry.graph.Graph;
import com.revolsys.geometry.graph.Node;
import com.revolsys.geometry.graph.event.NodeEventListener;
import com.revolsys.geometry.index.IdObjectIndex;
import com.revolsys.geometry.model.BoundingBox;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.geometry.model.LineString;
import com.revolsys.geometry.model.Point;
import com.revolsys.geometry.util.LineStringUtil;
public class SplitCrossingEdgesVisitor<T> extends AbstractEdgeListenerVisitor<T> {
public static final String CROSSING_EDGES = "Crossing edges";
private final Graph<T> graph;
private final SplitEdgesCloseToNodeVisitor<T> splitEdgesCloseToNodeVisitor;
public SplitCrossingEdgesVisitor(final Graph<T> graph) {
this.graph = graph;
this.splitEdgesCloseToNodeVisitor = new SplitEdgesCloseToNodeVisitor<>(graph, CROSSING_EDGES,
1);
}
@Override
public void accept(final Edge<T> edge) {
final IdObjectIndex<Edge<T>> edgeIndex = this.graph.getEdgeIndex();
final LineString line = edge.getLine();
final List<Edge<T>> crossings = queryCrosses(edgeIndex, line);
crossings.remove(edge);
for (final Edge<T> crossEdge : crossings) {
if (!crossEdge.isRemoved()) {
final LineString crossLine = crossEdge.getLine();
final Point intersection = LineStringUtil.getCrossingIntersection(line, crossLine);
if (intersection != null) {
final Point point = this.graph.getPrecisionModel().getPreciseCoordinates(intersection);
final Node<T> node = this.graph.getNode(point);
this.splitEdgesCloseToNodeVisitor.accept(node);
}
}
}
}
@Override
public void addNodeListener(final NodeEventListener<T> listener) {
this.splitEdgesCloseToNodeVisitor.addNodeListener(listener);
}
public Collection<Edge<T>> getNewEdges() {
return this.splitEdgesCloseToNodeVisitor.getNewEdges();
}
public Collection<T> getSplitObjects() {
return this.splitEdgesCloseToNodeVisitor.getSplitObjects();
}
public List<Edge<T>> queryCrosses(final IdObjectIndex<Edge<T>> edgeIndex, final LineString line) {
final Geometry preparedLine = line.prepare();
final BoundingBox envelope = line.getBoundingBox();
final List<Edge<T>> edges = edgeIndex.query(envelope);
// TODO change to use an visitor
for (final Iterator<Edge<T>> iterator = edges.iterator(); iterator.hasNext();) {
final Edge<T> edge = iterator.next();
final LineString matchLine = edge.getLine();
if (!preparedLine.crosses(matchLine)) {
iterator.remove();
}
}
return edges;
}
public void setNewEdges(final Collection<Edge<T>> newEdges) {
this.splitEdgesCloseToNodeVisitor.setNewEdges(newEdges);
}
public void setSplitObjects(final Collection<T> splitObjects) {
this.splitEdgesCloseToNodeVisitor.setSplitObjects(splitObjects);
}
}