package de.fub.agg2graph.structs.frechet;
import java.util.ArrayList;
import de.fub.agg2graph.agg.AggConnection;
import de.fub.agg2graph.structs.GPSEdge;
/**
* In both directions extendible frechet distance decision algorithm. One
* can append and prepend edges to the curves.
* At the Moment reverseFd is deactivated
*
*/
public class BidirectionalFrechetDistance {
public FrechetDistance fd;
public FrechetDistance reverseFd;
public void setEpsilon(double epsilon) {
fd.setEpsilon(epsilon);
reverseFd.setEpsilon(epsilon);
}
public BidirectionalFrechetDistance(double maxDistance) {
fd = new FrechetDistance(maxDistance);
fd.P = new ArrayList<>();//P
fd.Q = new ArrayList<>();//Q
reverseFd = new FrechetDistance(maxDistance);
reverseFd.P = new ArrayList<>();
reverseFd.Q = new ArrayList<>();
}
public void appendToP(AggConnection conn) {
fd.P.add(conn);
// fd.P.add(edge);
if(reverseFd.P.isEmpty()) {
prependToP(conn);
}
fd.resizeCells();
fd.updateFreeSpace();
}
//
public void removeLastOfP() {
assert(!fd.P.isEmpty());
fd.P.remove(fd.P.size() - 1);
// remove the overlapped cells.
if(fd.P.isEmpty() && reverseFd.P.size() <= 2) {
reverseFd.P.remove(0);
}
fd.resizeCells();
fd.updateFreeSpace();
}
//
public void prependToP(AggConnection conn) {
reverseFd.P.add(reversed(conn));
if(fd.P.isEmpty()) {
appendToP(conn);
}
reverseFd.resizeCells();
reverseFd.updateFreeSpace();
}
//
public void removeFirstOfP() {
assert(!reverseFd.P.isEmpty());
reverseFd.P.remove(reverseFd.P.size() - 1);
if(reverseFd.P.isEmpty() && fd.P.size() <= 2) {
fd.P.remove(0);
}
reverseFd.resizeCells();
reverseFd.updateFreeSpace();
}
//
public void appendToQ(GPSEdge edge) {
fd.Q.add(edge);
if(reverseFd.Q.isEmpty()) {
prependToQ(edge);
}
fd.resizeCells();
fd.updateFreeSpace();
}
//
public void removeLastOfQ() {
assert(!fd.Q.isEmpty());
fd.Q.remove(fd.Q.size() - 1);
if(fd.Q.isEmpty() && reverseFd.Q.size() <= 2) {
reverseFd.Q.remove(0);
}
fd.resizeCells();
fd.updateFreeSpace();
}
//
public void prependToQ(GPSEdge edge) {
reverseFd.Q.add(reversed(edge));
if(fd.Q.isEmpty()) {
appendToQ(edge);
}
reverseFd.resizeCells();
reverseFd.updateFreeSpace();
}
//
public void removeFirstOfQ() {
assert(!reverseFd.Q.isEmpty());
reverseFd.Q.remove(reverseFd.Q.size() - 1);
if(reverseFd.Q.isEmpty() && fd.Q.size() <= 2) {
fd.Q.remove(0);
}
reverseFd.resizeCells();
reverseFd.updateFreeSpace();
}
//
public boolean isInDistance() {
// return fd.isInDistance();
return fd.isInDistance() && reverseFd.isInDistance();
}
//
public double approximateDistance() {
// if(fd.P.size() < 1 || fd.Q.size() < 1)
if(fd.P.size() < 1 || fd.Q.size() < 1 || reverseFd.P.size() < 1 || reverseFd.Q.size() < 1)
return Double.POSITIVE_INFINITY;
double e1 = fd.computeEpsilon();
double e2 = reverseFd.computeEpsilon();
// return Math.max(e1, e2); TODO: Original
return Math.min(e1, e2);
}
//
private AggConnection reversed(AggConnection conn) {
return new AggConnection(conn.getTo(), conn.getFrom(), conn.getDistance());
}
//
private GPSEdge reversed(GPSEdge edge) {
return new GPSEdge(edge.getTo(), edge.getFrom(), edge.getDistance());
}
}