WIP - Gpx approximation

This commit is contained in:
max-klaus 2020-08-08 19:35:57 +03:00
parent c9a1fd05bf
commit 355d6bb309
9 changed files with 460 additions and 56 deletions

View file

@ -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<LatLon> latLonList;
private List<Location> locationList;
private List<WptPt> 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<LatLon>) locations;
size = locations.size();
break;
case LOCATION_TYPE_LOCATION:
locationList = (List<Location>) locations;
size = locations.size();
break;
case LOCATION_TYPE_WPTPT:
wptPtList = (List<WptPt>) 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 <T> List<T> getList(int locationType) {
List<T> 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<LatLon> getLatLonList() {
if (this.locationType == LOCATION_TYPE_LATLON) {
return latLonList;
} else {
return getList(LOCATION_TYPE_LATLON);
}
}
public List<WptPt> getWptPtList() {
if (this.locationType == LOCATION_TYPE_WPTPT) {
return wptPtList;
} else {
return getList(LOCATION_TYPE_WPTPT);
}
}
public List<Location> 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));
}
}
}

View file

@ -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<LatLon> points) throws IOException, InterruptedException {
public GpxRouteApproximation searchGpxRoute(GpxRouteApproximation gctx, List<GpxPoint> gpxPoints) throws IOException, InterruptedException {
long timeToCalculate = System.nanoTime();
if (gctx.ctx.calculationProgress == null) {
gctx.ctx.calculationProgress = new RouteCalculationProgress();
}
gctx.ctx.keepNativeRoutingContext = true;
List<GpxPoint> 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<GpxPoint> generageGpxPoints(List<LatLon> points, GpxRouteApproximation gctx) {
List<GpxPoint> gpxPoints = new ArrayList<>(points.size());
public List<GpxPoint> generateGpxPoints(GpxRouteApproximation gctx, LocationsHolder locationsHolder) {
List<GpxPoint> 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;
}

View file

@ -16,9 +16,9 @@
<FrameLayout
android:id="@+id/bottom_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@drawable/bg_contextmenu_shadow"
android:foregroundGravity="top|fill_horizontal">
android:layout_height="match_parent">
<include layout="@layout/plan_route_progress_bar"/>
<net.osmand.plus.LockableScrollView
android:id="@+id/route_menu_bottom_scroll"

View file

@ -226,11 +226,13 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
return (menuState & (MenuState.HEADER_ONLY | MenuState.HALF_SCREEN)) != 0;
}
public static void showInstance(FragmentManager fm, Fragment targetFragment) {
public static void showInstance(@NonNull FragmentManager fm, @Nullable Fragment targetFragment, @NonNull ApplicationMode initialAppMode, int initialDistanceThreshold) {
try {
if (!fm.isStateSaved()) {
GpxApproximationFragment fragment = new GpxApproximationFragment();
fragment.setTargetFragment(targetFragment, 0);
fragment.snapToRoadAppMode = initialAppMode;
fragment.distanceThreshold = initialDistanceThreshold;
fm.beginTransaction()
.replace(R.id.fragmentContainer, fragment, TAG)
.addToBackStack(TAG)

View file

@ -17,6 +17,11 @@ import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.router.RouteCalculationProgress;
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.util.Algorithms;
import net.osmand.util.MapUtils;
import java.util.ArrayList;
@ -289,9 +294,13 @@ public class MeasurementEditingContext {
}
void addPoints() {
List<WptPt> points = getNewGpxData().getTrkSegment().points;
if (isSnapToRoadTrack()) {
List<WptPt> routePoints = getNewGpxData().getGpxFile().getRoutePoints();
NewGpxData newGpxData = getNewGpxData();
if (newGpxData == null || newGpxData.getTrkSegment() == null || Algorithms.isEmpty(newGpxData.getTrkSegment().points)) {
return;
}
List<WptPt> points = newGpxData.getTrkSegment().points;
if (isTrackSnappedToRoad()) {
List<WptPt> routePoints = newGpxData.getGpxFile().getRoutePoints();
int prevPointIndex = 0;
for (int i = 0; i < routePoints.size() - 1; i++) {
Pair<WptPt, WptPt> 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<GpxPoint> 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<WptPt, WptPt> pair = new Pair<>(p1, p2);
List<WptPt> 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<WptPt> 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) {

View file

@ -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<WptPt> 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);

View file

@ -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<GpxPoint> 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);
}
}

View file

@ -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<GpxPoint> generateGpxPoints(RoutingEnvironment env, GpxRouteApproximation gctx, LocationsHolder locationsHolder) {
return env.router.generateGpxPoints(gctx, locationsHolder);
}
public GpxRouteApproximation calculateGpxPointsApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List<GpxPoint> 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<Location> 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<RouteSegmentResult> 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<LatLon> inters = new ArrayList<LatLon>();
List<LatLon> inters = new ArrayList<LatLon>();
if (params.intermediates != null) {
inters = new ArrayList<LatLon>(params.intermediates);
inters = new ArrayList<LatLon>(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,

View file

@ -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<GpxPoint> generateGpxPoints(RoutingEnvironment env, GpxRouteApproximation gctx, LocationsHolder locationsHolder) {
return provider.generateGpxPoints(env, gctx, locationsHolder);
}
public GpxRouteApproximation calculateGpxApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List<GpxPoint> points) throws IOException, InterruptedException {
return provider.calculateGpxPointsApproximation(env, gctx, points);
}
public void notifyIfRouteIsCalculated() {
if(route.isCalculated()) {
if (route.isCalculated()) {
voiceRouter.newRouteIsCalculated(true) ;
}
}