/** * OSM2ShareNav * * * @version $Revision$ ($Name$) * * Copyright (C) 2007 Harald Mueller */ package net.sharenav.osmToShareNav.route; import java.awt.Dimension; import java.awt.Point; import java.awt.Shape; import java.awt.geom.Arc2D; import java.awt.geom.Area; import java.awt.geom.Path2D; import java.awt.geom.PathIterator; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import java.nio.charset.Charset; import java.util.LinkedList; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import javax.swing.JFrame; import org.openstreetmap.gui.jmapviewer.JMapViewer; import org.openstreetmap.gui.jmapviewer.MapMarkerDot; import org.openstreetmap.gui.jmapviewer.MemoryTileCache; import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker; import net.sharenav.osmToShareNav.MyMath; import net.sharenav.osmToShareNav.model.Node; /** * @author hmu * */ public class Route { // final public static transient double HALF_PI=Math.PI/2d; // final public static transient double FAC_RADTODEC = 180.0d/Math.PI; // final public static transient double FAC_DECTORAD = Math.PI / 180d; // final public static transient double PLANET_RADIUS = 6371000.8d; /** * The URL of the route calculation at open route service */ private static final String ORS_URL_CALC_ROUTE="http://www.openrouteservice.org/php/OpenLSRS_DetermineRoute.php"; private static final String ORS_URL_REV_SEARCH="http://www.openrouteservice.org/php/OpenLSLUS_Geocode.php"; /*Lon=8.65809499075895&Lat=49.48157911916741&MaxResponse=10&_=*/ private static final String ORS_URL_ADDR_SEARCH="http://www.openrouteservice.org/php/OpenLSLUS_Geocode.php"; /*FreeFormAdress=Schwarzenbruck, Brixener strasse&MaxResponse=25&_=*/ Pattern startPattern = Pattern.compile("<gml:LineString"); Pattern posPattern = Pattern.compile("<gml:pos>(-*[0-9.]+) (-*[0-9.]+)</gml:pos>"); Pattern countryPattern = Pattern.compile("<xls:Address countryCode=\"(.*)\">"); Pattern streetPattern = Pattern.compile("<xls:Street officialName=\"(.*)\"/>"); Pattern subDivPattern = Pattern.compile("<xls:Place type=\"CountrySubdivision\">(.*)</xls:Place>"); Pattern cityPattern = Pattern.compile("<xls:Place type=\"Municipality\">(.*)</xls:Place>"); Pattern zipPattern = Pattern.compile(" <xls:PostalCode>(.*)</xls:PostalCode>"); Vector<Node> routeResult = new Vector<Node>(); Vector<Location> routeList=new Vector<Location>(); private double corridorR=10000d; private JMapViewer map; /** * @param routeList */ public Route(Vector<Location> routeList,double corridorWidth, JMapViewer map) { this.routeList = routeList; this.corridorR = corridorWidth/2d; this.map=map; calculateRoute(); } // private Outline createOutline(){ // Outline o=new Outline(); // Node p1=routeResult.elementAt(0); // Node p2=routeResult.elementAt(1); // Node o1; // Node o2; // double dir[]=MyMath.calcDistanceAndCourse(p1, p2); // p1=MyMath.moveBearingDist(p1, dir[1]+180d, corridorR); // //// follow the path forward on the right side // for (int i=1;i<routeResult.size();i++){ // p1=p2; // p2=routeResult.elementAt(i); // System.out.println("process " + i + "("+routeResult.size()+") " + p1 + p2); // dir=MyMath.calcDistanceAndCourse(p1, p2); // o1=MyMath.moveBearingDist(p1, dir[1]+90d, corridorR); // o2=MyMath.moveBearingDist(p2, dir[1]+90d, corridorR); // o.append(new Vertex(o1, o)); // o.append(new Vertex(o2, o)); // for (int i1=1;i1<(o.vertexCount()-1);i1++){ // double dirO[]=MyMath.calcDistanceAndCourse(o.getNode(i1-1), o.getNode(i1)); // Node inter=MyMath.intersection(o.getNode(i1-1),dirO[1],o1,dir[1]); // System.out.println("intersection = " + inter); // } // } // return o; // } /** * */ public Route() { } public Area createArea() { Area a = null; // Outline o=new Outline() Node last = null; Node n1 = routeResult.elementAt(0); double firstDir = 0; for (int i = 1; i < routeResult.size(); i++) { Node n2 = routeResult.elementAt(i); double dir[] = MyMath.calcDistanceAndCourse(n1, n2); double delta = Math.abs((720+dir[1] - firstDir)%360); if (dir[0] > corridorR /*|| delta > 20 */ || i==routeResult.size()) { firstDir=dir[1]; // Node nb = MyMath.moveBearingDist(n1, dir[1] + 180d, corridorR); Node nb1 = MyMath.moveBearingDist(n1, dir[1] - 90d, corridorR); Node nb2 = MyMath.moveBearingDist(n1, dir[1] - 126d, corridorR); Node nb3 = MyMath.moveBearingDist(n1, dir[1] - 162d, corridorR); Node nb4 = MyMath.moveBearingDist(n1, dir[1] - 198d, corridorR); Node nb5 = MyMath.moveBearingDist(n1, dir[1] - 234d, corridorR); Node nb6 = MyMath.moveBearingDist(n1, dir[1] - 270d, corridorR); // Node nf = MyMath.moveBearingDist(n2, dir[1], corridorR); Node nf1 = MyMath.moveBearingDist(n2, dir[1] - 90d, corridorR); Node nf2 = MyMath.moveBearingDist(n2, dir[1] - 54d, corridorR); Node nf3 = MyMath.moveBearingDist(n2, dir[1] - 18d, corridorR); Node nf4 = MyMath.moveBearingDist(n2, dir[1] + 18d, corridorR); Node nf5 = MyMath.moveBearingDist(n2, dir[1] + 54d, corridorR); Node nf6 = MyMath.moveBearingDist(n2, dir[1] + 90d, corridorR); Path2D p = new Path2D.Double(); p.moveTo(nb1.lat, nb1.lon); p.lineTo(nb2.lat, nb2.lon); p.lineTo(nb3.lat, nb3.lon); p.lineTo(nb4.lat, nb4.lon); p.lineTo(nb5.lat, nb5.lon); p.lineTo(nb6.lat, nb6.lon); p.lineTo(nf1.lat, nf1.lon); p.lineTo(nf2.lat, nf2.lon); p.lineTo(nf3.lat, nf3.lon); p.lineTo(nf4.lat, nf4.lon); p.lineTo(nf5.lat, nf5.lon); p.lineTo(nf6.lat, nf6.lon); p.closePath(); if (a == null) { a = new Area(p); } else { a.add(new Area(p)); } n1 = n2; // if (i%100==0){ LinkedList<MapMarker> marker = new LinkedList<MapMarker>(); System.out.println("process " + i + "(" + routeResult.size() + ") "); PathIterator it = a.getPathIterator(null); double[] coords = new double[6]; int co = 0; while (!it.isDone()) { it.currentSegment(coords); marker.add(new MapMarkerDot(coords[0], coords[1])); it.next(); co++; } System.out.println("area lines " + co); map.setMapMarkerList(marker); map.setDisplayToFitMapMarkers(); map.repaint(); // } } else { System.out.println("skip node " + i + " because dist="+dir[0]+ " delta dir="+delta); } } return a; } private void calculateRoute() { routeResult = new Vector<Node>(); if (routeList != null && routeList.size() > 1) {; try { fetchRoute("Fastest",false); fetchRoute("Fastest",true); fetchRoute("Shortest",false); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private void fetchRoute(String routepref, boolean noMotorways) throws MalformedURLException, IOException, ProtocolException { StringBuffer post = new StringBuffer(); post.append(createPar("Start", routeList.firstElement().getNode())); post.append("&"); post.append(createPar("End", routeList.lastElement().getNode())); post.append("&"); post.append(createPar("Via", routeList)); post.append("&lang=en&distunit=KM&routepref="); post.append(routepref); post.append("&avoidAreas=&useTMC=false&noMotorways="); post.append(noMotorways); post.append("&noTollways=false&instructions=false&_="); BufferedReader in = openHttpResponse(ORS_URL_CALC_ROUTE,post.toString()); decodeRouteXML(in); in.close(); // map.repaint(); } private BufferedReader openHttpResponse(String urlString,String post) throws MalformedURLException, IOException, ProtocolException { URL url; url = new URL(urlString); // url = new URL(ORS_URL_CALC_ROUTE); HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); urlConn.setReadTimeout(240000); // 30 seconds read timeout urlConn.setDoOutput(true); urlConn.setRequestMethod("POST"); urlConn.setRequestProperty("User-agent", "OSM2ShareNav"); // urlConn.setRequestProperty("User-agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6"); urlConn.setRequestProperty("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"); urlConn.setRequestProperty("Pragma", "no-cache"); urlConn.setRequestProperty("Cache-Control", "no-cache"); urlConn.setRequestProperty("Accept-Encoding", "gzip,deflate"); String length=""+post.length(); System.out.println("Length = " + length); urlConn.setRequestProperty("Content-Length",length); OutputStreamWriter out = new OutputStreamWriter( urlConn.getOutputStream()); out.write(post); out.close(); // urlConn. if ("gzip".equals(urlConn.getContentEncoding())){ System.out.println(urlString); System.out.println(""+post.length()+":"+post); BufferedReader in = new BufferedReader(new InputStreamReader(new GZIPInputStream(urlConn.getInputStream()),Charset.forName("UTF-8"))); return in; } else { System.out.println("Resposonse is " + urlConn.getContentEncoding() ); } return null; } private void decodeRouteXML(BufferedReader in) throws IOException { String decodedString; boolean start = false; while ((decodedString = in.readLine()) != null) { System.out.print(decodedString); if (start) { Matcher m = posPattern.matcher(decodedString); if (m.find()) { double lon = Double.parseDouble(m.group(1)); double lat = Double.parseDouble(m.group(2)); Node c = new Node((float)lat, (float)lon,-1); System.out.println(" --> " + c); routeResult.add(c); // map.addMapMarker(new MapMarkerDot(Color.RED, lat, lon)); } else { System.out.println(" start but no match"); } } else if (startPattern.matcher(decodedString).find()) { start = true; System.out.println(" --> found start "); } else { System.out.println(" not jet started"); } // System.out.println(decodedString); } } public void revResolv(Location l){ StringBuffer post = new StringBuffer(); post.append(createPar("Lon", l.getNode().lon)); post.append("&"); post.append(createPar("Lat", l.getNode().lat)); post.append("&MaxResponse=10&_="); try { BufferedReader in = openHttpResponse(ORS_URL_REV_SEARCH,post.toString()); String s; decodeGml(in, l); in.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * @param string * @param firstElement * @return */ private String createPar(String string, Node c) { return string + "=" + c.lon + "," + c.lat; } /** * @param string * @param firstElement * @return */ private String createPar(String string,float v) { return string + "=" + v; } /** * @param string * @param firstElement * @return */ private Object createPar(String par,Vector<Location> li) { /* <xls:ViaPoint><xls:Position><gml:Point><gml:pos>11.2264324 49.3543942</gml:pos></gml:Point></xls:Position></xls:ViaPoint> <xls:ViaPoint><xls:Position><gml:Point><gml:pos>11.2320758 49.3839049</gml:pos></gml:Point></xls:Position></xls:ViaPoint> */ StringBuffer v=new StringBuffer(par); v.append("="); for (int i=1; i<(li.size()-1);i++){ Node c=li.get(i).getNode(); v.append("<xls:ViaPoint><xls:Position><gml:Point><gml:pos>"); v.append(c.lon + " " + c.lat); v.append("</gml:pos></gml:Point></xls:Position></xls:ViaPoint>"); } return v.toString(); } private void decodeGml(BufferedReader in,Location l) throws IOException{ String decodedString; while ((decodedString = in.readLine()) != null) { System.out.print(decodedString); Matcher m = countryPattern.matcher(decodedString); if (m.find()){ l.setCountry(m.group(1)); } m = cityPattern.matcher(decodedString); if (m.find()){ l.setCity(m.group(1)); } m = zipPattern.matcher(decodedString); if (m.find()){ l.setZip(m.group(1)); } m = streetPattern.matcher(decodedString); if (m.find()){ l.setStreet(m.group(1)); } } } public static void main(String[] args) { Route r=new Route(null, 100000,null); try { BufferedReader in = new BufferedReader(new FileReader("route.xml")); r.decodeRouteXML(in); in.close(); r.map = new JMapViewer(new MemoryTileCache(), 4); r.map.setSize(1000, 800); JFrame f=new JFrame(); f.setMinimumSize(new Dimension(1200, 1000)); // f.setSize(1000, 800); f.add(r.map); f.pack(); f.setVisible(true); for (int i=0;i<r.routeResult.size();i++){ Node node = r.routeResult.get(i); r.map.addMapMarker(new MapMarkerDot(node.lat, node.lon)); } r.map.setDisplayToFitMapMarkers(); r.map.repaint(); r.createArea(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }