commit
41d76662bd
44 changed files with 1236 additions and 810 deletions
|
@ -52,6 +52,7 @@ public class GPXUtilities {
|
|||
private static final String DEFAULT_ICON_NAME = "special_star";
|
||||
private static final String BACKGROUND_TYPE_EXTENSION = "background";
|
||||
private static final String PROFILE_TYPE_EXTENSION = "profile";
|
||||
private static final String GAP_PROFILE_TYPE = "gap";
|
||||
private static final String TRKPT_INDEX_EXTENSION = "trkpt_idx";
|
||||
|
||||
private final static String GPX_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$
|
||||
|
@ -324,6 +325,20 @@ public class GPXUtilities {
|
|||
getExtensionsToWrite().put(PROFILE_TYPE_EXTENSION, profileType);
|
||||
}
|
||||
|
||||
public boolean hasProfile() {
|
||||
String profileType = getProfileType();
|
||||
return profileType != null && !GAP_PROFILE_TYPE.equals(profileType);
|
||||
}
|
||||
|
||||
public boolean isGap() {
|
||||
String profileType = getProfileType();
|
||||
return GAP_PROFILE_TYPE.equals(profileType);
|
||||
}
|
||||
|
||||
public void setGap() {
|
||||
setProfileType(GAP_PROFILE_TYPE);
|
||||
}
|
||||
|
||||
public void removeProfileType() {
|
||||
getExtensionsToWrite().remove(PROFILE_TYPE_EXTENSION);
|
||||
}
|
||||
|
@ -374,11 +389,16 @@ public class GPXUtilities {
|
|||
|
||||
public static class TrkSegment extends GPXExtensions {
|
||||
public boolean generalSegment = false;
|
||||
|
||||
public List<WptPt> points = new ArrayList<>();
|
||||
|
||||
public Object renderer;
|
||||
|
||||
public List<RouteSegment> routeSegments = new ArrayList<>();
|
||||
public List<RouteType> routeTypes = new ArrayList<>();
|
||||
|
||||
public boolean hasRoute() {
|
||||
return !routeSegments.isEmpty() && !routeTypes.isEmpty();
|
||||
}
|
||||
|
||||
public List<GPXTrackAnalysis> splitByDistance(double meters, boolean joinSegments) {
|
||||
return split(getDistanceMetric(), getTimeSplit(), meters, joinSegments);
|
||||
|
@ -393,7 +413,6 @@ public class GPXUtilities {
|
|||
splitSegment(metric, secondaryMetric, metricLimit, splitSegments, this, joinSegments);
|
||||
return convert(splitSegments);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Track extends GPXExtensions {
|
||||
|
@ -1078,9 +1097,6 @@ public class GPXUtilities {
|
|||
private List<WptPt> points = new ArrayList<>();
|
||||
public List<Route> routes = new ArrayList<>();
|
||||
|
||||
public List<RouteSegment> routeSegments = new ArrayList<>();
|
||||
public List<RouteType> routeTypes = new ArrayList<>();
|
||||
|
||||
public Exception error = null;
|
||||
public String path = "";
|
||||
public boolean showCurrentTrack;
|
||||
|
@ -1108,7 +1124,7 @@ public class GPXUtilities {
|
|||
}
|
||||
|
||||
public boolean hasRoute() {
|
||||
return !routeSegments.isEmpty() && !routeTypes.isEmpty();
|
||||
return getNonEmptyTrkSegments(true).size() > 0;
|
||||
}
|
||||
|
||||
public List<WptPt> getPoints() {
|
||||
|
@ -1218,7 +1234,7 @@ public class GPXUtilities {
|
|||
GPXTrackAnalysis g = new GPXTrackAnalysis();
|
||||
g.wptPoints = points.size();
|
||||
g.wptCategoryNames = getWaypointCategories(true);
|
||||
List<SplitSegment> splitSegments = new ArrayList<GPXUtilities.SplitSegment>();
|
||||
List<SplitSegment> splitSegments = new ArrayList<>();
|
||||
for (int i = 0; i < tracks.size(); i++) {
|
||||
Track subtrack = tracks.get(i);
|
||||
for (TrkSegment segment : subtrack.segments) {
|
||||
|
@ -1243,6 +1259,15 @@ public class GPXUtilities {
|
|||
return points;
|
||||
}
|
||||
|
||||
public List<WptPt> getRoutePoints(int routeIndex) {
|
||||
List<WptPt> points = new ArrayList<>();
|
||||
if (routes.size() > routeIndex) {
|
||||
Route rt = routes.get(routeIndex);
|
||||
points.addAll(rt.points);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
public boolean hasRtePt() {
|
||||
for (Route r : routes) {
|
||||
if (r.points.size() > 0) {
|
||||
|
@ -1318,15 +1343,16 @@ public class GPXUtilities {
|
|||
return pt;
|
||||
}
|
||||
|
||||
public TrkSegment getNonEmptyTrkSegment() {
|
||||
for (GPXUtilities.Track t : tracks) {
|
||||
public List<TrkSegment> getNonEmptyTrkSegments(boolean routesOnly) {
|
||||
List<TrkSegment> segments = new ArrayList<>();
|
||||
for (Track t : tracks) {
|
||||
for (TrkSegment s : t.segments) {
|
||||
if (s.points.size() > 0) {
|
||||
return s;
|
||||
if (!s.generalSegment && s.points.size() > 0 && (!routesOnly || s.hasRoute())) {
|
||||
segments.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return segments;
|
||||
}
|
||||
|
||||
public void addTrkSegment(List<WptPt> points) {
|
||||
|
@ -1365,8 +1391,8 @@ public class GPXUtilities {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void addRoutePoints(List<WptPt> points) {
|
||||
if (routes.size() == 0) {
|
||||
public void addRoutePoints(List<WptPt> points, boolean addRoute) {
|
||||
if (routes.size() == 0 || addRoute) {
|
||||
Route route = new Route();
|
||||
routes.add(route);
|
||||
}
|
||||
|
@ -1608,7 +1634,7 @@ public class GPXUtilities {
|
|||
bottom = Math.min(bottom, p.getLatitude());
|
||||
}
|
||||
}
|
||||
for (GPXUtilities.Route route : routes) {
|
||||
for (Route route : routes) {
|
||||
for (WptPt p : route.points) {
|
||||
if (left == 0 && right == 0) {
|
||||
left = p.getLongitude();
|
||||
|
@ -1720,7 +1746,7 @@ public class GPXUtilities {
|
|||
|
||||
public static String asString(GPXFile file) {
|
||||
final Writer writer = new StringWriter();
|
||||
GPXUtilities.writeGpx(writer, file);
|
||||
writeGpx(writer, file);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
|
@ -1807,6 +1833,8 @@ public class GPXUtilities {
|
|||
writeWpt(format, serializer, p);
|
||||
serializer.endTag(null, "trkpt"); //$NON-NLS-1$
|
||||
}
|
||||
assignRouteExtensionWriter(segment);
|
||||
writeExtensions(serializer, segment);
|
||||
serializer.endTag(null, "trkseg"); //$NON-NLS-1$
|
||||
}
|
||||
writeExtensions(serializer, track);
|
||||
|
@ -1834,7 +1862,6 @@ public class GPXUtilities {
|
|||
serializer.endTag(null, "wpt"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
assignRouteExtensionWriter(file);
|
||||
writeExtensions(serializer, file);
|
||||
|
||||
serializer.endTag(null, "gpx"); //$NON-NLS-1$
|
||||
|
@ -1847,19 +1874,19 @@ public class GPXUtilities {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static void assignRouteExtensionWriter(final GPXFile gpxFile) {
|
||||
if (gpxFile.hasRoute() && gpxFile.getExtensionsWriter() == null) {
|
||||
gpxFile.setExtensionsWriter(new GPXExtensionsWriter() {
|
||||
private static void assignRouteExtensionWriter(final TrkSegment segment) {
|
||||
if (segment.hasRoute() && segment.getExtensionsWriter() == null) {
|
||||
segment.setExtensionsWriter(new GPXExtensionsWriter() {
|
||||
@Override
|
||||
public void writeExtensions(XmlSerializer serializer) {
|
||||
StringBundle bundle = new StringBundle();
|
||||
List<StringBundle> segmentsBundle = new ArrayList<>();
|
||||
for (RouteSegment segment : gpxFile.routeSegments) {
|
||||
for (RouteSegment segment : segment.routeSegments) {
|
||||
segmentsBundle.add(segment.toStringBundle());
|
||||
}
|
||||
bundle.putBundleList("route", "segment", segmentsBundle);
|
||||
List<StringBundle> typesBundle = new ArrayList<>();
|
||||
for (RouteType routeType : gpxFile.routeTypes) {
|
||||
for (RouteType routeType : segment.routeTypes) {
|
||||
typesBundle.add(routeType.toStringBundle());
|
||||
}
|
||||
bundle.putBundleList("types", "type", typesBundle);
|
||||
|
@ -1901,12 +1928,15 @@ public class GPXUtilities {
|
|||
}
|
||||
|
||||
private static void writeExtensions(XmlSerializer serializer, GPXExtensions p) throws IOException {
|
||||
Map<String, String> extensionsToRead = p.getExtensionsToRead();
|
||||
writeExtensions(serializer, p.getExtensionsToRead(), p);
|
||||
}
|
||||
|
||||
private static void writeExtensions(XmlSerializer serializer, Map<String, String> extensions, GPXExtensions p) throws IOException {
|
||||
GPXExtensionsWriter extensionsWriter = p.getExtensionsWriter();
|
||||
if (!extensionsToRead.isEmpty() || extensionsWriter != null) {
|
||||
if (!extensions.isEmpty() || extensionsWriter != null) {
|
||||
serializer.startTag(null, "extensions");
|
||||
if (!extensionsToRead.isEmpty()) {
|
||||
for (Entry<String, String> s : extensionsToRead.entrySet()) {
|
||||
if (!extensions.isEmpty()) {
|
||||
for (Entry<String, String> s : extensions.entrySet()) {
|
||||
writeNotNullText(serializer, s.getKey(), s.getValue());
|
||||
}
|
||||
}
|
||||
|
@ -1943,8 +1973,21 @@ public class GPXUtilities {
|
|||
if (!Float.isNaN(p.heading)) {
|
||||
p.getExtensionsToWrite().put("heading", String.valueOf(Math.round(p.heading)));
|
||||
}
|
||||
Map<String, String> extensions = p.getExtensionsToRead();
|
||||
if (!"rtept".equals(serializer.getName())) {
|
||||
// Leave "profile" and "trkpt" tags for rtept only
|
||||
extensions.remove(PROFILE_TYPE_EXTENSION);
|
||||
extensions.remove(TRKPT_INDEX_EXTENSION);
|
||||
writeExtensions(serializer, extensions, p);
|
||||
} else {
|
||||
// Remove "gap" profile
|
||||
String profile = extensions.get(PROFILE_TYPE_EXTENSION);
|
||||
if (GAP_PROFILE_TYPE.equals(profile)) {
|
||||
extensions.remove(PROFILE_TYPE_EXTENSION);
|
||||
}
|
||||
writeExtensions(serializer, p);
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeAuthor(XmlSerializer serializer, Author author) throws IOException {
|
||||
writeNotNullText(serializer, "name", author.name);
|
||||
|
@ -2099,10 +2142,11 @@ public class GPXUtilities {
|
|||
TrkSegment routeTrackSegment = new TrkSegment();
|
||||
routeTrack.segments.add(routeTrackSegment);
|
||||
Stack<GPXExtensions> parserState = new Stack<>();
|
||||
TrkSegment firstSegment = null;
|
||||
boolean extensionReadMode = false;
|
||||
boolean routePointExtension = false;
|
||||
List<RouteSegment> routeSegments = gpxFile.routeSegments;
|
||||
List<RouteType> routeTypes = gpxFile.routeTypes;
|
||||
List<RouteSegment> routeSegments = new ArrayList<>();
|
||||
List<RouteType> routeTypes = new ArrayList<>();
|
||||
boolean routeExtension = false;
|
||||
boolean typesExtension = false;
|
||||
parserState.push(gpxFile);
|
||||
|
@ -2403,6 +2447,16 @@ public class GPXUtilities {
|
|||
assert pop instanceof Route;
|
||||
} else if (tag.equals("trkseg")) {
|
||||
Object pop = parserState.pop();
|
||||
if (pop instanceof TrkSegment) {
|
||||
TrkSegment segment = (TrkSegment) pop;
|
||||
segment.routeSegments = routeSegments;
|
||||
segment.routeTypes = routeTypes;
|
||||
routeSegments = new ArrayList<>();
|
||||
routeTypes = new ArrayList<>();
|
||||
if (firstSegment == null) {
|
||||
firstSegment = segment;
|
||||
}
|
||||
}
|
||||
assert pop instanceof TrkSegment;
|
||||
} else if (tag.equals("rpt")) {
|
||||
Object pop = parserState.pop();
|
||||
|
@ -2413,6 +2467,10 @@ public class GPXUtilities {
|
|||
if (!routeTrackSegment.points.isEmpty()) {
|
||||
gpxFile.tracks.add(routeTrack);
|
||||
}
|
||||
if (!routeSegments.isEmpty() && !routeTypes.isEmpty() && firstSegment != null) {
|
||||
firstSegment.routeSegments = routeSegments;
|
||||
firstSegment.routeTypes = routeTypes;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
gpxFile.error = e;
|
||||
log.error("Error reading gpx", e); //$NON-NLS-1$
|
||||
|
|
|
@ -20,10 +20,10 @@ public class RouteExporter {
|
|||
|
||||
public static final String OSMAND_ROUTER_V2 = "OsmAndRouterV2";
|
||||
|
||||
private String name;
|
||||
private List<RouteSegmentResult> route;
|
||||
private List<Location> locations;
|
||||
private List<WptPt> points;
|
||||
private final String name;
|
||||
private final List<RouteSegmentResult> route;
|
||||
private final List<Location> locations;
|
||||
private final List<WptPt> points;
|
||||
|
||||
public RouteExporter(String name, List<RouteSegmentResult> route, List<Location> locations, List<WptPt> points) {
|
||||
this.name = name;
|
||||
|
@ -33,6 +33,34 @@ public class RouteExporter {
|
|||
}
|
||||
|
||||
public GPXFile exportRoute() {
|
||||
GPXFile gpx = new GPXFile(OSMAND_ROUTER_V2);
|
||||
Track track = new Track();
|
||||
track.name = name;
|
||||
gpx.tracks.add(track);
|
||||
track.segments.add(generateRouteSegment());
|
||||
if (points != null) {
|
||||
for (WptPt pt : points) {
|
||||
gpx.addPoint(pt);
|
||||
}
|
||||
}
|
||||
return gpx;
|
||||
}
|
||||
|
||||
public static GPXFile exportRoute(String name, List<TrkSegment> trkSegments, List<WptPt> points) {
|
||||
GPXFile gpx = new GPXFile(OSMAND_ROUTER_V2);
|
||||
Track track = new Track();
|
||||
track.name = name;
|
||||
gpx.tracks.add(track);
|
||||
track.segments.addAll(trkSegments);
|
||||
if (points != null) {
|
||||
for (WptPt pt : points) {
|
||||
gpx.addPoint(pt);
|
||||
}
|
||||
}
|
||||
return gpx;
|
||||
}
|
||||
|
||||
public TrkSegment generateRouteSegment() {
|
||||
RouteDataResources resources = new RouteDataResources(locations);
|
||||
List<StringBundle> routeItems = new ArrayList<>();
|
||||
if (!Algorithms.isEmpty(route)) {
|
||||
|
@ -57,15 +85,9 @@ public class RouteExporter {
|
|||
typeList.add(typeBundle);
|
||||
}
|
||||
|
||||
GPXFile gpx = new GPXFile(OSMAND_ROUTER_V2);
|
||||
Track track = new Track();
|
||||
track.name = name;
|
||||
gpx.tracks.add(track);
|
||||
TrkSegment trkSegment = new TrkSegment();
|
||||
track.segments.add(trkSegment);
|
||||
|
||||
if (locations == null || locations.isEmpty()) {
|
||||
return gpx;
|
||||
return trkSegment;
|
||||
}
|
||||
for (int i = 0; i < locations.size(); i++) {
|
||||
Location loc = locations.get(i);
|
||||
|
@ -83,23 +105,17 @@ public class RouteExporter {
|
|||
}
|
||||
trkSegment.points.add(pt);
|
||||
}
|
||||
if (points != null) {
|
||||
for (WptPt pt : points) {
|
||||
gpx.addPoint(pt);
|
||||
}
|
||||
}
|
||||
|
||||
List<RouteSegment> routeSegments = new ArrayList<>();
|
||||
for (StringBundle item : routeItems) {
|
||||
routeSegments.add(RouteSegment.fromStringBundle(item));
|
||||
}
|
||||
gpx.routeSegments = routeSegments;
|
||||
trkSegment.routeSegments = routeSegments;
|
||||
List<RouteType> routeTypes = new ArrayList<>();
|
||||
for (StringBundle item : typeList) {
|
||||
routeTypes.add(RouteType.fromStringBundle(item));
|
||||
}
|
||||
gpx.routeTypes = routeTypes;
|
||||
|
||||
return gpx;
|
||||
trkSegment.routeTypes = routeTypes;
|
||||
return trkSegment;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import net.osmand.GPXUtilities;
|
|||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.RouteSegment;
|
||||
import net.osmand.GPXUtilities.RouteType;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.Location;
|
||||
import net.osmand.PlatformUtil;
|
||||
|
@ -28,10 +29,9 @@ public class RouteImporter {
|
|||
|
||||
private File file;
|
||||
private GPXFile gpxFile;
|
||||
private TrkSegment segment;
|
||||
|
||||
private List<RouteSegmentResult> route = new ArrayList<>();
|
||||
private RouteRegion region = new RouteRegion();
|
||||
private RouteDataResources resources = new RouteDataResources();
|
||||
private final List<RouteSegmentResult> route = new ArrayList<>();
|
||||
|
||||
public RouteImporter(File file) {
|
||||
this.file = file;
|
||||
|
@ -41,8 +41,12 @@ public class RouteImporter {
|
|||
this.gpxFile = gpxFile;
|
||||
}
|
||||
|
||||
public RouteImporter(TrkSegment segment) {
|
||||
this.segment = segment;
|
||||
}
|
||||
|
||||
public List<RouteSegmentResult> importRoute() {
|
||||
if (gpxFile != null) {
|
||||
if (gpxFile != null || segment != null) {
|
||||
parseRoute();
|
||||
} else if (file != null) {
|
||||
FileInputStream fis = null;
|
||||
|
@ -69,19 +73,34 @@ public class RouteImporter {
|
|||
}
|
||||
|
||||
private void parseRoute() {
|
||||
collectLocations();
|
||||
collectSegments();
|
||||
collectTypes();
|
||||
for (RouteSegmentResult segment : route) {
|
||||
segment.fillNames(resources);
|
||||
if (segment != null) {
|
||||
parseRoute(segment);
|
||||
} else if (gpxFile != null) {
|
||||
List<TrkSegment> segments = gpxFile.getNonEmptyTrkSegments(true);
|
||||
for (TrkSegment s : segments) {
|
||||
parseRoute(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void collectLocations() {
|
||||
private void parseRoute(TrkSegment segment) {
|
||||
RouteRegion region = new RouteRegion();
|
||||
RouteDataResources resources = new RouteDataResources();
|
||||
|
||||
collectLocations(resources, segment);
|
||||
List<RouteSegmentResult> route = collectRouteSegments(region, resources, segment);
|
||||
collectRouteTypes(region, segment);
|
||||
for (RouteSegmentResult routeSegment : route) {
|
||||
routeSegment.fillNames(resources);
|
||||
}
|
||||
this.route.addAll(route);
|
||||
}
|
||||
|
||||
private void collectLocations(RouteDataResources resources, TrkSegment segment) {
|
||||
List<Location> locations = resources.getLocations();
|
||||
double lastElevation = HEIGHT_UNDEFINED;
|
||||
if (gpxFile.tracks.size() > 0 && gpxFile.tracks.get(0).segments.size() > 0 && gpxFile.tracks.get(0).segments.get(0).points.size() > 0) {
|
||||
for (WptPt point : gpxFile.tracks.get(0).segments.get(0).points) {
|
||||
if (segment.hasRoute()) {
|
||||
for (WptPt point : segment.points) {
|
||||
Location loc = new Location("", point.getLatitude(), point.getLongitude());
|
||||
if (!Double.isNaN(point.ele)) {
|
||||
loc.setAltitude(point.ele);
|
||||
|
@ -94,18 +113,20 @@ public class RouteImporter {
|
|||
}
|
||||
}
|
||||
|
||||
private void collectSegments() {
|
||||
for (RouteSegment segment : gpxFile.routeSegments) {
|
||||
private List<RouteSegmentResult> collectRouteSegments(RouteRegion region, RouteDataResources resources, TrkSegment segment) {
|
||||
List<RouteSegmentResult> route = new ArrayList<>();
|
||||
for (RouteSegment routeSegment : segment.routeSegments) {
|
||||
RouteDataObject object = new RouteDataObject(region);
|
||||
RouteSegmentResult segmentResult = new RouteSegmentResult(object);
|
||||
segmentResult.readFromBundle(new RouteDataBundle(resources, segment.toStringBundle()));
|
||||
segmentResult.readFromBundle(new RouteDataBundle(resources, routeSegment.toStringBundle()));
|
||||
route.add(segmentResult);
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
private void collectTypes() {
|
||||
private void collectRouteTypes(RouteRegion region, TrkSegment segment) {
|
||||
int i = 0;
|
||||
for (RouteType routeType : gpxFile.routeTypes) {
|
||||
for (RouteType routeType : segment.routeTypes) {
|
||||
StringBundle bundle = routeType.toStringBundle();
|
||||
String t = bundle.getString("t", null);
|
||||
String v = bundle.getString("v", null);
|
||||
|
|
|
@ -243,9 +243,6 @@ public class RoutePlannerFrontEnd {
|
|||
start = gpxPoints.get(0);
|
||||
}
|
||||
while (start != null && !gctx.ctx.calculationProgress.isCancelled) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
return null;
|
||||
}
|
||||
double routeDist = gctx.MAXIMUM_STEP_APPROXIMATION;
|
||||
GpxPoint next = findNextGpxPointWithin(gctx, gpxPoints, start, routeDist);
|
||||
boolean routeFound = false;
|
||||
|
|
|
@ -255,7 +255,8 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
|
|||
@Override
|
||||
public void writeToBundle(RouteDataBundle bundle) {
|
||||
Map<RouteTypeRule, Integer> rules = bundle.getResources().getRules();
|
||||
bundle.putInt("length", (Math.abs(endPointIndex - startPointIndex) + 1) * (endPointIndex >= startPointIndex ? 1 : -1));
|
||||
boolean reversed = endPointIndex < startPointIndex;
|
||||
bundle.putInt("length", Math.abs(endPointIndex - startPointIndex) + 1);
|
||||
bundle.putFloat("segmentTime", segmentTime, 2);
|
||||
bundle.putFloat("speed", speed, 2);
|
||||
if (turnType != null) {
|
||||
|
@ -278,17 +279,22 @@ public class RouteSegmentResult implements StringExternalizable<RouteDataBundle>
|
|||
int end = Math.max(startPointIndex, endPointIndex) + 1;
|
||||
if (object.pointTypes != null && start < object.pointTypes.length) {
|
||||
int[][] types = Arrays.copyOfRange(object.pointTypes, start, Math.min(end, object.pointTypes.length));
|
||||
if (reversed) {
|
||||
Algorithms.reverseArray(types);
|
||||
}
|
||||
bundle.putArray("pointTypes", convertTypes(types, rules));
|
||||
}
|
||||
if (object.nameIds != null) {
|
||||
bundle.putArray("names", convertNameIds(object.nameIds, rules));
|
||||
}
|
||||
if (object.pointNameTypes != null && start < object.pointNameTypes.length) {
|
||||
if (object.pointNameTypes != null && start < object.pointNameTypes.length && object.pointNames != null) {
|
||||
int[][] types = Arrays.copyOfRange(object.pointNameTypes, start, Math.min(end, object.pointNameTypes.length));
|
||||
if (object.pointNames != null) {
|
||||
String[][] names = Arrays.copyOfRange(object.pointNames, start, Math.min(end, object.pointNames.length));
|
||||
bundle.putArray("pointNames", convertPointNames(types, names, rules));
|
||||
if (reversed) {
|
||||
Algorithms.reverseArray(types);
|
||||
Algorithms.reverseArray(names);
|
||||
}
|
||||
bundle.putArray("pointNames", convertPointNames(types, names, rules));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -886,6 +886,14 @@ public class Algorithms {
|
|||
return map;
|
||||
}
|
||||
|
||||
public static <T> void reverseArray(T[] array) {
|
||||
for (int i = 0; i < array.length / 2; i++) {
|
||||
T temp = array[i];
|
||||
array[i] = array[array.length - i - 1];
|
||||
array[array.length - i - 1] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsInArrayL(long[] array, long value) {
|
||||
return Arrays.binarySearch(array, value) >= 0;
|
||||
}
|
||||
|
|
32
OsmAnd/res/drawable/shadow.xml
Normal file
32
OsmAnd/res/drawable/shadow.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape
|
||||
android:dither="true"
|
||||
android:shape="rectangle">
|
||||
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:startColor="#1A000000"
|
||||
android:centerColor="#00FFFFFF"
|
||||
android:endColor="#00FFFFFF" />
|
||||
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<shape
|
||||
android:dither="true"
|
||||
android:shape="rectangle">
|
||||
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:startColor="#0D000000"
|
||||
android:centerColor="#00FFFFFF"
|
||||
android:endColor="#00FFFFFF" />
|
||||
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -38,9 +38,9 @@
|
|||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/buttons_shadow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/bg_contextmenu_shadow_top_light"
|
||||
android:background="@drawable/shadow"
|
||||
android:visibility="gone" />
|
||||
|
||||
<include layout="@layout/bottom_buttons" />
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/buttons_shadow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/bg_contextmenu_shadow_top_light"
|
||||
android:background="@drawable/shadow"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/buttons_shadow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
android:background="@drawable/bg_contextmenu_shadow_top_light" />
|
||||
android:layout_height="8dp"
|
||||
android:background="@drawable/shadow" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -128,9 +128,9 @@
|
|||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/buttons_shadow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/bg_contextmenu_shadow_top_light" />
|
||||
android:background="@drawable/shadow" />
|
||||
|
||||
<include
|
||||
layout="@layout/bottom_buttons"
|
||||
|
|
|
@ -98,9 +98,9 @@
|
|||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/buttons_shadow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/bg_contextmenu_shadow_top_light" />
|
||||
android:background="@drawable/shadow" />
|
||||
|
||||
<include
|
||||
layout="@layout/bottom_buttons"
|
||||
|
|
|
@ -591,9 +591,9 @@
|
|||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/buttons_shadow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/bg_contextmenu_shadow_top_light" />
|
||||
android:background="@drawable/shadow" />
|
||||
|
||||
<include
|
||||
layout="@layout/route_info_menu_control_buttons"
|
||||
|
|
|
@ -129,9 +129,9 @@
|
|||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/buttons_shadow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/bg_contextmenu_shadow_top_light" />
|
||||
android:background="@drawable/shadow" />
|
||||
|
||||
<include
|
||||
layout="@layout/bottom_buttons"
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
Thx - Hardy
|
||||
|
||||
-->
|
||||
<string name="app_mode_gap">Gap</string>
|
||||
<string name="ltr_or_rtl_combine_via_dash">%1$s — %2$s</string>
|
||||
<string name="message_graph_will_be_available_after_recalculation">Wait for the route recalculation.\nGraph will be available after recalculation.</string>
|
||||
<string name="message_need_calculate_route_before_show_graph">%1$s data available only on the roads, you need to calculate a route using “Route between points” to get it.</string>
|
||||
<string name="shared_string_graph">Graph</string>
|
||||
|
|
|
@ -428,7 +428,7 @@ public class FavouritesDbHelper {
|
|||
while (fl) {
|
||||
fl = false;
|
||||
for (FavouritePoint fp : fdb.getFavouritePoints()) {
|
||||
if (fp.getName().equals(name) && p.getLatitude() != fp.getLatitude() && p.getLongitude() != fp.getLongitude()) {
|
||||
if (fp.getName().equals(name) && p.getLatitude() != fp.getLatitude() && p.getLongitude() != fp.getLongitude() && fp.getCategory().equals(p.getCategory())) {
|
||||
number++;
|
||||
index = " (" + number + ")";
|
||||
name = p.getName() + index;
|
||||
|
|
|
@ -21,7 +21,6 @@ import com.google.android.material.bottomnavigation.BottomNavigationView;
|
|||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.data.LatLon;
|
||||
|
@ -32,9 +31,7 @@ import net.osmand.plus.GpxSelectionHelper;
|
|||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.LockableViewPager;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment;
|
||||
import net.osmand.plus.measurementtool.GpxData;
|
||||
|
@ -44,6 +41,8 @@ import net.osmand.plus.myplaces.TrackBitmapDrawer;
|
|||
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
|
||||
import net.osmand.plus.myplaces.TrackPointFragment;
|
||||
import net.osmand.plus.myplaces.TrackSegmentFragment;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -136,14 +135,9 @@ public class TrackActivity extends TabActivity {
|
|||
}
|
||||
}
|
||||
|
||||
public void addNewGpxData(GpxData.ActionType actionType) {
|
||||
addNewGpxData(actionType, null);
|
||||
}
|
||||
|
||||
public void addNewGpxData(GpxData.ActionType actionType, TrkSegment segment) {
|
||||
public void addNewGpxData() {
|
||||
GPXFile gpxFile = getGpx();
|
||||
QuadRect rect = getRect();
|
||||
GpxData gpxData = new GpxData(gpxFile, rect, actionType, segment);
|
||||
GpxData gpxData = new GpxData(gpxFile);
|
||||
WptPt pointToShow = gpxFile != null ? gpxFile.findPointToShow() : null;
|
||||
if (pointToShow != null) {
|
||||
LatLon location = new LatLon(pointToShow.getLatitude(), pointToShow.getLongitude());
|
||||
|
@ -154,7 +148,6 @@ public class TrackActivity extends TabActivity {
|
|||
false,
|
||||
gpxData
|
||||
);
|
||||
|
||||
MapActivity.launchMapActivityMoveToTop(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -434,6 +434,21 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
|
|||
return !app.getSettings().isLightContent();
|
||||
}
|
||||
|
||||
private void showShadowButton() {
|
||||
buttonsShadow.setVisibility(View.VISIBLE);
|
||||
buttonsShadow.animate()
|
||||
.alpha(0.8f)
|
||||
.setDuration(200)
|
||||
.setListener(null);
|
||||
}
|
||||
|
||||
private void hideShadowButton() {
|
||||
buttonsShadow.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(200);
|
||||
|
||||
}
|
||||
|
||||
private void setupScrollShadow(View view) {
|
||||
final View scrollView;
|
||||
if (useScrollableItemsContainer()) {
|
||||
|
@ -446,7 +461,11 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
|
|||
@Override
|
||||
public void onScrollChanged() {
|
||||
boolean scrollToBottomAvailable = scrollView.canScrollVertically(1);
|
||||
AndroidUiHelper.updateVisibility(buttonsShadow, scrollToBottomAvailable);
|
||||
if (scrollToBottomAvailable) {
|
||||
showShadowButton();
|
||||
} else {
|
||||
hideShadowButton();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -670,7 +670,10 @@ public class ImportHelper {
|
|||
}
|
||||
fp.setAddress(p.getExtensionsToRead().get("address"));
|
||||
fp.setColor(p.getColor(0));
|
||||
fp.setIconIdFromName(app, p.getIconName());
|
||||
String iconName = p.getIconName();
|
||||
if (iconName != null) {
|
||||
fp.setIconIdFromName(app, iconName);
|
||||
}
|
||||
fp.setBackgroundType(BackgroundType.getByTypeName(p.getBackgroundType(), DEFAULT_BACKGROUND_TYPE));
|
||||
favourites.add(fp);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import androidx.fragment.app.FragmentActivity;
|
|||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.LocationsHolder;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
|
@ -27,11 +28,18 @@ 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.routing.GpxApproximator.GpxApproximationProgressCallback;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.osmand.plus.measurementtool.ProfileCard.ProfileCardListener;
|
||||
import static net.osmand.plus.measurementtool.SliderCard.SliderCardListener;
|
||||
|
||||
|
@ -49,8 +57,11 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
private ApplicationMode snapToRoadAppMode = ApplicationMode.CAR;
|
||||
private int distanceThreshold = 50;
|
||||
private boolean applyApproximation;
|
||||
private GpxApproximationProgressCallback approximationProgress;
|
||||
|
||||
private List<LocationsHolder> locationsHolders;
|
||||
private final Map<LocationsHolder, GpxRouteApproximation> resultMap = new HashMap<>();
|
||||
|
||||
private LocationsHolder locationsHolder;
|
||||
@Nullable
|
||||
private GpxApproximator gpxApproximator;
|
||||
private ProgressBar progressBar;
|
||||
|
@ -119,44 +130,26 @@ 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() {
|
||||
approximationProgress = new GpxApproximationProgressCallback() {
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (isResumed()) {
|
||||
startProgress();
|
||||
public void start(GpxApproximator approximator) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateProgress(GpxApproximator approximator, int progress) {
|
||||
if (isResumed() && approximator == GpxApproximationFragment.this.gpxApproximator) {
|
||||
float partSize = 100f / locationsHolders.size();
|
||||
float p = resultMap.size() * partSize + (progress / 100f) * partSize;
|
||||
GpxApproximationFragment.this.updateProgress((int) p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateProgress(int progress) {
|
||||
if (isResumed()) {
|
||||
GpxApproximationFragment.this.updateProgress(progress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
if (isResumed()) {
|
||||
finishProgress();
|
||||
}
|
||||
}
|
||||
});
|
||||
public void finish(GpxApproximator approximator) {
|
||||
}
|
||||
};
|
||||
|
||||
applyButton = mainView.findViewById(R.id.right_bottom_button);
|
||||
cancelButton = mainView.findViewById(R.id.dismiss_button);
|
||||
|
@ -180,7 +173,7 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
}
|
||||
runLayoutListener();
|
||||
|
||||
calculateGpxApproximation();
|
||||
calculateGpxApproximation(true);
|
||||
|
||||
return mainView;
|
||||
}
|
||||
|
@ -219,6 +212,20 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
}
|
||||
}
|
||||
|
||||
private GpxApproximator getNewGpxApproximator(@NonNull LocationsHolder locationsHolder) {
|
||||
GpxApproximator gpxApproximator = null;
|
||||
try {
|
||||
OsmandApplication app = getMyApplication();
|
||||
if (app != null) {
|
||||
gpxApproximator = new GpxApproximator(app, snapToRoadAppMode, distanceThreshold, locationsHolder);
|
||||
gpxApproximator.setApproximationProgress(approximationProgress);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
}
|
||||
return gpxApproximator;
|
||||
}
|
||||
|
||||
private void updateCardsLayout() {
|
||||
View mainView = getMainView();
|
||||
if (mainView != null) {
|
||||
|
@ -299,13 +306,17 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
}
|
||||
|
||||
public static void showInstance(@NonNull FragmentManager fm, @Nullable Fragment targetFragment,
|
||||
@NonNull LocationsHolder locationsHolder, @Nullable ApplicationMode appMode) {
|
||||
@NonNull List<List<WptPt>> pointsList, @Nullable ApplicationMode appMode) {
|
||||
try {
|
||||
if (!fm.isStateSaved()) {
|
||||
GpxApproximationFragment fragment = new GpxApproximationFragment();
|
||||
fragment.setRetainInstance(true);
|
||||
fragment.setTargetFragment(targetFragment, REQUEST_CODE);
|
||||
fragment.setLocationsHolder(locationsHolder);
|
||||
List<LocationsHolder> locationsHolders = new ArrayList<>();
|
||||
for (List<WptPt> points : pointsList) {
|
||||
locationsHolders.add(new LocationsHolder(points));
|
||||
}
|
||||
fragment.setLocationsHolders(locationsHolders);
|
||||
fragment.setSnapToRoadAppMode(appMode);
|
||||
fm.beginTransaction()
|
||||
.replace(R.id.fragmentContainer, fragment, TAG)
|
||||
|
@ -328,30 +339,48 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
}
|
||||
}
|
||||
|
||||
public void calculateGpxApproximation() {
|
||||
public boolean calculateGpxApproximation(boolean newCalculation) {
|
||||
if (newCalculation) {
|
||||
if (gpxApproximator != null) {
|
||||
gpxApproximator.cancelApproximation();
|
||||
gpxApproximator = null;
|
||||
}
|
||||
resultMap.clear();
|
||||
startProgress();
|
||||
}
|
||||
GpxApproximator gpxApproximator = null;
|
||||
for (LocationsHolder locationsHolder : locationsHolders) {
|
||||
if (!resultMap.containsKey(locationsHolder)) {
|
||||
gpxApproximator = getNewGpxApproximator(locationsHolder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gpxApproximator != null) {
|
||||
try {
|
||||
this.gpxApproximator = gpxApproximator;
|
||||
gpxApproximator.setMode(snapToRoadAppMode);
|
||||
gpxApproximator.setPointApproximation(distanceThreshold);
|
||||
approximateGpx();
|
||||
approximateGpx(gpxApproximator);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSliderChange(int sliderValue) {
|
||||
if (distanceThreshold != sliderValue) {
|
||||
distanceThreshold = sliderValue;
|
||||
calculateGpxApproximation();
|
||||
calculateGpxApproximation(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProfileSelect(ApplicationMode applicationMode) {
|
||||
if (setSnapToRoadAppMode(applicationMode)) {
|
||||
calculateGpxApproximation();
|
||||
calculateGpxApproximation(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,12 +392,12 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
return false;
|
||||
}
|
||||
|
||||
public LocationsHolder getLocationsHolder() {
|
||||
return locationsHolder;
|
||||
public List<LocationsHolder> getLocationsHolders() {
|
||||
return locationsHolders;
|
||||
}
|
||||
|
||||
public void setLocationsHolder(LocationsHolder locationsHolder) {
|
||||
this.locationsHolder = locationsHolder;
|
||||
public void setLocationsHolders(List<LocationsHolder> locationsHolders) {
|
||||
this.locationsHolders = locationsHolders;
|
||||
}
|
||||
|
||||
public void startProgress() {
|
||||
|
@ -393,9 +422,8 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
}
|
||||
}
|
||||
|
||||
private void approximateGpx() {
|
||||
if (gpxApproximator != null) {
|
||||
setApplyButtonEnabled(false);
|
||||
private void approximateGpx(@NonNull final GpxApproximator gpxApproximator) {
|
||||
onApproximationStarted();
|
||||
gpxApproximator.calculateGpxApproximation(new ResultMatcher<GpxRouteApproximation>() {
|
||||
@Override
|
||||
public boolean publish(final GpxRouteApproximation gpxApproximation) {
|
||||
|
@ -404,16 +432,18 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
app.runInUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof GpxApproximationFragmentListener) {
|
||||
((GpxApproximationFragmentListener) fragment).onGpxApproximationDone(gpxApproximation, gpxApproximator.getMode());
|
||||
if (!gpxApproximator.isCancelled()) {
|
||||
if (gpxApproximation != null) {
|
||||
resultMap.put(gpxApproximator.getLocationsHolder(), gpxApproximation);
|
||||
}
|
||||
if (!calculateGpxApproximation(false)) {
|
||||
onApproximationFinished();
|
||||
}
|
||||
}
|
||||
setApplyButtonEnabled(gpxApproximation != null);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -422,6 +452,28 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onApproximationStarted() {
|
||||
setApplyButtonEnabled(false);
|
||||
}
|
||||
|
||||
private void onApproximationFinished() {
|
||||
finishProgress();
|
||||
Fragment fragment = getTargetFragment();
|
||||
List<GpxRouteApproximation> approximations = new ArrayList<>();
|
||||
List<List<WptPt>> points = new ArrayList<>();
|
||||
for (LocationsHolder locationsHolder : locationsHolders) {
|
||||
GpxRouteApproximation approximation = resultMap.get(locationsHolder);
|
||||
if (approximation != null) {
|
||||
approximations.add(approximation);
|
||||
points.add(locationsHolder.getWptPtList());
|
||||
}
|
||||
}
|
||||
if (fragment instanceof GpxApproximationFragmentListener) {
|
||||
((GpxApproximationFragmentListener) fragment).onGpxApproximationDone(
|
||||
approximations, points, snapToRoadAppMode);
|
||||
}
|
||||
setApplyButtonEnabled(!approximations.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -431,7 +483,7 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
|
|||
|
||||
public interface GpxApproximationFragmentListener {
|
||||
|
||||
void onGpxApproximationDone(GpxRouteApproximation gpxApproximation, ApplicationMode mode);
|
||||
void onGpxApproximationDone(List<GpxRouteApproximation> gpxApproximations, List<List<WptPt>> pointsList, ApplicationMode mode);
|
||||
|
||||
void onApplyGpxApproximation();
|
||||
|
||||
|
|
|
@ -1,35 +1,20 @@
|
|||
package net.osmand.plus.measurementtool;
|
||||
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.data.QuadRect;
|
||||
|
||||
public class GpxData {
|
||||
|
||||
public enum ActionType {
|
||||
ADD_SEGMENT,
|
||||
ADD_ROUTE_POINTS,
|
||||
EDIT_SEGMENT,
|
||||
OVERWRITE_SEGMENT
|
||||
}
|
||||
private final GPXFile gpxFile;
|
||||
private final QuadRect rect;
|
||||
|
||||
private GPXFile gpxFile;
|
||||
private TrkSegment trkSegment;
|
||||
private QuadRect rect;
|
||||
private ActionType actionType;
|
||||
|
||||
public GpxData(GPXFile gpxFile, QuadRect rect, ActionType actionType, TrkSegment trkSegment) {
|
||||
public GpxData(GPXFile gpxFile) {
|
||||
this.gpxFile = gpxFile;
|
||||
this.rect = rect;
|
||||
this.actionType = actionType;
|
||||
this.trkSegment = trkSegment;
|
||||
if (gpxFile != null) {
|
||||
this.rect = gpxFile.getRect();
|
||||
} else {
|
||||
this.rect = new QuadRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public GpxData(GPXFile gpxFile, GpxData gpxData) {
|
||||
this.gpxFile = gpxFile;
|
||||
this.rect = gpxData.rect;
|
||||
this.actionType = gpxData.actionType;
|
||||
this.trkSegment = gpxData.trkSegment;
|
||||
}
|
||||
|
||||
public GPXFile getGpxFile() {
|
||||
|
@ -39,12 +24,4 @@ public class GpxData {
|
|||
public QuadRect getRect() {
|
||||
return rect;
|
||||
}
|
||||
|
||||
public ActionType getActionType() {
|
||||
return actionType;
|
||||
}
|
||||
|
||||
public TrkSegment getTrkSegment() {
|
||||
return trkSegment;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,7 +341,7 @@ public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListen
|
|||
if (editingCtx.getGpxData() != null) {
|
||||
gpx = editingCtx.getGpxData().getGpxFile();
|
||||
} else {
|
||||
gpx = editingCtx.exportRouteAsGpx(GRAPH_DATA_GPX_FILE_NAME);
|
||||
gpx = editingCtx.exportGpx(GRAPH_DATA_GPX_FILE_NAME);
|
||||
}
|
||||
return gpx != null ? gpx.getAnalysis(0) : null;
|
||||
}
|
||||
|
|
|
@ -53,9 +53,11 @@ public class MeasurementEditingContext {
|
|||
private final MeasurementCommandManager commandManager = new MeasurementCommandManager();
|
||||
|
||||
private final TrkSegment before = new TrkSegment();
|
||||
private TrkSegment beforeCacheForSnap;
|
||||
private List<TrkSegment> beforeSegments = new ArrayList<>();
|
||||
private List<TrkSegment> beforeSegmentsForSnap;
|
||||
private final TrkSegment after = new TrkSegment();
|
||||
private TrkSegment afterCacheForSnap;
|
||||
private List<TrkSegment> afterSegments = new ArrayList<>();
|
||||
private List<TrkSegment> afterSegmentsForSnap;
|
||||
|
||||
private GpxData gpxData;
|
||||
|
||||
|
@ -63,6 +65,7 @@ public class MeasurementEditingContext {
|
|||
private WptPt originalPointToMove;
|
||||
|
||||
private boolean inAddPointMode;
|
||||
private boolean inAddPointBeforeMode;
|
||||
private boolean inApproximationMode;
|
||||
private int calculatedPairs;
|
||||
private int pointsToCalculateSize;
|
||||
|
@ -72,18 +75,23 @@ public class MeasurementEditingContext {
|
|||
private RouteCalculationProgress calculationProgress;
|
||||
private Map<Pair<WptPt, WptPt>, RoadSegmentData> roadSegmentData = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public enum CalculationMode {
|
||||
NEXT_SEGMENT,
|
||||
WHOLE_TRACK
|
||||
}
|
||||
|
||||
public enum AdditionMode {
|
||||
UNDEFINED,
|
||||
ADD_AFTER,
|
||||
ADD_BEFORE,
|
||||
}
|
||||
|
||||
public static class RoadSegmentData {
|
||||
private ApplicationMode appMode;
|
||||
private WptPt start;
|
||||
private WptPt end;
|
||||
private List<WptPt> points;
|
||||
private List<RouteSegmentResult> segments;
|
||||
private final ApplicationMode appMode;
|
||||
private final WptPt start;
|
||||
private final WptPt end;
|
||||
private final List<WptPt> points;
|
||||
private final List<RouteSegmentResult> segments;
|
||||
private double distance;
|
||||
|
||||
public RoadSegmentData(@NonNull ApplicationMode appMode, @NonNull WptPt start, @NonNull WptPt end,
|
||||
|
@ -156,8 +164,12 @@ public class MeasurementEditingContext {
|
|||
return inAddPointMode;
|
||||
}
|
||||
|
||||
public void updateCacheForSnap() {
|
||||
updateCacheForSnap(true);
|
||||
public boolean isInAddPointBeforeMode() {
|
||||
return inAddPointBeforeMode;
|
||||
}
|
||||
|
||||
public void updateSegmentsForSnap() {
|
||||
updateSegmentsForSnap(true);
|
||||
}
|
||||
|
||||
public int getSelectedPointPosition() {
|
||||
|
@ -176,8 +188,9 @@ public class MeasurementEditingContext {
|
|||
this.originalPointToMove = originalPointToMove;
|
||||
}
|
||||
|
||||
void setInAddPointMode(boolean inAddPointMode) {
|
||||
void setInAddPointMode(boolean inAddPointMode, boolean inAddPointAfterMode) {
|
||||
this.inAddPointMode = inAddPointMode;
|
||||
this.inAddPointBeforeMode = inAddPointAfterMode;
|
||||
}
|
||||
|
||||
public boolean isInApproximationMode() {
|
||||
|
@ -188,10 +201,10 @@ public class MeasurementEditingContext {
|
|||
this.inApproximationMode = inApproximationMode;
|
||||
}
|
||||
|
||||
public List<WptPt> getOriginalTrackPointList() {
|
||||
public List<List<WptPt>> getOriginalSegmentPointsList() {
|
||||
MeasurementModeCommand command = commandManager.getLastCommand();
|
||||
if (command.getType() == APPROXIMATE_POINTS) {
|
||||
return ((ApplyGpxApproximationCommand) command).getPoints();
|
||||
return ((ApplyGpxApproximationCommand) command).getOriginalSegmentPointsList();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -213,10 +226,6 @@ public class MeasurementEditingContext {
|
|||
return gpxData != null && gpxData.getGpxFile() != null && gpxData.getGpxFile().hasRtePt();
|
||||
}
|
||||
|
||||
public boolean hasSavedRoute() {
|
||||
return gpxData != null && gpxData.getGpxFile() != null && gpxData.getGpxFile().hasRoute();
|
||||
}
|
||||
|
||||
public CalculationMode getLastCalculationMode() {
|
||||
return lastCalculationMode;
|
||||
}
|
||||
|
@ -279,28 +288,104 @@ public class MeasurementEditingContext {
|
|||
return !roadSegmentData.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isApproximationNeeded() {
|
||||
boolean hasDefaultPoints = false;
|
||||
boolean newData = isNewData();
|
||||
if (!newData) {
|
||||
List<WptPt> points = getPoints();
|
||||
WptPt prevPoint = null;
|
||||
for (WptPt point : points) {
|
||||
if (!point.hasProfile() && (prevPoint == null || !prevPoint.hasProfile())) {
|
||||
hasDefaultPoints = true;
|
||||
break;
|
||||
}
|
||||
prevPoint = point;
|
||||
}
|
||||
}
|
||||
return !newData && hasDefaultPoints && getPoints().size() > 2;
|
||||
}
|
||||
|
||||
public boolean isSelectionNeedApproximation() {
|
||||
boolean hasDefaultPoints = false;
|
||||
boolean newData = isNewData();
|
||||
if (!newData && selectedPointPosition != -1) {
|
||||
WptPt selectedPoint = getPoints().get(selectedPointPosition);
|
||||
List<TrkSegment> segments = getBeforeSegments();
|
||||
List<WptPt> points = null;
|
||||
for (TrkSegment segment : segments) {
|
||||
if (segment.points.contains(selectedPoint)) {
|
||||
points = segment.points;
|
||||
}
|
||||
}
|
||||
WptPt prevPoint = null;
|
||||
if (points != null) {
|
||||
for (WptPt point : points) {
|
||||
if (!point.hasProfile() && (prevPoint == null || !prevPoint.hasProfile())) {
|
||||
hasDefaultPoints = true;
|
||||
break;
|
||||
}
|
||||
prevPoint = point;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !newData && hasDefaultPoints && getPoints().size() > 2;
|
||||
}
|
||||
|
||||
public void clearSnappedToRoadPoints() {
|
||||
roadSegmentData.clear();
|
||||
}
|
||||
|
||||
TrkSegment getBeforeTrkSegmentLine() {
|
||||
if (beforeCacheForSnap != null) {
|
||||
return beforeCacheForSnap;
|
||||
List<TrkSegment> getBeforeTrkSegmentLine() {
|
||||
if (beforeSegmentsForSnap != null) {
|
||||
return beforeSegmentsForSnap;
|
||||
}
|
||||
return before;
|
||||
return beforeSegments;
|
||||
}
|
||||
|
||||
TrkSegment getAfterTrkSegmentLine() {
|
||||
if (afterCacheForSnap != null) {
|
||||
return afterCacheForSnap;
|
||||
List<TrkSegment> getAfterTrkSegmentLine() {
|
||||
if (afterSegmentsForSnap != null) {
|
||||
return afterSegmentsForSnap;
|
||||
}
|
||||
return after;
|
||||
return afterSegments;
|
||||
}
|
||||
|
||||
public List<TrkSegment> getBeforeSegments() {
|
||||
return beforeSegments;
|
||||
}
|
||||
|
||||
public List<TrkSegment> getAfterSegments() {
|
||||
return afterSegments;
|
||||
}
|
||||
|
||||
public List<WptPt> getPoints() {
|
||||
return getBeforePoints();
|
||||
}
|
||||
|
||||
public List<List<WptPt>> getPointsSegments(boolean plain, boolean route) {
|
||||
List<List<WptPt>> res = new ArrayList<>();
|
||||
List<WptPt> allPoints = getPoints();
|
||||
List<WptPt> segment = new ArrayList<>();
|
||||
String prevProfileType = null;
|
||||
for (WptPt point : allPoints) {
|
||||
String profileType = point.getProfileType();
|
||||
boolean isGap = point.isGap();
|
||||
boolean plainPoint = Algorithms.isEmpty(profileType) || (isGap && Algorithms.isEmpty(prevProfileType));
|
||||
boolean routePoint = !plainPoint;
|
||||
if (plain && plainPoint || route && routePoint) {
|
||||
segment.add(point);
|
||||
if (isGap) {
|
||||
res.add(segment);
|
||||
segment = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
prevProfileType = profileType;
|
||||
}
|
||||
if (!segment.isEmpty()) {
|
||||
res.add(segment);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
List<WptPt> getBeforePoints() {
|
||||
return before.points;
|
||||
}
|
||||
|
@ -335,31 +420,118 @@ public class MeasurementEditingContext {
|
|||
after.points.clear();
|
||||
before.points.addAll(points.subList(0, position));
|
||||
after.points.addAll(points.subList(position, points.size()));
|
||||
updateCacheForSnap(true);
|
||||
updateSegmentsForSnap(true);
|
||||
}
|
||||
|
||||
private void preAddPoint(int position, AdditionMode additionMode, WptPt point) {
|
||||
switch (additionMode) {
|
||||
case UNDEFINED: {
|
||||
if (appMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||
point.setProfileType(appMode.getStringKey());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADD_AFTER: {
|
||||
List<WptPt> points = getBeforePoints();
|
||||
if (position > 0 && position <= points.size()) {
|
||||
WptPt prevPt = points.get(position - 1);
|
||||
if (prevPt.isGap()) {
|
||||
point.setGap();
|
||||
if (position > 1) {
|
||||
WptPt pt = points.get(position - 2);
|
||||
if (pt.hasProfile()) {
|
||||
prevPt.setProfileType(pt.getProfileType());
|
||||
} else {
|
||||
prevPt.removeProfileType();
|
||||
}
|
||||
}
|
||||
} else if (prevPt.hasProfile()) {
|
||||
point.setProfileType(prevPt.getProfileType());
|
||||
}
|
||||
} else if (appMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||
point.setProfileType(appMode.getStringKey());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADD_BEFORE: {
|
||||
List<WptPt> points = getAfterPoints();
|
||||
if (position >= -1 && position + 1 < points.size()) {
|
||||
WptPt nextPt = points.get(position + 1);
|
||||
if (nextPt.hasProfile()) {
|
||||
point.setProfileType(nextPt.getProfileType());
|
||||
}
|
||||
} else if (appMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||
point.setProfileType(appMode.getStringKey());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addPoint(WptPt pt) {
|
||||
addPoint(pt, AdditionMode.UNDEFINED);
|
||||
}
|
||||
|
||||
public void addPoint(WptPt pt, AdditionMode additionMode) {
|
||||
if (additionMode == AdditionMode.ADD_AFTER || additionMode == AdditionMode.ADD_BEFORE) {
|
||||
preAddPoint(additionMode == AdditionMode.ADD_BEFORE ? -1 : getBeforePoints().size(), additionMode, pt);
|
||||
}
|
||||
before.points.add(pt);
|
||||
updateCacheForSnap(false);
|
||||
updateSegmentsForSnap(false);
|
||||
}
|
||||
|
||||
public void addPoint(int position, WptPt pt) {
|
||||
addPoint(position, pt, AdditionMode.UNDEFINED);
|
||||
}
|
||||
|
||||
public void addPoint(int position, WptPt pt, AdditionMode additionMode) {
|
||||
if (additionMode == AdditionMode.ADD_AFTER || additionMode == AdditionMode.ADD_BEFORE) {
|
||||
preAddPoint(position, additionMode, pt);
|
||||
}
|
||||
before.points.add(position, pt);
|
||||
updateCacheForSnap(false);
|
||||
updateSegmentsForSnap(false);
|
||||
}
|
||||
|
||||
public void addPoints(List<WptPt> points) {
|
||||
before.points.addAll(points);
|
||||
updateCacheForSnap(false);
|
||||
updateSegmentsForSnap(false);
|
||||
}
|
||||
|
||||
public void replacePoints(List<WptPt> originalPoints, List<WptPt> points) {
|
||||
if (originalPoints.size() > 1) {
|
||||
int firstPointIndex = before.points.indexOf(originalPoints.get(0));
|
||||
int lastPointIndex = before.points.indexOf(originalPoints.get(originalPoints.size() - 1));
|
||||
List<WptPt> newPoints = new ArrayList<>();
|
||||
if (firstPointIndex != -1 && lastPointIndex != -1) {
|
||||
newPoints.addAll(before.points.subList(0, firstPointIndex));
|
||||
newPoints.addAll(points);
|
||||
if (before.points.size() > lastPointIndex + 1) {
|
||||
newPoints.addAll(before.points.subList(lastPointIndex + 1, before.points.size()));
|
||||
}
|
||||
} else {
|
||||
newPoints.addAll(points);
|
||||
}
|
||||
before.points = newPoints;
|
||||
} else {
|
||||
before.points = points;
|
||||
}
|
||||
updateSegmentsForSnap(false);
|
||||
}
|
||||
|
||||
public WptPt removePoint(int position, boolean updateSnapToRoad) {
|
||||
if (position < 0 || position >= before.points.size()) {
|
||||
return new WptPt();
|
||||
}
|
||||
WptPt pt = before.points.remove(position);
|
||||
WptPt pt = before.points.get(position);
|
||||
if (position > 0 && pt.isGap()) {
|
||||
WptPt prevPt = before.points.get(position - 1);
|
||||
if (!prevPt.isGap()) {
|
||||
prevPt.setGap();
|
||||
}
|
||||
}
|
||||
before.points.remove(position);
|
||||
if (updateSnapToRoad) {
|
||||
updateCacheForSnap(false);
|
||||
updateSegmentsForSnap(false);
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
|
@ -382,24 +554,40 @@ public class MeasurementEditingContext {
|
|||
|
||||
public void clearBeforeSegments() {
|
||||
before.points.clear();
|
||||
if (beforeCacheForSnap != null) {
|
||||
beforeCacheForSnap.points.clear();
|
||||
if (beforeSegmentsForSnap != null) {
|
||||
beforeSegmentsForSnap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAfterSegments() {
|
||||
after.points.clear();
|
||||
if (afterCacheForSnap != null) {
|
||||
afterCacheForSnap.points.clear();
|
||||
if (afterSegmentsForSnap != null) {
|
||||
afterSegmentsForSnap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFirstPointSelected() {
|
||||
return selectedPointPosition == 0;
|
||||
return isBorderPointSelected(true);
|
||||
}
|
||||
|
||||
public boolean isLastPointSelected() {
|
||||
return selectedPointPosition == getPoints().size() - 1;
|
||||
return isBorderPointSelected(false);
|
||||
}
|
||||
|
||||
private boolean isBorderPointSelected(boolean first) {
|
||||
WptPt selectedPoint = getPoints().get(selectedPointPosition);
|
||||
List<TrkSegment> segments = getBeforeSegments();
|
||||
int count = 0;
|
||||
for (TrkSegment segment : segments) {
|
||||
int i = segment.points.indexOf(selectedPoint);
|
||||
if (i != -1) {
|
||||
int segmentPosition = selectedPointPosition - count;
|
||||
return first ? segmentPosition == 0 : segmentPosition == segment.points.size() - 1;
|
||||
} else {
|
||||
count += segment.points.size();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ApplicationMode getSelectedPointAppMode() {
|
||||
|
@ -438,8 +626,10 @@ public class MeasurementEditingContext {
|
|||
List<Pair<WptPt, WptPt>> res = new ArrayList<>();
|
||||
for (List<WptPt> points : Arrays.asList(before.points, after.points)) {
|
||||
for (int i = 0; i < points.size() - 1; i++) {
|
||||
Pair<WptPt, WptPt> pair = new Pair<>(points.get(i), points.get(i + 1));
|
||||
if (roadSegmentData.get(pair) == null) {
|
||||
WptPt startPoint = points.get(i);
|
||||
WptPt endPoint = points.get(i + 1);
|
||||
Pair<WptPt, WptPt> pair = new Pair<>(startPoint, endPoint);
|
||||
if (roadSegmentData.get(pair) == null && startPoint.hasProfile()) {
|
||||
res.add(pair);
|
||||
}
|
||||
}
|
||||
|
@ -457,46 +647,82 @@ public class MeasurementEditingContext {
|
|||
return keys;
|
||||
}
|
||||
|
||||
private void recreateCacheForSnap(TrkSegment cache, TrkSegment original, boolean calculateIfNeeded) {
|
||||
boolean hasDefaultModeOnly = true;
|
||||
if (original.points.size() > 1) {
|
||||
for (int i = 0; i < original.points.size(); i++) {
|
||||
String profileType = original.points.get(i).getProfileType();
|
||||
if (profileType != null && !profileType.equals(DEFAULT_APP_MODE.getStringKey())) {
|
||||
hasDefaultModeOnly = false;
|
||||
break;
|
||||
private void recreateSegments(List<TrkSegment> segments, List<TrkSegment> segmentsForSnap, List<WptPt> points, boolean calculateIfNeeded) {
|
||||
List<Integer> roadSegmentIndexes = new ArrayList<>();
|
||||
TrkSegment s = new TrkSegment();
|
||||
segments.add(s);
|
||||
boolean defaultMode = true;
|
||||
if (points.size() > 1) {
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
WptPt point = points.get(i);
|
||||
s.points.add(point);
|
||||
String profileType = point.getProfileType();
|
||||
if (profileType != null) {
|
||||
boolean isDefault = profileType.equals(DEFAULT_APP_MODE.getStringKey());
|
||||
boolean isGap = point.isGap();
|
||||
if (defaultMode && !isDefault && !isGap) {
|
||||
roadSegmentIndexes.add(segments.size() - 1);
|
||||
defaultMode = false;
|
||||
}
|
||||
if (isGap) {
|
||||
if (!s.points.isEmpty()) {
|
||||
s = new TrkSegment();
|
||||
segments.add(s);
|
||||
defaultMode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (original.points.size() > 1) {
|
||||
for (int i = 0; i < original.points.size() - 1; i++) {
|
||||
Pair<WptPt, WptPt> pair = new Pair<>(original.points.get(i), original.points.get(i + 1));
|
||||
}
|
||||
} else {
|
||||
s.points.addAll(points);
|
||||
}
|
||||
if (s.points.isEmpty()) {
|
||||
segments.remove(s);
|
||||
}
|
||||
if (!segments.isEmpty()) {
|
||||
for (TrkSegment segment : segments) {
|
||||
TrkSegment segmentForSnap = new TrkSegment();
|
||||
for (int i = 0; i < segment.points.size() - 1; i++) {
|
||||
Pair<WptPt, WptPt> pair = new Pair<>(segment.points.get(i), segment.points.get(i + 1));
|
||||
RoadSegmentData data = this.roadSegmentData.get(pair);
|
||||
List<WptPt> pts = data != null ? data.getPoints() : null;
|
||||
if (pts != null) {
|
||||
cache.points.addAll(pts);
|
||||
segmentForSnap.points.addAll(pts);
|
||||
} else {
|
||||
if (calculateIfNeeded && !hasDefaultModeOnly) {
|
||||
if (calculateIfNeeded && roadSegmentIndexes.contains(segmentsForSnap.size())) {
|
||||
scheduleRouteCalculateIfNotEmpty();
|
||||
}
|
||||
cache.points.addAll(Arrays.asList(pair.first, pair.second));
|
||||
segmentForSnap.points.addAll(Arrays.asList(pair.first, pair.second));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cache.points.addAll(original.points);
|
||||
if (segmentForSnap.points.isEmpty()) {
|
||||
segmentForSnap.points.addAll(segment.points);
|
||||
}
|
||||
segmentsForSnap.add(segmentForSnap);
|
||||
}
|
||||
} else if (!points.isEmpty()) {
|
||||
TrkSegment segmentForSnap = new TrkSegment();
|
||||
segmentForSnap.points.addAll(points);
|
||||
segmentsForSnap.add(segmentForSnap);
|
||||
}
|
||||
}
|
||||
|
||||
void addPoints() {
|
||||
GpxData gpxData = getGpxData();
|
||||
if (gpxData == null || gpxData.getTrkSegment() == null || Algorithms.isEmpty(gpxData.getTrkSegment().points)) {
|
||||
if (gpxData == null || gpxData.getGpxFile() == null) {
|
||||
return;
|
||||
}
|
||||
List<WptPt> points = gpxData.getTrkSegment().points;
|
||||
if (isTrackSnappedToRoad()) {
|
||||
RouteImporter routeImporter = new RouteImporter(gpxData.getGpxFile());
|
||||
List<RouteSegmentResult> segments = routeImporter.importRoute();
|
||||
List<WptPt> routePoints = gpxData.getGpxFile().getRoutePoints();
|
||||
List<TrkSegment> segments = gpxData.getGpxFile().getNonEmptyTrkSegments(false);
|
||||
if (Algorithms.isEmpty(segments)) {
|
||||
return;
|
||||
}
|
||||
for (int si = 0; si < segments.size(); si++) {
|
||||
TrkSegment segment = segments.get(si);
|
||||
List<WptPt> points = segment.points;
|
||||
if (segment.hasRoute()) {
|
||||
RouteImporter routeImporter = new RouteImporter(segment);
|
||||
List<RouteSegmentResult> routeSegments = routeImporter.importRoute();
|
||||
List<WptPt> routePoints = gpxData.getGpxFile().getRoutePoints(si);
|
||||
int prevPointIndex = 0;
|
||||
if (routePoints.isEmpty() && points.size() > 1) {
|
||||
routePoints.add(points.get(0));
|
||||
|
@ -521,11 +747,11 @@ public class MeasurementEditingContext {
|
|||
if (points.size() > prevPointIndex + 1) {
|
||||
pairPoints.add(points.get(prevPointIndex + 1));
|
||||
}
|
||||
Iterator<RouteSegmentResult> it = segments.iterator();
|
||||
Iterator<RouteSegmentResult> it = routeSegments.iterator();
|
||||
int k = endIndex - startIndex - 1;
|
||||
List<RouteSegmentResult> pairSegments = new ArrayList<>();
|
||||
if (k == 0 && !segments.isEmpty()) {
|
||||
pairSegments.add(segments.remove(0));
|
||||
if (k == 0 && !routeSegments.isEmpty()) {
|
||||
pairSegments.add(routeSegments.remove(0));
|
||||
} else {
|
||||
while (it.hasNext() && k > 0) {
|
||||
RouteSegmentResult s = it.next();
|
||||
|
@ -538,17 +764,23 @@ public class MeasurementEditingContext {
|
|||
roadSegmentData.put(pair, new RoadSegmentData(appMode, pair.first, pair.second, pairPoints, pairSegments));
|
||||
}
|
||||
}
|
||||
if (!routePoints.isEmpty() && si < segments.size() - 1) {
|
||||
routePoints.get(routePoints.size() - 1).setGap();
|
||||
}
|
||||
addPoints(routePoints);
|
||||
} else {
|
||||
addPoints(points);
|
||||
if (!points.isEmpty() && si < segments.size() - 1) {
|
||||
points.get(points.size() - 1).setGap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPoints(GpxRouteApproximation gpxApproximation, ApplicationMode mode) {
|
||||
public List<WptPt> setPoints(GpxRouteApproximation gpxApproximation, List<WptPt> originalPoints, ApplicationMode mode) {
|
||||
if (gpxApproximation == null || Algorithms.isEmpty(gpxApproximation.finalPoints) || Algorithms.isEmpty(gpxApproximation.result)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
roadSegmentData.clear();
|
||||
List<WptPt> routePoints = new ArrayList<>();
|
||||
List<GpxPoint> gpxPoints = gpxApproximation.finalPoints;
|
||||
for (int i = 0; i < gpxPoints.size(); i++) {
|
||||
|
@ -590,7 +822,13 @@ public class MeasurementEditingContext {
|
|||
break;
|
||||
}
|
||||
}
|
||||
addPoints(routePoints);
|
||||
WptPt lastOriginalPoint = originalPoints.get(originalPoints.size() - 1);
|
||||
WptPt lastRoutePoint = routePoints.get(routePoints.size() - 1);
|
||||
if (lastOriginalPoint.isGap()) {
|
||||
lastRoutePoint.setGap();
|
||||
}
|
||||
replacePoints(originalPoints, routePoints);
|
||||
return routePoints;
|
||||
}
|
||||
|
||||
private boolean isLastGpxPoint(List<GpxPoint> gpxPoints, int index) {
|
||||
|
@ -648,24 +886,21 @@ public class MeasurementEditingContext {
|
|||
return index;
|
||||
}
|
||||
|
||||
boolean isTrackSnappedToRoad() {
|
||||
GpxData gpxData = getGpxData();
|
||||
return gpxData != null && gpxData.getTrkSegment() != null
|
||||
&& !gpxData.getTrkSegment().points.isEmpty()
|
||||
&& gpxData.getGpxFile().hasRoute();
|
||||
}
|
||||
|
||||
private void updateCacheForSnap(boolean both) {
|
||||
recreateCacheForSnap(beforeCacheForSnap = new TrkSegment(), before, true);
|
||||
private void updateSegmentsForSnap(boolean both) {
|
||||
recreateSegments(beforeSegments = new ArrayList<>(),
|
||||
beforeSegmentsForSnap = new ArrayList<>(), before.points, true);
|
||||
if (both) {
|
||||
recreateCacheForSnap(afterCacheForSnap = new TrkSegment(), after, true);
|
||||
recreateSegments(afterSegments = new ArrayList<>(),
|
||||
afterSegmentsForSnap = new ArrayList<>(), after.points, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCacheForSnap(boolean both, boolean calculateIfNeeded) {
|
||||
recreateCacheForSnap(beforeCacheForSnap = new TrkSegment(), before, calculateIfNeeded);
|
||||
private void updateSegmentsForSnap(boolean both, boolean calculateIfNeeded) {
|
||||
recreateSegments(beforeSegments = new ArrayList<>(),
|
||||
beforeSegmentsForSnap = new ArrayList<>(), before.points, calculateIfNeeded);
|
||||
if (both) {
|
||||
recreateCacheForSnap(afterCacheForSnap = new TrkSegment(), after, calculateIfNeeded);
|
||||
recreateSegments(afterSegments = new ArrayList<>(),
|
||||
afterSegmentsForSnap = new ArrayList<>(), after.points, calculateIfNeeded);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,7 +997,7 @@ public class MeasurementEditingContext {
|
|||
application.runInUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateCacheForSnap(true, false);
|
||||
updateSegmentsForSnap(true, false);
|
||||
progressListener.refresh();
|
||||
RouteCalculationParams params = getParams(false);
|
||||
if (params != null) {
|
||||
|
@ -777,34 +1012,41 @@ public class MeasurementEditingContext {
|
|||
return params;
|
||||
}
|
||||
|
||||
public List<WptPt> getRoutePoints() {
|
||||
List<WptPt> res = new ArrayList<>();
|
||||
List<WptPt> points = new ArrayList<>(before.points);
|
||||
points.addAll(after.points);
|
||||
int size = points.size();
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
Pair<WptPt, WptPt> pair = new Pair<>(points.get(i), points.get(i + 1));
|
||||
RoadSegmentData data = this.roadSegmentData.get(pair);
|
||||
if (data != null) {
|
||||
res.addAll(data.points);
|
||||
public List<List<WptPt>> getRoutePoints() {
|
||||
List<List<WptPt>> res = new ArrayList<>();
|
||||
List<WptPt> plainPoints = new ArrayList<>(before.points);
|
||||
plainPoints.addAll(after.points);
|
||||
List<WptPt> points = new ArrayList<>();
|
||||
for (WptPt point : plainPoints) {
|
||||
if (point.getTrkPtIndex() != -1) {
|
||||
points.add(point);
|
||||
if (point.isGap()) {
|
||||
res.add(points);
|
||||
points = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!points.isEmpty()) {
|
||||
res.add(points);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GPXFile exportRouteAsGpx(@NonNull String gpxName) {
|
||||
if (application == null || before.points.isEmpty() || !hasRoute()) {
|
||||
public GPXFile exportGpx(@NonNull String gpxName) {
|
||||
if (application == null || before.points.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return RouteExporter.exportRoute(gpxName, getRouteSegments(), null);
|
||||
}
|
||||
|
||||
private TrkSegment getRouteSegment(int startPointIndex, int endPointIndex) {
|
||||
List<RouteSegmentResult> route = new ArrayList<>();
|
||||
List<Location> locations = new ArrayList<>();
|
||||
before.points.get(0).setTrkPtIndex(0);
|
||||
int size = before.points.size();
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
for (int i = startPointIndex; i < endPointIndex; i++) {
|
||||
Pair<WptPt, WptPt> pair = new Pair<>(before.points.get(i), before.points.get(i + 1));
|
||||
RoadSegmentData data = this.roadSegmentData.get(pair);
|
||||
if (data != null) {
|
||||
if (data != null && data.points != null && data.segments != null) {
|
||||
for (WptPt pt : data.points) {
|
||||
Location l = new Location("");
|
||||
l.setLatitude(pt.getLatitude());
|
||||
|
@ -814,11 +1056,42 @@ public class MeasurementEditingContext {
|
|||
}
|
||||
locations.add(l);
|
||||
}
|
||||
pair.second.setTrkPtIndex(i < size - 1 ? locations.size() : locations.size() - 1);
|
||||
pair.second.setTrkPtIndex(i + 1 < before.points.size() - 1 ? locations.size() : locations.size() - 1);
|
||||
route.addAll(data.segments);
|
||||
}
|
||||
}
|
||||
return new RouteExporter(gpxName, route, locations, null).exportRoute();
|
||||
if (!locations.isEmpty() && !route.isEmpty()) {
|
||||
before.points.get(startPointIndex).setTrkPtIndex(0);
|
||||
return new RouteExporter("", route, locations, null).generateRouteSegment();
|
||||
} else if (endPointIndex - startPointIndex >= 0) {
|
||||
TrkSegment segment = new TrkSegment();
|
||||
segment.points = before.points.subList(startPointIndex, endPointIndex + 1);
|
||||
return segment;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<TrkSegment> getRouteSegments() {
|
||||
List<TrkSegment> res = new ArrayList<>();
|
||||
List<Integer> lastPointIndexes = new ArrayList<>();
|
||||
for (int i = 0; i < before.points.size(); i++) {
|
||||
WptPt pt = before.points.get(i);
|
||||
if (pt.isGap()) {
|
||||
lastPointIndexes.add(i);
|
||||
}
|
||||
}
|
||||
if (lastPointIndexes.isEmpty() || lastPointIndexes.get(lastPointIndexes.size() - 1) < before.points.size() - 1) {
|
||||
lastPointIndexes.add(before.points.size() - 1);
|
||||
}
|
||||
int firstPointIndex = 0;
|
||||
for (Integer lastPointIndex : lastPointIndexes) {
|
||||
TrkSegment segment = getRouteSegment(firstPointIndex, lastPointIndex);
|
||||
if (segment != null) {
|
||||
res.add(segment);
|
||||
}
|
||||
firstPointIndex = lastPointIndex + 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
interface SnapToRoadProgressListener {
|
||||
|
|
|
@ -34,9 +34,7 @@ import net.osmand.AndroidUtils;
|
|||
import net.osmand.FileUtils;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.LocationsHolder;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
|
@ -53,7 +51,6 @@ import net.osmand.plus.base.BaseOsmAndFragment;
|
|||
import net.osmand.plus.base.ContextMenuFragment.MenuState;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.measurementtool.GpxApproximationFragment.GpxApproximationFragmentListener;
|
||||
import net.osmand.plus.measurementtool.GpxData.ActionType;
|
||||
import net.osmand.plus.measurementtool.OptionsBottomSheetDialogFragment.OptionsFragmentListener;
|
||||
import net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsDialogMode;
|
||||
import net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsDialogType;
|
||||
|
@ -139,7 +136,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
private static final int UNDO_MODE = 0x8;
|
||||
private int modes = 0x0;
|
||||
|
||||
private boolean approximationApplied = false;
|
||||
private boolean portrait;
|
||||
private boolean nightMode;
|
||||
private int cachedMapPosition;
|
||||
|
@ -149,7 +145,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
private LatLon initialPoint;
|
||||
|
||||
enum SaveType {
|
||||
ROUTE_POINT,
|
||||
ROUTE,
|
||||
LINE
|
||||
}
|
||||
|
||||
|
@ -355,7 +351,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
mainView.findViewById(R.id.options_button).setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
boolean trackSnappedToRoad = editingCtx.isTrackSnappedToRoad() || editingCtx.isNewData() || approximationApplied;
|
||||
boolean trackSnappedToRoad = !editingCtx.isApproximationNeeded();
|
||||
OptionsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
||||
MeasurementToolFragment.this,
|
||||
trackSnappedToRoad,
|
||||
|
@ -503,7 +499,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
if (savedInstanceState == null) {
|
||||
if (fileName != null) {
|
||||
addNewGpxData(getGpxFile(fileName));
|
||||
} else if (!editingCtx.isNewData() && !editingCtx.hasRoutePoints() && !editingCtx.hasRoute() && editingCtx.getPointsCount() > 1) {
|
||||
} else if (editingCtx.isApproximationNeeded()) {
|
||||
enterApproximationMode(mapActivity);
|
||||
}
|
||||
} else {
|
||||
|
@ -570,7 +566,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
if (mapActivity != null) {
|
||||
editingCtx.getCommandManager().setMeasurementLayer(mapActivity.getMapLayers().getMeasurementToolLayer());
|
||||
enterMeasurementMode();
|
||||
updateSnapToRoadControls();
|
||||
if (gpxData != null && addPoints) {
|
||||
if (!isUndoMode()) {
|
||||
List<WptPt> points = gpxData.getGpxFile().getRoutePoints();
|
||||
|
@ -581,13 +576,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
}
|
||||
}
|
||||
}
|
||||
ActionType actionType = gpxData.getActionType();
|
||||
if (actionType == ActionType.ADD_ROUTE_POINTS) {
|
||||
displayRoutePoints();
|
||||
} else if (actionType == ActionType.EDIT_SEGMENT) {
|
||||
displaySegmentPoints();
|
||||
}
|
||||
collectPoints();
|
||||
}
|
||||
updateSnapToRoadControls();
|
||||
setMode(UNDO_MODE, false);
|
||||
}
|
||||
}
|
||||
|
@ -675,16 +666,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
|
||||
private void updateMainIcon() {
|
||||
GpxData gpxData = editingCtx.getGpxData();
|
||||
if (gpxData != null) {
|
||||
ActionType actionType = gpxData.getActionType();
|
||||
if (actionType == ActionType.ADD_SEGMENT || actionType == ActionType.EDIT_SEGMENT) {
|
||||
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_polygom_dark));
|
||||
} else {
|
||||
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_markers_dark));
|
||||
}
|
||||
} else {
|
||||
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_ruler));
|
||||
}
|
||||
mainIcon.setImageDrawable(getActiveIcon(gpxData != null ? R.drawable.ic_action_polygom_dark : R.drawable.ic_action_ruler));
|
||||
}
|
||||
|
||||
private void startSnapToRoad(boolean rememberPreviousTitle) {
|
||||
|
@ -696,15 +678,15 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
toolBarController.setTitle(getString(R.string.route_between_points));
|
||||
mapActivity.refreshMap();
|
||||
|
||||
if (editingCtx.isNewData() || editingCtx.hasRoutePoints() || editingCtx.hasRoute() || editingCtx.getPointsCount() <= 2) {
|
||||
if (editingCtx.isApproximationNeeded()) {
|
||||
enterApproximationMode(mapActivity);
|
||||
} else {
|
||||
RouteBetweenPointsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
||||
this, RouteBetweenPointsDialogType.WHOLE_ROUTE_CALCULATION,
|
||||
editingCtx.getLastCalculationMode() == CalculationMode.NEXT_SEGMENT
|
||||
? RouteBetweenPointsDialogMode.SINGLE
|
||||
: RouteBetweenPointsDialogMode.ALL,
|
||||
editingCtx.getAppMode());
|
||||
} else {
|
||||
enterApproximationMode(mapActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -713,12 +695,11 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
if (editingCtx.getPointsCount() > 0) {
|
||||
GpxData gpxData = editingCtx.getGpxData();
|
||||
if (editingCtx.isNewData() || (isInEditMode() && gpxData.getActionType() == ActionType.EDIT_SEGMENT)) {
|
||||
if (editingCtx.isNewData() || isInEditMode()) {
|
||||
if (showDialog) {
|
||||
openSaveAsNewTrackMenu(mapActivity);
|
||||
} else {
|
||||
saveNewGpx(null, getSuggestedFileName(), true, false, finalSaveAction);
|
||||
saveNewGpx("", getSuggestedFileName(), true, false, finalSaveAction);
|
||||
}
|
||||
} else {
|
||||
addToGpx(mapActivity, finalSaveAction);
|
||||
|
@ -732,6 +713,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
switch (requestCode) {
|
||||
case SnapTrackWarningFragment.REQUEST_CODE:
|
||||
switch (resultCode) {
|
||||
|
@ -742,14 +724,16 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
updateToolbar();
|
||||
break;
|
||||
case SnapTrackWarningFragment.CONTINUE_RESULT_CODE:
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
ApplicationMode mode = editingCtx.getAppMode();
|
||||
if (mode == ApplicationMode.DEFAULT || "public_transport".equals(mode.getRoutingProfile())) {
|
||||
mode = null;
|
||||
}
|
||||
GpxApproximationFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
||||
this, new LocationsHolder(editingCtx.getPoints()), mode);
|
||||
List<List<WptPt>> pointsSegments = editingCtx.getPointsSegments(true, false);
|
||||
if (!pointsSegments.isEmpty()) {
|
||||
GpxApproximationFragment.showInstance(
|
||||
mapActivity.getSupportFragmentManager(), this, pointsSegments, mode);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -757,10 +741,14 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
case ExitBottomSheetDialogFragment.REQUEST_CODE:
|
||||
switch (resultCode) {
|
||||
case ExitBottomSheetDialogFragment.EXIT_RESULT_CODE:
|
||||
if (mapActivity != null) {
|
||||
dismiss(getMapActivity());
|
||||
}
|
||||
break;
|
||||
case ExitBottomSheetDialogFragment.SAVE_RESULT_CODE:
|
||||
if (mapActivity != null) {
|
||||
openSaveAsNewTrackMenu(getMapActivity());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -792,7 +780,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
} else {
|
||||
String trackName = getSuggestedFileName();
|
||||
if (editingCtx.hasRoute()) {
|
||||
GPXFile gpx = editingCtx.exportRouteAsGpx(trackName);
|
||||
GPXFile gpx = editingCtx.exportGpx(trackName);
|
||||
if (gpx != null) {
|
||||
dismiss(mapActivity);
|
||||
runNavigation(gpx, appMode);
|
||||
|
@ -800,15 +788,15 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
Toast.makeText(mapActivity, getString(R.string.error_occurred_saving_gpx), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} else {
|
||||
if (editingCtx.isNewData() || editingCtx.hasRoutePoints()) {
|
||||
if (editingCtx.isApproximationNeeded()) {
|
||||
setMode(DIRECTION_MODE, true);
|
||||
enterApproximationMode(mapActivity);
|
||||
} else {
|
||||
GPXFile gpx = new GPXFile(Version.getFullVersion(requireMyApplication()));
|
||||
gpx.addRoutePoints(points);
|
||||
gpx.addRoutePoints(points, true);
|
||||
dismiss(mapActivity);
|
||||
targetPointsHelper.clearAllPoints(false);
|
||||
mapActions.enterRoutePlanningModeGivenGpx(gpx, appMode, null, null, true, true, MenuState.HEADER_ONLY);
|
||||
} else {
|
||||
setMode(DIRECTION_MODE, true);
|
||||
enterApproximationMode(mapActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -860,7 +848,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addToTheTrackOnClick() {
|
||||
public void addToTrackOnClick() {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
if (editingCtx.getPointsCount() > 0) {
|
||||
|
@ -927,7 +915,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
||||
if (measurementLayer != null) {
|
||||
measurementLayer.moveMapToPoint(editingCtx.getSelectedPointPosition());
|
||||
editingCtx.setInAddPointMode(true);
|
||||
editingCtx.setInAddPointMode(true, false);
|
||||
editingCtx.splitSegments(editingCtx.getSelectedPointPosition() + 1);
|
||||
}
|
||||
((TextView) mainView.findViewById(R.id.add_point_before_after_text)).setText(mainView.getResources().getString(R.string.add_point_after));
|
||||
|
@ -940,7 +928,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
||||
if (measurementLayer != null) {
|
||||
measurementLayer.moveMapToPoint(editingCtx.getSelectedPointPosition());
|
||||
editingCtx.setInAddPointMode(true);
|
||||
editingCtx.setInAddPointMode(true, true);
|
||||
editingCtx.splitSegments(editingCtx.getSelectedPointPosition());
|
||||
}
|
||||
((TextView) mainView.findViewById(R.id.add_point_before_after_text)).setText(mainView.getResources().getString(R.string.add_point_before));
|
||||
|
@ -1081,8 +1069,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper()
|
||||
.getSelectedFileByPath(gpxFile.path);
|
||||
boolean showOnMap = selectedGpxFile != null;
|
||||
saveExistingGpx(gpxFile, showOnMap, ActionType.ADD_SEGMENT,
|
||||
editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, FinalSaveAction.SHOW_TOAST);
|
||||
saveExistingGpx(gpxFile, showOnMap, false, true, FinalSaveAction.SHOW_TOAST);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1107,10 +1094,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
private GpxData setupGpxData(@Nullable GPXFile gpxFile) {
|
||||
GpxData gpxData = null;
|
||||
if (gpxFile != null) {
|
||||
QuadRect rect = gpxFile.getRect();
|
||||
TrkSegment segment = gpxFile.getNonEmptyTrkSegment();
|
||||
ActionType actionType = segment == null ? ActionType.ADD_ROUTE_POINTS : ActionType.EDIT_SEGMENT;
|
||||
gpxData = new GpxData(gpxFile, rect, actionType, segment);
|
||||
gpxData = new GpxData(gpxFile);
|
||||
}
|
||||
editingCtx.setGpxData(gpxData);
|
||||
return gpxData;
|
||||
|
@ -1128,22 +1112,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onSaveAsNewTrack(String folderName, String fileName, boolean showOnMap, boolean simplifiedTrack) {
|
||||
saveNewGpx(folderName, fileName, showOnMap, simplifiedTrack, FinalSaveAction.SHOW_IS_SAVED_FRAGMENT);
|
||||
}
|
||||
|
||||
private void saveNewGpx(String folderName, String fileName, boolean showOnMap, boolean simplifiedTrack,
|
||||
FinalSaveAction finalSaveAction) {
|
||||
OsmandApplication app = getMyApplication();
|
||||
if (app != null) {
|
||||
File dir = getMyApplication().getAppPath(GPX_INDEX_DIR);
|
||||
if (folderName != null && !dir.getName().equals(folderName)) {
|
||||
dir = new File(dir, folderName);
|
||||
}
|
||||
fileName += GPX_FILE_EXT;
|
||||
SaveType saveType = simplifiedTrack ? SaveType.LINE : SaveType.ROUTE_POINT;
|
||||
saveNewGpx(dir, fileName, showOnMap, saveType, finalSaveAction);
|
||||
}
|
||||
public void onSaveAsNewTrack(String folderName, String fileName, boolean showOnMap, boolean simplified) {
|
||||
saveNewGpx(folderName, fileName, showOnMap, simplified, FinalSaveAction.SHOW_IS_SAVED_FRAGMENT);
|
||||
}
|
||||
|
||||
MeasurementAdapterListener createMeasurementAdapterListener(final ItemTouchHelper touchHelper) {
|
||||
|
@ -1219,7 +1189,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
final ApplicationMode appMode = editingCtx.getAppMode();
|
||||
if (mapActivity != null) {
|
||||
Drawable icon;
|
||||
if (editingCtx.isTrackSnappedToRoad() || editingCtx.isNewData() || approximationApplied) {
|
||||
if (!editingCtx.isApproximationNeeded() || editingCtx.isNewData()) {
|
||||
if (appMode == MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||
icon = getActiveIcon(R.drawable.ic_action_split_interval);
|
||||
} else {
|
||||
|
@ -1241,23 +1211,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
}
|
||||
}
|
||||
|
||||
private void displayRoutePoints() {
|
||||
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
||||
GpxData gpxData = editingCtx.getGpxData();
|
||||
GPXFile gpx = gpxData != null ? gpxData.getGpxFile() : null;
|
||||
if (gpx != null) {
|
||||
List<WptPt> points = gpx.getRoutePoints();
|
||||
if (measurementLayer != null) {
|
||||
if (!isUndoMode()) {
|
||||
editingCtx.addPoints(points);
|
||||
}
|
||||
updateAdditionalInfoView();
|
||||
updateDistancePointsText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void displaySegmentPoints() {
|
||||
private void collectPoints() {
|
||||
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
||||
if (measurementLayer != null) {
|
||||
if (!isUndoMode()) {
|
||||
|
@ -1354,7 +1308,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
switchAddPointBeforeAfterMode(false);
|
||||
editingCtx.splitSegments(editingCtx.getBeforePoints().size() + editingCtx.getAfterPoints().size());
|
||||
editingCtx.setSelectedPointPosition(-1);
|
||||
editingCtx.setInAddPointMode(false);
|
||||
editingCtx.setInAddPointMode(false, false);
|
||||
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
||||
if (measurementLayer != null) {
|
||||
measurementLayer.refreshMap();
|
||||
|
@ -1366,7 +1320,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
switchAddPointBeforeAfterMode(false);
|
||||
editingCtx.splitSegments(editingCtx.getBeforePoints().size() + editingCtx.getAfterPoints().size());
|
||||
editingCtx.setSelectedPointPosition(-1);
|
||||
editingCtx.setInAddPointMode(false);
|
||||
editingCtx.setInAddPointMode(false, false);
|
||||
MeasurementToolLayer measurementToolLayer = getMeasurementLayer();
|
||||
if (measurementToolLayer != null) {
|
||||
measurementToolLayer.refreshMap();
|
||||
|
@ -1520,8 +1474,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
SelectedGpxFile selectedGpxFile =
|
||||
mapActivity.getMyApplication().getSelectedGpxHelper().getSelectedFileByPath(gpx.path);
|
||||
boolean showOnMap = selectedGpxFile != null;
|
||||
saveExistingGpx(gpx, showOnMap, gpxData.getActionType(),
|
||||
editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, finalSaveAction);
|
||||
saveExistingGpx(gpx, showOnMap, false, false, finalSaveAction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1555,30 +1508,45 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
return displayedName;
|
||||
}
|
||||
|
||||
private void saveNewGpx(@NonNull File dir, @NonNull String fileName, boolean showOnMap, SaveType saveType, FinalSaveAction finalSaveAction) {
|
||||
saveGpx(new File(dir, fileName), null, null, saveType, finalSaveAction, showOnMap);
|
||||
private void saveNewGpx(String folderName, String fileName, boolean showOnMap,
|
||||
boolean simplified, FinalSaveAction finalSaveAction) {
|
||||
OsmandApplication app = getMyApplication();
|
||||
if (app != null) {
|
||||
File dir = getMyApplication().getAppPath(GPX_INDEX_DIR);
|
||||
if (!Algorithms.isEmpty(folderName) && !dir.getName().equals(folderName)) {
|
||||
dir = new File(dir, folderName);
|
||||
}
|
||||
fileName += GPX_FILE_EXT;
|
||||
saveNewGpx(dir, fileName, showOnMap, simplified, finalSaveAction);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveExistingGpx(@NonNull GPXFile gpx, boolean showOnMap, ActionType actionType,
|
||||
SaveType saveType, FinalSaveAction finalSaveAction) {
|
||||
saveGpx(new File(gpx.path), gpx, actionType, saveType, finalSaveAction, showOnMap);
|
||||
private void saveNewGpx(@NonNull File dir, @NonNull String fileName, boolean showOnMap,
|
||||
boolean simplified, FinalSaveAction finalSaveAction) {
|
||||
saveGpx(new File(dir, fileName), null, simplified, false, finalSaveAction, showOnMap);
|
||||
}
|
||||
|
||||
private void saveGpx(@NonNull final File outFile, @Nullable GPXFile gpxFile, final ActionType actionType,
|
||||
SaveType saveType, final FinalSaveAction finalSaveAction, final boolean showOnMap) {
|
||||
private void saveExistingGpx(@NonNull GPXFile gpx, boolean showOnMap,
|
||||
boolean simplified, boolean addToTrack, FinalSaveAction finalSaveAction) {
|
||||
saveGpx(new File(gpx.path), gpx, simplified, addToTrack, finalSaveAction, showOnMap);
|
||||
}
|
||||
|
||||
private void saveGpx(@NonNull final File outFile, @Nullable GPXFile gpxFile, boolean simplified,
|
||||
boolean addToTrack, final FinalSaveAction finalSaveAction, final boolean showOnMap) {
|
||||
SaveGpxRouteListener saveGpxRouteListener = new SaveGpxRouteListener() {
|
||||
@Override
|
||||
public void gpxSavingFinished(Exception warning, GPXFile savedGpxFile, File backupFile) {
|
||||
onGpxSaved(warning, savedGpxFile, outFile, backupFile, actionType, finalSaveAction, showOnMap);
|
||||
onGpxSaved(warning, savedGpxFile, outFile, backupFile, finalSaveAction, showOnMap);
|
||||
}
|
||||
};
|
||||
|
||||
SaveGpxRouteAsyncTask saveTask = new SaveGpxRouteAsyncTask(this, outFile, gpxFile, actionType, saveType, showOnMap, saveGpxRouteListener);
|
||||
SaveGpxRouteAsyncTask saveTask = new SaveGpxRouteAsyncTask(this, outFile, gpxFile, simplified,
|
||||
addToTrack, showOnMap, saveGpxRouteListener);
|
||||
saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void onGpxSaved(Exception warning, GPXFile savedGpxFile, final File outFile, final File backupFile,
|
||||
final ActionType actionType, FinalSaveAction finalSaveAction, final boolean showOnMap) {
|
||||
FinalSaveAction finalSaveAction, final boolean showOnMap) {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity == null) {
|
||||
return;
|
||||
|
@ -1586,9 +1554,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
mapActivity.refreshMap();
|
||||
if (warning == null) {
|
||||
if (editingCtx.isNewData() && savedGpxFile != null) {
|
||||
QuadRect rect = savedGpxFile.getRect();
|
||||
TrkSegment segment = savedGpxFile.getNonEmptyTrkSegment();
|
||||
GpxData gpxData = new GpxData(savedGpxFile, rect, ActionType.EDIT_SEGMENT, segment);
|
||||
GpxData gpxData = new GpxData(savedGpxFile);
|
||||
editingCtx.setGpxData(gpxData);
|
||||
updateToolbar();
|
||||
}
|
||||
|
@ -1614,7 +1580,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
GPXFile gpx = GPXUtilities.loadGPXFile(outFile);
|
||||
setupGpxData(gpx);
|
||||
if (showOnMap) {
|
||||
showGpxOnMap(app, gpx, actionType, false);
|
||||
showGpxOnMap(app, gpx, false);
|
||||
}
|
||||
} else {
|
||||
setupGpxData(null);
|
||||
|
@ -1660,14 +1626,12 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
}
|
||||
}
|
||||
|
||||
protected static void showGpxOnMap(OsmandApplication app, GPXFile gpx, ActionType actionType, boolean isNewGpx) {
|
||||
protected static void showGpxOnMap(OsmandApplication app, GPXFile gpx, boolean isNewGpx) {
|
||||
SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpx, true, false);
|
||||
if (sf != null && !isNewGpx) {
|
||||
if (actionType == ActionType.ADD_SEGMENT || actionType == ActionType.EDIT_SEGMENT) {
|
||||
sf.processPoints(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUndoRedoButton(boolean enable, View view) {
|
||||
view.setEnabled(enable);
|
||||
|
@ -1704,25 +1668,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
if (mapActivity == null) {
|
||||
return;
|
||||
}
|
||||
final GpxData gpxData = editingCtx.getGpxData();
|
||||
String fileName = getSuggestedFileName();
|
||||
String actionStr = getString(R.string.plan_route);
|
||||
boolean editMode = isInEditMode();
|
||||
if (editMode) {
|
||||
ActionType actionType = gpxData.getActionType();
|
||||
switch (actionType) {
|
||||
case ADD_ROUTE_POINTS:
|
||||
actionStr = getString(R.string.add_route_points);
|
||||
break;
|
||||
case ADD_SEGMENT:
|
||||
actionStr = getString(R.string.add_line);
|
||||
break;
|
||||
case EDIT_SEGMENT:
|
||||
case OVERWRITE_SEGMENT:
|
||||
actionStr = getString(R.string.edit_line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
String actionStr = getString(editMode ? R.string.edit_line : R.string.plan_route);
|
||||
if (!editMode && editingCtx.getPointsCount() > 1) {
|
||||
toolBarController.setTitle(fileName.replace('_', ' '));
|
||||
toolBarController.setDescription(actionStr);
|
||||
|
@ -1969,12 +1917,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onGpxApproximationDone(GpxRouteApproximation gpxApproximation, ApplicationMode mode) {
|
||||
public void onGpxApproximationDone(List<GpxRouteApproximation> gpxApproximations, List<List<WptPt>> pointsList, ApplicationMode mode) {
|
||||
MeasurementToolLayer measurementLayer = getMeasurementLayer();
|
||||
if (measurementLayer != null) {
|
||||
boolean approximationMode = editingCtx.isInApproximationMode();
|
||||
editingCtx.setInApproximationMode(true);
|
||||
ApplyGpxApproximationCommand command = new ApplyGpxApproximationCommand(measurementLayer, gpxApproximation, mode);
|
||||
if (!editingCtx.getCommandManager().update(command)) {
|
||||
ApplyGpxApproximationCommand command = new ApplyGpxApproximationCommand(measurementLayer, gpxApproximations, pointsList, mode);
|
||||
if (!approximationMode || !editingCtx.getCommandManager().update(command)) {
|
||||
editingCtx.getCommandManager().execute(command);
|
||||
}
|
||||
if (additionalInfoExpanded) {
|
||||
|
@ -1986,7 +1935,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
|
||||
@Override
|
||||
public void onApplyGpxApproximation() {
|
||||
approximationApplied = true;
|
||||
exitApproximationMode();
|
||||
doAddOrMovePointCommonStuff();
|
||||
updateSnapToRoadControls();
|
||||
|
@ -2001,7 +1949,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
if (mapActivity != null) {
|
||||
if (editingCtx.hasRoute()) {
|
||||
String trackName = getSuggestedFileName();
|
||||
GPXFile gpx = editingCtx.exportRouteAsGpx(trackName);
|
||||
GPXFile gpx = editingCtx.exportGpx(trackName);
|
||||
if (gpx != null) {
|
||||
ApplicationMode appMode = editingCtx.getAppMode();
|
||||
dismiss(mapActivity);
|
||||
|
|
|
@ -17,7 +17,7 @@ import net.osmand.data.PointDescription;
|
|||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.data.RotatedTileBox;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext.AdditionMode;
|
||||
import net.osmand.plus.views.OsmandMapLayer;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.plus.views.Renderable;
|
||||
|
@ -183,22 +183,27 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
|||
lineAttrs.updatePaints(view.getApplication(), settings, tb);
|
||||
|
||||
if (editingCtx.isInApproximationMode()) {
|
||||
List<WptPt> originalTrackPointList = editingCtx.getOriginalTrackPointList();
|
||||
if (originalTrackPointList != null) {
|
||||
List<List<WptPt>> originalPointsList = editingCtx.getOriginalSegmentPointsList();
|
||||
if (originalPointsList != null) {
|
||||
lineAttrs.customColorPaint.setColor(ContextCompat.getColor(view.getContext(),
|
||||
R.color.activity_background_transparent_color_dark));
|
||||
new Renderable.StandardTrack(new ArrayList<>(originalTrackPointList), 17.2).
|
||||
for (List<WptPt> points : originalPointsList) {
|
||||
new Renderable.StandardTrack(new ArrayList<>(points), 17.2).
|
||||
drawSegment(view.getZoom(), lineAttrs.customColorPaint, canvas, tb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TrkSegment before = editingCtx.getBeforeTrkSegmentLine();
|
||||
new Renderable.StandardTrack(new ArrayList<>(before.points), 17.2).
|
||||
List<TrkSegment> before = editingCtx.getBeforeTrkSegmentLine();
|
||||
for (TrkSegment segment : before) {
|
||||
new Renderable.StandardTrack(new ArrayList<>(segment.points), 17.2).
|
||||
drawSegment(view.getZoom(), lineAttrs.paint, canvas, tb);
|
||||
|
||||
TrkSegment after = editingCtx.getAfterTrkSegmentLine();
|
||||
new Renderable.StandardTrack(new ArrayList<>(after.points), 17.2).
|
||||
}
|
||||
List<TrkSegment> after = editingCtx.getAfterTrkSegmentLine();
|
||||
for (TrkSegment segment : after) {
|
||||
new Renderable.StandardTrack(new ArrayList<>(segment.points), 17.2).
|
||||
drawSegment(view.getZoom(), lineAttrs.paint, canvas, tb);
|
||||
}
|
||||
|
||||
drawPoints(canvas, tb);
|
||||
}
|
||||
|
@ -308,38 +313,54 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
|||
}
|
||||
|
||||
private void drawBeforeAfterPath(Canvas canvas, RotatedTileBox tb) {
|
||||
TrkSegment before = editingCtx.getBeforeTrkSegmentLine();
|
||||
TrkSegment after = editingCtx.getAfterTrkSegmentLine();
|
||||
if (before.points.size() > 0 || after.points.size() > 0) {
|
||||
List<TrkSegment> before = editingCtx.getBeforeSegments();
|
||||
List<TrkSegment> after = editingCtx.getAfterSegments();
|
||||
if (before.size() > 0 || after.size() > 0) {
|
||||
path.reset();
|
||||
tx.clear();
|
||||
ty.clear();
|
||||
|
||||
if (before.points.size() > 0) {
|
||||
WptPt pt = before.points.get(before.points.size() - 1);
|
||||
boolean hasPointsBefore = false;
|
||||
boolean hasGapBefore = false;
|
||||
if (before.size() > 0) {
|
||||
TrkSegment segment = before.get(before.size() - 1);
|
||||
if (segment.points.size() > 0) {
|
||||
hasPointsBefore = true;
|
||||
WptPt pt = segment.points.get(segment.points.size() - 1);
|
||||
hasGapBefore = pt.isGap();
|
||||
if (!pt.isGap() || !editingCtx.isInAddPointBeforeMode()) {
|
||||
float locX = tb.getPixXFromLatLon(pt.lat, pt.lon);
|
||||
float locY = tb.getPixYFromLatLon(pt.lat, pt.lon);
|
||||
tx.add(locX);
|
||||
ty.add(locY);
|
||||
}
|
||||
tx.add((float) tb.getCenterPixelX());
|
||||
ty.add((float) tb.getCenterPixelY());
|
||||
}
|
||||
if (after.points.size() > 0) {
|
||||
if (before.points.size() == 0) {
|
||||
}
|
||||
if (after.size() > 0) {
|
||||
TrkSegment segment = after.get(0);
|
||||
if (segment.points.size() > 0) {
|
||||
if (!hasPointsBefore) {
|
||||
tx.add((float) tb.getCenterPixelX());
|
||||
ty.add((float) tb.getCenterPixelY());
|
||||
}
|
||||
WptPt pt = after.points.get(0);
|
||||
if (!hasGapBefore || editingCtx.isInAddPointBeforeMode()) {
|
||||
WptPt pt = segment.points.get(0);
|
||||
float locX = tb.getPixXFromLatLon(pt.lat, pt.lon);
|
||||
float locY = tb.getPixYFromLatLon(pt.lat, pt.lon);
|
||||
tx.add(locX);
|
||||
ty.add(locY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!tx.isEmpty() && !ty.isEmpty()) {
|
||||
GeometryWay.calculatePath(tb, tx, ty, path);
|
||||
canvas.drawPath(path, lineAttrs.paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawCenterIcon(Canvas canvas, RotatedTileBox tb, boolean nightMode) {
|
||||
canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
|
||||
|
@ -359,7 +380,7 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
|||
canvas.rotate(tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
|
||||
}
|
||||
|
||||
public WptPt addCenterPoint() {
|
||||
public WptPt addCenterPoint(boolean addPointBefore) {
|
||||
RotatedTileBox tb = view.getCurrentRotatedTileBox();
|
||||
LatLon l = tb.getCenterLatLon();
|
||||
WptPt pt = new WptPt();
|
||||
|
@ -367,18 +388,13 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
|||
pt.lon = l.getLongitude();
|
||||
boolean allowed = editingCtx.getPointsCount() == 0 || !editingCtx.getPoints().get(editingCtx.getPointsCount() - 1).equals(pt);
|
||||
if (allowed) {
|
||||
|
||||
ApplicationMode applicationMode = editingCtx.getAppMode();
|
||||
if (applicationMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||
pt.setProfileType(applicationMode.getStringKey());
|
||||
}
|
||||
editingCtx.addPoint(pt);
|
||||
editingCtx.addPoint(pt, addPointBefore ? AdditionMode.ADD_BEFORE : AdditionMode.ADD_AFTER);
|
||||
return pt;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public WptPt addPoint() {
|
||||
public WptPt addPoint(boolean addPointBefore) {
|
||||
if (pressedPointLatLon != null) {
|
||||
WptPt pt = new WptPt();
|
||||
double lat = pressedPointLatLon.getLatitude();
|
||||
|
@ -388,11 +404,7 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
|||
pressedPointLatLon = null;
|
||||
boolean allowed = editingCtx.getPointsCount() == 0 || !editingCtx.getPoints().get(editingCtx.getPointsCount() - 1).equals(pt);
|
||||
if (allowed) {
|
||||
ApplicationMode applicationMode = editingCtx.getAppMode();
|
||||
if (applicationMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||
pt.setProfileType(applicationMode.getStringKey());
|
||||
}
|
||||
editingCtx.addPoint(pt);
|
||||
editingCtx.addPoint(pt, addPointBefore ? AdditionMode.ADD_BEFORE : AdditionMode.ADD_AFTER);
|
||||
moveMapToLatLon(lat, lon);
|
||||
return pt;
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm
|
|||
public void onClick(View v) {
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof OptionsFragmentListener) {
|
||||
((OptionsFragmentListener) fragment).addToTheTrackOnClick();
|
||||
((OptionsFragmentListener) fragment).addToTrackOnClick();
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm
|
|||
|
||||
void saveAsNewTrackOnClick();
|
||||
|
||||
void addToTheTrackOnClick();
|
||||
void addToTrackOnClick();
|
||||
|
||||
void directionsOnClick();
|
||||
|
||||
|
|
|
@ -35,9 +35,7 @@ public class PointsCard extends BaseCard implements OnUpdateAdditionalInfoListen
|
|||
@Override
|
||||
protected void updateContent() {
|
||||
MeasurementEditingContext editingCtx = fragment.getEditingCtx();
|
||||
final GpxData gpxData = editingCtx.getGpxData();
|
||||
adapter = new MeasurementToolAdapter(mapActivity, editingCtx.getPoints(),
|
||||
gpxData != null ? gpxData.getActionType() : null);
|
||||
adapter = new MeasurementToolAdapter(mapActivity, editingCtx.getPoints());
|
||||
RecyclerView pointsRv = view.findViewById(R.id.measure_points_recycler_view);
|
||||
ItemTouchHelper touchHelper = new ItemTouchHelper(new ReorderItemTouchHelperCallback(adapter));
|
||||
touchHelper.attachToRecyclerView(pointsRv);
|
||||
|
|
|
@ -4,10 +4,13 @@ import android.app.ProgressDialog;
|
|||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.FileUtils;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.Route;
|
||||
import net.osmand.GPXUtilities.Track;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
|
@ -15,42 +18,38 @@ import net.osmand.plus.OsmandApplication;
|
|||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.measurementtool.GpxData.ActionType;
|
||||
import net.osmand.plus.measurementtool.MeasurementToolFragment.SaveType;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.IndexConstants.GPX_FILE_EXT;
|
||||
|
||||
class SaveGpxRouteAsyncTask extends AsyncTask<Void, Void, Exception> {
|
||||
|
||||
private WeakReference<MeasurementToolFragment> fragmentRef;
|
||||
private final WeakReference<MeasurementToolFragment> fragmentRef;
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
private SaveType saveType;
|
||||
private ActionType actionType;
|
||||
|
||||
private File outFile;
|
||||
private final File outFile;
|
||||
private File backupFile;
|
||||
private GPXFile gpxFile;
|
||||
private final GPXFile gpxFile;
|
||||
private GPXFile savedGpxFile;
|
||||
private boolean showOnMap;
|
||||
|
||||
private SaveGpxRouteListener saveGpxRouteListener;
|
||||
private final boolean simplified;
|
||||
private final boolean addToTrack;
|
||||
private final boolean showOnMap;
|
||||
|
||||
private final SaveGpxRouteListener saveGpxRouteListener;
|
||||
|
||||
public SaveGpxRouteAsyncTask(MeasurementToolFragment fragment, File outFile, GPXFile gpxFile,
|
||||
ActionType actionType, SaveType saveType, boolean showOnMap, SaveGpxRouteListener saveGpxRouteListener) {
|
||||
boolean simplified, boolean addToTrack, boolean showOnMap,
|
||||
SaveGpxRouteListener saveGpxRouteListener) {
|
||||
fragmentRef = new WeakReference<>(fragment);
|
||||
this.outFile = outFile;
|
||||
this.showOnMap = showOnMap;
|
||||
this.gpxFile = gpxFile;
|
||||
this.actionType = actionType;
|
||||
this.saveType = saveType;
|
||||
this.simplified = simplified;
|
||||
this.addToTrack = addToTrack;
|
||||
this.saveGpxRouteListener = saveGpxRouteListener;
|
||||
}
|
||||
|
||||
|
@ -77,119 +76,73 @@ class SaveGpxRouteAsyncTask extends AsyncTask<Void, Void, Exception> {
|
|||
OsmandApplication app = mapActivity.getMyApplication();
|
||||
MeasurementToolLayer measurementLayer = mapActivity.getMapLayers().getMeasurementToolLayer();
|
||||
MeasurementEditingContext editingCtx = fragment.getEditingCtx();
|
||||
|
||||
List<WptPt> points = editingCtx.getPoints();
|
||||
TrkSegment before = editingCtx.getBeforeTrkSegmentLine();
|
||||
TrkSegment after = editingCtx.getAfterTrkSegmentLine();
|
||||
Exception res = null;
|
||||
if (gpxFile == null) {
|
||||
String fileName = outFile.getName();
|
||||
String trackName = fileName.substring(0, fileName.length() - GPX_FILE_EXT.length());
|
||||
GPXFile gpx = new GPXFile(Version.getFullVersion(app));
|
||||
if (measurementLayer != null) {
|
||||
if (saveType == MeasurementToolFragment.SaveType.LINE) {
|
||||
TrkSegment segment = new TrkSegment();
|
||||
if (editingCtx.hasRoute()) {
|
||||
segment.points.addAll(editingCtx.getRoutePoints());
|
||||
} else {
|
||||
segment.points.addAll(before.points);
|
||||
segment.points.addAll(after.points);
|
||||
}
|
||||
Track track = new Track();
|
||||
track.name = trackName;
|
||||
track.segments.add(segment);
|
||||
gpx.tracks.add(track);
|
||||
} else if (saveType == MeasurementToolFragment.SaveType.ROUTE_POINT) {
|
||||
if (editingCtx.hasRoute()) {
|
||||
GPXFile newGpx = editingCtx.exportRouteAsGpx(trackName);
|
||||
if (newGpx != null) {
|
||||
gpx = newGpx;
|
||||
}
|
||||
}
|
||||
gpx.addRoutePoints(points);
|
||||
}
|
||||
}
|
||||
Exception res = GPXUtilities.writeGpxFile(outFile, gpx);
|
||||
GPXFile gpx = generateGpxFile(measurementLayer, editingCtx, trackName, new GPXFile(Version.getFullVersion(app)));
|
||||
res = GPXUtilities.writeGpxFile(outFile, gpx);
|
||||
gpx.path = outFile.getAbsolutePath();
|
||||
savedGpxFile = gpx;
|
||||
if (showOnMap) {
|
||||
MeasurementToolFragment.showGpxOnMap(app, gpx, actionType, true);
|
||||
MeasurementToolFragment.showGpxOnMap(app, gpx, true);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
GPXFile gpx = gpxFile;
|
||||
backupFile = FileUtils.backupFile(app, outFile);
|
||||
String trackName = Algorithms.getFileNameWithoutExtension(outFile);
|
||||
if (measurementLayer != null) {
|
||||
if (fragment.isPlanRouteMode()) {
|
||||
if (saveType == MeasurementToolFragment.SaveType.LINE) {
|
||||
TrkSegment segment = new TrkSegment();
|
||||
if (editingCtx.hasRoute()) {
|
||||
segment.points.addAll(editingCtx.getRoutePoints());
|
||||
} else {
|
||||
segment.points.addAll(before.points);
|
||||
segment.points.addAll(after.points);
|
||||
}
|
||||
Track track = new Track();
|
||||
track.name = trackName;
|
||||
track.segments.add(segment);
|
||||
gpx.tracks.add(track);
|
||||
} else if (saveType == MeasurementToolFragment.SaveType.ROUTE_POINT) {
|
||||
if (editingCtx.hasRoute()) {
|
||||
GPXFile newGpx = editingCtx.exportRouteAsGpx(trackName);
|
||||
if (newGpx != null) {
|
||||
gpx = newGpx;
|
||||
}
|
||||
}
|
||||
gpx.addRoutePoints(points);
|
||||
}
|
||||
} else if (actionType != null) {
|
||||
GpxData gpxData = editingCtx.getGpxData();
|
||||
switch (actionType) {
|
||||
case ADD_SEGMENT: {
|
||||
List<WptPt> snappedPoints = new ArrayList<>();
|
||||
snappedPoints.addAll(before.points);
|
||||
snappedPoints.addAll(after.points);
|
||||
gpx.addTrkSegment(snappedPoints);
|
||||
break;
|
||||
}
|
||||
case ADD_ROUTE_POINTS: {
|
||||
gpx.replaceRoutePoints(points);
|
||||
break;
|
||||
}
|
||||
case EDIT_SEGMENT: {
|
||||
if (gpxData != null) {
|
||||
TrkSegment segment = new TrkSegment();
|
||||
segment.points.addAll(points);
|
||||
gpx.replaceSegment(gpxData.getTrkSegment(), segment);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OVERWRITE_SEGMENT: {
|
||||
if (gpxData != null) {
|
||||
List<WptPt> snappedPoints = new ArrayList<>();
|
||||
snappedPoints.addAll(before.points);
|
||||
snappedPoints.addAll(after.points);
|
||||
TrkSegment segment = new TrkSegment();
|
||||
segment.points.addAll(snappedPoints);
|
||||
gpx.replaceSegment(gpxData.getTrkSegment(), segment);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gpx.addRoutePoints(points);
|
||||
}
|
||||
}
|
||||
Exception res = null;
|
||||
GPXFile gpx = generateGpxFile(measurementLayer, editingCtx, trackName, gpxFile);
|
||||
if (!gpx.showCurrentTrack) {
|
||||
res = GPXUtilities.writeGpxFile(outFile, gpx);
|
||||
}
|
||||
savedGpxFile = gpx;
|
||||
if (showOnMap) {
|
||||
MeasurementToolFragment.showGpxOnMap(app, gpx, actionType, false);
|
||||
MeasurementToolFragment.showGpxOnMap(app, gpx, false);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private GPXFile generateGpxFile(MeasurementToolLayer measurementLayer, MeasurementEditingContext editingCtx,
|
||||
String trackName, @NonNull GPXFile gpx) {
|
||||
if (measurementLayer != null) {
|
||||
List<TrkSegment> before = editingCtx.getBeforeTrkSegmentLine();
|
||||
List<TrkSegment> after = editingCtx.getAfterTrkSegmentLine();
|
||||
if (simplified) {
|
||||
Track track = new Track();
|
||||
track.name = trackName;
|
||||
gpx.tracks.add(track);
|
||||
for (TrkSegment s : before) {
|
||||
TrkSegment segment = new TrkSegment();
|
||||
segment.points.addAll(s.points);
|
||||
track.segments.add(segment);
|
||||
}
|
||||
for (TrkSegment s : after) {
|
||||
TrkSegment segment = new TrkSegment();
|
||||
segment.points.addAll(s.points);
|
||||
track.segments.add(segment);
|
||||
}
|
||||
} else {
|
||||
GPXFile newGpx = editingCtx.exportGpx(trackName);
|
||||
if (newGpx != null) {
|
||||
List<Track> gpxTracks = gpx.tracks;
|
||||
List<WptPt> gpxPoints = gpx.getPoints();
|
||||
List<Route> gpxRoutes = gpx.routes;
|
||||
gpx = newGpx;
|
||||
List<List<WptPt>> routePoints = editingCtx.getRoutePoints();
|
||||
for (List<WptPt> points : routePoints) {
|
||||
gpx.addRoutePoints(points, true);
|
||||
}
|
||||
if (!Algorithms.isEmpty(gpxPoints)) {
|
||||
gpx.addPoints(gpxPoints);
|
||||
}
|
||||
if (addToTrack) {
|
||||
gpx.tracks.addAll(gpxTracks);
|
||||
gpx.routes.addAll(gpxRoutes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return gpx;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.osmand.plus.measurementtool;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
@ -25,7 +26,6 @@ import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
|
|||
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleDividerItem;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.measurementtool.GpxData.ActionType;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
|
@ -39,6 +39,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
|
|||
private static final Log LOG = PlatformUtil.getLog(SelectedPointBottomSheetDialogFragment.class);
|
||||
private MeasurementEditingContext editingCtx;
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
|
@ -172,7 +173,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
|
|||
dismiss();
|
||||
}
|
||||
})
|
||||
.setDisabled(editingCtx.isFirstPointSelected())
|
||||
.setDisabled(editingCtx.isFirstPointSelected() || editingCtx.isSelectionNeedApproximation())
|
||||
.create();
|
||||
items.add(changeRouteTypeBefore);
|
||||
|
||||
|
@ -191,7 +192,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
|
|||
dismiss();
|
||||
}
|
||||
})
|
||||
.setDisabled(editingCtx.isLastPointSelected())
|
||||
.setDisabled(editingCtx.isLastPointSelected() || editingCtx.isSelectionNeedApproximation())
|
||||
.create();
|
||||
items.add(changeRouteTypeAfter);
|
||||
|
||||
|
@ -264,11 +265,7 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
|
|||
if (!TextUtils.isEmpty(pointName)) {
|
||||
return pointName;
|
||||
}
|
||||
GpxData gpxData = editingCtx.getGpxData();
|
||||
if (gpxData != null && gpxData.getActionType() == ActionType.ADD_ROUTE_POINTS) {
|
||||
return getString(R.string.route_point) + " - " + (pos + 1);
|
||||
}
|
||||
return getString(R.string.plugin_distance_point) + " - " + (pos + 1);
|
||||
return getString(R.string.ltr_or_rtl_combine_via_dash, getString(R.string.plugin_distance_point), String.valueOf(pos + 1));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -305,8 +302,6 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
|
|||
}
|
||||
description.append(OsmAndFormatter.getFormattedDistance(dist, mapActivity.getMyApplication()));
|
||||
}
|
||||
GpxData gpxData = editingCtx.getGpxData();
|
||||
if (gpxData != null && gpxData.getActionType() == ActionType.EDIT_SEGMENT) {
|
||||
double elevation = pt.ele;
|
||||
if (!Double.isNaN(elevation)) {
|
||||
description.append(" ").append((getString(R.string.altitude)).substring(0, 1)).append(": ");
|
||||
|
@ -317,7 +312,6 @@ public class SelectedPointBottomSheetDialogFragment extends MenuBottomSheetDialo
|
|||
description.append(" ").append((getString(R.string.map_widget_speed)).substring(0, 1)).append(": ");
|
||||
description.append(OsmAndFormatter.getFormattedSpeed(speed, mapActivity.getMyApplication()));
|
||||
}
|
||||
}
|
||||
return description.toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ import net.osmand.plus.OsmAndFormatter;
|
|||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.measurementtool.GpxData.ActionType;
|
||||
import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback;
|
||||
|
||||
import java.util.Collections;
|
||||
|
@ -32,13 +31,11 @@ public class MeasurementToolAdapter extends RecyclerView.Adapter<MeasurementTool
|
|||
private final List<WptPt> points;
|
||||
private MeasurementAdapterListener listener;
|
||||
private boolean nightMode;
|
||||
private final ActionType actionType;
|
||||
private final static String BULLET = " • ";
|
||||
|
||||
public MeasurementToolAdapter(MapActivity mapActivity, List<WptPt> points, ActionType actionType) {
|
||||
public MeasurementToolAdapter(MapActivity mapActivity, List<WptPt> points) {
|
||||
this.mapActivity = mapActivity;
|
||||
this.points = points;
|
||||
this.actionType = actionType;
|
||||
}
|
||||
|
||||
public void setAdapterListener(MeasurementAdapterListener listener) {
|
||||
|
@ -79,11 +76,7 @@ public class MeasurementToolAdapter extends RecyclerView.Adapter<MeasurementTool
|
|||
if (!TextUtils.isEmpty(pointTitle)) {
|
||||
holder.title.setText(pointTitle);
|
||||
} else {
|
||||
if (actionType == ActionType.ADD_ROUTE_POINTS) {
|
||||
holder.title.setText(mapActivity.getString(R.string.route_point) + " - " + (pos + 1));
|
||||
} else {
|
||||
holder.title.setText(mapActivity.getString(R.string.plugin_distance_point) + " - " + (pos + 1));
|
||||
}
|
||||
holder.title.setText(mapActivity.getString(R.string.ltr_or_rtl_combine_via_dash, mapActivity.getString(R.string.plugin_distance_point), String.valueOf(pos + 1)));
|
||||
}
|
||||
String pointDesc = pt.desc;
|
||||
if (!TextUtils.isEmpty(pointDesc)) {
|
||||
|
@ -114,11 +107,11 @@ public class MeasurementToolAdapter extends RecyclerView.Adapter<MeasurementTool
|
|||
holder.descr.setText(text);
|
||||
}
|
||||
}
|
||||
if (actionType == ActionType.EDIT_SEGMENT) {
|
||||
double elevation = pt.ele;
|
||||
if (!Double.isNaN(elevation)) {
|
||||
String eleStr = (mapActivity.getString(R.string.altitude)).substring(0, 1);
|
||||
holder.elevation.setText(eleStr + ": " + OsmAndFormatter.getFormattedAlt(elevation, mapActivity.getMyApplication()));
|
||||
holder.elevation.setText(mapActivity.getString(R.string.ltr_or_rtl_combine_via_colon,
|
||||
eleStr, OsmAndFormatter.getFormattedAlt(elevation, mapActivity.getMyApplication())));
|
||||
} else {
|
||||
holder.elevation.setText("");
|
||||
}
|
||||
|
@ -129,7 +122,6 @@ public class MeasurementToolAdapter extends RecyclerView.Adapter<MeasurementTool
|
|||
} else {
|
||||
holder.speed.setText("");
|
||||
}
|
||||
}
|
||||
holder.deleteBtn.setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_remove_dark,
|
||||
nightMode ? R.color.icon_color_default_dark : R.color.icon_color_default_light));
|
||||
holder.deleteBtn.setOnClickListener(new View.OnClickListener() {
|
||||
|
|
|
@ -3,48 +3,57 @@ package net.osmand.plus.measurementtool.command;
|
|||
import net.osmand.data.LatLon;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext.AdditionMode;
|
||||
import net.osmand.plus.measurementtool.MeasurementToolLayer;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AddPointCommand extends MeasurementModeCommand {
|
||||
|
||||
private int position;
|
||||
private WptPt point;
|
||||
private String prevPointProfile;
|
||||
private boolean center;
|
||||
private boolean addPointBefore;
|
||||
|
||||
public AddPointCommand(MeasurementToolLayer measurementLayer, boolean center) {
|
||||
super(measurementLayer);
|
||||
init(measurementLayer, null, center);
|
||||
init(null, center);
|
||||
}
|
||||
|
||||
public AddPointCommand(MeasurementToolLayer measurementLayer, LatLon latLon) {
|
||||
super(measurementLayer);
|
||||
init(measurementLayer, latLon, false);
|
||||
init(latLon, false);
|
||||
}
|
||||
|
||||
private void init(MeasurementToolLayer measurementLayer, LatLon latLon, boolean center) {
|
||||
private void init(LatLon latLon, boolean center) {
|
||||
MeasurementEditingContext ctx = getEditingCtx();
|
||||
if (latLon != null) {
|
||||
point = new WptPt();
|
||||
point.lat = latLon.getLatitude();
|
||||
point.lon = latLon.getLongitude();
|
||||
ApplicationMode appMode = measurementLayer.getEditingCtx().getAppMode();
|
||||
if (appMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
|
||||
point.setProfileType(appMode.getStringKey());
|
||||
}
|
||||
}
|
||||
this.center = center;
|
||||
position = measurementLayer.getEditingCtx().getPointsCount();
|
||||
position = ctx.getPointsCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute() {
|
||||
MeasurementEditingContext ctx = getEditingCtx();
|
||||
addPointBefore = ctx.isInAddPointBeforeMode();
|
||||
List<WptPt> points = ctx.getPoints();
|
||||
if (points.size() > 0) {
|
||||
WptPt prevPt = points.get(points.size() - 1);
|
||||
prevPointProfile = prevPt.getProfileType();
|
||||
}
|
||||
if (point != null) {
|
||||
getEditingCtx().addPoint(point);
|
||||
ctx.addPoint(point, addPointBefore ? AdditionMode.ADD_BEFORE : AdditionMode.ADD_AFTER);
|
||||
measurementLayer.moveMapToPoint(position);
|
||||
} else if (center) {
|
||||
point = measurementLayer.addCenterPoint();
|
||||
point = measurementLayer.addCenterPoint(addPointBefore);
|
||||
} else {
|
||||
point = measurementLayer.addPoint();
|
||||
point = measurementLayer.addPoint(addPointBefore);
|
||||
}
|
||||
refreshMap();
|
||||
return point != null;
|
||||
|
@ -52,13 +61,22 @@ public class AddPointCommand extends MeasurementModeCommand {
|
|||
|
||||
@Override
|
||||
public void undo() {
|
||||
getEditingCtx().removePoint(position, true);
|
||||
MeasurementEditingContext ctx = getEditingCtx();
|
||||
if (position > 0) {
|
||||
WptPt prevPt = ctx.getPoints().get(position - 1);
|
||||
if (prevPointProfile != null) {
|
||||
prevPt.setProfileType(prevPointProfile);
|
||||
} else {
|
||||
prevPt.removeProfileType();
|
||||
}
|
||||
}
|
||||
ctx.removePoint(position, true);
|
||||
refreshMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo() {
|
||||
getEditingCtx().addPoint(position, point);
|
||||
getEditingCtx().addPoint(position, point, addPointBefore ? AdditionMode.ADD_BEFORE : AdditionMode.ADD_AFTER);
|
||||
refreshMap();
|
||||
measurementLayer.moveMapToPoint(position);
|
||||
}
|
||||
|
|
|
@ -1,24 +1,36 @@
|
|||
package net.osmand.plus.measurementtool.command;
|
||||
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData;
|
||||
import net.osmand.plus.measurementtool.MeasurementToolLayer;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ApplyGpxApproximationCommand extends MeasurementModeCommand {
|
||||
|
||||
private ApplicationMode mode;
|
||||
private GpxRouteApproximation approximation;
|
||||
private List<WptPt> points;
|
||||
private Map<Pair<WptPt, WptPt>, RoadSegmentData> roadSegmentData;
|
||||
private List<GpxRouteApproximation> approximations;
|
||||
private List<List<WptPt>> segmentPointsList;
|
||||
private final List<List<WptPt>> originalSegmentPointsList;
|
||||
|
||||
public ApplyGpxApproximationCommand(MeasurementToolLayer measurementLayer, GpxRouteApproximation approximation, ApplicationMode mode) {
|
||||
public ApplyGpxApproximationCommand(MeasurementToolLayer measurementLayer,
|
||||
List<GpxRouteApproximation> approximations,
|
||||
List<List<WptPt>> segmentPointsList, ApplicationMode mode) {
|
||||
super(measurementLayer);
|
||||
this.approximation = approximation;
|
||||
this.approximations = approximations;
|
||||
this.segmentPointsList = segmentPointsList;
|
||||
this.originalSegmentPointsList = new ArrayList<>(segmentPointsList);
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
|
@ -26,6 +38,10 @@ public class ApplyGpxApproximationCommand extends MeasurementModeCommand {
|
|||
return points;
|
||||
}
|
||||
|
||||
public List<List<WptPt>> getOriginalSegmentPointsList() {
|
||||
return originalSegmentPointsList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeasurementCommandType getType() {
|
||||
return MeasurementCommandType.APPROXIMATE_POINTS;
|
||||
|
@ -33,8 +49,9 @@ public class ApplyGpxApproximationCommand extends MeasurementModeCommand {
|
|||
|
||||
@Override
|
||||
public boolean execute() {
|
||||
List<WptPt> pts = getEditingCtx().getPoints();
|
||||
points = new ArrayList<>(pts);
|
||||
MeasurementEditingContext ctx = getEditingCtx();
|
||||
points = new ArrayList<>(ctx.getPoints());
|
||||
roadSegmentData = ctx.getRoadSegmentData();
|
||||
applyApproximation();
|
||||
refreshMap();
|
||||
return true;
|
||||
|
@ -44,7 +61,7 @@ public class ApplyGpxApproximationCommand extends MeasurementModeCommand {
|
|||
public boolean update(@NonNull Command command) {
|
||||
if (command instanceof ApplyGpxApproximationCommand) {
|
||||
ApplyGpxApproximationCommand approxCommand = (ApplyGpxApproximationCommand) command;
|
||||
approximation = approxCommand.approximation;
|
||||
approximations = approxCommand.approximations;
|
||||
mode = approxCommand.mode;
|
||||
applyApproximation();
|
||||
refreshMap();
|
||||
|
@ -55,10 +72,12 @@ public class ApplyGpxApproximationCommand extends MeasurementModeCommand {
|
|||
|
||||
@Override
|
||||
public void undo() {
|
||||
getEditingCtx().resetAppMode();
|
||||
getEditingCtx().clearSegments();
|
||||
getEditingCtx().addPoints(points);
|
||||
getEditingCtx().updateCacheForSnap();
|
||||
MeasurementEditingContext ctx = getEditingCtx();
|
||||
ctx.resetAppMode();
|
||||
ctx.clearSegments();
|
||||
ctx.setRoadSegmentData(roadSegmentData);
|
||||
ctx.addPoints(points);
|
||||
segmentPointsList = new ArrayList<>(originalSegmentPointsList);
|
||||
refreshMap();
|
||||
}
|
||||
|
||||
|
@ -69,8 +88,15 @@ public class ApplyGpxApproximationCommand extends MeasurementModeCommand {
|
|||
}
|
||||
|
||||
public void applyApproximation() {
|
||||
getEditingCtx().setAppMode(mode);
|
||||
getEditingCtx().clearSegments();
|
||||
getEditingCtx().setPoints(approximation, mode);
|
||||
MeasurementEditingContext ctx = getEditingCtx();
|
||||
ctx.setAppMode(mode);
|
||||
for (int i = 0; i < approximations.size(); i++) {
|
||||
GpxRouteApproximation approximation = approximations.get(i);
|
||||
List<WptPt> segmentPoints = segmentPointsList.get(i);
|
||||
List<WptPt> newSegmentPoints = ctx.setPoints(approximation, segmentPoints, mode);
|
||||
if (newSegmentPoints != null) {
|
||||
segmentPointsList.set(i, newSegmentPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ public class ChangeRouteModeCommand extends MeasurementModeCommand {
|
|||
editingCtx.addPoints(oldPoints);
|
||||
editingCtx.setAppMode(oldMode);
|
||||
editingCtx.setRoadSegmentData(oldRoadSegmentData);
|
||||
editingCtx.updateCacheForSnap();
|
||||
editingCtx.updateSegmentsForSnap();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -146,10 +146,11 @@ public class ChangeRouteModeCommand extends MeasurementModeCommand {
|
|||
if (newRoadSegmentData != null) {
|
||||
editingCtx.setRoadSegmentData(newRoadSegmentData);
|
||||
}
|
||||
editingCtx.updateCacheForSnap();
|
||||
editingCtx.updateSegmentsForSnap();
|
||||
}
|
||||
|
||||
private void updateProfileType(WptPt pt) {
|
||||
if (!pt.isGap()) {
|
||||
if (newMode != null && newMode != DEFAULT_APP_MODE) {
|
||||
pt.setProfileType(newMode.getStringKey());
|
||||
} else {
|
||||
|
@ -157,3 +158,4 @@ public class ChangeRouteModeCommand extends MeasurementModeCommand {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
package net.osmand.plus.measurementtool.command;
|
||||
|
||||
import android.util.Pair;
|
||||
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData;
|
||||
import net.osmand.plus.measurementtool.MeasurementToolLayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ClearPointsCommand extends MeasurementModeCommand {
|
||||
|
||||
private List<WptPt> points;
|
||||
private Map<Pair<WptPt, WptPt>, RoadSegmentData> roadSegmentData;
|
||||
private ClearCommandMode clearMode;
|
||||
private int pointPosition;
|
||||
|
||||
|
@ -31,27 +37,30 @@ public class ClearPointsCommand extends MeasurementModeCommand {
|
|||
}
|
||||
|
||||
private void executeCommand() {
|
||||
List<WptPt> pts = getEditingCtx().getPoints();
|
||||
MeasurementEditingContext ctx = getEditingCtx();
|
||||
List<WptPt> pts = ctx.getPoints();
|
||||
points = new ArrayList<>(pts);
|
||||
roadSegmentData = ctx.getRoadSegmentData();
|
||||
switch (clearMode) {
|
||||
case ALL:
|
||||
pts.clear();
|
||||
getEditingCtx().clearSegments();
|
||||
ctx.clearSegments();
|
||||
break;
|
||||
case BEFORE:
|
||||
getEditingCtx().trimBefore(pointPosition);
|
||||
ctx.trimBefore(pointPosition);
|
||||
break;
|
||||
case AFTER:
|
||||
getEditingCtx().trimAfter(pointPosition);
|
||||
ctx.trimAfter(pointPosition);
|
||||
}
|
||||
refreshMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
getEditingCtx().clearSegments();
|
||||
getEditingCtx().addPoints(points);
|
||||
getEditingCtx().updateCacheForSnap();
|
||||
MeasurementEditingContext ctx = getEditingCtx();
|
||||
ctx.clearSegments();
|
||||
ctx.setRoadSegmentData(roadSegmentData);
|
||||
ctx.addPoints(points);
|
||||
refreshMap();
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,6 @@ public class MeasurementCommandManager {
|
|||
}
|
||||
|
||||
public MeasurementModeCommand getLastCommand() {
|
||||
return undoCommands.getLast();
|
||||
return undoCommands.getFirst();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ public class RemovePointCommand extends MeasurementModeCommand {
|
|||
|
||||
private final int position;
|
||||
private WptPt point;
|
||||
private String prevPointProfile;
|
||||
|
||||
public RemovePointCommand(MeasurementToolLayer measurementLayer, int position) {
|
||||
super(measurementLayer);
|
||||
|
@ -15,6 +16,9 @@ public class RemovePointCommand extends MeasurementModeCommand {
|
|||
|
||||
@Override
|
||||
public boolean execute() {
|
||||
if (position > 0) {
|
||||
prevPointProfile = getEditingCtx().getPoints().get(position - 1).getProfileType();
|
||||
}
|
||||
point = getEditingCtx().removePoint(position, true);
|
||||
refreshMap();
|
||||
return true;
|
||||
|
@ -22,6 +26,14 @@ public class RemovePointCommand extends MeasurementModeCommand {
|
|||
|
||||
@Override
|
||||
public void undo() {
|
||||
if (position > 0) {
|
||||
WptPt prevPt = getEditingCtx().getPoints().get(position - 1);
|
||||
if (prevPointProfile != null) {
|
||||
prevPt.setProfileType(prevPointProfile);
|
||||
} else {
|
||||
prevPt.removeProfileType();
|
||||
}
|
||||
}
|
||||
getEditingCtx().addPoint(position, point);
|
||||
refreshMap();
|
||||
measurementLayer.moveMapToPoint(position);
|
||||
|
|
|
@ -18,7 +18,7 @@ public class ReorderPointCommand extends MeasurementModeCommand {
|
|||
|
||||
@Override
|
||||
public boolean execute() {
|
||||
getEditingCtx().updateCacheForSnap();
|
||||
getEditingCtx().updateSegmentsForSnap();
|
||||
refreshMap();
|
||||
return true;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public class ReorderPointCommand extends MeasurementModeCommand {
|
|||
private void reorder(int addTo, int removeFrom) {
|
||||
List<WptPt> points = getEditingCtx().getPoints();
|
||||
points.add(addTo, points.remove(removeFrom));
|
||||
getEditingCtx().updateCacheForSnap();
|
||||
getEditingCtx().updateSegmentsForSnap();
|
||||
refreshMap();
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ public class ReversePointsCommand extends MeasurementModeCommand {
|
|||
WptPt lastPoint = newPoints.get(newPoints.size() - 1);
|
||||
editingCtx.setAppMode(ApplicationMode.valueOfStringKey(lastPoint.getProfileType(), DEFAULT_APP_MODE));
|
||||
}
|
||||
editingCtx.updateCacheForSnap();
|
||||
editingCtx.updateSegmentsForSnap();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,7 +57,7 @@ public class ReversePointsCommand extends MeasurementModeCommand {
|
|||
editingCtx.addPoints(oldPoints);
|
||||
editingCtx.setAppMode(oldMode);
|
||||
editingCtx.setRoadSegmentData(oldRoadSegmentData);
|
||||
editingCtx.updateCacheForSnap();
|
||||
editingCtx.updateSegmentsForSnap();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -50,14 +50,13 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
|||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.TrackActivity;
|
||||
import net.osmand.plus.dialogs.GpxAppearanceAdapter;
|
||||
import net.osmand.plus.measurementtool.GpxData;
|
||||
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.GpxSplitType;
|
||||
import net.osmand.plus.track.SplitTrackAsyncTask;
|
||||
import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener;
|
||||
|
@ -918,17 +917,10 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
}
|
||||
|
||||
public void addNewGpxData(GpxData.ActionType actionType) {
|
||||
public void addNewGpxData() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
activity.addNewGpxData(actionType);
|
||||
}
|
||||
}
|
||||
|
||||
public void addNewGpxData(GpxData.ActionType actionType, GPXUtilities.TrkSegment segment) {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
activity.addNewGpxData(actionType, segment);
|
||||
activity.addNewGpxData();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -951,10 +943,8 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
PointDescription pointWptDescription =
|
||||
new PointDescription(PointDescription.POINT_TYPE_WPT, app.getString(R.string.add_waypoint));
|
||||
addPoint(pointWptDescription);
|
||||
} else if (i == R.id.route_text_layout || i == R.id.route_fab) {
|
||||
addNewGpxData(GpxData.ActionType.ADD_ROUTE_POINTS);
|
||||
} else if (i == R.id.line_text_layout || i == R.id.line_fab) {
|
||||
addNewGpxData(GpxData.ActionType.ADD_SEGMENT);
|
||||
} else if (i == R.id.route_text_layout || i == R.id.route_fab || i == R.id.line_fab) {
|
||||
addNewGpxData();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -65,11 +65,10 @@ import net.osmand.plus.helpers.GpxUiHelper;
|
|||
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
|
||||
import net.osmand.plus.measurementtool.GpxData;
|
||||
import net.osmand.plus.track.SaveGpxAsyncTask;
|
||||
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
|
||||
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.SaveGpxAsyncTask;
|
||||
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip.CustomTabProvider;
|
||||
import net.osmand.plus.views.controls.WrapContentHeightViewPager;
|
||||
|
@ -1026,7 +1025,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
|
|||
private void editSegment() {
|
||||
TrkSegment segment = getTrkSegment();
|
||||
if (segment != null && fragmentAdapter != null) {
|
||||
fragmentAdapter.addNewGpxData(GpxData.ActionType.EDIT_SEGMENT, segment);
|
||||
fragmentAdapter.addNewGpxData();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package net.osmand.plus.routepreparationmenu;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
@ -16,6 +19,7 @@ import android.view.ViewGroup.MarginLayoutParams;
|
|||
import android.view.ViewTreeObserver.OnScrollChangedListener;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -24,7 +28,6 @@ import androidx.fragment.app.FragmentManager;
|
|||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.CallbackWithObject;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
|
@ -44,7 +47,6 @@ import net.osmand.plus.helpers.GpxUiHelper.GPXInfo;
|
|||
import net.osmand.plus.importfiles.ImportHelper;
|
||||
import net.osmand.plus.importfiles.ImportHelper.OnGpxImportCompleteListener;
|
||||
import net.osmand.plus.measurementtool.GpxData;
|
||||
import net.osmand.plus.measurementtool.GpxData.ActionType;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||
import net.osmand.plus.measurementtool.MeasurementToolFragment;
|
||||
import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.LocalRoutingParameter;
|
||||
|
@ -86,6 +88,8 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca
|
|||
|
||||
private GPXFile gpxFile;
|
||||
|
||||
private View buttonsShadow;
|
||||
|
||||
private boolean editingTrack;
|
||||
private boolean selectingTrack;
|
||||
private int menuTitleHeight;
|
||||
|
@ -148,6 +152,7 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca
|
|||
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||
if (view != null) {
|
||||
ImageButton closeButton = view.findViewById(R.id.close_button);
|
||||
buttonsShadow = view.findViewById(R.id.buttons_shadow);
|
||||
closeButton.setImageDrawable(getContentIcon(AndroidUtils.getNavigationIconResId(app)));
|
||||
closeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -174,6 +179,22 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca
|
|||
return view;
|
||||
}
|
||||
|
||||
private void showShadowButton() {
|
||||
buttonsShadow.setVisibility(View.VISIBLE);
|
||||
buttonsShadow.animate()
|
||||
.alpha(0.8f)
|
||||
.setDuration(200)
|
||||
.setListener(null);
|
||||
}
|
||||
|
||||
private void hideShadowButton() {
|
||||
buttonsShadow.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(200);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void setupCards() {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
|
@ -554,10 +575,7 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca
|
|||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null && gpxFile != null) {
|
||||
editingTrack = true;
|
||||
QuadRect rect = gpxFile.getRect();
|
||||
TrkSegment segment = gpxFile.getNonEmptyTrkSegment();
|
||||
ActionType actionType = segment == null ? ActionType.ADD_ROUTE_POINTS : ActionType.EDIT_SEGMENT;
|
||||
GpxData gpxData = new GpxData(gpxFile, rect, actionType, segment);
|
||||
GpxData gpxData = new GpxData(gpxFile);
|
||||
MeasurementEditingContext editingContext = new MeasurementEditingContext();
|
||||
editingContext.setGpxData(gpxData);
|
||||
editingContext.setAppMode(app.getRoutingHelper().getAppMode());
|
||||
|
@ -598,20 +616,16 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca
|
|||
}
|
||||
|
||||
private void setupScrollShadow() {
|
||||
int shadowIconId = isNightMode() ? R.drawable.bg_contextmenu_shadow : R.drawable.bg_contextmenu_shadow;
|
||||
final Drawable shadowIcon = app.getUIUtilities().getIcon(shadowIconId);
|
||||
|
||||
final View scrollView = getBottomScrollView();
|
||||
final FrameLayout bottomContainer = getBottomContainer();
|
||||
scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {
|
||||
|
||||
@Override
|
||||
public void onScrollChanged() {
|
||||
int scrollY = scrollView.getScrollY();
|
||||
if (scrollY <= 0 && bottomContainer.getForeground() != null) {
|
||||
bottomContainer.setForeground(null);
|
||||
} else if (scrollY > 0 && bottomContainer.getForeground() == null) {
|
||||
bottomContainer.setForeground(shadowIcon);
|
||||
boolean scrollToBottomAvailable = scrollView.canScrollVertically(1);
|
||||
if (scrollToBottomAvailable) {
|
||||
showShadowButton();
|
||||
} else {
|
||||
hideShadowButton();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,28 +1,23 @@
|
|||
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.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -31,29 +26,31 @@ public class GpxApproximator {
|
|||
|
||||
protected static final Log log = PlatformUtil.getLog(GpxApproximator.class);
|
||||
|
||||
private OsmandApplication ctx;
|
||||
private RoutingHelper routingHelper;
|
||||
private final OsmandApplication ctx;
|
||||
private final RoutingHelper routingHelper;
|
||||
|
||||
private RoutingEnvironment env;
|
||||
private GpxRouteApproximation gctx;
|
||||
private ApplicationMode mode;
|
||||
private LocationsHolder locationsHolder;
|
||||
private final LocationsHolder locationsHolder;
|
||||
private List<GpxPoint> points;
|
||||
private LatLon start;
|
||||
private LatLon end;
|
||||
private double pointApproximation = 50;
|
||||
private Runnable approximationTask;
|
||||
|
||||
private static final ThreadPoolExecutor SINGLE_THREAD_EXECUTOR
|
||||
= new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());;
|
||||
|
||||
private ThreadPoolExecutor singleThreadedExecutor;
|
||||
private GpxApproximationProgressCallback approximationProgress;
|
||||
private Future<?> currentApproximationTask;
|
||||
|
||||
public interface GpxApproximationProgressCallback {
|
||||
|
||||
void start();
|
||||
void start(GpxApproximator approximator);
|
||||
|
||||
void updateProgress(int progress);
|
||||
void updateProgress(GpxApproximator approximator, int progress);
|
||||
|
||||
void finish();
|
||||
void finish(GpxApproximator approximator);
|
||||
}
|
||||
|
||||
public GpxApproximator(@NonNull OsmandApplication ctx, @NonNull LocationsHolder locationsHolder) throws IOException {
|
||||
|
@ -61,12 +58,7 @@ public class GpxApproximator {
|
|||
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);
|
||||
}
|
||||
init();
|
||||
initEnvironment(mode, locationsHolder);
|
||||
}
|
||||
|
||||
public GpxApproximator(@NonNull OsmandApplication ctx, @NonNull ApplicationMode mode, double pointApproximation, @NonNull LocationsHolder locationsHolder) throws IOException {
|
||||
|
@ -75,16 +67,15 @@ public class GpxApproximator {
|
|||
this.pointApproximation = pointApproximation;
|
||||
this.routingHelper = ctx.getRoutingHelper();
|
||||
this.mode = mode;
|
||||
initEnvironment(mode, locationsHolder);
|
||||
}
|
||||
|
||||
private void initEnvironment(@NonNull ApplicationMode mode, @NonNull LocationsHolder locationsHolder) throws IOException {
|
||||
if (locationsHolder.getSize() > 1) {
|
||||
start = locationsHolder.getLatLon(0);
|
||||
end = locationsHolder.getLatLon(locationsHolder.getSize() - 1);
|
||||
prepareEnvironment(ctx, mode);
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -140,6 +131,10 @@ public class GpxApproximator {
|
|||
this.approximationProgress = approximationProgress;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return gctx != null && gctx.ctx.calculationProgress.isCancelled;
|
||||
}
|
||||
|
||||
public void cancelApproximation() {
|
||||
if (gctx != null) {
|
||||
gctx.ctx.calculationProgress.isCancelled = true;
|
||||
|
@ -154,10 +149,7 @@ public class GpxApproximator {
|
|||
this.gctx = gctx;
|
||||
startProgress();
|
||||
updateProgress(gctx);
|
||||
if (currentApproximationTask != null) {
|
||||
currentApproximationTask.cancel(true);
|
||||
}
|
||||
currentApproximationTask = singleThreadedExecutor.submit(new Runnable() {
|
||||
approximationTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
@ -166,21 +158,23 @@ public class GpxApproximator {
|
|||
resultMatcher.publish(null);
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
approximationTask = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
SINGLE_THREAD_EXECUTOR.submit(approximationTask);
|
||||
}
|
||||
|
||||
private void startProgress() {
|
||||
final GpxApproximationProgressCallback approximationProgress = this.approximationProgress;
|
||||
if (approximationProgress != null) {
|
||||
approximationProgress.start();
|
||||
approximationProgress.start(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void finishProgress() {
|
||||
final GpxApproximationProgressCallback approximationProgress = this.approximationProgress;
|
||||
if (approximationProgress != null) {
|
||||
approximationProgress.finish();
|
||||
approximationProgress.finish(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,15 +186,13 @@ public class GpxApproximator {
|
|||
@Override
|
||||
public void run() {
|
||||
RouteCalculationProgress calculationProgress = gctx.ctx.calculationProgress;
|
||||
if (!gctx.result.isEmpty() && GpxApproximator.this.gctx == gctx) {
|
||||
if (approximationTask == null && GpxApproximator.this.gctx == gctx) {
|
||||
finishProgress();
|
||||
}
|
||||
if (gctx.result.isEmpty() && calculationProgress != null && !calculationProgress.isCancelled) {
|
||||
if (approximationTask != null && calculationProgress != null && !calculationProgress.isCancelled) {
|
||||
float pr = calculationProgress.getLinearProgress();
|
||||
approximationProgress.updateProgress((int) pr);
|
||||
if (GpxApproximator.this.gctx != gctx) {
|
||||
// different calculation started
|
||||
} else {
|
||||
approximationProgress.updateProgress(GpxApproximator.this, (int) pr);
|
||||
if (GpxApproximator.this.gctx == gctx) {
|
||||
updateProgress(gctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ public class ApplicationMode {
|
|||
public static final ApplicationMode DEFAULT = createBase(R.string.app_mode_default, "default")
|
||||
.icon(R.drawable.ic_world_globe_dark).reg();
|
||||
|
||||
public static final ApplicationMode GAP = new ApplicationMode(R.string.app_mode_gap, "gap");
|
||||
|
||||
public static final ApplicationMode CAR = createBase(R.string.app_mode_car, "car")
|
||||
.icon(R.drawable.ic_action_car_dark)
|
||||
|
|
|
@ -475,24 +475,33 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
AndroidUiHelper.updateVisibility(saveButton, true);
|
||||
AndroidUiHelper.updateVisibility(view.findViewById(R.id.buttons_divider), true);
|
||||
}
|
||||
private void showShadowButton() {
|
||||
buttonsShadow.setVisibility(View.VISIBLE);
|
||||
buttonsShadow.animate()
|
||||
.alpha(0.8f)
|
||||
.setDuration(200)
|
||||
.setListener(null);
|
||||
}
|
||||
|
||||
private void hideShadowButton() {
|
||||
buttonsShadow.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(200);
|
||||
|
||||
}
|
||||
|
||||
private void setupScrollShadow() {
|
||||
int shadowIconId = isNightMode() ? R.drawable.bg_contextmenu_shadow : R.drawable.bg_contextmenu_shadow;
|
||||
final Drawable shadowIcon = app.getUIUtilities().getIcon(shadowIconId);
|
||||
|
||||
final View scrollView = getBottomScrollView();
|
||||
final FrameLayout bottomContainer = getBottomContainer();
|
||||
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
|
||||
|
||||
@Override
|
||||
public void onScrollChanged() {
|
||||
int scrollY = scrollView.getScrollY();
|
||||
if (scrollY <= 0 && bottomContainer.getForeground() != null) {
|
||||
bottomContainer.setForeground(null);
|
||||
} else if (scrollY > 0 && bottomContainer.getForeground() == null) {
|
||||
bottomContainer.setForeground(shadowIcon);
|
||||
boolean scrollToBottomAvailable = scrollView.canScrollVertically(1);
|
||||
if (scrollToBottomAvailable) {
|
||||
showShadowButton();
|
||||
} else {
|
||||
hideShadowButton();
|
||||
}
|
||||
updateButtonsShadow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue