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);
|
||||
switch (locationType) {
|
||||
case LOCATION_TYPE_LATLON:
|
||||
latLonList = (List<LatLon>) locations;
|
||||
latLonList = new ArrayList<>((List<LatLon>) locations);
|
||||
size = locations.size();
|
||||
break;
|
||||
case LOCATION_TYPE_LOCATION:
|
||||
locationList = (List<Location>) locations;
|
||||
locationList = new ArrayList<>((List<Location>) locations);
|
||||
size = locations.size();
|
||||
break;
|
||||
case LOCATION_TYPE_WPTPT:
|
||||
wptPtList = (List<WptPt>) locations;
|
||||
wptPtList = new ArrayList<>((List<WptPt>) locations);
|
||||
size = locations.size();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ package net.osmand.router;
|
|||
import net.osmand.LocationsHolder;
|
||||
import net.osmand.NativeLibrary;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
import net.osmand.binary.BinaryMapRouteReaderAdapter;
|
||||
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
|
||||
|
@ -62,17 +63,29 @@ public class RoutePlannerFrontEnd {
|
|||
public int routeDistance;
|
||||
public int routeGapDistance;
|
||||
public int routeDistanceUnmatched;
|
||||
|
||||
|
||||
public boolean calculationCancelled;
|
||||
private boolean calculationDone;
|
||||
|
||||
public GpxRouteApproximation(RoutingContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public GpxRouteApproximation(GpxRouteApproximation gctx) {
|
||||
this.ctx = gctx.ctx;
|
||||
this.routeDistance = gctx.routeDistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
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);
|
||||
}
|
||||
|
||||
public boolean isCalculationDone() {
|
||||
return calculationDone;
|
||||
}
|
||||
|
||||
public double distFromLastPoint(LatLon startPoint) {
|
||||
if (result.size() > 0) {
|
||||
return MapUtils.getDistance(getLastPoint(), startPoint);
|
||||
|
@ -87,7 +100,7 @@ public class RoutePlannerFrontEnd {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class GpxPoint {
|
||||
public int ind;
|
||||
public LatLon loc;
|
||||
|
@ -97,6 +110,15 @@ public class RoutePlannerFrontEnd {
|
|||
public List<RouteSegmentResult> stepBackRoute;
|
||||
public int targetInd = -1;
|
||||
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) {
|
||||
|
@ -206,7 +228,6 @@ public class RoutePlannerFrontEnd {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, LatLon start, LatLon end, List<LatLon> intermediates) throws IOException, InterruptedException {
|
||||
return searchRoute(ctx, start, end, intermediates, null);
|
||||
}
|
||||
|
@ -215,19 +236,16 @@ public class RoutePlannerFrontEnd {
|
|||
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();
|
||||
if (gctx.ctx.calculationProgress == null) {
|
||||
gctx.ctx.calculationProgress = new RouteCalculationProgress();
|
||||
}
|
||||
gctx.ctx.keepNativeRoutingContext = true;
|
||||
GpxPoint start = null;
|
||||
GpxPoint prev = null;
|
||||
if(gpxPoints.size() > 0) {
|
||||
if (gpxPoints.size() > 0) {
|
||||
gctx.ctx.calculationProgress.totalIterations = (int) (gpxPoints.get(gpxPoints.size() - 1).cumDist / gctx.MAXIMUM_STEP_APPROXIMATION + 1);
|
||||
start = gpxPoints.get(0);
|
||||
}
|
||||
while (start != null) {
|
||||
while (start != null && !gctx.calculationCancelled) {
|
||||
double routeDist = gctx.MAXIMUM_STEP_APPROXIMATION;
|
||||
GpxPoint next = findNextGpxPointWithin(gctx, gpxPoints, start, routeDist);
|
||||
boolean routeFound = false;
|
||||
|
@ -287,10 +305,14 @@ public class RoutePlannerFrontEnd {
|
|||
gctx.ctx.deleteNativeRoutingContext();
|
||||
BinaryRoutePlanner.printDebugMemoryInformation(gctx.ctx);
|
||||
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);
|
||||
System.out.println(gctx);
|
||||
}
|
||||
if (resultMatcher != null) {
|
||||
resultMatcher.publish(gctx);
|
||||
}
|
||||
gctx.calculationDone = true;
|
||||
return gctx;
|
||||
}
|
||||
|
||||
|
@ -343,7 +365,7 @@ public class RoutePlannerFrontEnd {
|
|||
reg.initRouteEncodingRule(0, "highway", RouteResultPreparation.UNMATCHED_HIGHWAY_TYPE);
|
||||
List<LatLon> lastStraightLine = 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);
|
||||
if (pnt.routeToTarget != null && !pnt.routeToTarget.isEmpty()) {
|
||||
LatLon startPoint = pnt.routeToTarget.get(0).getStartPoint();
|
||||
|
@ -402,7 +424,7 @@ public class RoutePlannerFrontEnd {
|
|||
private void cleanupResultAndAddTurns(GpxRouteApproximation gctx) {
|
||||
// cleanup double joints
|
||||
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);
|
||||
for(int j = i + 2; j <= i + LOOK_AHEAD && j < gctx.result.size(); j++) {
|
||||
RouteSegmentResult e = gctx.result.get(j);
|
||||
|
@ -419,7 +441,9 @@ public class RoutePlannerFrontEnd {
|
|||
r.setTurnType(null);
|
||||
r.setDescription("");
|
||||
}
|
||||
preparation.prepareTurnResults(gctx.ctx, gctx.result);
|
||||
if (!gctx.calculationCancelled) {
|
||||
preparation.prepareTurnResults(gctx.ctx, gctx.result);
|
||||
}
|
||||
}
|
||||
|
||||
private void addStraightLine(GpxRouteApproximation gctx, List<LatLon> lastStraightLine, GpxPoint strPnt, RouteRegion reg) {
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include layout="@layout/plan_route_progress_bar"/>
|
||||
|
||||
<net.osmand.plus.LockableScrollView
|
||||
android:id="@+id/route_menu_bottom_scroll"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -37,6 +35,9 @@
|
|||
</LinearLayout>
|
||||
|
||||
</net.osmand.plus.LockableScrollView>
|
||||
|
||||
<include layout="@layout/plan_route_progress_bar"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -54,6 +54,7 @@ import androidx.annotation.ColorInt;
|
|||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
@ -169,11 +170,11 @@ public class AndroidUtils {
|
|||
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) {
|
||||
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) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -15,18 +16,25 @@ import androidx.fragment.app.FragmentActivity;
|
|||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.LocationsHolder;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.base.ContextMenuScrollFragment;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.routing.GpxApproximator;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import static net.osmand.plus.measurementtool.ProfileCard.*;
|
||||
import static net.osmand.plus.measurementtool.SliderCard.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import static net.osmand.plus.measurementtool.ProfileCard.ProfileCardListener;
|
||||
import static net.osmand.plus.measurementtool.SliderCard.SliderCardListener;
|
||||
|
||||
public class GpxApproximationFragment extends ContextMenuScrollFragment
|
||||
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 SNAP_TO_ROAD_APP_MODE_STRING_KEY = "snap_to_road_app_mode";
|
||||
|
||||
public static final int REQUEST_CODE = 1100;
|
||||
|
||||
private int menuTitleHeight;
|
||||
private ApplicationMode snapToRoadAppMode = ApplicationMode.CAR;
|
||||
private int distanceThreshold = 30;
|
||||
private int distanceThreshold = 50;
|
||||
|
||||
private LocationsHolder locationsHolder;
|
||||
@Nullable
|
||||
private GpxApproximator gpxApproximator;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
@Override
|
||||
public int getMainLayoutId() {
|
||||
|
@ -85,6 +100,43 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
distanceThreshold = savedInstanceState.getInt(DISTANCE_THRESHOLD_KEY);
|
||||
snapToRoadAppMode = ApplicationMode.valueOfStringKey(
|
||||
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()) {
|
||||
|
@ -93,6 +145,12 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
updateCards();
|
||||
updateButtons(mainView);
|
||||
|
||||
progressBar = mainView.findViewById(R.id.progress_bar);
|
||||
if (progressBar != null) {
|
||||
requireMapActivity().setupRouteCalculationProgressBar(progressBar);
|
||||
progressBar.setIndeterminate(false);
|
||||
}
|
||||
|
||||
if (!isPortrait()) {
|
||||
int widthNoShadow = getLandscapeNoShadowWidth();
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
|
@ -102,6 +160,8 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
enterGpxApproximationMode();
|
||||
runLayoutListener();
|
||||
|
||||
calculateGpxApproximation();
|
||||
|
||||
return mainView;
|
||||
}
|
||||
|
||||
|
@ -159,7 +219,7 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
public void onClick(View v) {
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof GpxApproximationFragmentListener) {
|
||||
((GpxApproximationFragmentListener) fragment).onApplyGpxApproximation(snapToRoadAppMode, distanceThreshold);
|
||||
((GpxApproximationFragmentListener) fragment).onApplyGpxApproximation();
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
@ -226,13 +286,13 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
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 {
|
||||
if (!fm.isStateSaved()) {
|
||||
GpxApproximationFragment fragment = new GpxApproximationFragment();
|
||||
fragment.setTargetFragment(targetFragment, 0);
|
||||
fragment.snapToRoadAppMode = initialAppMode;
|
||||
fragment.distanceThreshold = initialDistanceThreshold;
|
||||
fragment.setRetainInstance(true);
|
||||
fragment.setTargetFragment(targetFragment, REQUEST_CODE);
|
||||
fragment.setLocationsHolder(locationsHolder);
|
||||
fm.beginTransaction()
|
||||
.replace(R.id.fragmentContainer, fragment, TAG)
|
||||
.addToBackStack(TAG)
|
||||
|
@ -254,29 +314,94 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSliderChange(int sliderValue) {
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof GpxApproximationFragmentListener) {
|
||||
((GpxApproximationFragmentListener) fragment).onChangeGpxApproxDistanceThreshold(snapToRoadAppMode, sliderValue);
|
||||
distanceThreshold = sliderValue;
|
||||
public void calculateGpxApproximation() {
|
||||
if (gpxApproximator != null) {
|
||||
try {
|
||||
gpxApproximator.setMode(snapToRoadAppMode);
|
||||
gpxApproximator.setPointApproximation(distanceThreshold);
|
||||
approximateGpx();
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSliderChange(int sliderValue) {
|
||||
distanceThreshold = sliderValue;
|
||||
calculateGpxApproximation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProfileSelect(ApplicationMode applicationMode) {
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof GpxApproximationFragmentListener) {
|
||||
((GpxApproximationFragmentListener) fragment).onChangeGpxApproxDistanceThreshold(applicationMode, distanceThreshold);
|
||||
snapToRoadAppMode = 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();
|
||||
if (fragment instanceof GpxApproximationFragmentListener) {
|
||||
((GpxApproximationFragmentListener) fragment).onGpxApproximationDone(gpxApproximation);
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public interface GpxApproximationFragmentListener {
|
||||
|
||||
void onChangeGpxApproxDistanceThreshold(ApplicationMode mode, int distanceThreshold);
|
||||
void onGpxApproximationDone(GpxRouteApproximation gpxApproximation);
|
||||
|
||||
void onApplyGpxApproximation(ApplicationMode mode, int distanceThreshold);
|
||||
void onApplyGpxApproximation();
|
||||
|
||||
void onCancelGpxApproximation();
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ import net.osmand.plus.activities.MapActivity;
|
|||
import net.osmand.plus.activities.TrackActivity;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
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.OptionsBottomSheetDialogFragment.OptionsFragmentListener;
|
||||
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.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;
|
||||
|
@ -84,7 +84,6 @@ 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;
|
||||
|
@ -94,7 +93,6 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
|
||||
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.ExportAsGpxListener;
|
||||
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;
|
||||
|
||||
public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener,
|
||||
GpxApproximationFragmentListener, OptionsFragmentListener {
|
||||
OptionsFragmentListener, GpxApproximationFragmentListener {
|
||||
|
||||
public static final String TAG = MeasurementToolFragment.class.getSimpleName();
|
||||
|
||||
|
@ -138,7 +136,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
private boolean gpxPointsAdded;
|
||||
|
||||
private MeasurementEditingContext editingCtx = new MeasurementEditingContext();
|
||||
private GpxApproximator gpxApproximator;
|
||||
|
||||
private LatLon initialPoint;
|
||||
|
||||
|
@ -547,39 +544,6 @@ 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
|
||||
public void onApplyGpxApproximation(ApplicationMode mode, int distanceThreshold) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelGpxApproximation() {
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MapActivity getMapActivity() {
|
||||
Activity activity = getActivity();
|
||||
|
@ -659,13 +623,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
case SnapTrackWarningBottomSheet.CONTINUE_REQUEST_CODE:
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
try {
|
||||
gpxApproximator = new GpxApproximator(requireMyApplication(), new LocationsHolder(editingCtx.getPoints()));
|
||||
GpxApproximationFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
||||
this, gpxApproximator.getMode(), (int) gpxApproximator.getPointApproximation());
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
GpxApproximationFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
||||
this, new LocationsHolder(editingCtx.getPoints()));
|
||||
}
|
||||
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();
|
||||
if (measurementLayer != null) {
|
||||
editingCtx.setPoints(gpxApproximation);
|
||||
|
@ -1968,4 +1927,19 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
return NO_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGpxApproximationDone(GpxRouteApproximation gpxApproximation) {
|
||||
displayApproximatedPoints(gpxApproximation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplyGpxApproximation() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelGpxApproximation() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,9 +46,19 @@ public class SliderCard extends BaseCard {
|
|||
if (fromUser) {
|
||||
String valueStr = getStringValueWithMetric((int) value);
|
||||
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;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.LocationsHolder;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.measurementtool.GpxApproximationFragment;
|
||||
import net.osmand.plus.routing.RouteProvider.RoutingEnvironment;
|
||||
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.search.core.SearchResult;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class GpxApproximator {
|
||||
|
||||
protected static final Log log = PlatformUtil.getLog(GpxApproximator.class);
|
||||
|
||||
private OsmandApplication ctx;
|
||||
private RoutingHelper routingHelper;
|
||||
|
||||
|
@ -23,8 +40,21 @@ public class GpxApproximator {
|
|||
private List<GpxPoint> points;
|
||||
private LatLon start;
|
||||
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.locationsHolder = locationsHolder;
|
||||
this.routingHelper = ctx.getRoutingHelper();
|
||||
|
@ -33,26 +63,48 @@ public class GpxApproximator {
|
|||
start = locationsHolder.getLatLon(0);
|
||||
end = locationsHolder.getLatLon(locationsHolder.getSize() - 1);
|
||||
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.locationsHolder = locationsHolder;
|
||||
this.pointApproximation = pointApproximation;
|
||||
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);
|
||||
}
|
||||
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.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() {
|
||||
|
@ -68,18 +120,82 @@ public class GpxApproximator {
|
|||
}
|
||||
|
||||
public double getPointApproximation() {
|
||||
return gctx.MINIMUM_POINT_APPROXIMATION;
|
||||
return pointApproximation;
|
||||
}
|
||||
|
||||
public void setPointApproximation(double pointApproximation) {
|
||||
gctx.MINIMUM_POINT_APPROXIMATION = pointApproximation;
|
||||
this.pointApproximation = pointApproximation;
|
||||
}
|
||||
|
||||
public LocationsHolder getLocationsHolder() {
|
||||
return locationsHolder;
|
||||
}
|
||||
|
||||
public GpxRouteApproximation calculateGpxApproximation() throws IOException, InterruptedException {
|
||||
return routingHelper.calculateGpxApproximation(env, gctx, points);
|
||||
public GpxApproximationProgressCallback getApproximationProgress() {
|
||||
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.LocationsHolder;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.LocationPoint;
|
||||
|
@ -716,13 +717,8 @@ public class RouteProvider {
|
|||
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;
|
||||
public GpxRouteApproximation calculateGpxPointsApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List<GpxPoint> points, ResultMatcher<GpxRouteApproximation> resultMatcher) throws IOException, InterruptedException {
|
||||
return env.router.searchGpxRoute(gctx, points, resultMatcher);
|
||||
}
|
||||
|
||||
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.LocationsHolder;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.ValueHolder;
|
||||
import net.osmand.binary.RouteDataObject;
|
||||
import net.osmand.data.LatLon;
|
||||
|
@ -1364,8 +1365,8 @@ public class RoutingHelper {
|
|||
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 GpxRouteApproximation calculateGpxApproximation(RoutingEnvironment env, GpxRouteApproximation gctx, List<GpxPoint> points, ResultMatcher<GpxRouteApproximation> resultMatcher) throws IOException, InterruptedException {
|
||||
return provider.calculateGpxPointsApproximation(env, gctx, points, resultMatcher);
|
||||
}
|
||||
|
||||
public void notifyIfRouteIsCalculated() {
|
||||
|
|
Loading…
Reference in a new issue