diff --git a/OsmAnd/src/net/osmand/plus/routing/GPXRouteParams.java b/OsmAnd/src/net/osmand/plus/routing/GPXRouteParams.java index f62c686d3c..93b2f0875d 100644 --- a/OsmAnd/src/net/osmand/plus/routing/GPXRouteParams.java +++ b/OsmAnd/src/net/osmand/plus/routing/GPXRouteParams.java @@ -1,8 +1,9 @@ package net.osmand.plus.routing; +import android.util.Pair; + import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.Route; -import net.osmand.GPXUtilities.TrkSegment; import net.osmand.GPXUtilities.WptPt; import net.osmand.Location; import net.osmand.PlatformUtil; @@ -18,6 +19,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static net.osmand.plus.routing.RouteProvider.collectSegmentPointsFromGpx; import static net.osmand.router.RouteExporter.OSMAND_ROUTER_V2; public class GPXRouteParams { @@ -29,6 +31,7 @@ public class GPXRouteParams { protected List directions; protected List points = new ArrayList<>(); protected List routePoints = new ArrayList<>(); + protected List> segmentEndpoints = new ArrayList<>(); protected boolean reverse; protected boolean passWholeRoute; protected boolean calculateOsmAndRoute; @@ -82,7 +85,7 @@ public class GPXRouteParams { } int selectedSegment = builder.getSelectedSegment(); if (OSMAND_ROUTER_V2.equals(file.author)) { - route = RouteProvider.parseOsmAndGPXRoute(points, file, selectedSegment); + route = RouteProvider.parseOsmAndGPXRoute(points, file, segmentEndpoints, selectedSegment); if (selectedSegment == -1) { routePoints = file.getRoutePoints(); } else { @@ -94,7 +97,7 @@ public class GPXRouteParams { } addMissingTurns = route != null && route.isEmpty(); } else if (file.isCloudmadeRouteFile() || OSMAND_ROUTER.equals(file.author)) { - directions = RouteProvider.parseOsmAndGPXRoute(points, file, OSMAND_ROUTER.equals(file.author), builder.leftSide, 10, selectedSegment); + directions = RouteProvider.parseOsmAndGPXRoute(points, file, segmentEndpoints, OSMAND_ROUTER.equals(file.author), builder.leftSide, 10, selectedSegment); if (OSMAND_ROUTER.equals(file.author) && file.hasRtePt()) { // For files generated by OSMAND_ROUTER use directions contained unaltered addMissingTurns = false; @@ -108,19 +111,7 @@ public class GPXRouteParams { } else { // first of all check tracks if (!useIntermediatePointsRTE) { - List segments = file.getNonEmptyTrkSegments(false); - if (selectedSegment != -1 && segments.size() > selectedSegment) { - TrkSegment segment = segments.get(selectedSegment); - for (WptPt p : segment.points) { - points.add(RouteProvider.createLocation(p)); - } - } else { - for (TrkSegment tkSeg : segments) { - for (WptPt p : tkSeg.points) { - points.add(RouteProvider.createLocation(p)); - } - } - } + collectSegmentPointsFromGpx(file, points, segmentEndpoints, selectedSegment); } if (points.isEmpty()) { for (Route rte : file.routes) { diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index 9521ccb52d..45e113c597 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -3,6 +3,7 @@ package net.osmand.plus.routing; import android.os.Bundle; import android.util.Base64; +import android.util.Pair; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; @@ -22,6 +23,7 @@ import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.onlinerouting.OnlineRoutingHelper; import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.OnlineRoutingResponse; import net.osmand.plus.render.NativeOsmandLibrary; +import net.osmand.plus.routing.GPXRouteParams.GPXRouteParamsBuilder; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.CommonPreference; import net.osmand.plus.settings.backend.OsmandSettings; @@ -266,6 +268,7 @@ public class RouteProvider { } final List inputDirections = gpxParams.directions; List gpxDirections = calcDirections(startI, endI, inputDirections); + insertSegments(routeParams, gpxRoute, gpxDirections, gpxParams.segmentEndpoints, calculateOsmAndRouteParts); insertInitialSegment(routeParams, gpxRoute, gpxDirections, calculateOsmAndRouteParts); insertFinalSegment(routeParams, gpxRoute, gpxDirections, calculateOsmAndRouteParts); @@ -279,6 +282,28 @@ public class RouteProvider { gpxParams.wpt, routeParams.gpxRoute.addMissingTurns); } + public void insertSegments(RouteCalculationParams routeParams, List points, List directions, + List> segmentEndpoints, boolean calculateOsmAndRouteParts) { + for (Pair pair : segmentEndpoints) { + int index = points.indexOf(pair.second); + if (calculateOsmAndRouteParts && index != -1 && points.contains(pair.first)) { + LatLon end = new LatLon(pair.second.getLatitude(), pair.second.getLongitude()); + RouteCalculationResult newRes = findOfflineRouteSegment(routeParams, pair.first, end); + + if (newRes != null && newRes.isCalculated()) { + List loct = newRes.getImmutableAllLocations(); + List dt = newRes.getImmutableAllDirections(); + + for (RouteDirectionInfo i : dt) { + i.routePointOffset += points.size(); + } + points.addAll(index, loct); + directions.addAll(dt); + } + } + } + } + private RouteCalculationResult calculateOsmAndRouteWithIntermediatePoints(RouteCalculationParams routeParams, final List intermediates) throws IOException { RouteCalculationParams rp = new RouteCalculationParams(); @@ -737,7 +762,9 @@ public class RouteProvider { return new RouteCalculationResult("Empty result"); } - protected static List parseOsmAndGPXRoute(List points, GPXFile gpxFile, int selectedSegment) { + protected static List parseOsmAndGPXRoute(List points, GPXFile gpxFile, + List> segmentEndpoints, + int selectedSegment) { List segments = gpxFile.getNonEmptyTrkSegments(false); if (selectedSegment != -1 && segments.size() > selectedSegment) { TrkSegment segment = segments.get(selectedSegment); @@ -747,37 +774,50 @@ public class RouteProvider { RouteImporter routeImporter = new RouteImporter(segment); return routeImporter.importRoute(); } else { - for (TrkSegment ts : segments) { - for (WptPt p : ts.points) { - points.add(createLocation(p)); - } - } + collectPointsFromSegments(segments, points, segmentEndpoints); RouteImporter routeImporter = new RouteImporter(gpxFile); return routeImporter.importRoute(); } } - protected static List parseOsmAndGPXRoute(List points, GPXFile gpxFile, boolean osmandRouter, - boolean leftSide, float defSpeed, int selectedSegment) { + protected static void collectSegmentPointsFromGpx(GPXFile gpxFile, List points, + List> segmentEndpoints, int selectedSegment) { + List segments = gpxFile.getNonEmptyTrkSegments(false); + if (selectedSegment != -1 && segments.size() > selectedSegment) { + TrkSegment segment = segments.get(selectedSegment); + for (WptPt wptPt : segment.points) { + points.add(createLocation(wptPt)); + } + } else { + collectPointsFromSegments(segments, points, segmentEndpoints); + } + } + + protected static void collectPointsFromSegments(List segments, List points, List> segmentEndpoints) { + Location lastPoint = null; + for (int i = 0; i < segments.size(); i++) { + TrkSegment segment = segments.get(i); + for (WptPt wptPt : segment.points) { + points.add(createLocation(wptPt)); + } + if (i <= segments.size() - 1 && lastPoint != null) { + segmentEndpoints.add(new Pair<>(lastPoint, points.get((points.size() - segment.points.size())))); + } + lastPoint = points.get(points.size() - 1); + } + } + + protected static List parseOsmAndGPXRoute(List points, GPXFile gpxFile, + List> segmentEndpoints, + boolean osmandRouter, boolean leftSide, + float defSpeed, int selectedSegment) { List directions = null; if (!osmandRouter) { for (WptPt pt : gpxFile.getPoints()) { points.add(createLocation(pt)); } } else { - List segments = gpxFile.getNonEmptyTrkSegments(false); - if (selectedSegment != -1 && segments.size() > selectedSegment) { - TrkSegment segment = segments.get(selectedSegment); - for (WptPt p : segment.points) { - points.add(createLocation(p)); - } - } else { - for (TrkSegment ts : segments) { - for (WptPt p : ts.points) { - points.add(createLocation(p)); - } - } - } + collectSegmentPointsFromGpx(gpxFile, points, segmentEndpoints, selectedSegment); } float[] distanceToEnd = new float[points.size()]; for (int i = points.size() - 2; i >= 0; i--) { @@ -1042,9 +1082,10 @@ public class RouteProvider { bpars.putString("turnInstructionFormat", "osmand"); bpars.putString("acceptCompressedResult", "true"); - OsmandApplication ctx = (OsmandApplication) params.ctx; + OsmandApplication ctx = params.ctx; List res = new ArrayList(); - List dir = new ArrayList<>(); + List dir = new ArrayList<>(); + List> segmentEndpoints = new ArrayList<>(); IBRouterService brouterService = ctx.getBRouterService(); if (brouterService == null) { @@ -1057,22 +1098,22 @@ public class RouteProvider { boolean isZ64Encoded = gpxMessage.startsWith("ejY0"); // base-64 version of "z64" - if (!( isZ64Encoded || gpxMessage.startsWith("<") ) ) { + if (!(isZ64Encoded || gpxMessage.startsWith("<"))) { return new RouteCalculationResult(gpxMessage); } InputStream gpxStream; - if ( isZ64Encoded ) { - ByteArrayInputStream bais = new ByteArrayInputStream( Base64.decode(gpxMessage, Base64.DEFAULT) ); - bais.read( new byte[3] ); // skip prefix - gpxStream = new GZIPInputStream( bais ); + if (isZ64Encoded) { + ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(gpxMessage, Base64.DEFAULT)); + bais.read(new byte[3]); // skip prefix + gpxStream = new GZIPInputStream(bais); } else { gpxStream = new ByteArrayInputStream(gpxMessage.getBytes("UTF-8")); } GPXFile gpxFile = GPXUtilities.loadGPXFile(gpxStream); - dir = parseOsmAndGPXRoute(res, gpxFile, true, params.leftSide, params.mode.getDefaultSpeed(), -1); + dir = parseOsmAndGPXRoute(res, gpxFile, segmentEndpoints, true, params.leftSide, params.mode.getDefaultSpeed(), -1); if (dir != null) { addMissingTurns = false;