456 lines
15 KiB
Java
456 lines
15 KiB
Java
package net.osmand.swing;
|
|
|
|
import java.awt.Color;
|
|
import java.awt.Graphics;
|
|
import java.awt.Point;
|
|
import java.awt.event.ActionEvent;
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.io.RandomAccessFile;
|
|
import java.io.StringReader;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.net.URL;
|
|
import java.net.URLConnection;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import javax.swing.AbstractAction;
|
|
import javax.swing.Action;
|
|
import javax.swing.JOptionPane;
|
|
import javax.swing.JPopupMenu;
|
|
import javax.swing.SwingUtilities;
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
|
|
import net.osmand.binary.BinaryMapDataObject;
|
|
import net.osmand.binary.BinaryMapIndexReader;
|
|
import net.osmand.binary.BinaryRouteDataReader;
|
|
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
|
|
import net.osmand.binary.BinaryRouteDataReader.RouteSegment;
|
|
import net.osmand.binary.BinaryRouteDataReader.RouteSegmentResult;
|
|
import net.osmand.binary.BinaryRouteDataReader.RouteSegmentVisitor;
|
|
import net.osmand.binary.BinaryRouteDataReader.RoutingContext;
|
|
import net.osmand.data.DataTileManager;
|
|
import net.osmand.osm.LatLon;
|
|
import net.osmand.osm.MapUtils;
|
|
import net.osmand.osm.Way;
|
|
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.Node;
|
|
import org.w3c.dom.NodeList;
|
|
import org.xml.sax.InputSource;
|
|
import org.xml.sax.SAXException;
|
|
|
|
|
|
public class MapRouterLayer implements MapPanelLayer {
|
|
|
|
private MapPanel map;
|
|
private LatLon startRoute;
|
|
private LatLon endRoute;
|
|
@Override
|
|
public void destroyLayer() {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void initLayer(MapPanel map) {
|
|
this.map = map;
|
|
fillPopupMenuWithActions(map.getPopupMenu());
|
|
}
|
|
|
|
public void fillPopupMenuWithActions(JPopupMenu menu) {
|
|
Action start = new AbstractAction("Mark start point") {
|
|
private static final long serialVersionUID = 507156107455281238L;
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Point popupMenuPoint = map.getPopupMenuPoint();
|
|
double fy = (popupMenuPoint.y - map.getCenterPointY()) / map.getTileSize();
|
|
double fx = (popupMenuPoint.x - map.getCenterPointX()) / map.getTileSize();
|
|
double latitude = MapUtils.getLatitudeFromTile(map.getZoom(), map.getYTile() + fy);
|
|
double longitude = MapUtils.getLongitudeFromTile(map.getZoom(), map.getXTile() + fx);
|
|
startRoute = new LatLon(latitude, longitude);
|
|
map.repaint();
|
|
}
|
|
};
|
|
menu.add(start);
|
|
Action end= new AbstractAction("Mark end point") {
|
|
private static final long serialVersionUID = 4446789424902471319L;
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
Point popupMenuPoint = map.getPopupMenuPoint();
|
|
double fy = (popupMenuPoint.y - map.getCenterPointY()) / map.getTileSize();
|
|
double fx = (popupMenuPoint.x - map.getCenterPointX()) / map.getTileSize();
|
|
double latitude = MapUtils.getLatitudeFromTile(map.getZoom(), map.getYTile() + fy);
|
|
double longitude = MapUtils.getLongitudeFromTile(map.getZoom(), map.getXTile() + fx);
|
|
endRoute = new LatLon(latitude, longitude);
|
|
map.repaint();
|
|
}
|
|
};
|
|
menu.add(end);
|
|
Action route = new AbstractAction("Calculate YOURS route") {
|
|
private static final long serialVersionUID = 507156107455281238L;
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
new Thread(){
|
|
@Override
|
|
public void run() {
|
|
List<Way> ways = route(startRoute, endRoute);
|
|
DataTileManager<Way> points = new DataTileManager<Way>();
|
|
points.setZoom(11);
|
|
for(Way w : ways){
|
|
LatLon n = w.getLatLon();
|
|
points.registerObject(n.getLatitude(), n.getLongitude(), w);
|
|
}
|
|
map.setPoints(points);
|
|
}
|
|
}.start();
|
|
}
|
|
};
|
|
menu.add(route);
|
|
Action altroute = new AbstractAction("Calculate CloudMade route") {
|
|
private static final long serialVersionUID = 507156107455281238L;
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
new Thread() {
|
|
@Override
|
|
public void run() {
|
|
List<Way> ways = alternateRoute(startRoute, endRoute);
|
|
DataTileManager<Way> points = new DataTileManager<Way>();
|
|
points.setZoom(11);
|
|
for (Way w : ways) {
|
|
LatLon n = w.getLatLon();
|
|
points.registerObject(n.getLatitude(), n.getLongitude(), w);
|
|
}
|
|
map.setPoints(points);
|
|
}
|
|
}.start();
|
|
}
|
|
};
|
|
menu.add(altroute);
|
|
Action selfRoute = new AbstractAction("Calculate OsmAnd route") {
|
|
private static final long serialVersionUID = 507156107455281238L;
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
new Thread() {
|
|
@Override
|
|
public void run() {
|
|
List<Way> ways = selfRoute(startRoute, endRoute);
|
|
if (ways != null) {
|
|
DataTileManager<Way> points = new DataTileManager<Way>();
|
|
points.setZoom(11);
|
|
for (Way w : ways) {
|
|
LatLon n = w.getLatLon();
|
|
points.registerObject(n.getLatitude(), n.getLongitude(), w);
|
|
}
|
|
map.setPoints(points);
|
|
}
|
|
}
|
|
}.start();
|
|
}
|
|
};
|
|
|
|
menu.add(selfRoute);
|
|
|
|
}
|
|
|
|
|
|
// for vector rendering we should extract from osm
|
|
// 1. Ways (different kinds) with tag highway= ?,highway=stop ...
|
|
// 2. Junction = roundabout
|
|
// 3. barrier, traffic_calming=bump
|
|
// 4. Save {name, ref} of way to unify it
|
|
|
|
// + for future routing we should extract from osm
|
|
// 1. oneway
|
|
// 2. max_speed
|
|
// 3. toll
|
|
// 4. traffic_signals
|
|
// 5. max_heigtht, max_width, min_speed, ...
|
|
// 6. incline ?
|
|
|
|
public static List<Way> route(LatLon start, LatLon end){
|
|
List<Way> res = new ArrayList<Way>();
|
|
long time = System.currentTimeMillis();
|
|
System.out.println("Route from " + start + " to " + end);
|
|
if (start != null && end != null) {
|
|
try {
|
|
StringBuilder uri = new StringBuilder();
|
|
uri.append("http://www.yournavigation.org/api/1.0/gosmore.php?format=kml");
|
|
uri.append("&flat=").append(start.getLatitude());
|
|
uri.append("&flon=").append(start.getLongitude());
|
|
uri.append("&tlat=").append(end.getLatitude());
|
|
uri.append("&tlon=").append(end.getLongitude());
|
|
uri.append("&v=motorcar").append("&fast=1").append("&layer=mapnik");
|
|
|
|
URL url = new URL(uri.toString());
|
|
URLConnection connection = url.openConnection();
|
|
StringBuilder content = new StringBuilder();
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
{
|
|
String s = null;
|
|
boolean fist = true;
|
|
while ((s = reader.readLine()) != null) {
|
|
if (fist) {
|
|
fist = false;
|
|
}
|
|
content.append(s).append("\n");
|
|
}
|
|
System.out.println(content);
|
|
}
|
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
|
DocumentBuilder dom = factory.newDocumentBuilder();
|
|
Document doc = dom.parse(new InputSource(new StringReader(content.toString())));
|
|
NodeList list = doc.getElementsByTagName("coordinates");
|
|
for(int i=0; i<list.getLength(); i++){
|
|
Node item = list.item(i);
|
|
String str = item.getTextContent();
|
|
int st = 0;
|
|
int next = 0;
|
|
Way w = new Way(-1);
|
|
while((next = str.indexOf('\n', st)) != -1){
|
|
String coordinate = str.substring(st, next + 1);
|
|
int s = coordinate.indexOf(',');
|
|
if (s != -1) {
|
|
try {
|
|
double lon = Double.parseDouble(coordinate.substring(0, s));
|
|
double lat = Double.parseDouble(coordinate.substring(s + 1));
|
|
w.addNode(new net.osmand.osm.Node(lat, lon, -1));
|
|
} catch (NumberFormatException e) {
|
|
}
|
|
}
|
|
st = next + 1;
|
|
}
|
|
if(!w.getNodes().isEmpty()){
|
|
res.add(w);
|
|
}
|
|
|
|
}
|
|
} catch (IOException e) {
|
|
ExceptionHandler.handle(e);
|
|
} catch (ParserConfigurationException e) {
|
|
ExceptionHandler.handle(e);
|
|
} catch (SAXException e) {
|
|
ExceptionHandler.handle(e);
|
|
}
|
|
System.out.println("Finding routes " + res.size() + " " + (System.currentTimeMillis() - time) + " ms");
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<Way> alternateRoute(LatLon start, LatLon end) {
|
|
List<Way> res = new ArrayList<Way>();
|
|
long time = System.currentTimeMillis();
|
|
System.out.println("Cloud made route from " + start + " to " + end);
|
|
if (start != null && end != null) {
|
|
try {
|
|
StringBuilder uri = new StringBuilder();
|
|
// possibly hide that API key because it is privacy of osmand
|
|
uri.append("http://routes.cloudmade.com/A6421860EBB04234AB5EF2D049F2CD8F/api/0.3/");
|
|
|
|
uri.append(start.getLatitude()+"").append(",");
|
|
uri.append(start.getLongitude()+"").append(",");
|
|
uri.append(end.getLatitude()+"").append(",");
|
|
uri.append(end.getLongitude()+"").append("/");
|
|
uri.append("car.gpx").append("?lang=ru");
|
|
|
|
URL url = new URL(uri.toString());
|
|
URLConnection connection = url.openConnection();
|
|
StringBuilder content = new StringBuilder();
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
{
|
|
String s = null;
|
|
boolean fist = true;
|
|
while ((s = reader.readLine()) != null) {
|
|
if (fist) {
|
|
fist = false;
|
|
}
|
|
content.append(s).append("\n");
|
|
}
|
|
System.out.println(content);
|
|
}
|
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
|
DocumentBuilder dom = factory.newDocumentBuilder();
|
|
Document doc = dom.parse(new InputSource(new StringReader(content.toString())));
|
|
NodeList list = doc.getElementsByTagName("wpt");
|
|
Way w = new Way(-1);
|
|
for (int i = 0; i < list.getLength(); i++) {
|
|
Element item = (Element) list.item(i);
|
|
try {
|
|
double lon = Double.parseDouble(item.getAttribute("lon"));
|
|
double lat = Double.parseDouble(item.getAttribute("lat"));
|
|
w.addNode(new net.osmand.osm.Node(lat, lon, -1));
|
|
} catch (NumberFormatException e) {
|
|
}
|
|
}
|
|
list = doc.getElementsByTagName("rtept");
|
|
for (int i = 0; i < list.getLength(); i++) {
|
|
Element item = (Element) list.item(i);
|
|
try {
|
|
double lon = Double.parseDouble(item.getAttribute("lon"));
|
|
double lat = Double.parseDouble(item.getAttribute("lat"));
|
|
System.out.println("Lat " + lat + " lon " + lon);
|
|
System.out.println("Distance : " + item.getElementsByTagName("distance").item(0).getTextContent());
|
|
System.out.println("Time : " + item.getElementsByTagName("time").item(0).getTextContent());
|
|
System.out.println("Offset : " + item.getElementsByTagName("offset").item(0).getTextContent());
|
|
System.out.println("Direction : " + item.getElementsByTagName("direction").item(0).getTextContent());
|
|
} catch (NumberFormatException e) {
|
|
}
|
|
}
|
|
|
|
if (!w.getNodes().isEmpty()) {
|
|
res.add(w);
|
|
}
|
|
} catch (IOException e) {
|
|
ExceptionHandler.handle(e);
|
|
} catch (ParserConfigurationException e) {
|
|
ExceptionHandler.handle(e);
|
|
} catch (SAXException e) {
|
|
ExceptionHandler.handle(e);
|
|
}
|
|
System.out.println("Finding cloudmade routes " + res.size() + " " + (System.currentTimeMillis() - time) + " ms");
|
|
}
|
|
return res;
|
|
}
|
|
|
|
public List<Way> selfRoute(LatLon start, LatLon end) {
|
|
List<Way> res = new ArrayList<Way>();
|
|
long time = System.currentTimeMillis();
|
|
File[] files = DataExtractionSettings.getSettings().getDefaultRoutingFile();
|
|
if(files == null){
|
|
JOptionPane.showMessageDialog(OsmExtractionUI.MAIN_APP.getFrame(), "Please specify obf file in settings", "Obf file not found",
|
|
JOptionPane.ERROR_MESSAGE);
|
|
return null;
|
|
}
|
|
System.out.println("Self made route from " + start + " to " + end);
|
|
if (start != null && end != null) {
|
|
try {
|
|
BinaryMapIndexReader[] rs = new BinaryMapIndexReader[files.length];
|
|
for(int i=0; i<files.length; i++){
|
|
RandomAccessFile raf = new RandomAccessFile(files[i], "r"); //$NON-NLS-1$ //$NON-NLS-2$
|
|
rs[i] = new BinaryMapIndexReader(raf);
|
|
|
|
}
|
|
|
|
BinaryRouteDataReader router = new BinaryRouteDataReader(rs);
|
|
RoutingContext ctx = new RoutingContext();
|
|
|
|
// find closest way
|
|
RouteSegment st = router.findRouteSegment(start.getLatitude(), start.getLongitude(), ctx);
|
|
if (st != null) {
|
|
BinaryMapDataObject road = st.getRoad();
|
|
TagValuePair pair = road.getTagValue(0);
|
|
System.out.println("ROAD TO START " + pair.tag + " " + pair.value + " " + road.getName() + " "
|
|
+ (road.getId() >> 3));
|
|
}
|
|
|
|
RouteSegment e = router.findRouteSegment(end.getLatitude(), end.getLongitude(), ctx);
|
|
if ( e != null) {
|
|
BinaryMapDataObject road = e.getRoad();
|
|
TagValuePair pair = road.getTagValue(0);
|
|
System.out.println("ROAD TO END " + pair.tag + " " + pair.value + " " + road.getName()+ " " +
|
|
+ (road.getId() >> 3));
|
|
}
|
|
|
|
final DataTileManager<Way> points = new DataTileManager<Way>();
|
|
points.setZoom(11);
|
|
map.setPoints(points);
|
|
ctx.visitor = new RouteSegmentVisitor() {
|
|
private final static int F_SIZE = 10;
|
|
private List<RouteSegment> cache = new ArrayList<RouteSegment>();
|
|
|
|
@Override
|
|
public void visitSegment(RouteSegment s) {
|
|
cache.add(s);
|
|
if(cache.size() < F_SIZE){
|
|
return;
|
|
}
|
|
for (RouteSegment segment : cache) {
|
|
Way way = new Way(-1);
|
|
for (int i = 0; i < segment.getRoad().getPointsLength(); i++) {
|
|
net.osmand.osm.Node n = new net.osmand.osm.Node(MapUtils.get31LatitudeY(segment.getRoad()
|
|
.getPoint31YTile(i)), MapUtils.get31LongitudeX(segment.getRoad().getPoint31XTile(i)), -1);
|
|
way.addNode(n);
|
|
}
|
|
LatLon n = way.getLatLon();
|
|
points.registerObject(n.getLatitude(), n.getLongitude(), way);
|
|
}
|
|
cache.clear();
|
|
try {
|
|
SwingUtilities.invokeAndWait(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
map.prepareImage();
|
|
}
|
|
});
|
|
} catch (InterruptedException e1) {
|
|
} catch (InvocationTargetException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
};
|
|
List<RouteSegmentResult> searchRoute = router.searchRoute(ctx, st, e);
|
|
try {
|
|
Thread.sleep(4000);
|
|
} catch (InterruptedException e1) {
|
|
}
|
|
|
|
for(RouteSegmentResult s : searchRoute){
|
|
// double dist = MapUtils.getDistance(s.startPoint, s.endPoint);
|
|
Way way = new Way(-1);
|
|
boolean plus = s.startPointIndex < s.endPointIndex;
|
|
int i=s.startPointIndex;
|
|
while (true) {
|
|
net.osmand.osm.Node n = new net.osmand.osm.Node(MapUtils.get31LatitudeY(s.object.getPoint31YTile(i)), MapUtils
|
|
.get31LongitudeX(s.object.getPoint31XTile(i)), -1);
|
|
way.addNode(n);
|
|
if (i == s.endPointIndex) {
|
|
break;
|
|
}
|
|
if (plus) {
|
|
i++;
|
|
} else {
|
|
i--;
|
|
}
|
|
}
|
|
res.add(way);
|
|
}
|
|
} catch (IOException e) {
|
|
ExceptionHandler.handle(e);
|
|
}
|
|
System.out.println("Finding self routes " + res.size() + " " + (System.currentTimeMillis() - time) + " ms");
|
|
}
|
|
return res;
|
|
}
|
|
|
|
@Override
|
|
public void prepareToDraw() {
|
|
}
|
|
|
|
|
|
@Override
|
|
public void paintLayer(Graphics g) {
|
|
g.setColor(Color.green);
|
|
if(startRoute != null){
|
|
int x = map.getMapXForPoint(startRoute.getLongitude());
|
|
int y = map.getMapYForPoint(startRoute.getLatitude());
|
|
g.drawOval(x, y, 12, 12);
|
|
g.fillOval(x, y, 12, 12);
|
|
}
|
|
g.setColor(Color.red);
|
|
if(endRoute != null){
|
|
int x = map.getMapXForPoint(endRoute.getLongitude());
|
|
int y = map.getMapYForPoint(endRoute.getLatitude());
|
|
g.drawOval(x, y, 12, 12);
|
|
g.fillOval(x, y, 12, 12);
|
|
}
|
|
}
|
|
|
|
}
|