WIP - Gpx approximation
This commit is contained in:
parent
c9a1fd05bf
commit
355d6bb309
9 changed files with 460 additions and 56 deletions
159
OsmAnd-java/src/main/java/net/osmand/LocationsHolder.java
Normal file
159
OsmAnd-java/src/main/java/net/osmand/LocationsHolder.java
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
85
OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java
Normal file
85
OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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) ;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue