Support multiple segments
This commit is contained in:
parent
bf55e86a7e
commit
14209dbd01
4 changed files with 95 additions and 80 deletions
|
@ -219,14 +219,11 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
||||||
|
|
||||||
if (editingCtx.isInMultiProfileMode()) {
|
if (editingCtx.isInMultiProfileMode()) {
|
||||||
multiProfileGeometryWayContext.updatePaints(settings.isNightMode(), multiProfileLineAttrs);
|
multiProfileGeometryWayContext.updatePaints(settings.isNightMode(), multiProfileLineAttrs);
|
||||||
for (int i = 0; i < editingCtx.getBeforeSegments().size(); i++) {
|
List<TrkSegment> allSegments = new ArrayList<>();
|
||||||
multiProfileGeometry.updateRoute(tb, editingCtx.getRoadSegmentData(), true, editingCtx.getBeforeSegments(), i);
|
allSegments.addAll(editingCtx.getBeforeSegments());
|
||||||
multiProfileGeometry.drawSegments(canvas, tb);
|
allSegments.addAll(editingCtx.getAfterSegments());
|
||||||
}
|
multiProfileGeometry.updateRoute(tb, editingCtx.getRoadSegmentData(), allSegments);
|
||||||
for (int i = 0; i < editingCtx.getAfterSegments().size(); i++) {
|
multiProfileGeometry.drawSegments(canvas, tb);
|
||||||
multiProfileGeometry.updateRoute(tb, editingCtx.getRoadSegmentData(), false, editingCtx.getAfterSegments(), i);
|
|
||||||
multiProfileGeometry.drawSegments(canvas, tb);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
multiProfileGeometry.clearWay();
|
multiProfileGeometry.clearWay();
|
||||||
List<TrkSegment> before = editingCtx.getBeforeTrkSegmentLine();
|
List<TrkSegment> before = editingCtx.getBeforeTrkSegmentLine();
|
||||||
|
|
|
@ -36,8 +36,7 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
private static final String DEFAULT_PROFILE_KEY = ApplicationMode.DEFAULT.getStringKey();
|
private static final String DEFAULT_PROFILE_KEY = ApplicationMode.DEFAULT.getStringKey();
|
||||||
|
|
||||||
private Map<Pair<WptPt, WptPt>, RoadSegmentData> segmentData;
|
private Map<Pair<WptPt, WptPt>, RoadSegmentData> segmentData;
|
||||||
private List<TrkSegment> beforeSegments;
|
private List<TrkSegment> segments;
|
||||||
private List<TrkSegment> afterSegments;
|
|
||||||
|
|
||||||
public MultiProfileGeometryWay(MultiProfileGeometryWayContext context) {
|
public MultiProfileGeometryWay(MultiProfileGeometryWayContext context) {
|
||||||
super(context, new MultiProfileGeometryWayDrawer(context));
|
super(context, new MultiProfileGeometryWayDrawer(context));
|
||||||
|
@ -60,8 +59,10 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
|
|
||||||
for (int i = 0; i < pathStyles.size(); i++) {
|
for (int i = 0; i < pathStyles.size(); i++) {
|
||||||
Pair<Path, GeometryWayStyle<?>> currPathStyle = pathStyles.get(i);
|
Pair<Path, GeometryWayStyle<?>> currPathStyle = pathStyles.get(i);
|
||||||
getDrawer().drawPathBorder(canvas, currPathStyle.first, currPathStyle.second);
|
if (!((GeometryMultiProfileWayStyle) currPathStyle.second).isGap) {
|
||||||
getDrawer().drawPath(canvas, currPathStyle.first, currPathStyle.second);
|
getDrawer().drawPathBorder(canvas, currPathStyle.first, currPathStyle.second);
|
||||||
|
getDrawer().drawPath(canvas, currPathStyle.first, currPathStyle.second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
getDrawer().drawArrowsOverPath(canvas, tb, tx, ty, angles, distances, distToFinish, styles);
|
getDrawer().drawArrowsOverPath(canvas, tb, tx, ty, angles, distances, distToFinish, styles);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -69,20 +70,18 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateRoute(RotatedTileBox tileBox, Map<Pair<WptPt, WptPt>, RoadSegmentData> segmentData,
|
public void updateRoute(RotatedTileBox tileBox, Map<Pair<WptPt, WptPt>, RoadSegmentData> segmentData, List<TrkSegment> segments) {
|
||||||
boolean before, List<TrkSegment> segments, int segmentIdx) {
|
|
||||||
boolean shouldUpdateRoute = tileBox.getMapDensity() != getMapDensity() || segmentDataChanged(segmentData)
|
boolean shouldUpdateRoute = tileBox.getMapDensity() != getMapDensity() || segmentDataChanged(segmentData)
|
||||||
|| getSegments(before) != segments || getLocationProvider() == null;
|
|| this.segments != segments || getLocationProvider() == null;
|
||||||
if (shouldUpdateRoute) {
|
if (shouldUpdateRoute) {
|
||||||
this.segmentData = segmentData;
|
this.segmentData = segmentData;
|
||||||
setSegments(before, segments);
|
this.segments = segments;
|
||||||
List<WptPt> userPoints = segments.get(segmentIdx).points;
|
|
||||||
List<Location> locations;
|
List<Location> locations;
|
||||||
Map<Integer, GeometryWayStyle<?>> styleMap;
|
Map<Integer, GeometryWayStyle<?>> styleMap;
|
||||||
|
|
||||||
List<Way> ways = new ArrayList<>();
|
List<Way> ways = new ArrayList<>();
|
||||||
List<GeometryWayStyle<?>> styles = new ArrayList<>();
|
List<GeometryWayStyle<?>> styles = new ArrayList<>();
|
||||||
setStyles(tileBox, userPoints, ways, styles);
|
setStyles(tileBox, segments, ways, styles);
|
||||||
locations = new ArrayList<>();
|
locations = new ArrayList<>();
|
||||||
|
|
||||||
styleMap = new TreeMap<>();
|
styleMap = new TreeMap<>();
|
||||||
|
@ -105,51 +104,72 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setStyles(RotatedTileBox tileBox, List<WptPt> userPoints, List<Way> ways, List<GeometryWayStyle<?>> styles) {
|
@Override
|
||||||
MultiProfileGeometryWayContext context = getContext();
|
public void clearWay() {
|
||||||
|
super.clearWay();
|
||||||
|
if (segmentData != null) {
|
||||||
|
segmentData.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setStyles(RotatedTileBox tileBox, List<TrkSegment> segments, List<Way> ways, List<GeometryWayStyle<?>> styles) {
|
||||||
Path path = new Path();
|
Path path = new Path();
|
||||||
PathMeasure pathMeasure = new PathMeasure();
|
PathMeasure pathMeasure = new PathMeasure();
|
||||||
|
|
||||||
for (int i = 0; i < userPoints.size() - 1; i++) {
|
for (TrkSegment segment : segments) {
|
||||||
WptPt leftPt = userPoints.get(i);
|
List<WptPt> points = segment.points;
|
||||||
Pair<WptPt, WptPt> userLine = new Pair<>(leftPt, userPoints.get(i + 1));
|
for (int i = 0; i < points.size() - 1; i++) {
|
||||||
RoadSegmentData routeBetweenPoints = segmentData.get(userLine);
|
setStylesInternal(tileBox, points, i, ways, styles, path, pathMeasure);
|
||||||
|
}
|
||||||
|
styles.add(new GeometryMultiProfileWayStyle(getContext(), 0, 0, true));
|
||||||
Way way = new Way(-1);
|
Way way = new Way(-1);
|
||||||
String currProfileKey = getProfileKey(leftPt);
|
WptPt last = points.get(points.size() - 1);
|
||||||
Pair<Integer, Integer> profileData = getProfileData(currProfileKey);
|
way.addNode(new Node(last.lat, last.lon, -1));
|
||||||
GeometryMultiProfileWayStyle style = new GeometryMultiProfileWayStyle(
|
|
||||||
getContext(), currProfileKey, profileData.first, profileData.second);
|
|
||||||
styles.add(style);
|
|
||||||
ways.add(way);
|
ways.add(way);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
path.reset();
|
private void setStylesInternal(RotatedTileBox tileBox, List<WptPt> points, int idx, List<Way> ways,
|
||||||
boolean isSecondToLast = i + 2 == userPoints.size();
|
List<GeometryWayStyle<?>> styles, Path path, PathMeasure pathMeasure) {
|
||||||
if (routeBetweenPoints == null || Algorithms.isEmpty(routeBetweenPoints.getPoints())) {
|
MultiProfileGeometryWayContext context = getContext();
|
||||||
way.addNode(new Node(userLine.first.lat, userLine.first.lon, -1));
|
WptPt leftPt = points.get(idx);
|
||||||
if (isSecondToLast) {
|
Pair<WptPt, WptPt> userLine = new Pair<>(leftPt, points.get(idx + 1));
|
||||||
way.addNode(new Node(userLine.second.lat, userLine.second.lon, -1));
|
RoadSegmentData routeBetweenPoints = segmentData.get(userLine);
|
||||||
}
|
boolean isSecondToLast = idx + 2 == points.size();
|
||||||
movePathToWpt(path, tileBox, userLine.first);
|
|
||||||
pathLineToWpt(path, tileBox, userLine.second);
|
|
||||||
} else {
|
|
||||||
movePathToWpt(path, tileBox, routeBetweenPoints.getPoints().get(0));
|
|
||||||
for (WptPt pt : routeBetweenPoints.getPoints()) {
|
|
||||||
if (pt.lat != userLine.second.lat && pt.lon != userLine.second.lon || isSecondToLast) {
|
|
||||||
way.addNode(new Node(pt.lat, pt.lon, -1));
|
|
||||||
}
|
|
||||||
pathLineToWpt(path, tileBox, pt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float[] xy = new float[2];
|
Way way = new Way(-1);
|
||||||
pathMeasure.setPath(path, false);
|
String currProfileKey = getProfileKey(leftPt);
|
||||||
float routeLength = pathMeasure.getLength();
|
Pair<Integer, Integer> profileData = getProfileData(currProfileKey);
|
||||||
if ((routeLength - context.circleSize) / 2 >= context.minIconMargin) {
|
GeometryMultiProfileWayStyle style = new GeometryMultiProfileWayStyle(
|
||||||
pathMeasure.getPosTan(pathMeasure.getLength() * 0.5f, xy, null);
|
getContext(), profileData.first, profileData.second);
|
||||||
style.setIconLat(tileBox.getLatFromPixel(xy[0], xy[1]));
|
styles.add(style);
|
||||||
style.setIconLon(tileBox.getLonFromPixel(xy[0], xy[1]));
|
ways.add(way);
|
||||||
|
|
||||||
|
path.reset();
|
||||||
|
if (routeBetweenPoints == null || Algorithms.isEmpty(routeBetweenPoints.getPoints())) {
|
||||||
|
way.addNode(new Node(userLine.first.lat, userLine.first.lon, -1));
|
||||||
|
if (isSecondToLast) {
|
||||||
|
way.addNode(new Node(userLine.second.lat, userLine.second.lon, -1));
|
||||||
}
|
}
|
||||||
|
movePathToWpt(path, tileBox, userLine.first);
|
||||||
|
pathLineToWpt(path, tileBox, userLine.second);
|
||||||
|
} else {
|
||||||
|
movePathToWpt(path, tileBox, routeBetweenPoints.getPoints().get(0));
|
||||||
|
for (WptPt pt : routeBetweenPoints.getPoints()) {
|
||||||
|
if (pt.lat != userLine.second.lat && pt.lon != userLine.second.lon || isSecondToLast) {
|
||||||
|
way.addNode(new Node(pt.lat, pt.lon, -1));
|
||||||
|
}
|
||||||
|
pathLineToWpt(path, tileBox, pt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] xy = new float[2];
|
||||||
|
pathMeasure.setPath(path, false);
|
||||||
|
float routeLength = pathMeasure.getLength();
|
||||||
|
if ((routeLength - context.circleSize) / 2 >= context.minIconMargin) {
|
||||||
|
pathMeasure.getPosTan(pathMeasure.getLength() * 0.5f, xy, null);
|
||||||
|
style.setIconLat(tileBox.getLatFromPixel(xy[0], xy[1]));
|
||||||
|
style.setIconLon(tileBox.getLonFromPixel(xy[0], xy[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,18 +201,6 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSegments(boolean before, List<TrkSegment> segments) {
|
|
||||||
if (before) {
|
|
||||||
this.beforeSegments = segments;
|
|
||||||
} else {
|
|
||||||
this.afterSegments = segments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<TrkSegment> getSegments(boolean before) {
|
|
||||||
return before ? this.beforeSegments : this.afterSegments;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void movePathToWpt(Path path, RotatedTileBox tileBox, WptPt pt) {
|
private void movePathToWpt(Path path, RotatedTileBox tileBox, WptPt pt) {
|
||||||
path.moveTo(tileBox.getPixXFromLatLon(pt.lat, pt.lon), tileBox.getPixYFromLatLon(pt.lat, pt.lon));
|
path.moveTo(tileBox.getPixXFromLatLon(pt.lat, pt.lon), tileBox.getPixYFromLatLon(pt.lat, pt.lon));
|
||||||
}
|
}
|
||||||
|
@ -221,9 +229,8 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GeometryMultiProfileWayStyle extends GeometryWayStyle<MultiProfileGeometryWayContext> {
|
public static class GeometryMultiProfileWayStyle extends GeometryWayStyle<MultiProfileGeometryWayContext> {
|
||||||
|
|
||||||
private final String profileKey;
|
|
||||||
@ColorInt
|
@ColorInt
|
||||||
private final int lineColor;
|
private final int lineColor;
|
||||||
@ColorInt
|
@ColorInt
|
||||||
|
@ -231,16 +238,25 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
@DrawableRes
|
@DrawableRes
|
||||||
private final int profileIconRes;
|
private final int profileIconRes;
|
||||||
|
|
||||||
private double iconLat;
|
private final boolean isGap;
|
||||||
private double iconLon;
|
|
||||||
|
|
||||||
public GeometryMultiProfileWayStyle(MultiProfileGeometryWayContext context, String profileKey,
|
private double iconLat = Double.NaN;
|
||||||
@ColorInt int profileColor, @DrawableRes int profileIconRes) {
|
private double iconLon = Double.NaN;
|
||||||
|
|
||||||
|
public GeometryMultiProfileWayStyle(MultiProfileGeometryWayContext context,
|
||||||
|
@ColorInt int profileColor, @DrawableRes int profileIconRes,
|
||||||
|
boolean isGap) {
|
||||||
super(context);
|
super(context);
|
||||||
this.profileKey = profileKey;
|
|
||||||
this.lineColor = profileColor;
|
this.lineColor = profileColor;
|
||||||
this.borderColor = ColorUtils.blendARGB(profileColor, Color.BLACK, 0.2f);
|
this.borderColor = ColorUtils.blendARGB(profileColor, Color.BLACK, 0.2f);
|
||||||
this.profileIconRes = profileIconRes;
|
this.profileIconRes = profileIconRes;
|
||||||
|
this.isGap = isGap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public GeometryMultiProfileWayStyle(MultiProfileGeometryWayContext context,
|
||||||
|
@ColorInt int profileColor, @DrawableRes int profileIconRes) {
|
||||||
|
this(context, profileColor, profileIconRes, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ColorInt
|
@ColorInt
|
||||||
|
@ -255,7 +271,7 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bitmap getPointBitmap() {
|
public Bitmap getPointBitmap() {
|
||||||
return getContext().getProfileIconBitmap(profileKey, profileIconRes, borderColor);
|
return getContext().getProfileIconBitmap(profileIconRes, borderColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIconLat(double lat) {
|
public void setIconLat(double lat) {
|
||||||
|
|
|
@ -73,8 +73,8 @@ public class MultiProfileGeometryWayContext extends GeometryWayContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public Bitmap getProfileIconBitmap(String profileKey, @DrawableRes int iconRes, @ColorInt int color) {
|
public Bitmap getProfileIconBitmap(@DrawableRes int iconRes, @ColorInt int color) {
|
||||||
String key = profileKey + "_" + iconRes + "_" + color;
|
String key = iconRes + "_" + color;
|
||||||
Bitmap bitmap = profileIconsBitmapCache.get(key);
|
Bitmap bitmap = profileIconsBitmapCache.get(key);
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
bitmap = Bitmap.createBitmap((int) circleSize, (int) circleSize, Bitmap.Config.ARGB_8888);
|
bitmap = Bitmap.createBitmap((int) circleSize, (int) circleSize, Bitmap.Config.ARGB_8888);
|
||||||
|
|
|
@ -34,9 +34,11 @@ public class MultiProfileGeometryWayDrawer extends GeometryWayDrawer<MultiProfil
|
||||||
style = (GeometryMultiProfileWayStyle) styles.get(i);
|
style = (GeometryMultiProfileWayStyle) styles.get(i);
|
||||||
double lat = style.getIconLat();
|
double lat = style.getIconLat();
|
||||||
double lon = style.getIconLon();
|
double lon = style.getIconLon();
|
||||||
float x = tb.getPixXFromLatLon(lat, lon) - context.circleSize / 2;
|
if (!Double.isNaN(lat) && !Double.isNaN(lon)) {
|
||||||
float y = tb.getPixYFromLatLon(lat, lon) - context.circleSize / 2;
|
float x = tb.getPixXFromLatLon(lat, lon) - context.circleSize / 2;
|
||||||
canvas.drawBitmap(style.getPointBitmap(), x, y, null);
|
float y = tb.getPixYFromLatLon(lat, lon) - context.circleSize / 2;
|
||||||
|
canvas.drawBitmap(style.getPointBitmap(), x, y, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue