package com.revolsys.geometry.algorithm.linematch;
import java.util.function.Predicate;
import com.revolsys.geometry.graph.Edge;
import com.revolsys.geometry.graph.Node;
import com.revolsys.geometry.model.BoundingBox;
public class LineMatchEdgeFilter implements Predicate<Edge<LineSegmentMatch>> {
public static double getDistance(final Edge<LineSegmentMatch> edge,
final Node<LineSegmentMatch> node, final double tolerance) {
final double distance = edge.distancePoint(node);
if (distance == 0) {
return 0;
} else if (distance < tolerance) {
if (distance == node.distancePoint(edge.getFromNode())) {
return Double.MAX_VALUE;
} else if (distance == node.distancePoint(edge.getToNode())) {
return Double.MAX_VALUE;
} else {
return distance;
}
}
return distance;
}
public static boolean isEitherOppositeNodesWithinDistance(final Edge<LineSegmentMatch> edge1,
final Edge<LineSegmentMatch> edge2, final Node<LineSegmentMatch> fromNode2,
final double tolerance) {
if (isOppositeNodeWithinDistance(edge1, edge2, fromNode2, tolerance)) {
return true;
} else if (isOppositeNodeWithinDistance(edge2, edge1, fromNode2, tolerance)) {
return true;
} else {
return false;
}
}
public static boolean isOppositeNodeWithinDistance(final Edge<LineSegmentMatch> edge1,
final Edge<LineSegmentMatch> edge2, final Node<LineSegmentMatch> node, final double tolerance) {
final Node<LineSegmentMatch> oppositeNode = edge1.getOppositeNode(node);
final double oppositeNodeEdge2Distance = edge2.distancePoint(oppositeNode);
if (oppositeNodeEdge2Distance < tolerance) {
if (oppositeNodeEdge2Distance == edge1.getLength()) {
return false;
} else {
return true;
}
} else {
return false;
}
}
private final Edge<LineSegmentMatch> edge;
private final LineSegmentMatch edgeMatch;
private BoundingBox envelope;
private final Node<LineSegmentMatch> fromNode;
private final int index;
private final double tolerance;
private final Node<LineSegmentMatch> toNode;
public LineMatchEdgeFilter(final Edge<LineSegmentMatch> edge, final int index,
final double tolerance) {
this.edge = edge;
this.index = index;
this.tolerance = tolerance;
this.envelope = edge.getBoundingBox();
this.envelope = this.envelope.expand(tolerance);
this.edgeMatch = edge.getObject();
this.fromNode = edge.getFromNode();
this.toNode = edge.getToNode();
}
private boolean checkTolerance(final double from1Distance, final double to1Distance,
final double from2Distance, final double to2Distance) {
if (from1Distance < this.tolerance) {
if (to1Distance < this.tolerance || from2Distance < this.tolerance
|| to2Distance < this.tolerance) {
return true;
} else {
return false;
}
} else {
return false;
}
}
public com.revolsys.geometry.model.BoundingBox getEnvelope() {
return this.envelope;
}
@Override
public boolean test(final Edge<LineSegmentMatch> edge2) {
if (edge2.getBoundingBox().intersects(this.envelope)) {
final LineSegmentMatch edgeMatch2 = edge2.getObject();
if (!edgeMatch2.hasSegment(this.index)) {
final Node<LineSegmentMatch> fromNode2 = edge2.getFromNode();
final Node<LineSegmentMatch> toNode2 = edge2.getToNode();
if (this.edge.hasNode(fromNode2)) {
return isEitherOppositeNodesWithinDistance(this.edge, edge2, fromNode2, this.tolerance);
} else if (this.edge.hasNode(toNode2)) {
return isEitherOppositeNodesWithinDistance(this.edge, edge2, toNode2, this.tolerance);
} else if (this.edge.distance(edge2) < this.tolerance) {
final double edge2FromNodeDistance = getDistance(edge2, this.fromNode, this.tolerance);
final double edge2ToNodeDistance = getDistance(edge2, this.toNode, this.tolerance);
final double edgeFromNode2Distance = getDistance(this.edge, fromNode2, this.tolerance);
final double edgeToNode2Distance = getDistance(this.edge, toNode2, this.tolerance);
if (checkTolerance(edge2FromNodeDistance, edge2ToNodeDistance, edgeFromNode2Distance,
edgeToNode2Distance)) {
return true;
} else if (checkTolerance(edge2ToNodeDistance, edge2FromNodeDistance,
edgeFromNode2Distance, edgeToNode2Distance)) {
return true;
} else if (checkTolerance(edgeFromNode2Distance, edgeToNode2Distance,
edge2FromNodeDistance, edge2ToNodeDistance)) {
return true;
} else if (checkTolerance(edgeToNode2Distance, edgeFromNode2Distance,
edge2FromNodeDistance, edge2ToNodeDistance)) {
return true;
} else {
return false;
}
}
}
}
return false;
}
}