From 355d6bb3096f532d1398eaaebac1fcfbd4421b83 Mon Sep 17 00:00:00 2001 From: max-klaus Date: Sat, 8 Aug 2020 19:35:57 +0300 Subject: [PATCH] WIP - Gpx approximation --- .../main/java/net/osmand/LocationsHolder.java | 159 ++++++++++++++++++ .../osmand/router/RoutePlannerFrontEnd.java | 30 ++-- ..._gpx_approximation_bottom_sheet_dialog.xml | 6 +- .../GpxApproximationFragment.java | 4 +- .../MeasurementEditingContext.java | 56 +++++- .../MeasurementToolFragment.java | 49 +++++- .../osmand/plus/routing/GpxApproximator.java | 85 ++++++++++ .../osmand/plus/routing/RouteProvider.java | 103 +++++++++--- .../osmand/plus/routing/RoutingHelper.java | 24 ++- 9 files changed, 460 insertions(+), 56 deletions(-) create mode 100644 OsmAnd-java/src/main/java/net/osmand/LocationsHolder.java create mode 100644 OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java diff --git a/OsmAnd-java/src/main/java/net/osmand/LocationsHolder.java b/OsmAnd-java/src/main/java/net/osmand/LocationsHolder.java new file mode 100644 index 0000000000..875f481644 --- /dev/null +++ b/OsmAnd-java/src/main/java/net/osmand/LocationsHolder.java @@ -0,0 +1,159 @@ +package net.osmand; + +import net.osmand.GPXUtilities.WptPt; +import net.osmand.data.LatLon; +import net.osmand.util.Algorithms; + +import java.util.ArrayList; +import java.util.List; + +public class LocationsHolder { + + private static final int LOCATION_TYPE_UNKNOWN = -1; + private static final int LOCATION_TYPE_LATLON = 0; + private static final int LOCATION_TYPE_LOCATION = 1; + private static final int LOCATION_TYPE_WPTPT = 2; + + private List latLonList; + private List locationList; + private List wptPtList; + private int locationType; + private int size; + + @SuppressWarnings("unchecked") + public LocationsHolder(List locations) { + this.locationType = resolveLocationType(locations); + switch (locationType) { + case LOCATION_TYPE_LATLON: + latLonList = (List) locations; + size = locations.size(); + break; + case LOCATION_TYPE_LOCATION: + locationList = (List) locations; + size = locations.size(); + break; + case LOCATION_TYPE_WPTPT: + wptPtList = (List) locations; + size = locations.size(); + break; + } + } + + private int resolveLocationType(List locations) { + if (!Algorithms.isEmpty(locations)) { + Object locationObj = locations.get(0); + if (locationObj instanceof LatLon) { + return LOCATION_TYPE_LATLON; + } else if (locationObj instanceof WptPt) { + return LOCATION_TYPE_WPTPT; + } else if (locationObj instanceof Location) { + return LOCATION_TYPE_LOCATION; + } else { + throw new IllegalArgumentException("Unsupported location type: " + locationObj.getClass().getSimpleName()); + } + } + return LOCATION_TYPE_UNKNOWN; + } + + public double getLatitude(int index) { + switch (locationType) { + case LOCATION_TYPE_LATLON: + return latLonList.get(index).getLatitude(); + case LOCATION_TYPE_LOCATION: + return locationList.get(index).getLatitude(); + case LOCATION_TYPE_WPTPT: + return wptPtList.get(index).getLatitude(); + default: + return 0; + } + } + + public double getLongitude(int index) { + switch (locationType) { + case LOCATION_TYPE_LATLON: + return latLonList.get(index).getLongitude(); + case LOCATION_TYPE_LOCATION: + return locationList.get(index).getLongitude(); + case LOCATION_TYPE_WPTPT: + return wptPtList.get(index).getLongitude(); + default: + return 0; + } + } + + public int getSize() { + return size; + } + + @SuppressWarnings("unchecked") + private List getList(int locationType) { + List res = new ArrayList<>(); + if (size > 0) { + for (int i = 0; i < size; i++) { + switch (locationType) { + case LOCATION_TYPE_LATLON: + res.add((T) getLatLon(i)); + break; + case LOCATION_TYPE_LOCATION: + res.add((T) getLocation(i)); + break; + case LOCATION_TYPE_WPTPT: + res.add((T) getWptPt(i)); + break; + } + } + } + return res; + } + + public List getLatLonList() { + if (this.locationType == LOCATION_TYPE_LATLON) { + return latLonList; + } else { + return getList(LOCATION_TYPE_LATLON); + } + } + + public List getWptPtList() { + if (this.locationType == LOCATION_TYPE_WPTPT) { + return wptPtList; + } else { + return getList(LOCATION_TYPE_WPTPT); + } + } + + public List getLocationsList() { + if (this.locationType == LOCATION_TYPE_LOCATION) { + return locationList; + } else { + return getList(LOCATION_TYPE_LOCATION); + } + } + + public LatLon getLatLon(int index) { + if (this.locationType == LOCATION_TYPE_LATLON) { + return latLonList.get(index); + } else { + return new LatLon(getLatitude(index), getLongitude(index)); + } + } + + public WptPt getWptPt(int index) { + if (this.locationType == LOCATION_TYPE_WPTPT) { + return wptPtList.get(index); + } else { + WptPt wptPt = new WptPt(); + wptPt.lat = getLatitude(index); + wptPt.lon = getLongitude(index); + return wptPt; + } + } + + public Location getLocation(int index) { + if (this.locationType == LOCATION_TYPE_LOCATION) { + return locationList.get(index); + } else { + return new Location("", getLatitude(index), getLongitude(index)); + } + } +} diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java b/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java index a9bd16b566..22cf7b434d 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java @@ -1,14 +1,7 @@ package net.osmand.router; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.List; - +import net.osmand.LocationsHolder; import net.osmand.NativeLibrary; import net.osmand.PlatformUtil; import net.osmand.binary.BinaryMapIndexReader; @@ -23,6 +16,14 @@ import net.osmand.util.MapUtils; import org.apache.commons.logging.Log; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; + import gnu.trove.list.array.TIntArrayList; public class RoutePlannerFrontEnd { @@ -214,13 +215,12 @@ public class RoutePlannerFrontEnd { useSmartRouteRecalculation = use; } - public GpxRouteApproximation searchGpxRoute(GpxRouteApproximation gctx, List points) throws IOException, InterruptedException { + public GpxRouteApproximation searchGpxRoute(GpxRouteApproximation gctx, List gpxPoints) throws IOException, InterruptedException { long timeToCalculate = System.nanoTime(); if (gctx.ctx.calculationProgress == null) { gctx.ctx.calculationProgress = new RouteCalculationProgress(); } gctx.ctx.keepNativeRoutingContext = true; - List gpxPoints = generageGpxPoints(points, gctx); GpxPoint start = null; GpxPoint prev = null; if(gpxPoints.size() > 0) { @@ -288,7 +288,7 @@ public class RoutePlannerFrontEnd { BinaryRoutePlanner.printDebugMemoryInformation(gctx.ctx); calculateGpxRoute(gctx, gpxPoints); if (!gctx.result.isEmpty()) { - new RouteResultPreparation().printResults(gctx.ctx, points.get(0), points.get(points.size() - 1), gctx.result); + new RouteResultPreparation().printResults(gctx.ctx, gpxPoints.get(0).loc, gpxPoints.get(gpxPoints.size() - 1).loc, gctx.result); System.out.println(gctx); } return gctx; @@ -382,13 +382,13 @@ public class RoutePlannerFrontEnd { cleanupResultAndAddTurns(gctx); } - private List generageGpxPoints(List points, GpxRouteApproximation gctx) { - List gpxPoints = new ArrayList<>(points.size()); + public List generateGpxPoints(GpxRouteApproximation gctx, LocationsHolder locationsHolder) { + List gpxPoints = new ArrayList<>(locationsHolder.getSize()); GpxPoint prev = null; - for(int i = 0; i < points.size(); i++) { + for(int i = 0; i < locationsHolder.getSize(); i++) { GpxPoint p = new GpxPoint(); p.ind = i; - p.loc = points.get(i); + p.loc = locationsHolder.getLatLon(i); if (prev != null) { p.cumDist = MapUtils.getDistance(p.loc, prev.loc) + prev.cumDist; } diff --git a/OsmAnd/res/layout/fragment_gpx_approximation_bottom_sheet_dialog.xml b/OsmAnd/res/layout/fragment_gpx_approximation_bottom_sheet_dialog.xml index 3aff5d8aa5..2699fa722f 100644 --- a/OsmAnd/res/layout/fragment_gpx_approximation_bottom_sheet_dialog.xml +++ b/OsmAnd/res/layout/fragment_gpx_approximation_bottom_sheet_dialog.xml @@ -16,9 +16,9 @@ + android:layout_height="match_parent"> + + points = getNewGpxData().getTrkSegment().points; - if (isSnapToRoadTrack()) { - List routePoints = getNewGpxData().getGpxFile().getRoutePoints(); + NewGpxData newGpxData = getNewGpxData(); + if (newGpxData == null || newGpxData.getTrkSegment() == null || Algorithms.isEmpty(newGpxData.getTrkSegment().points)) { + return; + } + List points = newGpxData.getTrkSegment().points; + if (isTrackSnappedToRoad()) { + List routePoints = newGpxData.getGpxFile().getRoutePoints(); int prevPointIndex = 0; for (int i = 0; i < routePoints.size() - 1; i++) { Pair pair = new Pair<>(routePoints.get(i), routePoints.get(i + 1)); @@ -318,6 +327,38 @@ public class MeasurementEditingContext { } } + void setPoints(GpxRouteApproximation gpxApproximation) { + if (gpxApproximation == null || Algorithms.isEmpty(gpxApproximation.finalPoints) || Algorithms.isEmpty(gpxApproximation.result)) { + return; + } + clearSegments(); + List routePoints = gpxApproximation.finalPoints; + for (int i = 0; i < routePoints.size() - 1; i++) { + GpxPoint rp1 = routePoints.get(i); + GpxPoint rp2 = routePoints.get(i + 1); + WptPt p1 = new WptPt(); + p1.lat = rp1.loc.getLatitude(); + p1.lon = rp1.loc.getLongitude(); + WptPt p2 = new WptPt(); + p2.lat = rp2.loc.getLatitude(); + p2.lon = rp2.loc.getLongitude(); + Pair pair = new Pair<>(p1, p2); + List cacheSegment = new ArrayList<>(); + for (RouteSegmentResult seg : rp1.routeToTarget) { + int start = seg.isForwardDirection() ? seg.getStartPointIndex() : seg.getEndPointIndex(); + int end = seg.isForwardDirection() ? seg.getEndPointIndex() : seg.getStartPointIndex(); + for (int ik = start; ik <= end; ik++) { + LatLon l = seg.getPoint(ik); + WptPt pt = new WptPt(); + pt.lat = l.getLatitude(); + pt.lon = l.getLongitude(); + cacheSegment.add(pt); + } + } + snappedToRoadPoints.put(pair, cacheSegment); + } + } + private int findPointIndex(WptPt point, List points, int firstIndex) { double minDistance = Double.MAX_VALUE; int index = 0; @@ -331,10 +372,11 @@ public class MeasurementEditingContext { return index; } - boolean isSnapToRoadTrack() { - return getNewGpxData() != null && getNewGpxData().getTrkSegment() != null - && !getNewGpxData().getTrkSegment().points.isEmpty() - && !getNewGpxData().getGpxFile().getRoutePoints().isEmpty(); + boolean isTrackSnappedToRoad() { + NewGpxData newGpxData = getNewGpxData(); + return newGpxData != null && newGpxData.getTrkSegment() != null + && !newGpxData.getTrkSegment().points.isEmpty() + && !newGpxData.getGpxFile().getRoutePoints().isEmpty(); } private void updateCacheForSnapIfNeeded(boolean both) { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index 9cf318b36b..a0590f77f7 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -48,6 +48,7 @@ import net.osmand.GPXUtilities.Track; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.GPXUtilities.WptPt; import net.osmand.IndexConstants; +import net.osmand.LocationsHolder; import net.osmand.data.LatLon; import net.osmand.data.QuadRect; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; @@ -72,6 +73,7 @@ import net.osmand.plus.measurementtool.command.ClearPointsCommand; import net.osmand.plus.measurementtool.command.MovePointCommand; import net.osmand.plus.measurementtool.command.RemovePointCommand; import net.osmand.plus.measurementtool.command.ReorderPointCommand; +import net.osmand.plus.routing.GpxApproximator; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback; @@ -79,8 +81,10 @@ import net.osmand.plus.views.layers.MapControlsLayer; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView; +import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation; import java.io.File; +import java.io.IOException; import java.lang.ref.WeakReference; import java.text.MessageFormat; import java.text.SimpleDateFormat; @@ -134,6 +138,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private boolean gpxPointsAdded; private MeasurementEditingContext editingCtx = new MeasurementEditingContext(); + private GpxApproximator gpxApproximator; private LatLon initialPoint; @@ -287,7 +292,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route public void onClick(View view) { OptionsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(), MeasurementToolFragment.this, - editingCtx.isSnapToRoadTrack() || editingCtx.isNewData(), + editingCtx.isTrackSnappedToRoad() || editingCtx.isNewData(), editingCtx.isInSnapToRoadMode(), editingCtx.getSnapToRoadAppMode() != null ? editingCtx.getSnapToRoadAppMode().getStringKey() @@ -542,9 +547,27 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return R.color.status_bar_transparent_gradient; } + private void approximateGpx() { + if (gpxApproximator != null) { + try { + GpxRouteApproximation gpxApproximation = gpxApproximator.calculateGpxApproximation(); + displayApproximatedPoints(gpxApproximation); + } catch (IOException e) { + } catch (InterruptedException e) { + } + } + } + @Override public void onChangeGpxApproxDistanceThreshold(ApplicationMode mode, int distanceThreshold) { - + if (gpxApproximator != null) { + try { + gpxApproximator.setMode(mode); + gpxApproximator.setPointApproximation(distanceThreshold); + approximateGpx(); + } catch (IOException e) { + } + } } @Override @@ -636,7 +659,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route case SnapTrackWarningBottomSheet.CONTINUE_REQUEST_CODE: MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { - GpxApproximationFragment.showInstance(mapActivity.getSupportFragmentManager(), this); + try { + gpxApproximator = new GpxApproximator(requireMyApplication(), new LocationsHolder(editingCtx.getPoints())); + GpxApproximationFragment.showInstance(mapActivity.getSupportFragmentManager(), + this, gpxApproximator.getMode(), (int) gpxApproximator.getPointApproximation()); + } catch (IOException e) { + + } } break; } @@ -1050,8 +1079,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } private void displayRoutePoints() { - final MeasurementToolLayer measurementLayer = getMeasurementLayer(); - + MeasurementToolLayer measurementLayer = getMeasurementLayer(); GPXFile gpx = editingCtx.getNewGpxData().getGpxFile(); List points = gpx.getRoutePoints(); if (measurementLayer != null) { @@ -1062,7 +1090,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } private void displaySegmentPoints() { - final MeasurementToolLayer measurementLayer = getMeasurementLayer(); + MeasurementToolLayer measurementLayer = getMeasurementLayer(); if (measurementLayer != null) { editingCtx.addPoints(); adapter.notifyDataSetChanged(); @@ -1070,6 +1098,15 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } + private void displayApproximatedPoints(GpxRouteApproximation gpxApproximation) { + MeasurementToolLayer measurementLayer = getMeasurementLayer(); + if (measurementLayer != null) { + editingCtx.setPoints(gpxApproximation); + adapter.notifyDataSetChanged(); + updateDistancePointsText(); + } + } + private void openSelectedPointMenu(MapActivity mapActivity) { SelectedPointBottomSheetDialogFragment fragment = new SelectedPointBottomSheetDialogFragment(); fragment.setUsedOnMap(true); diff --git a/OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java b/OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java new file mode 100644 index 0000000000..318fbd63e9 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java @@ -0,0 +1,85 @@ +package net.osmand.plus.routing; + +import net.osmand.LocationsHolder; +import net.osmand.data.LatLon; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.routing.RouteProvider.RoutingEnvironment; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.router.RoutePlannerFrontEnd.GpxPoint; +import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation; + +import java.io.IOException; +import java.util.List; + +public class GpxApproximator { + + private OsmandApplication ctx; + private RoutingHelper routingHelper; + + private RoutingEnvironment env; + private GpxRouteApproximation gctx; + private ApplicationMode mode; + private LocationsHolder locationsHolder; + private List points; + private LatLon start; + private LatLon end; + + public GpxApproximator(OsmandApplication ctx, LocationsHolder locationsHolder) throws IOException { + this.ctx = ctx; + this.locationsHolder = locationsHolder; + this.routingHelper = ctx.getRoutingHelper(); + this.mode = ApplicationMode.CAR; + if (locationsHolder.getSize() > 1) { + start = locationsHolder.getLatLon(0); + end = locationsHolder.getLatLon(locationsHolder.getSize() - 1); + prepareEnvironment(ctx, mode); + this.points = routingHelper.generateGpxPoints(env, gctx, locationsHolder); + } + } + + public GpxApproximator(OsmandApplication ctx, ApplicationMode mode, double pointApproximation, LocationsHolder locationsHolder) throws IOException { + this.ctx = ctx; + this.routingHelper = ctx.getRoutingHelper(); + this.mode = mode; + if (locationsHolder.getSize() > 1) { + start = locationsHolder.getLatLon(0); + end = locationsHolder.getLatLon(locationsHolder.getSize() - 1); + prepareEnvironment(ctx, mode); + gctx.MINIMUM_POINT_APPROXIMATION = pointApproximation; + this.points = routingHelper.generateGpxPoints(env, gctx, locationsHolder); + } + } + + private void prepareEnvironment(OsmandApplication ctx, ApplicationMode mode) throws IOException { + this.env = routingHelper.getRoutingEnvironment(ctx, mode, start, end); + this.gctx = new GpxRouteApproximation(env.getCtx()); + } + + public ApplicationMode getMode() { + return mode; + } + + public void setMode(ApplicationMode mode) throws IOException { + boolean changed = this.mode != mode; + this.mode = mode; + if (changed) { + prepareEnvironment(ctx, mode); + } + } + + public double getPointApproximation() { + return gctx.MINIMUM_POINT_APPROXIMATION; + } + + public void setPointApproximation(double pointApproximation) { + gctx.MINIMUM_POINT_APPROXIMATION = pointApproximation; + } + + public LocationsHolder getLocationsHolder() { + return locationsHolder; + } + + public GpxRouteApproximation calculateGpxApproximation() throws IOException, InterruptedException { + return routingHelper.calculateGpxApproximation(env, gctx, points); + } +} diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index bcad053301..6aaac45c1d 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -13,6 +13,7 @@ import net.osmand.GPXUtilities.Track; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.GPXUtilities.WptPt; import net.osmand.Location; +import net.osmand.LocationsHolder; import net.osmand.PlatformUtil; import net.osmand.binary.BinaryMapIndexReader; import net.osmand.data.LatLon; @@ -35,6 +36,8 @@ import net.osmand.router.PrecalculatedRouteDirection; import net.osmand.router.RouteExporter; import net.osmand.router.RouteImporter; import net.osmand.router.RoutePlannerFrontEnd; +import net.osmand.router.RoutePlannerFrontEnd.GpxPoint; +import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation; import net.osmand.router.RoutePlannerFrontEnd.RouteCalculationMode; import net.osmand.router.RouteSegmentResult; import net.osmand.router.RoutingConfiguration; @@ -120,6 +123,36 @@ public class RouteProvider { } } + public static class RoutingEnvironment { + private RoutePlannerFrontEnd router; + private RoutingContext ctx; + private RoutingContext complexCtx; + private PrecalculatedRouteDirection precalculated; + + public RoutingEnvironment(RoutePlannerFrontEnd router, RoutingContext ctx, RoutingContext complexCtx, PrecalculatedRouteDirection precalculated) { + this.router = router; + this.ctx = ctx; + this.complexCtx = complexCtx; + this.precalculated = precalculated; + } + + public RoutePlannerFrontEnd getRouter() { + return router; + } + + public RoutingContext getCtx() { + return ctx; + } + + public RoutingContext getComplexCtx() { + return complexCtx; + } + + public PrecalculatedRouteDirection getPrecalculated() { + return precalculated; + } + } + public RouteProvider() { } @@ -670,7 +703,29 @@ public class RouteProvider { return ctx.getString(resId); } - protected RouteCalculationResult findVectorMapsRoute(final RouteCalculationParams params, boolean calcGPXRoute) throws IOException { + public RoutingEnvironment getRoutingEnvironment(OsmandApplication ctx, ApplicationMode mode, LatLon start, LatLon end) throws IOException { + RouteCalculationParams params = new RouteCalculationParams(); + params.ctx = ctx; + params.mode = mode; + params.start = new Location("", start.getLatitude(), start.getLongitude()); + params.end = end; + return calculateRoutingEnvironment(params, false, true); + } + + public List generateGpxPoints(RoutingEnvironment env, GpxRouteApproximation gctx, LocationsHolder locationsHolder) { + return env.router.generateGpxPoints(gctx, locationsHolder); + } + + public GpxRouteApproximation calculateGpxPointsApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List points) throws IOException, InterruptedException { + if (points != null && points.size() > 1) { + if (!Algorithms.isEmpty(points)) { + return env.router.searchGpxRoute(gctx, points); + } + } + return null; + } + + protected RoutingEnvironment calculateRoutingEnvironment(RouteCalculationParams params, boolean calcGPXRoute, boolean skipComplex) throws IOException { BinaryMapIndexReader[] files = params.ctx.getResourceManager().getRoutingMapFiles(); RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(); OsmandSettings settings = params.ctx.getSettings(); @@ -679,18 +734,18 @@ public class RouteProvider { RoutingConfiguration.Builder config = params.ctx.getRoutingConfigForMode(params.mode); GeneralRouter generalRouter = params.ctx.getRouter(config, params.mode); if (generalRouter == null) { - return applicationModeNotSupported(params); + return null; } RoutingConfiguration cf = initOsmAndRoutingConfig(config, params, settings, generalRouter); - if(cf == null){ - return applicationModeNotSupported(params); + if (cf == null) { + return null; } PrecalculatedRouteDirection precalculated = null; - if(calcGPXRoute) { + if (calcGPXRoute) { ArrayList sublist = findStartAndEndLocationsFromRoute(params.gpxRoute.points, params.start, params.end, null, null); LatLon[] latLon = new LatLon[sublist.size()]; - for(int k = 0; k < latLon.length; k ++) { + for (int k = 0; k < latLon.length; k++) { latLon[k] = new LatLon(sublist.get(k).getLatitude(), sublist.get(k).getLongitude()); } precalculated = PrecalculatedRouteDirection.build(latLon, generalRouter.getMaxSpeed()); @@ -717,46 +772,50 @@ public class RouteProvider { rightX = Math.max(MapUtils.get31TileNumberX(l.getLongitude()), rightX); bottomY = Math.max(MapUtils.get31TileNumberY(l.getLatitude()), bottomY); topY = Math.min(MapUtils.get31TileNumberY(l.getLatitude()), topY); - + params.ctx.getResourceManager().getRenderer().checkInitialized(15, lib, leftX, rightX, bottomY, topY); - - RoutingContext ctx = router.buildRoutingContext(cf, - lib, files, - RouteCalculationMode.NORMAL); - + + RoutingContext ctx = router.buildRoutingContext(cf, lib, files, RouteCalculationMode.NORMAL); + RoutingContext complexCtx = null; - boolean complex = params.mode.isDerivedRoutingFrom(ApplicationMode.CAR) && !settings.DISABLE_COMPLEX_ROUTING.get() + boolean complex = !skipComplex && params.mode.isDerivedRoutingFrom(ApplicationMode.CAR) && !settings.DISABLE_COMPLEX_ROUTING.get() && precalculated == null; ctx.leftSideNavigation = params.leftSide; ctx.calculationProgress = params.calculationProgress; ctx.publicTransport = params.inPublicTransportMode; ctx.startTransportStop = params.startTransportStop; ctx.targetTransportStop = params.targetTransportStop; - if(params.previousToRecalculate != null && params.onlyStartPointChanged) { + if (params.previousToRecalculate != null && params.onlyStartPointChanged) { int currentRoute = params.previousToRecalculate.getCurrentRoute(); List originalRoute = params.previousToRecalculate.getOriginalRoute(); - if(originalRoute != null && currentRoute < originalRoute.size()) { + if (originalRoute != null && currentRoute < originalRoute.size()) { ctx.previouslyCalculatedRoute = originalRoute.subList(currentRoute, originalRoute.size()); } } - if(complex && router.getRecalculationEnd(ctx) != null) { + if (complex && router.getRecalculationEnd(ctx) != null) { complex = false; } - if(complex) { - complexCtx = router.buildRoutingContext(cf, lib,files, - RouteCalculationMode.COMPLEX); + if (complex) { + complexCtx = router.buildRoutingContext(cf, lib, files, RouteCalculationMode.COMPLEX); complexCtx.calculationProgress = params.calculationProgress; complexCtx.leftSideNavigation = params.leftSide; complexCtx.previouslyCalculatedRoute = ctx.previouslyCalculatedRoute; } + return new RoutingEnvironment(router, ctx, complexCtx, precalculated); + } + protected RouteCalculationResult findVectorMapsRoute(final RouteCalculationParams params, boolean calcGPXRoute) throws IOException { + RoutingEnvironment env = calculateRoutingEnvironment(params, calcGPXRoute, false); + if (env == null) { + return applicationModeNotSupported(params); + } LatLon st = new LatLon(params.start.getLatitude(), params.start.getLongitude()); LatLon en = new LatLon(params.end.getLatitude(), params.end.getLongitude()); - List inters = new ArrayList(); + List inters = new ArrayList(); if (params.intermediates != null) { - inters = new ArrayList(params.intermediates); + inters = new ArrayList(params.intermediates); } - return calcOfflineRouteImpl(params, router, ctx, complexCtx, st, en, inters, precalculated); + return calcOfflineRouteImpl(params, env.router, env.ctx, env.complexCtx, st, en, inters, env.precalculated); } private RoutingConfiguration initOsmAndRoutingConfig(Builder config, final RouteCalculationParams params, OsmandSettings settings, diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java index 7d1c9696d2..0899b586a9 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java @@ -1,13 +1,17 @@ package net.osmand.plus.routing; +import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; +import net.osmand.GPXUtilities.WptPt; import net.osmand.Location; +import net.osmand.LocationsHolder; import net.osmand.PlatformUtil; import net.osmand.ValueHolder; import net.osmand.binary.RouteDataObject; import net.osmand.data.LatLon; import net.osmand.data.QuadPoint; +import net.osmand.plus.routing.RouteProvider.RoutingEnvironment; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.NavigationService; import net.osmand.plus.settings.backend.OsmAndAppCustomization.OsmAndAppCustomizationListener; @@ -24,11 +28,15 @@ import net.osmand.plus.routing.RouteProvider.GPXRouteParamsBuilder; import net.osmand.plus.routing.RouteProvider.RouteService; import net.osmand.router.RouteCalculationProgress; import net.osmand.router.RouteExporter; +import net.osmand.router.RoutePlannerFrontEnd; +import net.osmand.router.RoutePlannerFrontEnd.GpxPoint; +import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation; import net.osmand.router.RouteSegmentResult; import net.osmand.router.TurnType; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; +import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Iterator; @@ -1344,12 +1352,24 @@ public class RoutingHelper { return generateGPXFileWithRoute(route, name); } - public GPXFile generateGPXFileWithRoute(RouteCalculationResult route, String name){ + public GPXFile generateGPXFileWithRoute(RouteCalculationResult route, String name) { return provider.createOsmandRouterGPX(route, app, name); } + public RoutingEnvironment getRoutingEnvironment(OsmandApplication ctx, ApplicationMode mode, LatLon start, LatLon end) throws IOException { + return provider.getRoutingEnvironment(ctx, mode, start, end); + } + + public List generateGpxPoints(RoutingEnvironment env, GpxRouteApproximation gctx, LocationsHolder locationsHolder) { + return provider.generateGpxPoints(env, gctx, locationsHolder); + } + + public GpxRouteApproximation calculateGpxApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List points) throws IOException, InterruptedException { + return provider.calculateGpxPointsApproximation(env, gctx, points); + } + public void notifyIfRouteIsCalculated() { - if(route.isCalculated()) { + if (route.isCalculated()) { voiceRouter.newRouteIsCalculated(true) ; } }