package btools.routingapp; import android.graphics.Point; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import btools.router.OsmNodeNamed; import btools.router.OsmNogoPolygon; /** * Read coordinates from a gpx-file */ public class CoordinateReader { protected static String[] posnames = new String[]{"from", "via1", "via2", "via3", "via4", "via5", "via6", "via7", "via8", "via9", "to"}; private final String internalDir; public List waypoints; public List nogopoints; public String basedir; public String rootdir; public String tracksdir; public List allpoints; private boolean nogosOnly; private Map> allpointsMap; private HashMap pointmap; public CoordinateReader(String basedir) { this.basedir = basedir; internalDir = basedir + "/brouter/import"; tracksdir = "/brouter/import/tracks"; rootdir = "/brouter/import"; } public static CoordinateReader obtainValidReader(String basedir) throws IOException { return obtainValidReader(basedir, false); } public static CoordinateReader obtainValidReader(String basedir, boolean nogosOnly) throws IOException { CoordinateReader cor = new CoordinateReader(basedir); cor.nogosOnly = nogosOnly; cor.readFromTo(); return cor; } public int getTurnInstructionMode() { return 4; // comment style } /* * read the from and to position from a gpx-file * (with hardcoded name for now) */ public void readPointmap() throws IOException { if (!_readPointmap(internalDir + "/favourites_bak.gpx")) { _readPointmap(internalDir + "/favourites.gpx"); } _readNogoLines(basedir + tracksdir); } private boolean _readPointmap(String filename) throws IOException { BufferedReader br; try { br = new BufferedReader( new InputStreamReader( new FileInputStream(filename))); } catch (FileNotFoundException e) { // ignore until it's reading error return false; } OsmNodeNamed n = null; for (; ; ) { String line = br.readLine(); if (line == null) break; int idx0 = line.indexOf(" lat=\""); int idx10 = line.indexOf(""); if (idx0 >= 0) { n = new OsmNodeNamed(); idx0 += 6; int idx1 = line.indexOf('"', idx0); n.ilat = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 90.) * 1000000. + 0.5); int idx2 = line.indexOf(" lon=\""); if (idx2 < 0) continue; idx2 += 6; int idx3 = line.indexOf('"', idx2); n.ilon = (int) ((Double.parseDouble(line.substring(idx2, idx3)) + 180.) * 1000000. + 0.5); if (idx3 < 0) continue; } if (n != null && idx10 >= 0) { idx10 += 6; int idx11 = line.indexOf("", idx10); if (idx11 >= 0) { n.name = line.substring(idx10, idx11).trim(); checkAddPoint("(one-for-all)", n); } } } br.close(); return true; } private void _readNogoLines(String dirname) { File dir = new File(dirname); if (dir.exists() && dir.isDirectory()) { for (final File file : dir.listFiles()) { final String name = file.getName(); if (name.startsWith("nogo") && name.endsWith(".gpx")) { try { _readNogoLine(file); } catch (Exception ignored) { } } } } } private void _readNogoLine(File file) throws Exception { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(false); XmlPullParser xpp = factory.newPullParser(); xpp.setInput(new FileReader(file)); List tmpPts = new ArrayList<>(); int eventType = xpp.getEventType(); int numSeg = 0; boolean bIsNogoPoint = false; String sNogoName = null; while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_TAG: { if (xpp.getName().equals("trkpt") || xpp.getName().equals("rtept") || xpp.getName().equals("wpt")) { final String lon = xpp.getAttributeValue(null, "lon"); final String lat = xpp.getAttributeValue(null, "lat"); if (lon != null && lat != null) { tmpPts.add(new Point( (int) ((Double.parseDouble(lon) + 180.) * 1000000. + 0.5), (int) ((Double.parseDouble(lat) + 90.) * 1000000. + 0.5))); if (xpp.getName().equals("wpt")) bIsNogoPoint = true; } } else if (bIsNogoPoint && xpp.getName().equals("name")) { sNogoName = xpp.nextText(); } break; } case XmlPullParser.END_TAG: { if (xpp.getName().equals("trkseg") || xpp.getName().equals("rte")) { // rte has no segment OsmNogoPolygon nogo; if (tmpPts.size() > 0) { if (tmpPts.get(0).x == tmpPts.get(tmpPts.size() - 1).x && tmpPts.get(0).y == tmpPts.get(tmpPts.size() - 1).y) { nogo = new OsmNogoPolygon(true); } else { nogo = new OsmNogoPolygon(false); } for (Point p : tmpPts) { nogo.addVertex(p.x, p.y); } nogo.calcBoundingCircle(); final String name = file.getName(); nogo.name = name.substring(0, name.length() - 4); if (numSeg > 0) { nogo.name += Integer.toString(numSeg + 1); } numSeg++; checkAddPoint("(one-for-all)", nogo); } tmpPts.clear(); } else if (xpp.getName().equals("wpt")) { Point p = tmpPts.get(tmpPts.size() - 1); if (p != null) { OsmNodeNamed nogo = new OsmNodeNamed(); nogo.ilon = p.x; nogo.ilat = p.y; nogo.name = (sNogoName != null ? sNogoName : "nogo1000 x"); nogo.isNogo = true; nogo.radius = 20; try { nogo.radius = (sNogoName != null ? Integer.parseInt(sNogoName.substring(4, sNogoName.indexOf(" "))) : 20); } catch (Exception e) { try { nogo.radius = (sNogoName != null ? Integer.parseInt(sNogoName.substring(4)) : 20); } catch (Exception e1) { nogo.radius = 20; } } bIsNogoPoint = false; sNogoName = null; checkAddPoint("(one-for-all)", nogo); tmpPts.clear(); } } break; } } eventType = xpp.next(); } } public void readAllPoints() throws Exception { allpointsMap = new TreeMap<>(); readFromTo(); allpoints = new ArrayList<>(); Set names = new HashSet<>(); for (String category : allpointsMap.keySet()) { Map cat = allpointsMap.get(category); if (cat != null && cat.size() < 101) { for (OsmNodeNamed wp : cat.values()) { if (names.add(wp.name)) { allpoints.add(wp); } } } else { OsmNodeNamed nocatHint = new OsmNodeNamed(); nocatHint.name = ""; allpoints.add(nocatHint); } } } /* * read the from, to and via-positions from a gpx-file */ public void readFromTo() throws IOException { pointmap = new HashMap<>(); waypoints = new ArrayList<>(); nogopoints = new ArrayList<>(); readPointmap(); boolean fromToMissing = false; for (String name : posnames) { OsmNodeNamed n = pointmap.get(name); if (n != null) { waypoints.add(n); } else { if ("from".equals(name)) fromToMissing = true; if ("to".equals(name)) fromToMissing = true; } } if (fromToMissing) waypoints.clear(); } protected void checkAddPoint(String category, OsmNodeNamed n) { if (allpointsMap != null) { if (category == null) category = ""; Map cat = allpointsMap.get(category); if (cat == null) { cat = new TreeMap<>(); allpointsMap.put(category, cat); } if (cat.size() < 101) { cat.put(n.name, n); } return; } boolean isKnown = false; for (String posname : posnames) { if (posname.equals(n.name)) { isKnown = true; break; } } if (isKnown) { if (pointmap.put(n.name, n) != null) { if (!nogosOnly) { throw new IllegalArgumentException("multiple " + n.name + "-positions!"); } } } else if (n.name != null && n.name.startsWith("nogo")) { n.isNogo = true; n.nogoWeight = Double.NaN; nogopoints.add(n); } } }