From 61670cc67ca6eeb8a4c40d8af0122127641833ab Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sun, 10 Jun 2012 20:16:26 +0200 Subject: [PATCH] Fix issue with start/end point --- .../binary/BinaryMapRouteReaderAdapter.java | 12 ++ .../osmand/data/preparation/IndexCreator.java | 2 +- .../net/osmand/router/BinaryRoutePlanner.java | 189 ++++++++---------- .../osmand/swing/DataExtractionSettings.java | 8 + .../src/net/osmand/swing/MapPointsLayer.java | 2 +- .../src/net/osmand/swing/MapRouterLayer.java | 59 ++++-- .../swing/OsmExtractionPreferencesDialog.java | 33 ++- 7 files changed, 178 insertions(+), 127 deletions(-) diff --git a/DataExtractionOSM/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java b/DataExtractionOSM/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java index fe2e61405a..67959ae76e 100644 --- a/DataExtractionOSM/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java +++ b/DataExtractionOSM/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java @@ -92,6 +92,8 @@ public class BinaryMapRouteReaderAdapter { type = RAILWAY_CROSSING; } else if(t.equalsIgnoreCase("roundabout") && v != null){ type = ROUNDABOUT; + } else if(t.equalsIgnoreCase("junction") && "roundabout".equalsIgnoreCase(v)){ + type = ROUNDABOUT; } else if(t.equalsIgnoreCase("highway") && v != null){ type = HIGHWAY_TYPE; } else if(t.startsWith("access") && v != null){ @@ -121,6 +123,16 @@ public class BinaryMapRouteReaderAdapter { public RouteDataObject(RouteRegion region) { this.region = region; } + + public RouteDataObject(RouteDataObject copy) { + this.region = copy.region; + this.pointsX = new TIntArrayList(copy.pointsX); + this.pointsY = new TIntArrayList(copy.pointsY); + this.types = new TIntArrayList(copy.types); + this.restrictions = new TLongArrayList(copy.restrictions); + this.pointTypes = new ArrayList(copy.pointTypes); + this.id = copy.id; + } public TIntArrayList types = new TIntArrayList(); public TIntArrayList pointsX = new TIntArrayList(); diff --git a/DataExtractionOSM/src/net/osmand/data/preparation/IndexCreator.java b/DataExtractionOSM/src/net/osmand/data/preparation/IndexCreator.java index 24470c404c..6e77df2564 100644 --- a/DataExtractionOSM/src/net/osmand/data/preparation/IndexCreator.java +++ b/DataExtractionOSM/src/net/osmand/data/preparation/IndexCreator.java @@ -746,7 +746,7 @@ public class IndexCreator { MapRenderingTypes rt = MapRenderingTypes.getDefault(); MapZooms zooms = MapZooms.getDefault(); // MapZooms.parseZooms("15-"); creator.setNodesDBFile(new File("/home/victor/projects/OsmAnd/data/osm-gen/nodes.tmp.odb")); - creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/RU-SPE.osm.bz2"), + creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/belarus.osm.pbf"), new ConsoleProgressImplementation(1), null, zooms, rt, log); diff --git a/DataExtractionOSM/src/net/osmand/router/BinaryRoutePlanner.java b/DataExtractionOSM/src/net/osmand/router/BinaryRoutePlanner.java index 0acfa29139..f70846a1c3 100644 --- a/DataExtractionOSM/src/net/osmand/router/BinaryRoutePlanner.java +++ b/DataExtractionOSM/src/net/osmand/router/BinaryRoutePlanner.java @@ -76,24 +76,11 @@ public class BinaryRoutePlanner { return (x1 - x2) * 0.011d; } - // calculate distance from C to AB (distnace doesn't calculate - private static double calculateDistance(int xA, int yA, int xB, int yB, int xC, int yC, double distAB){ - // Scalar multiplication between (AB', AC) - double multiple = (-convert31YToMeters(yB, yA)) * convert31XToMeters(xC,xA) + convert31XToMeters(xB,xA) * convert31YToMeters(yC, yA); - return multiple / distAB; - } - - // calculate square distance from C to AB (distance doesn't calculate - private static double calculatesquareDistance(int xA, int yA, int xB, int yB, int xC, int yC, double distAB) { - // Scalar multiplication between (AB', AC) - double multiple = (-convert31YToMeters(yB, yA)) * convert31XToMeters(xC,xA) + convert31XToMeters(xB,xA) * convert31YToMeters(yC, yA); - return (multiple * multiple) / (distAB*distAB); - } - private static double calculateProjection(int xA, int yA, int xB, int yB, int xC, int yC, double distAB) { + private static double calculateProjection(int xA, int yA, int xB, int yB, int xC, int yC) { // Scalar multiplication between (AB, AC) double multiple = convert31XToMeters(xB, xA) * convert31XToMeters(xC, xA) + convert31YToMeters(yB, yA) * convert31YToMeters(yC, yA); - return multiple / distAB; + return multiple; } @@ -109,26 +96,33 @@ public class BinaryRoutePlanner { for(RouteDataObject r : dataObjects){ if(r.getPointsLength() > 1){ -// double priority = ctx.getRouter().getRoadPriorityToCalculateRoute(r); for (int j = 1; j < r.getPointsLength(); j++) { double mDist = squareRootDist(r.getPoint31XTile(j), r.getPoint31YTile(j), r.getPoint31XTile(j - 1), r.getPoint31YTile(j - 1)); + int prx = r.getPoint31XTile(j); + int pry = r.getPoint31YTile(j); double projection = calculateProjection(r.getPoint31XTile(j - 1), r.getPoint31YTile(j - 1), r.getPoint31XTile(j), r.getPoint31YTile(j), - px, py, mDist); - double currentsDist; - if(projection < 0){//TODO: first 2 and last 2 points of a route should be only near and not based on road priority (I.E. a motorway road node unreachable near my house) - currentsDist = squareDist(r.getPoint31XTile(j - 1), r.getPoint31YTile(j - 1), px, py);// / (priority * priority); - } else if(projection > mDist){ - currentsDist = squareDist(r.getPoint31XTile(j), r.getPoint31YTile(j), px, py);// / (priority * priority); + px, py); + if(projection < 0){ + prx = r.getPoint31XTile(j - 1); + pry = r.getPoint31YTile(j - 1); + } else if(projection >= mDist * mDist){ + prx = r.getPoint31XTile(j); + pry = r.getPoint31YTile(j); } else { - currentsDist = calculatesquareDistance(r.getPoint31XTile(j - 1), r.getPoint31YTile(j - 1), r.getPoint31XTile(j), r.getPoint31YTile(j), - px, py, mDist);// / (priority * priority); + prx = (int) (r.getPoint31XTile(j - 1) + (r.getPoint31XTile(j) - r.getPoint31XTile(j - 1))* (projection / (mDist *mDist))); + pry = (int) (r.getPoint31YTile(j - 1) + (r.getPoint31YTile(j) - r.getPoint31YTile(j - 1)) * (projection / (mDist *mDist))); } - + double currentsDist = squareDist(prx, pry, px, py); if (road == null || currentsDist < sdist) { - road = new RouteSegment(r, j-1); -//TODO: first 2 and last 2 segments should be based on projection. my start/finish point S/F, fake point P between j-1 & j -> SP, PJ; should end at finish point: JP,PF - + RouteDataObject ro = new RouteDataObject(r); + road = new RouteSegment(ro, j); + ro.pointsX.insert(j, prx); + ro.pointsY.insert(j, pry); + if(ro.pointTypes.size() > j) { + ro.pointTypes.add(j, null); + } road.segmentEnd = j; + registerRouteDataObject(ctx, ro); sdist = currentsDist; } } @@ -189,40 +183,41 @@ public class BinaryRoutePlanner { start.distanceToEnd = h(ctx, targetEndX, targetEndY, startX, startY); end.distanceToEnd = start.distanceToEnd; - // because first point of the start is not visited do the same as in cycle but only for one point - // it matters when start point is intersection of different roads - // add start segment to priority queue - visitAllStartSegments(ctx, start, graphDirectSegments, visitedDirectSegments, startX, startY); - visitAllStartSegments(ctx, end, graphReverseSegments, visitedOppositeSegments, targetEndX, targetEndY); + graphDirectSegments.add(start); + graphReverseSegments.add(end); // Extract & analyze segment with min(f(x)) from queue while final segment is not found boolean inverse = false; + boolean init = false; PriorityQueue graphSegments = inverse ? graphReverseSegments : graphDirectSegments; - while(!graphSegments.isEmpty()){ + while (!graphSegments.isEmpty()) { RouteSegment segment = graphSegments.poll(); - - ctx.visitedSegments ++; + + ctx.visitedSegments++; // for debug purposes if (ctx.visitor != null) { ctx.visitor.visitSegment(segment, true); } boolean routeFound = false; if (!inverse) { - routeFound = processRouteSegment(ctx, end, false, graphDirectSegments, visitedDirectSegments, targetEndX, - targetEndY, segment, visitedOppositeSegments); + routeFound = processRouteSegment(ctx, end, false, graphDirectSegments, visitedDirectSegments, targetEndX, targetEndY, + segment, visitedOppositeSegments); } else { - routeFound = processRouteSegment(ctx, start, true, graphReverseSegments, visitedOppositeSegments, startX, - startY, segment, visitedDirectSegments); + routeFound = processRouteSegment(ctx, start, true, graphReverseSegments, visitedOppositeSegments, startX, startY, segment, + visitedDirectSegments); } - if(graphReverseSegments.isEmpty() || graphDirectSegments.isEmpty() || routeFound){ + if (graphReverseSegments.isEmpty() || graphDirectSegments.isEmpty() || routeFound) { break; } - if(ctx.planRouteIn2Directions()){ + if(!init) { + inverse = !inverse; + init = true; + } else if (ctx.planRouteIn2Directions()) { inverse = nonHeuristicSegmentsComparator.compare(graphDirectSegments.peek(), graphReverseSegments.peek()) > 0; if (graphDirectSegments.size() * 1.3 > graphReverseSegments.size()) { inverse = true; - } else if (graphDirectSegments.size() < 1.3 * graphReverseSegments.size()) { + } else if (graphDirectSegments.size() < 1.3 * graphReverseSegments.size()) { inverse = false; } } else { @@ -254,7 +249,44 @@ public class BinaryRoutePlanner { return result; } - + private void registerRouteDataObject(final RoutingContext ctx, RouteDataObject o) { + RouteDataObject old = ctx.idObjects.get(o.id); + // sometimes way are presented only partially in one index + if ((old != null && old.pointsX.size() >= o.pointsX.size()) || (!ctx.getRouter().acceptLine(o))) { + return; + } + ctx.idObjects.put(o.id, o); + for (int j = 0; j < o.pointsX.size(); j++) { + long l = (((long) o.pointsX.getQuick(j)) << 31) + (long) o.pointsY.getQuick(j); + RouteSegment segment = new RouteSegment(o , j); + segment.segmentEnd = j; + RouteSegment prev = ctx.routes.get(l); + boolean i = true; + if (prev != null) { + if (old == null) { + segment.next = prev; + } else if (prev.road == old) { + segment.next = prev.next; + } else { + // segment somewhere in the middle replace element in linked list + RouteSegment rr = prev; + while (rr != null) { + if (rr.road == old) { + prev.next = segment; + segment.next = rr.next; + break; + } + prev = rr; + rr = rr.next; + } + i = false; + } + } + if (i) { + ctx.routes.put(l, segment); + } + } + } public void loadRoutes(final RoutingContext ctx, int tile31X, int tile31Y, final List toFillIn) { int zoomToLoad = 31 - ctx.getZoomToLoadTileWithRoads(); @@ -273,21 +305,7 @@ public class BinaryRoutePlanner { toFillIn.add(o); } } - RouteDataObject old = ctx.idObjects.get(o.id); - // sometimes way are presented only partially in one index - if ((old != null && old.pointsX.size() >= o.pointsX.size()) || (!ctx.getRouter().acceptLine(o))) { - return false; - } - ctx.idObjects.put(o.id, o); - for (int j = 0; j < o.pointsX.size(); j++) { - long l = (((long) o.pointsX.getQuick(j)) << 31) + (long) o.pointsY.getQuick(j); - RouteSegment segment = new RouteSegment(o , j); - segment.segmentEnd = j; - if (ctx.routes.get(l) != null) { - segment.next = ctx.routes.get(l); - } - ctx.routes.put(l, segment); - } + registerRouteDataObject(ctx, o); return false; } @@ -309,30 +327,7 @@ public class BinaryRoutePlanner { ctx.timeToLoad += (System.nanoTime() - now); } - private void visitAllStartSegments(final RoutingContext ctx, RouteSegment start, PriorityQueue graphDirectSegments, - TLongObjectHashMap visitedSegments, int startX, int startY) throws IOException { - // mark as visited code seems to be duplicated - long nt = (start.road.getId() << 8l) + start.segmentStart; - visitedSegments.put(nt, start); - graphDirectSegments.add(start); - - loadRoutes(ctx, startX , startY,null); - long ls = (((long) startX) << 31) + (long) startY; - RouteSegment startNbs = ctx.routes.get(ls); - while(startNbs != null) { // startNbs.road.id >> 1, start.road.id >> 1 - if(startNbs.road.getId() != start.road.getId()){ - startNbs.parentRoute = start; - startNbs.parentSegmentEnd = start.segmentStart; - startNbs.distanceToEnd = start.distanceToEnd; - - // duplicated to be sure start is added - nt = (startNbs.road.getId() << 8l) + startNbs.segmentStart; - visitedSegments.put(nt, startNbs); - graphDirectSegments.add(startNbs); - } - startNbs = startNbs.next; - } - } + private boolean processRouteSegment(final RoutingContext ctx, RouteSegment end, boolean reverseWaySearch, @@ -542,7 +537,6 @@ public class BinaryRoutePlanner { nextIterator = ctx.segmentsToVisitPrescripted.iterator(); } // Calculate possible ways to put into priority queue - // for debug next.road.getId() >> 1 == 33911427 && road.getId() >> 1 == 33911442 RouteSegment next = inputNext; boolean hasNext = nextIterator == null || nextIterator.hasNext(); while (hasNext) { @@ -565,7 +559,6 @@ public class BinaryRoutePlanner { // Calculate complete distance from start double gDistFromStart = distFromStart + ctx.getRouter().calculateTurnTime(segment, next, segmentEnd); - /* next.road.getId() >> 1 (3) != road.getId() >> 1 (3) - used that line for debug with osm map */ // road.id could be equal on roundabout, but we should accept them boolean alreadyVisited = visitedSegments.contains(nts); if (!alreadyVisited) { @@ -666,16 +659,10 @@ public class BinaryRoutePlanner { while(segment != null){ RouteSegmentResult res = new RouteSegmentResult(); res.object = segment.road; - res.endPointIndex = segment.segmentStart; - res.startPointIndex = parentSegmentStart; + res.startPointIndex = segment.segmentStart; + res.endPointIndex = parentSegmentStart; parentSegmentStart = segment.parentSegmentEnd; segment = segment.parentRoute; - // reverse start and end point for start if needed - // rely that point.segmentStart <= point.segmentEnd for end, start - if(segment == null && res.startPointIndex >= res.endPointIndex && - res.endPointIndex < res.object.getPointsLength() - 1){ - res.endPointIndex ++; - } // do not add segments consists from 1 point if(res.startPointIndex != res.endPointIndex) { result.add(res); @@ -690,16 +677,11 @@ public class BinaryRoutePlanner { while(segment != null){ RouteSegmentResult res = new RouteSegmentResult(); res.object = segment.road; - res.endPointIndex = parentSegmentEnd; - res.startPointIndex = segment.segmentStart; + res.startPointIndex = parentSegmentEnd; + res.endPointIndex = segment.segmentStart; parentSegmentEnd = segment.parentSegmentEnd; segment = segment.parentRoute; - // reverse start and end point for start if needed - // rely that point.segmentStart <= point.segmentEnd for end, start - if(segment == null && res.startPointIndex < res.endPointIndex){ - res.startPointIndex ++; - } // do not add segments consists from 1 point if(res.startPointIndex != res.endPointIndex) { result.add(res); @@ -707,7 +689,7 @@ public class BinaryRoutePlanner { res.startPoint = convertPoint(res.object, res.startPointIndex); res.endPoint = convertPoint(res.object, res.endPointIndex); } - Collections.reverse(result); +// Collections.reverse(result); if (PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST) { @@ -720,14 +702,13 @@ public class BinaryRoutePlanner { " start_lat=\"{0}\" start_lon=\"{1}\" target_lat=\"{2}\" target_lon=\"{3}\">", startLat+"", startLon+"", endLat+"", endLon+"")); for (RouteSegmentResult res : result) { - String name = "Uknown";//res.object.getName(); + String name = "Unknown";//res.object.getName(); String ref = "";//res.object.getNameByType(res.object.getMapIndex().refEncodingType); if(ref != null) { name += " " + ref; } - // (res.object.getId() >> 1) System.out.println(MessageFormat.format("\t", - (res.object.getId() >> 1)+"", res.startPointIndex, res.endPointIndex, name)); + (res.object.getId())+"", res.startPointIndex, res.endPointIndex, name)); } System.out.println(""); } diff --git a/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java b/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java index 7376fd238a..c5443078a4 100644 --- a/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java +++ b/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java @@ -158,6 +158,14 @@ public class DataExtractionSettings { preferences.put("cityAdminLevel", s); } + public int getRouteDirection(){ + return preferences.getInt("routeDirection", 0); + } + + public void setRouteDirection(int s){ + preferences.putInt("routeDirection", s); + } + public String getNativeLibFile(){ String fl = preferences.get("nativeLibFile", null); if(fl != null) { diff --git a/DataExtractionOSM/src/net/osmand/swing/MapPointsLayer.java b/DataExtractionOSM/src/net/osmand/swing/MapPointsLayer.java index d0453fb578..f07f1d09fd 100644 --- a/DataExtractionOSM/src/net/osmand/swing/MapPointsLayer.java +++ b/DataExtractionOSM/src/net/osmand/swing/MapPointsLayer.java @@ -126,7 +126,7 @@ public class MapPointsLayer implements MapPanelLayer { } g.drawPolygon(xPoints, yPoints, 4); g.fillPolygon(xPoints, yPoints, 4); - if(name != null && map.getZoom() > 16) { + if(name != null && map.getZoom() >= 16) { Font prevFont = g.getFont(); Color prevColor = g.getColor(); AffineTransform prev = g.getTransform(); diff --git a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java index edb19fc94c..ff3b74b4e7 100644 --- a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java +++ b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java @@ -30,6 +30,7 @@ import javax.xml.parsers.ParserConfigurationException; import net.osmand.binary.BinaryMapIndexReader; import net.osmand.data.DataTileManager; +import net.osmand.osm.Entity; import net.osmand.osm.LatLon; import net.osmand.osm.MapUtils; import net.osmand.osm.Way; @@ -558,7 +559,10 @@ public class MapRouterLayer implements MapPanelLayer { BinaryRoutePlanner router = new BinaryRoutePlanner(rs); RoutingContext ctx = new RoutingContext(); ctx.setRouter(this.routerMode); - ctx.setPlanRoadDirection(true); + int dir = DataExtractionSettings.getSettings().getRouteDirection(); + if(dir != 0) { + ctx.setPlanRoadDirection(dir > 0 ? true : false); + } // find closest way RouteSegment st = router.findRouteSegment(start.getLatitude(), start.getLongitude(), ctx); @@ -573,7 +577,7 @@ public class MapRouterLayer implements MapPanelLayer { } System.out.println("ROAD TO END " + e.getRoad().getHighway() + " " + e.getRoad().id); - final DataTileManager points = new DataTileManager(); + final DataTileManager points = new DataTileManager(); points.setZoom(11); map.setPoints(points); ctx.setVisitor(new RouteSegmentVisitor() { @@ -610,21 +614,7 @@ public class MapRouterLayer implements MapPanelLayer { } } - private void redraw() { - try { - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - map.prepareImage(); - } - }); - } catch (InterruptedException e1) { - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - - private void registerObjects(final DataTileManager points, boolean white, + private void registerObjects(final DataTileManager points, boolean white, List registerCache) { for (RouteSegment segment : registerCache) { Way way = new Way(-1); @@ -633,8 +623,7 @@ public class MapRouterLayer implements MapPanelLayer { way.putTag("color", "white"); } 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); + net.osmand.osm.Node n = createNode(segment, i); way.addNode(n); } LatLon n = way.getLatLon(); @@ -643,8 +632,18 @@ public class MapRouterLayer implements MapPanelLayer { } }); + // TODO delete this block after + net.osmand.osm.Node ns = createNode(st, st.getSegmentStart()); + points.registerObject(ns.getLatitude(), ns.getLongitude(), ns); + ns = createNode(e, e.getSegmentStart()); + points.registerObject(ns.getLatitude(), ns.getLongitude(), ns); + if (pause && animateRoutingCalculation) { + waitNextPress(); + } + // TODO delete this block after + List searchRoute = router.searchRoute(ctx, st, e); - if (pause) { + if (pause && animateRoutingCalculation) { nextTurn.setText("FINISH"); waitNextPress(); nextTurn.setText(">>"); @@ -693,6 +692,26 @@ public class MapRouterLayer implements MapPanelLayer { return res; } + private net.osmand.osm.Node createNode(RouteSegment segment, int i) { + net.osmand.osm.Node n = new net.osmand.osm.Node(MapUtils.get31LatitudeY(segment.getRoad().getPoint31YTile(i)), + MapUtils.get31LongitudeX(segment.getRoad().getPoint31XTile(i)), -1); + return n; + } + + private void redraw() { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + map.prepareImage(); + } + }); + } catch (InterruptedException e1) { + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + private void waitNextPress() { nextTurn.setVisible(true); while (!nextAvailable) { diff --git a/DataExtractionOSM/src/net/osmand/swing/OsmExtractionPreferencesDialog.java b/DataExtractionOSM/src/net/osmand/swing/OsmExtractionPreferencesDialog.java index e28f6ddbfd..e151d52163 100644 --- a/DataExtractionOSM/src/net/osmand/swing/OsmExtractionPreferencesDialog.java +++ b/DataExtractionOSM/src/net/osmand/swing/OsmExtractionPreferencesDialog.java @@ -19,7 +19,6 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; -import net.osmand.data.preparation.MapZooms; public class OsmExtractionPreferencesDialog extends JDialog { @@ -31,6 +30,7 @@ public class OsmExtractionPreferencesDialog extends JDialog { private JTextField streetSuffixes; private JTextField streetDefaultSuffixes; private JTextField mapZooms; + private JTextField directionPlanRoute; private JTextField lineSmoothness; private JTextField cityAdminLevel; private JTextField osrmServerAddress; @@ -43,6 +43,8 @@ public class OsmExtractionPreferencesDialog extends JDialog { private JCheckBox animateRouting; + + // private JCheckBox supressWarning; // private JCheckBox loadWholeOsmInfo; @@ -139,6 +141,27 @@ public class OsmExtractionPreferencesDialog extends JDialog { constr.gridy = gridY++; l.setConstraints(nativeFilesDirectory, constr); + label = new JLabel("Direction to plan route (0 - both, 1 - forward, -1 - backward) : "); + panel.add(label); + constr = new GridBagConstraints(); + constr.ipadx = 5; + constr.gridx = 0; + constr.gridy = gridY; + constr.anchor = GridBagConstraints.WEST; + l.setConstraints(label, constr); + + directionPlanRoute = new JTextField(); + + directionPlanRoute.setText(DataExtractionSettings.getSettings().getRouteDirection() +""); + panel.add(directionPlanRoute); + constr = new GridBagConstraints(); + constr.weightx = 1; + constr.fill = GridBagConstraints.HORIZONTAL; + constr.ipadx = 5; + constr.gridx = 1; + constr.gridy = gridY++; + l.setConstraints(directionPlanRoute, constr); + label = new JLabel("City admin level : "); panel.add(label); @@ -394,6 +417,14 @@ public class OsmExtractionPreferencesDialog extends JDialog { } if(!settings.getCityAdminLevel().equals(cityAdminLevel.getText())){ settings.setCityAdminLevel(cityAdminLevel.getText()); + } + int directionRoute = 0; + try { + directionRoute = Integer.parseInt(directionPlanRoute.getText()); + } catch (Exception e) { + } + if(directionRoute != settings.getRouteDirection()){ + settings.setRouteDirection(directionRoute); } if(!settings.getOsrmServerAddress().equals(osrmServerAddress.getText())){ settings.setOsrmServerAddress(osrmServerAddress.getText());