package com.interview.flag.g;
import com.interview.basics.model.geometry.Line;
import com.interview.basics.model.graph.searcher.IndexedPriorityQueue;
import com.interview.utils.GeoUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Created_By: stefanie
* Date: 15-1-6
* Time: 下午3:20
*/
public class G8_ShortestDistanceWithWalls {
//Dijsktra
public float distance(float[] S, float[] T, List<Line> walls){
IndexedPriorityQueue<String, Float> heap = new IndexedPriorityQueue();
HashMap<String, Float> paths = new HashMap();
heap.add(getKey(S), 0.0f);
paths.put(getKey(S), 0.0f);
while(!heap.isEmpty()){
String point = heap.poll();
float[] coordinates = getCoordinates(point);
if(coordinates[0] == T[0] && coordinates[1] == T[1]) return paths.get(point);
Line intersectedWall = nearestIntersectedWalls(coordinates, T, walls);
float[][] next = null;
if(intersectedWall != null) next = intersectedWall.endpoints();
else next = new float[][]{T};
for(int i = 0; i < next.length; i++){
String candidate = getKey(next[i]);
float distance = paths.get(point) + GeoUtil.distance(coordinates, next[i]); //this distance should also consider convex hull to relax.
if(heap.contains(candidate)){
if(paths.get(candidate) > distance) {
heap.update(candidate, distance);
paths.put(candidate, distance);
}
} else {
heap.add(candidate, distance);
paths.put(candidate, distance);
}
}
}
return Float.MAX_VALUE;
}
public Line nearestIntersectedWalls(float[] S, float[] T, List<Line> walls){
Line st = new Line(S, T);
Line nearestWall = null;
float[] intersection = null;
for(int i = 0; i < walls.size(); i++){
float[] point = st.intersection(walls.get(i));
if(point != null && (point[0] != S[0] && point[1] != S[1])){
if(intersection == null || GeoUtil.distance(S, point) < GeoUtil.distance(S, intersection)){
intersection = point;
nearestWall = walls.get(i);
}
}
}
return nearestWall;
}
private float[] getCoordinates(String key){
float[] points = new float[2];
String[] splits = key.split("-");
for(int i = 0; i < splits.length; i++) points[i] = Float.parseFloat(splits[i]);
return points;
}
private String getKey(float[] points){
return points[0] + "-" + points[1];
}
public static void main(String[] args){
G8_ShortestDistanceWithWalls finder = new G8_ShortestDistanceWithWalls();
float[] S = new float[]{0,0};
float[] T = new float[]{10,10};
List<Line> walls = new ArrayList();
walls.add(new Line(new float[]{3,1}, new float[]{3,4}));
System.out.println(finder.distance(S, T, walls)); //14.219544
walls.add(new Line(new float[]{2,8}, new float[]{6,5}));
System.out.println(finder.distance(S, T, walls)); //14.564032
}
}