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.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.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import net.osmand.ExceptionHandler; 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.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) { 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); } }; menu.add(route); Action altroute = new AbstractAction("Calculate CloudMade route") { private static final long serialVersionUID = 507156107455281238L; public void actionPerformed(ActionEvent e) { 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); } }; menu.add(altroute); Action selfRoute = new AbstractAction("Calculate OsmAnd route") { private static final long serialVersionUID = 507156107455281238L; public void actionPerformed(ActionEvent e) { 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); } } }; 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)); } for(RouteSegmentResult s : router.searchRoute(ctx, st, e)){ // 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); } } }