Draw profile icon on line center
This commit is contained in:
parent
762e574bf0
commit
bf55e86a7e
6 changed files with 144 additions and 63 deletions
|
@ -151,6 +151,10 @@ public class AndroidUtils {
|
||||||
return resizedBitmap;
|
return resizedBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Bitmap createScaledBitmap(Drawable drawable, int width, int height) {
|
||||||
|
return scaleBitmap(drawableToBitmap(drawable), width, height, false);
|
||||||
|
}
|
||||||
|
|
||||||
public static ColorStateList createBottomNavColorStateList(Context ctx, boolean nightMode) {
|
public static ColorStateList createBottomNavColorStateList(Context ctx, boolean nightMode) {
|
||||||
return AndroidUtils.createCheckedColorStateList(ctx, nightMode,
|
return AndroidUtils.createCheckedColorStateList(ctx, nightMode,
|
||||||
R.color.icon_color_default_light, R.color.wikivoyage_active_light,
|
R.color.icon_color_default_light, R.color.wikivoyage_active_light,
|
||||||
|
|
|
@ -82,7 +82,8 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
||||||
multiProfileLineAttrs.isPaint3 = false;
|
multiProfileLineAttrs.isPaint3 = false;
|
||||||
multiProfileLineAttrs.paint3.setStrokeWidth(density * 2);
|
multiProfileLineAttrs.paint3.setStrokeWidth(density * 2);
|
||||||
|
|
||||||
multiProfileGeometryWayContext = new MultiProfileGeometryWayContext(view.getContext(), density);
|
multiProfileGeometryWayContext = new MultiProfileGeometryWayContext(
|
||||||
|
view.getContext(), view.getApplication().getUIUtilities(), density);
|
||||||
multiProfileGeometry = new MultiProfileGeometryWay(multiProfileGeometryWayContext);
|
multiProfileGeometry = new MultiProfileGeometryWay(multiProfileGeometryWayContext);
|
||||||
|
|
||||||
bitmapPaint = new Paint();
|
bitmapPaint = new Paint();
|
||||||
|
@ -227,6 +228,7 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
|
||||||
multiProfileGeometry.drawSegments(canvas, tb);
|
multiProfileGeometry.drawSegments(canvas, tb);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
multiProfileGeometry.clearWay();
|
||||||
List<TrkSegment> before = editingCtx.getBeforeTrkSegmentLine();
|
List<TrkSegment> before = editingCtx.getBeforeTrkSegmentLine();
|
||||||
for (TrkSegment segment : before) {
|
for (TrkSegment segment : before) {
|
||||||
new Renderable.StandardTrack(new ArrayList<>(segment.points), 17.2).
|
new Renderable.StandardTrack(new ArrayList<>(segment.points), 17.2).
|
||||||
|
|
|
@ -174,7 +174,7 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
}
|
}
|
||||||
double lat = locationProvider.getLatitude(i);
|
double lat = locationProvider.getLatitude(i);
|
||||||
double lon = locationProvider.getLongitude(i);
|
double lon = locationProvider.getLongitude(i);
|
||||||
if (shouldAddLocation(leftLongitude, rightLongitude, bottomLatitude, topLatitude,
|
if (shouldAddLocation(tb, leftLongitude, rightLongitude, bottomLatitude, topLatitude,
|
||||||
locationProvider, i)) {
|
locationProvider, i)) {
|
||||||
double dist = previous == -1 ? 0 : odistances.get(i);
|
double dist = previous == -1 ? 0 : odistances.get(i);
|
||||||
if (!previousVisible) {
|
if (!previousVisible) {
|
||||||
|
@ -188,7 +188,7 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
prevLon = lastProjection.getLongitude();
|
prevLon = lastProjection.getLongitude();
|
||||||
}
|
}
|
||||||
if (!Double.isNaN(prevLat) && !Double.isNaN(prevLon)) {
|
if (!Double.isNaN(prevLat) && !Double.isNaN(prevLon)) {
|
||||||
addLocation(tb, prevLat, prevLon, style, tx, ty, angles, distances, dist, styles); // first point
|
addLocation(tb, prevLat, prevLon, getStyle(i - 1, defaultWayStyle), tx, ty, angles, distances, dist, styles); // first point
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addLocation(tb, lat, lon, style, tx, ty, angles, distances, dist, styles);
|
addLocation(tb, lat, lon, style, tx, ty, angles, distances, dist, styles);
|
||||||
|
@ -208,8 +208,8 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
drawRouteSegment(tb, canvas, tx, ty, angles, distances, 0, styles);
|
drawRouteSegment(tb, canvas, tx, ty, angles, distances, 0, styles);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldAddLocation(double leftLon, double rightLon, double bottomLat, double topLat,
|
protected boolean shouldAddLocation(RotatedTileBox tileBox, double leftLon, double rightLon, double bottomLat,
|
||||||
GeometryWayProvider provider, int currLocationIdx) {
|
double topLat, GeometryWayProvider provider, int currLocationIdx) {
|
||||||
double lat = provider.getLatitude(currLocationIdx);
|
double lat = provider.getLatitude(currLocationIdx);
|
||||||
double lon = provider.getLongitude(currLocationIdx);
|
double lon = provider.getLongitude(currLocationIdx);
|
||||||
return leftLon <= lon && lon <= rightLon && bottomLat <= lat && lat <= topLat;
|
return leftLon <= lon && lon <= rightLon && bottomLat <= lat && lat <= topLat;
|
||||||
|
@ -261,16 +261,20 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
return x >= lx && x <= rx && y >= ty && y <= by;
|
return x >= lx && x <= rx && y >= ty && y <= by;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isIn(float x, float y, int lx, int ty, int rx, int by, float outMargin) {
|
||||||
|
return x >= lx - outMargin && x <= rx + outMargin && y >= ty - outMargin && y <= by + outMargin;
|
||||||
|
}
|
||||||
|
|
||||||
public static int calculatePath(RotatedTileBox tb, List<Float> xs, List<Float> ys, Path path) {
|
public static int calculatePath(RotatedTileBox tb, List<Float> xs, List<Float> ys, Path path) {
|
||||||
List<Pair<Path, GeometryWayStyle<?>>> paths = new ArrayList<>();
|
List<Pair<Path, GeometryWayStyle<?>>> paths = new ArrayList<>();
|
||||||
int res = calculatePath(tb, xs, ys, null, paths);
|
int res = calculatePath(tb, xs, ys, 0, null, paths);
|
||||||
if (paths.size() > 0) {
|
if (paths.size() > 0) {
|
||||||
path.addPath(paths.get(0).first);
|
path.addPath(paths.get(0).first);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int calculatePath(RotatedTileBox tb, List<Float> xs, List<Float> ys, List<GeometryWayStyle<?>> styles, List<Pair<Path, GeometryWayStyle<?>>> paths) {
|
public static int calculatePath(RotatedTileBox tb, List<Float> xs, List<Float> ys, float outMargin, List<GeometryWayStyle<?>> styles, List<Pair<Path, GeometryWayStyle<?>>> paths) {
|
||||||
boolean segmentStarted = false;
|
boolean segmentStarted = false;
|
||||||
float prevX = xs.get(0);
|
float prevX = xs.get(0);
|
||||||
float prevY = ys.get(0);
|
float prevY = ys.get(0);
|
||||||
|
@ -280,11 +284,11 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
boolean hasStyles = styles != null && styles.size() == xs.size();
|
boolean hasStyles = styles != null && styles.size() == xs.size();
|
||||||
GeometryWayStyle<?> style = hasStyles ? styles.get(0) : null;
|
GeometryWayStyle<?> style = hasStyles ? styles.get(0) : null;
|
||||||
Path path = new Path();
|
Path path = new Path();
|
||||||
boolean prevIn = isIn(prevX, prevY, 0, 0, width, height);
|
boolean prevIn = isIn(prevX, prevY, 0, 0, width, height, outMargin);
|
||||||
for (int i = 1; i < xs.size(); i++) {
|
for (int i = 1; i < xs.size(); i++) {
|
||||||
float currX = xs.get(i);
|
float currX = xs.get(i);
|
||||||
float currY = ys.get(i);
|
float currY = ys.get(i);
|
||||||
boolean currIn = isIn(currX, currY, 0, 0, width, height);
|
boolean currIn = isIn(currX, currY, 0, 0, width, height, outMargin);
|
||||||
boolean draw = false;
|
boolean draw = false;
|
||||||
if (prevIn && currIn) {
|
if (prevIn && currIn) {
|
||||||
draw = true;
|
draw = true;
|
||||||
|
@ -356,7 +360,7 @@ public abstract class GeometryWay<T extends GeometryWayContext, D extends Geomet
|
||||||
if (hasPathLine) {
|
if (hasPathLine) {
|
||||||
List<Pair<Path, GeometryWayStyle<?>>> paths = new ArrayList<>();
|
List<Pair<Path, GeometryWayStyle<?>>> paths = new ArrayList<>();
|
||||||
canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
|
canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
|
||||||
calculatePath(tb, tx, ty, styles, paths);
|
calculatePath(tb, tx, ty, 0, styles, paths);
|
||||||
for (Pair<Path, GeometryWayStyle<?>> pc : paths) {
|
for (Pair<Path, GeometryWayStyle<?>> pc : paths) {
|
||||||
GeometryWayStyle<?> style = pc.second;
|
GeometryWayStyle<?> style = pc.second;
|
||||||
if (style.hasPathLine()) {
|
if (style.hasPathLine()) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
|
import android.graphics.PathMeasure;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import net.osmand.GPXUtilities.TrkSegment;
|
import net.osmand.GPXUtilities.TrkSegment;
|
||||||
|
@ -55,14 +56,14 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
try {
|
try {
|
||||||
List<Pair<Path, GeometryWayStyle<?>>> pathStyles = new ArrayList<>();
|
List<Pair<Path, GeometryWayStyle<?>>> pathStyles = new ArrayList<>();
|
||||||
canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
|
canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
|
||||||
calculatePath(tb, tx, ty, styles, pathStyles);
|
calculatePath(tb, tx, ty, getContext().circleSize, styles, pathStyles);
|
||||||
|
|
||||||
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);
|
getDrawer().drawPathBorder(canvas, currPathStyle.first, currPathStyle.second);
|
||||||
getDrawer().drawPath(canvas, currPathStyle.first, currPathStyle.second);
|
getDrawer().drawPath(canvas, currPathStyle.first, currPathStyle.second);
|
||||||
}
|
}
|
||||||
// drawer.drawArrowsOverPath(canvas, tb, tx, ty, angles, distances, distToFinish, styles);
|
getDrawer().drawArrowsOverPath(canvas, tb, tx, ty, angles, distances, distToFinish, styles);
|
||||||
} finally {
|
} finally {
|
||||||
canvas.rotate(tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
|
canvas.rotate(tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
|
||||||
}
|
}
|
||||||
|
@ -71,8 +72,8 @@ 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,
|
||||||
boolean before, List<TrkSegment> segments, int segmentIdx) {
|
boolean before, List<TrkSegment> segments, int segmentIdx) {
|
||||||
boolean shouldUpdateRoute = tileBox.getMapDensity() != getMapDensity() || segmentDataChanged(segmentData)
|
boolean shouldUpdateRoute = tileBox.getMapDensity() != getMapDensity() || segmentDataChanged(segmentData)
|
||||||
|| getSegments(before) != segments || true;
|
|| getSegments(before) != segments || getLocationProvider() == null;
|
||||||
if (shouldUpdateRoute && segments.get(segmentIdx).points.size() >= 2) {
|
if (shouldUpdateRoute) {
|
||||||
this.segmentData = segmentData;
|
this.segmentData = segmentData;
|
||||||
setSegments(before, segments);
|
setSegments(before, segments);
|
||||||
List<WptPt> userPoints = segments.get(segmentIdx).points;
|
List<WptPt> userPoints = segments.get(segmentIdx).points;
|
||||||
|
@ -81,7 +82,7 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
|
|
||||||
List<Way> ways = new ArrayList<>();
|
List<Way> ways = new ArrayList<>();
|
||||||
List<GeometryWayStyle<?>> styles = new ArrayList<>();
|
List<GeometryWayStyle<?>> styles = new ArrayList<>();
|
||||||
setStyles(userPoints, ways, styles);
|
setStyles(tileBox, userPoints, ways, styles);
|
||||||
locations = new ArrayList<>();
|
locations = new ArrayList<>();
|
||||||
|
|
||||||
styleMap = new TreeMap<>();
|
styleMap = new TreeMap<>();
|
||||||
|
@ -104,45 +105,68 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setStyles(List<WptPt> userPoints, List<Way> ways, List<GeometryWayStyle<?>> styles) {
|
private void setStyles(RotatedTileBox tileBox, List<WptPt> userPoints, List<Way> ways, List<GeometryWayStyle<?>> styles) {
|
||||||
String prevProfileKey = "";
|
MultiProfileGeometryWayContext context = getContext();
|
||||||
Way way = new Way(-2);
|
Path path = new Path();
|
||||||
|
PathMeasure pathMeasure = new PathMeasure();
|
||||||
|
|
||||||
for (int i = 0; i < userPoints.size() - 1; i++) {
|
for (int i = 0; i < userPoints.size() - 1; i++) {
|
||||||
WptPt leftPt = userPoints.get(i);
|
WptPt leftPt = userPoints.get(i);
|
||||||
Pair<WptPt, WptPt> userLine = new Pair<>(leftPt, userPoints.get(i + 1));
|
Pair<WptPt, WptPt> userLine = new Pair<>(leftPt, userPoints.get(i + 1));
|
||||||
RoadSegmentData routeBetweenPoints = segmentData.get(userLine);
|
RoadSegmentData routeBetweenPoints = segmentData.get(userLine);
|
||||||
|
|
||||||
if (!prevProfileKey.equals(getProfileKey(leftPt)) && !leftPt.isGap()) {
|
Way way = new Way(-1);
|
||||||
way = new Way(-2);
|
String currProfileKey = getProfileKey(leftPt);
|
||||||
String currProfileKey = getProfileKey(leftPt);
|
Pair<Integer, Integer> profileData = getProfileData(currProfileKey);
|
||||||
Pair<Integer, Integer> profileData = getProfileData(currProfileKey);
|
GeometryMultiProfileWayStyle style = new GeometryMultiProfileWayStyle(
|
||||||
styles.add(new GeometryMultiProfileWayStyle(getContext(), profileData.first, profileData.second));
|
getContext(), currProfileKey, profileData.first, profileData.second);
|
||||||
ways.add(way);
|
styles.add(style);
|
||||||
prevProfileKey = currProfileKey;
|
ways.add(way);
|
||||||
}
|
|
||||||
|
|
||||||
|
path.reset();
|
||||||
boolean isSecondToLast = i + 2 == userPoints.size();
|
boolean isSecondToLast = i + 2 == userPoints.size();
|
||||||
if (routeBetweenPoints == null || Algorithms.isEmpty(routeBetweenPoints.getPoints())) {
|
if (routeBetweenPoints == null || Algorithms.isEmpty(routeBetweenPoints.getPoints())) {
|
||||||
way.addNode(new Node(userLine.first.lat, userLine.first.lon, -1));
|
way.addNode(new Node(userLine.first.lat, userLine.first.lon, -1));
|
||||||
if (isSecondToLast) {
|
if (isSecondToLast) {
|
||||||
way.addNode(new Node(userLine.second.lat, userLine.second.lon, -1));
|
way.addNode(new Node(userLine.second.lat, userLine.second.lon, -1));
|
||||||
}
|
}
|
||||||
|
movePathToWpt(path, tileBox, userLine.first);
|
||||||
|
pathLineToWpt(path, tileBox, userLine.second);
|
||||||
} else {
|
} else {
|
||||||
|
movePathToWpt(path, tileBox, routeBetweenPoints.getPoints().get(0));
|
||||||
for (WptPt pt : routeBetweenPoints.getPoints()) {
|
for (WptPt pt : routeBetweenPoints.getPoints()) {
|
||||||
if (pt.lat != userLine.second.lat && pt.lon != userLine.second.lon || isSecondToLast) {
|
if (pt.lat != userLine.second.lat && pt.lon != userLine.second.lon || isSecondToLast) {
|
||||||
way.addNode(new Node(pt.lat, pt.lon, -1));
|
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]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldAddLocation(double leftLon, double rightLon, double bottomLat, double topLat, GeometryWayProvider provider, int currLocationIdx) {
|
protected boolean shouldAddLocation(RotatedTileBox tileBox, double leftLon, double rightLon,
|
||||||
return super.shouldAddLocation(leftLon, rightLon, bottomLat, topLat, provider, currLocationIdx)
|
double bottomLat, double topLat, GeometryWayProvider provider,
|
||||||
|| currLocationIdx + 1 < provider.getSize()
|
int currLocationIdx) {
|
||||||
&& super.shouldAddLocation(leftLon, rightLon, bottomLat, topLat, provider, currLocationIdx + 1);
|
float currX = tileBox.getPixXFromLatLon(provider.getLatitude(currLocationIdx), provider.getLongitude(currLocationIdx));
|
||||||
|
float currY = tileBox.getPixYFromLatLon(provider.getLatitude(currLocationIdx), provider.getLongitude(currLocationIdx));
|
||||||
|
if (tileBox.containsPoint(currX, currY, getContext().circleSize)) {
|
||||||
|
return true;
|
||||||
|
} else if (currLocationIdx + 1 >= provider.getSize()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
float nextX = tileBox.getPixXFromLatLon(provider.getLatitude(currLocationIdx + 1), provider.getLongitude(currLocationIdx + 1));
|
||||||
|
float nextY = tileBox.getPixXFromLatLon(provider.getLatitude(currLocationIdx + 1), provider.getLongitude(currLocationIdx + 1));
|
||||||
|
return tileBox.containsPoint(nextX, nextY, getContext().circleSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean segmentDataChanged(Map<Pair<WptPt, WptPt>, RoadSegmentData> other) {
|
private boolean segmentDataChanged(Map<Pair<WptPt, WptPt>, RoadSegmentData> other) {
|
||||||
|
@ -169,6 +193,14 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
return before ? this.beforeSegments : this.afterSegments;
|
return before ? this.beforeSegments : this.afterSegments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void movePathToWpt(Path path, RotatedTileBox tileBox, WptPt pt) {
|
||||||
|
path.moveTo(tileBox.getPixXFromLatLon(pt.lat, pt.lon), tileBox.getPixYFromLatLon(pt.lat, pt.lon));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pathLineToWpt(Path path, RotatedTileBox tileBox, WptPt pt) {
|
||||||
|
path.lineTo(tileBox.getPixXFromLatLon(pt.lat, pt.lon), tileBox.getPixYFromLatLon(pt.lat, pt.lon));
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private String getProfileKey(WptPt pt) {
|
private String getProfileKey(WptPt pt) {
|
||||||
String key = pt.getProfileType();
|
String key = pt.getProfileType();
|
||||||
|
@ -191,6 +223,7 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
|
|
||||||
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
|
||||||
|
@ -198,9 +231,13 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
@DrawableRes
|
@DrawableRes
|
||||||
private final int profileIconRes;
|
private final int profileIconRes;
|
||||||
|
|
||||||
public GeometryMultiProfileWayStyle(MultiProfileGeometryWayContext context,
|
private double iconLat;
|
||||||
|
private double iconLon;
|
||||||
|
|
||||||
|
public GeometryMultiProfileWayStyle(MultiProfileGeometryWayContext context, String profileKey,
|
||||||
@ColorInt int profileColor, @DrawableRes int profileIconRes) {
|
@ColorInt int profileColor, @DrawableRes int profileIconRes) {
|
||||||
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;
|
||||||
|
@ -216,32 +253,30 @@ public class MultiProfileGeometryWay extends GeometryWay<MultiProfileGeometryWay
|
||||||
return lineColor;
|
return lineColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@DrawableRes
|
|
||||||
public int getProfileIconRes() {
|
|
||||||
return profileIconRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bitmap getPointBitmap() {
|
public Bitmap getPointBitmap() {
|
||||||
// return getContext().getProfileIconBitmap();
|
return getContext().getProfileIconBitmap(profileKey, profileIconRes, borderColor);
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
public void setIconLat(double lat) {
|
||||||
|
iconLat = lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIconLon(double lon) {
|
||||||
|
iconLon = lon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getIconLat() {
|
||||||
|
return iconLat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getIconLon() {
|
||||||
|
return iconLon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (this == other) {
|
return this == other;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (other == null || getClass() != other.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!super.equals(other)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GeometryMultiProfileWayStyle that = (GeometryMultiProfileWayStyle) other;
|
|
||||||
return lineColor == that.lineColor &&
|
|
||||||
borderColor == that.borderColor &&
|
|
||||||
profileIconRes == that.profileIconRes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,25 +6,36 @@ import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
|
||||||
|
import net.osmand.AndroidUtils;
|
||||||
|
import net.osmand.plus.UiUtilities;
|
||||||
import net.osmand.plus.views.OsmandMapLayer.RenderingLineAttributes;
|
import net.osmand.plus.views.OsmandMapLayer.RenderingLineAttributes;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class MultiProfileGeometryWayContext extends GeometryWayContext {
|
public class MultiProfileGeometryWayContext extends GeometryWayContext {
|
||||||
|
|
||||||
|
private final UiUtilities iconsCache;
|
||||||
|
|
||||||
|
public final float minIconMargin;
|
||||||
|
public final float circleSize;
|
||||||
|
|
||||||
private RenderingLineAttributes multiProfileAttrs;
|
private RenderingLineAttributes multiProfileAttrs;
|
||||||
|
|
||||||
private Bitmap pointIcon;
|
private Bitmap pointIcon;
|
||||||
|
|
||||||
private final Map<String, Bitmap> profileIconsBitmapCache;
|
private final Map<String, Bitmap> profileIconsBitmapCache;
|
||||||
|
|
||||||
public MultiProfileGeometryWayContext(Context ctx, float density) {
|
public MultiProfileGeometryWayContext(Context ctx, UiUtilities iconsCache, float density) {
|
||||||
super(ctx, density);
|
super(ctx, density);
|
||||||
|
this.iconsCache = iconsCache;
|
||||||
profileIconsBitmapCache = new HashMap<>();
|
profileIconsBitmapCache = new HashMap<>();
|
||||||
|
minIconMargin = density * 30;
|
||||||
|
circleSize = density * 70;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePaints(boolean nightMode, @NonNull RenderingLineAttributes multiProfileAttrs) {
|
public void updatePaints(boolean nightMode, @NonNull RenderingLineAttributes multiProfileAttrs) {
|
||||||
|
@ -62,18 +73,24 @@ public class MultiProfileGeometryWayContext extends GeometryWayContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public Bitmap getProfileIconBitmap(@NonNull String profileKey, int profileColor) {
|
public Bitmap getProfileIconBitmap(String profileKey, @DrawableRes int iconRes, @ColorInt int color) {
|
||||||
String key = profileKey + "_" + profileColor;
|
String key = profileKey + "_" + iconRes + "_" + color;
|
||||||
Bitmap bitmap = profileIconsBitmapCache.get(key);
|
Bitmap bitmap = profileIconsBitmapCache.get(key);
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
float density = getDensity();
|
bitmap = Bitmap.createBitmap((int) circleSize, (int) circleSize, Bitmap.Config.ARGB_8888);
|
||||||
float diameter = density * 18;
|
|
||||||
bitmap = Bitmap.createBitmap((int) diameter, (int) diameter, Bitmap.Config.ARGB_8888);
|
|
||||||
|
|
||||||
Canvas canvas = new Canvas(bitmap);
|
Canvas canvas = new Canvas(bitmap);
|
||||||
canvas.drawCircle(diameter / 2, diameter / 2, diameter / 2, multiProfileAttrs.paint_1);
|
float center = bitmap.getWidth() / 2f;
|
||||||
multiProfileAttrs.paint3.setColor(profileColor);
|
|
||||||
canvas.drawCircle(diameter / 2, diameter / 2, diameter / 2, multiProfileAttrs.paint3);
|
canvas.drawCircle(center, center, center / 2, multiProfileAttrs.paint_1);
|
||||||
|
multiProfileAttrs.paint3.setColor(color);
|
||||||
|
canvas.drawCircle(center, center, center / 2, multiProfileAttrs.paint3);
|
||||||
|
|
||||||
|
float iconSize = center - getDensity() * 10;
|
||||||
|
Bitmap profileIconBitmap = AndroidUtils.createScaledBitmap(
|
||||||
|
iconsCache.getPaintedIcon(iconRes, color), (int) iconSize, (int) iconSize);
|
||||||
|
canvas.drawBitmap(profileIconBitmap, center - iconSize / 2, center - iconSize / 2, multiProfileAttrs.paint3);
|
||||||
|
|
||||||
|
profileIconsBitmapCache.put(key, bitmap);
|
||||||
}
|
}
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,11 @@ package net.osmand.plus.views.layers.geometry;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
|
|
||||||
|
import net.osmand.data.RotatedTileBox;
|
||||||
|
import net.osmand.plus.views.OsmandMapLayer.RenderingLineAttributes;
|
||||||
import net.osmand.plus.views.layers.geometry.MultiProfileGeometryWay.GeometryMultiProfileWayStyle;
|
import net.osmand.plus.views.layers.geometry.MultiProfileGeometryWay.GeometryMultiProfileWayStyle;
|
||||||
|
|
||||||
import net.osmand.plus.views.OsmandMapLayer.RenderingLineAttributes;
|
import java.util.List;
|
||||||
|
|
||||||
public class MultiProfileGeometryWayDrawer extends GeometryWayDrawer<MultiProfileGeometryWayContext> {
|
public class MultiProfileGeometryWayDrawer extends GeometryWayDrawer<MultiProfileGeometryWayContext> {
|
||||||
|
|
||||||
|
@ -22,6 +24,23 @@ public class MultiProfileGeometryWayDrawer extends GeometryWayDrawer<MultiProfil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawArrowsOverPath(Canvas canvas, RotatedTileBox tb, List<Float> tx, List<Float> ty, List<Double> angles, List<Double> distances, double distPixToFinish, List<GeometryWayStyle<?>> styles) {
|
||||||
|
MultiProfileGeometryWayContext context = getContext();
|
||||||
|
GeometryMultiProfileWayStyle style = null;
|
||||||
|
|
||||||
|
for (int i = 0; i < styles.size(); i++) {
|
||||||
|
if (styles.get(i) != null && !styles.get(i).equals(style)) {
|
||||||
|
style = (GeometryMultiProfileWayStyle) styles.get(i);
|
||||||
|
double lat = style.getIconLat();
|
||||||
|
double lon = style.getIconLon();
|
||||||
|
float x = tb.getPixXFromLatLon(lat, lon) - context.circleSize / 2;
|
||||||
|
float y = tb.getPixYFromLatLon(lat, lon) - context.circleSize / 2;
|
||||||
|
canvas.drawBitmap(style.getPointBitmap(), x, y, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void drawPathBorder(Canvas canvas, Path path, GeometryWayStyle<?> style) {
|
public void drawPathBorder(Canvas canvas, Path path, GeometryWayStyle<?> style) {
|
||||||
if (style instanceof GeometryMultiProfileWayStyle) {
|
if (style instanceof GeometryMultiProfileWayStyle) {
|
||||||
RenderingLineAttributes attrs = getContext().getAttrs();
|
RenderingLineAttributes attrs = getContext().getAttrs();
|
||||||
|
|
Loading…
Reference in a new issue