Gpx approximation in progress
This commit is contained in:
parent
44b84bf65d
commit
2ab38a54b5
10 changed files with 358 additions and 110 deletions
|
@ -25,15 +25,15 @@ public class LocationsHolder {
|
||||||
this.locationType = resolveLocationType(locations);
|
this.locationType = resolveLocationType(locations);
|
||||||
switch (locationType) {
|
switch (locationType) {
|
||||||
case LOCATION_TYPE_LATLON:
|
case LOCATION_TYPE_LATLON:
|
||||||
latLonList = (List<LatLon>) locations;
|
latLonList = new ArrayList<>((List<LatLon>) locations);
|
||||||
size = locations.size();
|
size = locations.size();
|
||||||
break;
|
break;
|
||||||
case LOCATION_TYPE_LOCATION:
|
case LOCATION_TYPE_LOCATION:
|
||||||
locationList = (List<Location>) locations;
|
locationList = new ArrayList<>((List<Location>) locations);
|
||||||
size = locations.size();
|
size = locations.size();
|
||||||
break;
|
break;
|
||||||
case LOCATION_TYPE_WPTPT:
|
case LOCATION_TYPE_WPTPT:
|
||||||
wptPtList = (List<WptPt>) locations;
|
wptPtList = new ArrayList<>((List<WptPt>) locations);
|
||||||
size = locations.size();
|
size = locations.size();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ package net.osmand.router;
|
||||||
import net.osmand.LocationsHolder;
|
import net.osmand.LocationsHolder;
|
||||||
import net.osmand.NativeLibrary;
|
import net.osmand.NativeLibrary;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.ResultMatcher;
|
||||||
import net.osmand.binary.BinaryMapIndexReader;
|
import net.osmand.binary.BinaryMapIndexReader;
|
||||||
import net.osmand.binary.BinaryMapRouteReaderAdapter;
|
import net.osmand.binary.BinaryMapRouteReaderAdapter;
|
||||||
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
|
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
|
||||||
|
@ -63,16 +64,28 @@ public class RoutePlannerFrontEnd {
|
||||||
public int routeGapDistance;
|
public int routeGapDistance;
|
||||||
public int routeDistanceUnmatched;
|
public int routeDistanceUnmatched;
|
||||||
|
|
||||||
|
public boolean calculationCancelled;
|
||||||
|
private boolean calculationDone;
|
||||||
|
|
||||||
public GpxRouteApproximation(RoutingContext ctx) {
|
public GpxRouteApproximation(RoutingContext ctx) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GpxRouteApproximation(GpxRouteApproximation gctx) {
|
||||||
|
this.ctx = gctx.ctx;
|
||||||
|
this.routeDistance = gctx.routeDistance;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format(">> GPX approximation (%d of %d m route calcs, %d route points searched) for %d m: %d m umatched",
|
return String.format(">> GPX approximation (%d of %d m route calcs, %d route points searched) for %d m: %d m umatched",
|
||||||
routeCalculations, routeDistCalculations, routePointsSearched, routeDistance, routeDistanceUnmatched);
|
routeCalculations, routeDistCalculations, routePointsSearched, routeDistance, routeDistanceUnmatched);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCalculationDone() {
|
||||||
|
return calculationDone;
|
||||||
|
}
|
||||||
|
|
||||||
public double distFromLastPoint(LatLon startPoint) {
|
public double distFromLastPoint(LatLon startPoint) {
|
||||||
if (result.size() > 0) {
|
if (result.size() > 0) {
|
||||||
return MapUtils.getDistance(getLastPoint(), startPoint);
|
return MapUtils.getDistance(getLastPoint(), startPoint);
|
||||||
|
@ -97,6 +110,15 @@ public class RoutePlannerFrontEnd {
|
||||||
public List<RouteSegmentResult> stepBackRoute;
|
public List<RouteSegmentResult> stepBackRoute;
|
||||||
public int targetInd = -1;
|
public int targetInd = -1;
|
||||||
public boolean straightLine = false;
|
public boolean straightLine = false;
|
||||||
|
|
||||||
|
public GpxPoint() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public GpxPoint(GpxPoint point) {
|
||||||
|
this.ind = point.ind;
|
||||||
|
this.loc = point.loc;
|
||||||
|
this.cumDist = point.cumDist;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RoutingContext buildRoutingContext(RoutingConfiguration config, NativeLibrary nativeLibrary, BinaryMapIndexReader[] map, RouteCalculationMode rm) {
|
public RoutingContext buildRoutingContext(RoutingConfiguration config, NativeLibrary nativeLibrary, BinaryMapIndexReader[] map, RouteCalculationMode rm) {
|
||||||
|
@ -206,7 +228,6 @@ public class RoutePlannerFrontEnd {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, LatLon start, LatLon end, List<LatLon> intermediates) throws IOException, InterruptedException {
|
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, LatLon start, LatLon end, List<LatLon> intermediates) throws IOException, InterruptedException {
|
||||||
return searchRoute(ctx, start, end, intermediates, null);
|
return searchRoute(ctx, start, end, intermediates, null);
|
||||||
}
|
}
|
||||||
|
@ -215,11 +236,8 @@ public class RoutePlannerFrontEnd {
|
||||||
useSmartRouteRecalculation = use;
|
useSmartRouteRecalculation = use;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GpxRouteApproximation searchGpxRoute(GpxRouteApproximation gctx, List<GpxPoint> gpxPoints) throws IOException, InterruptedException {
|
public GpxRouteApproximation searchGpxRoute(GpxRouteApproximation gctx, List<GpxPoint> gpxPoints, ResultMatcher<GpxRouteApproximation> resultMatcher) throws IOException, InterruptedException {
|
||||||
long timeToCalculate = System.nanoTime();
|
long timeToCalculate = System.nanoTime();
|
||||||
if (gctx.ctx.calculationProgress == null) {
|
|
||||||
gctx.ctx.calculationProgress = new RouteCalculationProgress();
|
|
||||||
}
|
|
||||||
gctx.ctx.keepNativeRoutingContext = true;
|
gctx.ctx.keepNativeRoutingContext = true;
|
||||||
GpxPoint start = null;
|
GpxPoint start = null;
|
||||||
GpxPoint prev = null;
|
GpxPoint prev = null;
|
||||||
|
@ -227,7 +245,7 @@ public class RoutePlannerFrontEnd {
|
||||||
gctx.ctx.calculationProgress.totalIterations = (int) (gpxPoints.get(gpxPoints.size() - 1).cumDist / gctx.MAXIMUM_STEP_APPROXIMATION + 1);
|
gctx.ctx.calculationProgress.totalIterations = (int) (gpxPoints.get(gpxPoints.size() - 1).cumDist / gctx.MAXIMUM_STEP_APPROXIMATION + 1);
|
||||||
start = gpxPoints.get(0);
|
start = gpxPoints.get(0);
|
||||||
}
|
}
|
||||||
while (start != null) {
|
while (start != null && !gctx.calculationCancelled) {
|
||||||
double routeDist = gctx.MAXIMUM_STEP_APPROXIMATION;
|
double routeDist = gctx.MAXIMUM_STEP_APPROXIMATION;
|
||||||
GpxPoint next = findNextGpxPointWithin(gctx, gpxPoints, start, routeDist);
|
GpxPoint next = findNextGpxPointWithin(gctx, gpxPoints, start, routeDist);
|
||||||
boolean routeFound = false;
|
boolean routeFound = false;
|
||||||
|
@ -287,10 +305,14 @@ public class RoutePlannerFrontEnd {
|
||||||
gctx.ctx.deleteNativeRoutingContext();
|
gctx.ctx.deleteNativeRoutingContext();
|
||||||
BinaryRoutePlanner.printDebugMemoryInformation(gctx.ctx);
|
BinaryRoutePlanner.printDebugMemoryInformation(gctx.ctx);
|
||||||
calculateGpxRoute(gctx, gpxPoints);
|
calculateGpxRoute(gctx, gpxPoints);
|
||||||
if (!gctx.result.isEmpty()) {
|
if (!gctx.result.isEmpty() && !gctx.calculationCancelled) {
|
||||||
new RouteResultPreparation().printResults(gctx.ctx, gpxPoints.get(0).loc, gpxPoints.get(gpxPoints.size() - 1).loc, gctx.result);
|
new RouteResultPreparation().printResults(gctx.ctx, gpxPoints.get(0).loc, gpxPoints.get(gpxPoints.size() - 1).loc, gctx.result);
|
||||||
System.out.println(gctx);
|
System.out.println(gctx);
|
||||||
}
|
}
|
||||||
|
if (resultMatcher != null) {
|
||||||
|
resultMatcher.publish(gctx);
|
||||||
|
}
|
||||||
|
gctx.calculationDone = true;
|
||||||
return gctx;
|
return gctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +365,7 @@ public class RoutePlannerFrontEnd {
|
||||||
reg.initRouteEncodingRule(0, "highway", RouteResultPreparation.UNMATCHED_HIGHWAY_TYPE);
|
reg.initRouteEncodingRule(0, "highway", RouteResultPreparation.UNMATCHED_HIGHWAY_TYPE);
|
||||||
List<LatLon> lastStraightLine = null;
|
List<LatLon> lastStraightLine = null;
|
||||||
GpxPoint straightPointStart = null;
|
GpxPoint straightPointStart = null;
|
||||||
for (int i = 0; i < gpxPoints.size(); ) {
|
for (int i = 0; i < gpxPoints.size() && !gctx.calculationCancelled; ) {
|
||||||
GpxPoint pnt = gpxPoints.get(i);
|
GpxPoint pnt = gpxPoints.get(i);
|
||||||
if (pnt.routeToTarget != null && !pnt.routeToTarget.isEmpty()) {
|
if (pnt.routeToTarget != null && !pnt.routeToTarget.isEmpty()) {
|
||||||
LatLon startPoint = pnt.routeToTarget.get(0).getStartPoint();
|
LatLon startPoint = pnt.routeToTarget.get(0).getStartPoint();
|
||||||
|
@ -402,7 +424,7 @@ public class RoutePlannerFrontEnd {
|
||||||
private void cleanupResultAndAddTurns(GpxRouteApproximation gctx) {
|
private void cleanupResultAndAddTurns(GpxRouteApproximation gctx) {
|
||||||
// cleanup double joints
|
// cleanup double joints
|
||||||
int LOOK_AHEAD = 4;
|
int LOOK_AHEAD = 4;
|
||||||
for(int i = 0; i < gctx.result.size(); i++) {
|
for(int i = 0; i < gctx.result.size() && !gctx.calculationCancelled; i++) {
|
||||||
RouteSegmentResult s = gctx.result.get(i);
|
RouteSegmentResult s = gctx.result.get(i);
|
||||||
for(int j = i + 2; j <= i + LOOK_AHEAD && j < gctx.result.size(); j++) {
|
for(int j = i + 2; j <= i + LOOK_AHEAD && j < gctx.result.size(); j++) {
|
||||||
RouteSegmentResult e = gctx.result.get(j);
|
RouteSegmentResult e = gctx.result.get(j);
|
||||||
|
@ -419,8 +441,10 @@ public class RoutePlannerFrontEnd {
|
||||||
r.setTurnType(null);
|
r.setTurnType(null);
|
||||||
r.setDescription("");
|
r.setDescription("");
|
||||||
}
|
}
|
||||||
|
if (!gctx.calculationCancelled) {
|
||||||
preparation.prepareTurnResults(gctx.ctx, gctx.result);
|
preparation.prepareTurnResults(gctx.ctx, gctx.result);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addStraightLine(GpxRouteApproximation gctx, List<LatLon> lastStraightLine, GpxPoint strPnt, RouteRegion reg) {
|
private void addStraightLine(GpxRouteApproximation gctx, List<LatLon> lastStraightLine, GpxPoint strPnt, RouteRegion reg) {
|
||||||
RouteDataObject rdo = new RouteDataObject(reg);
|
RouteDataObject rdo = new RouteDataObject(reg);
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<include layout="@layout/plan_route_progress_bar"/>
|
|
||||||
|
|
||||||
<net.osmand.plus.LockableScrollView
|
<net.osmand.plus.LockableScrollView
|
||||||
android:id="@+id/route_menu_bottom_scroll"
|
android:id="@+id/route_menu_bottom_scroll"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -37,6 +35,9 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</net.osmand.plus.LockableScrollView>
|
</net.osmand.plus.LockableScrollView>
|
||||||
|
|
||||||
|
<include layout="@layout/plan_route_progress_bar"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -54,6 +54,7 @@ import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.ColorRes;
|
import androidx.annotation.ColorRes;
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.content.res.AppCompatResources;
|
import androidx.appcompat.content.res.AppCompatResources;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
|
@ -169,11 +170,11 @@ public class AndroidUtils {
|
||||||
return intent.resolveActivity(context.getPackageManager()) != null;
|
return intent.resolveActivity(context.getPackageManager()) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isActivityNotDestroyed(Activity activity) {
|
public static boolean isActivityNotDestroyed(@Nullable Activity activity) {
|
||||||
if (Build.VERSION.SDK_INT >= 17) {
|
if (Build.VERSION.SDK_INT >= 17) {
|
||||||
return !activity.isFinishing() && !activity.isDestroyed();
|
return activity != null && !activity.isFinishing() && !activity.isDestroyed();
|
||||||
}
|
}
|
||||||
return !activity.isFinishing();
|
return activity != null && !activity.isFinishing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Spannable replaceCharsWithIcon(String text, Drawable icon, String[] chars) {
|
public static Spannable replaceCharsWithIcon(String text, Drawable icon, String[] chars) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
@ -15,18 +16,25 @@ import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
import net.osmand.AndroidUtils;
|
import net.osmand.AndroidUtils;
|
||||||
|
import net.osmand.LocationsHolder;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.ResultMatcher;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.UiUtilities;
|
import net.osmand.plus.UiUtilities;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.base.ContextMenuScrollFragment;
|
import net.osmand.plus.base.ContextMenuScrollFragment;
|
||||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
|
import net.osmand.plus.routing.GpxApproximator;
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
|
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import static net.osmand.plus.measurementtool.ProfileCard.*;
|
import java.io.IOException;
|
||||||
import static net.osmand.plus.measurementtool.SliderCard.*;
|
|
||||||
|
import static net.osmand.plus.measurementtool.ProfileCard.ProfileCardListener;
|
||||||
|
import static net.osmand.plus.measurementtool.SliderCard.SliderCardListener;
|
||||||
|
|
||||||
public class GpxApproximationFragment extends ContextMenuScrollFragment
|
public class GpxApproximationFragment extends ContextMenuScrollFragment
|
||||||
implements SliderCardListener, ProfileCardListener {
|
implements SliderCardListener, ProfileCardListener {
|
||||||
|
@ -36,9 +44,16 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
||||||
public static final String DISTANCE_THRESHOLD_KEY = "distance_threshold";
|
public static final String DISTANCE_THRESHOLD_KEY = "distance_threshold";
|
||||||
public static final String SNAP_TO_ROAD_APP_MODE_STRING_KEY = "snap_to_road_app_mode";
|
public static final String SNAP_TO_ROAD_APP_MODE_STRING_KEY = "snap_to_road_app_mode";
|
||||||
|
|
||||||
|
public static final int REQUEST_CODE = 1100;
|
||||||
|
|
||||||
private int menuTitleHeight;
|
private int menuTitleHeight;
|
||||||
private ApplicationMode snapToRoadAppMode = ApplicationMode.CAR;
|
private ApplicationMode snapToRoadAppMode = ApplicationMode.CAR;
|
||||||
private int distanceThreshold = 30;
|
private int distanceThreshold = 50;
|
||||||
|
|
||||||
|
private LocationsHolder locationsHolder;
|
||||||
|
@Nullable
|
||||||
|
private GpxApproximator gpxApproximator;
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMainLayoutId() {
|
public int getMainLayoutId() {
|
||||||
|
@ -85,6 +100,43 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
||||||
distanceThreshold = savedInstanceState.getInt(DISTANCE_THRESHOLD_KEY);
|
distanceThreshold = savedInstanceState.getInt(DISTANCE_THRESHOLD_KEY);
|
||||||
snapToRoadAppMode = ApplicationMode.valueOfStringKey(
|
snapToRoadAppMode = ApplicationMode.valueOfStringKey(
|
||||||
savedInstanceState.getString(SNAP_TO_ROAD_APP_MODE_STRING_KEY), ApplicationMode.CAR);
|
savedInstanceState.getString(SNAP_TO_ROAD_APP_MODE_STRING_KEY), ApplicationMode.CAR);
|
||||||
|
try {
|
||||||
|
gpxApproximator = new GpxApproximator(requireMyApplication(), snapToRoadAppMode, distanceThreshold, locationsHolder);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
gpxApproximator = new GpxApproximator(requireMyApplication(), locationsHolder);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpxApproximator != null) {
|
||||||
|
gpxApproximator.setApproximationProgress(new GpxApproximator.GpxApproximationProgressCallback() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if (isResumed()) {
|
||||||
|
startProgress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateProgress(int progress) {
|
||||||
|
if (isResumed()) {
|
||||||
|
GpxApproximationFragment.this.updateProgress(progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
if (isResumed()) {
|
||||||
|
finishProgress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPortrait()) {
|
if (isPortrait()) {
|
||||||
|
@ -93,6 +145,12 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
||||||
updateCards();
|
updateCards();
|
||||||
updateButtons(mainView);
|
updateButtons(mainView);
|
||||||
|
|
||||||
|
progressBar = mainView.findViewById(R.id.progress_bar);
|
||||||
|
if (progressBar != null) {
|
||||||
|
requireMapActivity().setupRouteCalculationProgressBar(progressBar);
|
||||||
|
progressBar.setIndeterminate(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (!isPortrait()) {
|
if (!isPortrait()) {
|
||||||
int widthNoShadow = getLandscapeNoShadowWidth();
|
int widthNoShadow = getLandscapeNoShadowWidth();
|
||||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT);
|
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
@ -102,6 +160,8 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
||||||
enterGpxApproximationMode();
|
enterGpxApproximationMode();
|
||||||
runLayoutListener();
|
runLayoutListener();
|
||||||
|
|
||||||
|
calculateGpxApproximation();
|
||||||
|
|
||||||
return mainView;
|
return mainView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +219,7 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Fragment fragment = getTargetFragment();
|
Fragment fragment = getTargetFragment();
|
||||||
if (fragment instanceof GpxApproximationFragmentListener) {
|
if (fragment instanceof GpxApproximationFragmentListener) {
|
||||||
((GpxApproximationFragmentListener) fragment).onApplyGpxApproximation(snapToRoadAppMode, distanceThreshold);
|
((GpxApproximationFragmentListener) fragment).onApplyGpxApproximation();
|
||||||
}
|
}
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
|
@ -226,13 +286,13 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
||||||
return (menuState & (MenuState.HEADER_ONLY | MenuState.HALF_SCREEN)) != 0;
|
return (menuState & (MenuState.HEADER_ONLY | MenuState.HALF_SCREEN)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showInstance(@NonNull FragmentManager fm, @Nullable Fragment targetFragment, @NonNull ApplicationMode initialAppMode, int initialDistanceThreshold) {
|
public static void showInstance(@NonNull FragmentManager fm, @Nullable Fragment targetFragment, @NonNull LocationsHolder locationsHolder) {
|
||||||
try {
|
try {
|
||||||
if (!fm.isStateSaved()) {
|
if (!fm.isStateSaved()) {
|
||||||
GpxApproximationFragment fragment = new GpxApproximationFragment();
|
GpxApproximationFragment fragment = new GpxApproximationFragment();
|
||||||
fragment.setTargetFragment(targetFragment, 0);
|
fragment.setRetainInstance(true);
|
||||||
fragment.snapToRoadAppMode = initialAppMode;
|
fragment.setTargetFragment(targetFragment, REQUEST_CODE);
|
||||||
fragment.distanceThreshold = initialDistanceThreshold;
|
fragment.setLocationsHolder(locationsHolder);
|
||||||
fm.beginTransaction()
|
fm.beginTransaction()
|
||||||
.replace(R.id.fragmentContainer, fragment, TAG)
|
.replace(R.id.fragmentContainer, fragment, TAG)
|
||||||
.addToBackStack(TAG)
|
.addToBackStack(TAG)
|
||||||
|
@ -254,29 +314,94 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void calculateGpxApproximation() {
|
||||||
public void onSliderChange(int sliderValue) {
|
if (gpxApproximator != null) {
|
||||||
Fragment fragment = getTargetFragment();
|
try {
|
||||||
if (fragment instanceof GpxApproximationFragmentListener) {
|
gpxApproximator.setMode(snapToRoadAppMode);
|
||||||
((GpxApproximationFragmentListener) fragment).onChangeGpxApproxDistanceThreshold(snapToRoadAppMode, sliderValue);
|
gpxApproximator.setPointApproximation(distanceThreshold);
|
||||||
distanceThreshold = sliderValue;
|
approximateGpx();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSliderChange(int sliderValue) {
|
||||||
|
distanceThreshold = sliderValue;
|
||||||
|
calculateGpxApproximation();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onProfileSelect(ApplicationMode applicationMode) {
|
public void onProfileSelect(ApplicationMode applicationMode) {
|
||||||
|
snapToRoadAppMode = applicationMode;
|
||||||
|
calculateGpxApproximation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationsHolder getLocationsHolder() {
|
||||||
|
return locationsHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocationsHolder(LocationsHolder locationsHolder) {
|
||||||
|
this.locationsHolder = locationsHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startProgress() {
|
||||||
|
if (progressBar != null) {
|
||||||
|
progressBar.setProgress(0);
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finishProgress() {
|
||||||
|
if (progressBar != null) {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateProgress(int progress) {
|
||||||
|
if (progressBar != null) {
|
||||||
|
if (progressBar.getVisibility() != View.VISIBLE) {
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
progressBar.setProgress(progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void approximateGpx() {
|
||||||
|
if (gpxApproximator != null) {
|
||||||
|
gpxApproximator.calculateGpxApproximation(new ResultMatcher<GpxRouteApproximation>() {
|
||||||
|
@Override
|
||||||
|
public boolean publish(final GpxRouteApproximation gpxApproximation) {
|
||||||
|
OsmandApplication app = getMyApplication();
|
||||||
|
if (app != null) {
|
||||||
|
app.runInUIThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
Fragment fragment = getTargetFragment();
|
Fragment fragment = getTargetFragment();
|
||||||
if (fragment instanceof GpxApproximationFragmentListener) {
|
if (fragment instanceof GpxApproximationFragmentListener) {
|
||||||
((GpxApproximationFragmentListener) fragment).onChangeGpxApproxDistanceThreshold(applicationMode, distanceThreshold);
|
((GpxApproximationFragmentListener) fragment).onGpxApproximationDone(gpxApproximation);
|
||||||
snapToRoadAppMode = applicationMode;
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface GpxApproximationFragmentListener {
|
public interface GpxApproximationFragmentListener {
|
||||||
|
|
||||||
void onChangeGpxApproxDistanceThreshold(ApplicationMode mode, int distanceThreshold);
|
void onGpxApproximationDone(GpxRouteApproximation gpxApproximation);
|
||||||
|
|
||||||
void onApplyGpxApproximation(ApplicationMode mode, int distanceThreshold);
|
void onApplyGpxApproximation();
|
||||||
|
|
||||||
void onCancelGpxApproximation();
|
void onCancelGpxApproximation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.activities.TrackActivity;
|
import net.osmand.plus.activities.TrackActivity;
|
||||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
|
import net.osmand.plus.measurementtool.GpxApproximationFragment.GpxApproximationFragmentListener;
|
||||||
import net.osmand.plus.measurementtool.NewGpxData.ActionType;
|
import net.osmand.plus.measurementtool.NewGpxData.ActionType;
|
||||||
import net.osmand.plus.measurementtool.OptionsBottomSheetDialogFragment.OptionsFragmentListener;
|
import net.osmand.plus.measurementtool.OptionsBottomSheetDialogFragment.OptionsFragmentListener;
|
||||||
import net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsFragmentListener;
|
import net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsFragmentListener;
|
||||||
|
@ -73,7 +74,6 @@ import net.osmand.plus.measurementtool.command.ClearPointsCommand;
|
||||||
import net.osmand.plus.measurementtool.command.MovePointCommand;
|
import net.osmand.plus.measurementtool.command.MovePointCommand;
|
||||||
import net.osmand.plus.measurementtool.command.RemovePointCommand;
|
import net.osmand.plus.measurementtool.command.RemovePointCommand;
|
||||||
import net.osmand.plus.measurementtool.command.ReorderPointCommand;
|
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.ApplicationMode;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback;
|
import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback;
|
||||||
|
@ -84,7 +84,6 @@ import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView;
|
||||||
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -94,7 +93,6 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import static net.osmand.IndexConstants.GPX_FILE_EXT;
|
import static net.osmand.IndexConstants.GPX_FILE_EXT;
|
||||||
import static net.osmand.plus.measurementtool.GpxApproximationFragment.GpxApproximationFragmentListener;
|
|
||||||
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationType;
|
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationType;
|
||||||
import static net.osmand.plus.measurementtool.MeasurementEditingContext.ExportAsGpxListener;
|
import static net.osmand.plus.measurementtool.MeasurementEditingContext.ExportAsGpxListener;
|
||||||
import static net.osmand.plus.measurementtool.MeasurementEditingContext.SnapToRoadProgressListener;
|
import static net.osmand.plus.measurementtool.MeasurementEditingContext.SnapToRoadProgressListener;
|
||||||
|
@ -104,7 +102,7 @@ import static net.osmand.plus.measurementtool.SelectFileBottomSheet.SelectFileLi
|
||||||
import static net.osmand.plus.measurementtool.StartPlanRouteBottomSheet.StartPlanRouteListener;
|
import static net.osmand.plus.measurementtool.StartPlanRouteBottomSheet.StartPlanRouteListener;
|
||||||
|
|
||||||
public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener,
|
public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener,
|
||||||
GpxApproximationFragmentListener, OptionsFragmentListener {
|
OptionsFragmentListener, GpxApproximationFragmentListener {
|
||||||
|
|
||||||
public static final String TAG = MeasurementToolFragment.class.getSimpleName();
|
public static final String TAG = MeasurementToolFragment.class.getSimpleName();
|
||||||
|
|
||||||
|
@ -138,7 +136,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
private boolean gpxPointsAdded;
|
private boolean gpxPointsAdded;
|
||||||
|
|
||||||
private MeasurementEditingContext editingCtx = new MeasurementEditingContext();
|
private MeasurementEditingContext editingCtx = new MeasurementEditingContext();
|
||||||
private GpxApproximator gpxApproximator;
|
|
||||||
|
|
||||||
private LatLon initialPoint;
|
private LatLon initialPoint;
|
||||||
|
|
||||||
|
@ -547,39 +544,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
return R.color.status_bar_transparent_gradient;
|
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
|
|
||||||
public void onApplyGpxApproximation(ApplicationMode mode, int distanceThreshold) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancelGpxApproximation() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private MapActivity getMapActivity() {
|
private MapActivity getMapActivity() {
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
|
@ -659,13 +623,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
case SnapTrackWarningBottomSheet.CONTINUE_REQUEST_CODE:
|
case SnapTrackWarningBottomSheet.CONTINUE_REQUEST_CODE:
|
||||||
MapActivity mapActivity = getMapActivity();
|
MapActivity mapActivity = getMapActivity();
|
||||||
if (mapActivity != null) {
|
if (mapActivity != null) {
|
||||||
try {
|
|
||||||
gpxApproximator = new GpxApproximator(requireMyApplication(), new LocationsHolder(editingCtx.getPoints()));
|
|
||||||
GpxApproximationFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
GpxApproximationFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
||||||
this, gpxApproximator.getMode(), (int) gpxApproximator.getPointApproximation());
|
this, new LocationsHolder(editingCtx.getPoints()));
|
||||||
} catch (IOException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1098,7 +1057,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayApproximatedPoints(GpxRouteApproximation gpxApproximation) {
|
public void displayApproximatedPoints(GpxRouteApproximation gpxApproximation) {
|
||||||
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
||||||
if (measurementLayer != null) {
|
if (measurementLayer != null) {
|
||||||
editingCtx.setPoints(gpxApproximation);
|
editingCtx.setPoints(gpxApproximation);
|
||||||
|
@ -1968,4 +1927,19 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
||||||
return NO_COLOR;
|
return NO_COLOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGpxApproximationDone(GpxRouteApproximation gpxApproximation) {
|
||||||
|
displayApproximatedPoints(gpxApproximation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplyGpxApproximation() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelGpxApproximation() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,10 +46,20 @@ public class SliderCard extends BaseCard {
|
||||||
if (fromUser) {
|
if (fromUser) {
|
||||||
String valueStr = getStringValueWithMetric((int) value);
|
String valueStr = getStringValueWithMetric((int) value);
|
||||||
thresholdDistanceValue.setText(valueStr);
|
thresholdDistanceValue.setText(valueStr);
|
||||||
if (listener != null) {
|
|
||||||
listener.onSliderChange((int) value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
slider.addOnSliderTouchListener(new Slider.OnSliderTouchListener() {
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(@NonNull Slider slider) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(@NonNull Slider slider) {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onSliderChange((int) slider.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,35 @@
|
||||||
package net.osmand.plus.routing;
|
package net.osmand.plus.routing;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import net.osmand.LocationsHolder;
|
import net.osmand.LocationsHolder;
|
||||||
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.ResultMatcher;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.measurementtool.GpxApproximationFragment;
|
||||||
import net.osmand.plus.routing.RouteProvider.RoutingEnvironment;
|
import net.osmand.plus.routing.RouteProvider.RoutingEnvironment;
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
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.GpxPoint;
|
||||||
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
||||||
|
import net.osmand.search.core.SearchResult;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class GpxApproximator {
|
public class GpxApproximator {
|
||||||
|
|
||||||
|
protected static final Log log = PlatformUtil.getLog(GpxApproximator.class);
|
||||||
|
|
||||||
private OsmandApplication ctx;
|
private OsmandApplication ctx;
|
||||||
private RoutingHelper routingHelper;
|
private RoutingHelper routingHelper;
|
||||||
|
|
||||||
|
@ -23,8 +40,21 @@ public class GpxApproximator {
|
||||||
private List<GpxPoint> points;
|
private List<GpxPoint> points;
|
||||||
private LatLon start;
|
private LatLon start;
|
||||||
private LatLon end;
|
private LatLon end;
|
||||||
|
private double pointApproximation = 50;
|
||||||
|
|
||||||
public GpxApproximator(OsmandApplication ctx, LocationsHolder locationsHolder) throws IOException {
|
private ThreadPoolExecutor singleThreadedExecutor;
|
||||||
|
private GpxApproximationProgressCallback approximationProgress;
|
||||||
|
|
||||||
|
public interface GpxApproximationProgressCallback {
|
||||||
|
|
||||||
|
void start();
|
||||||
|
|
||||||
|
void updateProgress(int progress);
|
||||||
|
|
||||||
|
void finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GpxApproximator(@NonNull OsmandApplication ctx, @NonNull LocationsHolder locationsHolder) throws IOException {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.locationsHolder = locationsHolder;
|
this.locationsHolder = locationsHolder;
|
||||||
this.routingHelper = ctx.getRoutingHelper();
|
this.routingHelper = ctx.getRoutingHelper();
|
||||||
|
@ -33,26 +63,48 @@ public class GpxApproximator {
|
||||||
start = locationsHolder.getLatLon(0);
|
start = locationsHolder.getLatLon(0);
|
||||||
end = locationsHolder.getLatLon(locationsHolder.getSize() - 1);
|
end = locationsHolder.getLatLon(locationsHolder.getSize() - 1);
|
||||||
prepareEnvironment(ctx, mode);
|
prepareEnvironment(ctx, mode);
|
||||||
this.points = routingHelper.generateGpxPoints(env, gctx, locationsHolder);
|
|
||||||
}
|
}
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GpxApproximator(OsmandApplication ctx, ApplicationMode mode, double pointApproximation, LocationsHolder locationsHolder) throws IOException {
|
public GpxApproximator(@NonNull OsmandApplication ctx, @NonNull ApplicationMode mode, double pointApproximation, @NonNull LocationsHolder locationsHolder) throws IOException {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
|
this.locationsHolder = locationsHolder;
|
||||||
|
this.pointApproximation = pointApproximation;
|
||||||
this.routingHelper = ctx.getRoutingHelper();
|
this.routingHelper = ctx.getRoutingHelper();
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
if (locationsHolder.getSize() > 1) {
|
if (locationsHolder.getSize() > 1) {
|
||||||
start = locationsHolder.getLatLon(0);
|
start = locationsHolder.getLatLon(0);
|
||||||
end = locationsHolder.getLatLon(locationsHolder.getSize() - 1);
|
end = locationsHolder.getLatLon(locationsHolder.getSize() - 1);
|
||||||
prepareEnvironment(ctx, mode);
|
prepareEnvironment(ctx, mode);
|
||||||
gctx.MINIMUM_POINT_APPROXIMATION = pointApproximation;
|
|
||||||
this.points = routingHelper.generateGpxPoints(env, gctx, locationsHolder);
|
|
||||||
}
|
}
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareEnvironment(OsmandApplication ctx, ApplicationMode mode) throws IOException {
|
private void init() {
|
||||||
|
singleThreadedExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareEnvironment(@NonNull OsmandApplication ctx, @NonNull ApplicationMode mode) throws IOException {
|
||||||
this.env = routingHelper.getRoutingEnvironment(ctx, mode, start, end);
|
this.env = routingHelper.getRoutingEnvironment(ctx, mode, start, end);
|
||||||
this.gctx = new GpxRouteApproximation(env.getCtx());
|
}
|
||||||
|
|
||||||
|
private GpxRouteApproximation getNewGpxApproximationContext(@Nullable GpxRouteApproximation gctx) {
|
||||||
|
GpxRouteApproximation newContext = gctx != null ? new GpxRouteApproximation(gctx) : new GpxRouteApproximation(env.getCtx());
|
||||||
|
newContext.ctx.calculationProgress = new RouteCalculationProgress();
|
||||||
|
newContext.MINIMUM_POINT_APPROXIMATION = pointApproximation;
|
||||||
|
return newContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<GpxPoint> getPoints() {
|
||||||
|
if (points == null) {
|
||||||
|
points = routingHelper.generateGpxPoints(env, getNewGpxApproximationContext(null), locationsHolder);
|
||||||
|
}
|
||||||
|
List<GpxPoint> points = new ArrayList<>(this.points.size());
|
||||||
|
for (GpxPoint p : this.points) {
|
||||||
|
points.add(new GpxPoint(p));
|
||||||
|
}
|
||||||
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApplicationMode getMode() {
|
public ApplicationMode getMode() {
|
||||||
|
@ -68,18 +120,82 @@ public class GpxApproximator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getPointApproximation() {
|
public double getPointApproximation() {
|
||||||
return gctx.MINIMUM_POINT_APPROXIMATION;
|
return pointApproximation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPointApproximation(double pointApproximation) {
|
public void setPointApproximation(double pointApproximation) {
|
||||||
gctx.MINIMUM_POINT_APPROXIMATION = pointApproximation;
|
this.pointApproximation = pointApproximation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocationsHolder getLocationsHolder() {
|
public LocationsHolder getLocationsHolder() {
|
||||||
return locationsHolder;
|
return locationsHolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GpxRouteApproximation calculateGpxApproximation() throws IOException, InterruptedException {
|
public GpxApproximationProgressCallback getApproximationProgress() {
|
||||||
return routingHelper.calculateGpxApproximation(env, gctx, points);
|
return approximationProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApproximationProgress(GpxApproximationProgressCallback approximationProgress) {
|
||||||
|
this.approximationProgress = approximationProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void calculateGpxApproximation(@NonNull final ResultMatcher<GpxRouteApproximation> resultMatcher) {
|
||||||
|
if (gctx != null) {
|
||||||
|
gctx.calculationCancelled = true;
|
||||||
|
}
|
||||||
|
final GpxRouteApproximation gctx = getNewGpxApproximationContext(this.gctx);
|
||||||
|
this.gctx = gctx;
|
||||||
|
startProgress();
|
||||||
|
updateProgress(gctx);
|
||||||
|
singleThreadedExecutor.submit(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
routingHelper.calculateGpxApproximation(env, gctx, getPoints(), resultMatcher);
|
||||||
|
} catch (Exception e) {
|
||||||
|
resultMatcher.publish(null);
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startProgress() {
|
||||||
|
final GpxApproximationProgressCallback approximationProgress = this.approximationProgress;
|
||||||
|
if (approximationProgress != null) {
|
||||||
|
approximationProgress.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishProgress() {
|
||||||
|
final GpxApproximationProgressCallback approximationProgress = this.approximationProgress;
|
||||||
|
if (approximationProgress != null) {
|
||||||
|
approximationProgress.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgress(@NonNull final GpxRouteApproximation gctx) {
|
||||||
|
final GpxApproximationProgressCallback approximationProgress = this.approximationProgress;
|
||||||
|
if (approximationProgress != null) {
|
||||||
|
ctx.runInUIThread(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
RouteCalculationProgress calculationProgress = gctx.ctx.calculationProgress;
|
||||||
|
if (gctx.isCalculationDone() && GpxApproximator.this.gctx == gctx) {
|
||||||
|
finishProgress();
|
||||||
|
}
|
||||||
|
if (!gctx.isCalculationDone() && calculationProgress != null && !calculationProgress.isCancelled) {
|
||||||
|
float pr = calculationProgress.getLinearProgress();
|
||||||
|
approximationProgress.updateProgress((int) pr);
|
||||||
|
if (GpxApproximator.this.gctx != gctx) {
|
||||||
|
// different calculation started
|
||||||
|
} else {
|
||||||
|
updateProgress(gctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import net.osmand.GPXUtilities.WptPt;
|
||||||
import net.osmand.Location;
|
import net.osmand.Location;
|
||||||
import net.osmand.LocationsHolder;
|
import net.osmand.LocationsHolder;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.ResultMatcher;
|
||||||
import net.osmand.binary.BinaryMapIndexReader;
|
import net.osmand.binary.BinaryMapIndexReader;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.LocationPoint;
|
import net.osmand.data.LocationPoint;
|
||||||
|
@ -716,13 +717,8 @@ public class RouteProvider {
|
||||||
return env.router.generateGpxPoints(gctx, locationsHolder);
|
return env.router.generateGpxPoints(gctx, locationsHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GpxRouteApproximation calculateGpxPointsApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List<GpxPoint> points) throws IOException, InterruptedException {
|
public GpxRouteApproximation calculateGpxPointsApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List<GpxPoint> points, ResultMatcher<GpxRouteApproximation> resultMatcher) throws IOException, InterruptedException {
|
||||||
if (points != null && points.size() > 1) {
|
return env.router.searchGpxRoute(gctx, points, resultMatcher);
|
||||||
if (!Algorithms.isEmpty(points)) {
|
|
||||||
return env.router.searchGpxRoute(gctx, points);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RoutingEnvironment calculateRoutingEnvironment(RouteCalculationParams params, boolean calcGPXRoute, boolean skipComplex) throws IOException {
|
protected RoutingEnvironment calculateRoutingEnvironment(RouteCalculationParams params, boolean calcGPXRoute, boolean skipComplex) throws IOException {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import net.osmand.GPXUtilities.WptPt;
|
||||||
import net.osmand.Location;
|
import net.osmand.Location;
|
||||||
import net.osmand.LocationsHolder;
|
import net.osmand.LocationsHolder;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.ResultMatcher;
|
||||||
import net.osmand.ValueHolder;
|
import net.osmand.ValueHolder;
|
||||||
import net.osmand.binary.RouteDataObject;
|
import net.osmand.binary.RouteDataObject;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
|
@ -1364,8 +1365,8 @@ public class RoutingHelper {
|
||||||
return provider.generateGpxPoints(env, gctx, locationsHolder);
|
return provider.generateGpxPoints(env, gctx, locationsHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GpxRouteApproximation calculateGpxApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List<GpxPoint> points) throws IOException, InterruptedException {
|
public GpxRouteApproximation calculateGpxApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List<GpxPoint> points, ResultMatcher<GpxRouteApproximation> resultMatcher) throws IOException, InterruptedException {
|
||||||
return provider.calculateGpxPointsApproximation(env, gctx, points);
|
return provider.calculateGpxPointsApproximation(env, gctx, points, resultMatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyIfRouteIsCalculated() {
|
public void notifyIfRouteIsCalculated() {
|
||||||
|
|
Loading…
Reference in a new issue