diff --git a/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoActivity.java b/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoActivity.java index 7f4f053306..0ff0501349 100644 --- a/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoActivity.java @@ -189,7 +189,7 @@ public class ShowRouteInfoActivity extends OsmandListActivity { TextView cumulativeTimeLabel = (TextView) row.findViewById(R.id.cumulative_time); ImageView icon = (ImageView) row.findViewById(R.id.direction); - TurnPathHelper.RouteDrawable drawable = new TurnPathHelper.RouteDrawable(getResources()); + TurnPathHelper.RouteDrawable drawable = new TurnPathHelper.RouteDrawable(getResources(), true); drawable.setRouteType(model.getTurnType()); icon.setImageDrawable(drawable); diff --git a/OsmAnd/src/net/osmand/plus/views/TurnPathHelper.java b/OsmAnd/src/net/osmand/plus/views/TurnPathHelper.java index b5341dc779..9384ef3690 100644 --- a/OsmAnd/src/net/osmand/plus/views/TurnPathHelper.java +++ b/OsmAnd/src/net/osmand/plus/views/TurnPathHelper.java @@ -1,15 +1,24 @@ package net.osmand.plus.views; -import android.graphics.*; +import java.util.Map; + import net.osmand.plus.R; import net.osmand.router.TurnType; import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; import android.graphics.Paint.Style; -import android.graphics.Path.Direction; +import android.graphics.Path; +import android.graphics.PointF; +import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.drawable.Drawable; -import java.util.Map; - public class TurnPathHelper { //Index of processed turn @@ -20,7 +29,8 @@ public class TurnPathHelper { private static final boolean SHOW_STEPS = true; // 72x72 - public static void calcTurnPath(Path pathForTurn, Path outlay, TurnType turnType, Matrix transform) { + public static void calcTurnPath(Path pathForTurn, Path outlay, TurnType turnType, + Matrix transform, PointF center, boolean mini) { if(turnType == null){ return; } @@ -177,41 +187,57 @@ public class TurnPathHelper { pathForTurn.rLineTo(-harrowL / 2, harrowL / 2); // -15 15 pathForTurn.rLineTo(hpartArrowL + th, 0); //9 0 } else if(turnType != null && turnType.isRoundAbout() && USE_NEW_RNDB) { - int out = turnType.getExitOut(); boolean leftSide = turnType.isLeftSide(); - float radArrow = 37; - float radIn = 11; - float radOut = radIn + 6; + float radEndOfArrow = 44; + float radInnerCircle = 10; + float radOuterCircle = radInnerCircle + 8; - float radBottom = radOut + 8; - float radStepInter = radOut + 6; - float radAr = radOut + 4; - float radAr2 = radOut + 5; + float radBottom = radOuterCircle + 10; + float radStepInter = radOuterCircle + 6; + float radArrowTriangle1 = radOuterCircle + 7; + float radArrowTriangle2 = radOuterCircle + 8; float widthStepIn = 8; float widthStepInter = 6; float widthArrow = 22; - float cx = wa / 2 ; - float cy = ha / 2 ; - + double dfL = (leftSide ? 1 : -1) * Math.asin(widthStepIn / (2.0 * radBottom)); - double dfAr2 = (leftSide ? 1 : -1) * Math.asin(widthArrow / (2.0 * radAr2)); + double dfAr2 = (leftSide ? 1 : -1) * Math.asin(widthArrow / (2.0 * radArrowTriangle2)); double dfStepInter = (leftSide ? 1 : -1) * Math.asin(widthStepInter / radStepInter); - double dfAr = Math.asin(radBottom * Math.sin(dfL) / radAr); - double dfOut = Math.asin(radBottom * Math.sin(dfL) / radOut); - double dfStepOut = Math.asin(radStepInter * Math.sin(dfStepInter) / radOut); - double dfIn = Math.asin(radBottom * Math.sin(dfL) / radIn); + double dfAr = Math.asin(radBottom * Math.sin(dfL) / radArrowTriangle1); + double dfOut = Math.asin(radBottom * Math.sin(dfL) / radOuterCircle); + double dfStepOut = Math.asin(radStepInter * Math.sin(dfStepInter) / radOuterCircle); + double dfIn = Math.asin(radBottom * Math.sin(dfL) / radInnerCircle); double minDelta = Math.abs(dfIn * 2 / Math.PI * 180 ) + 2; - boolean showSteps = SHOW_STEPS; + boolean showSteps = SHOW_STEPS && !mini; // System.out.println("Angle " + dfL + " " + dfOut + " " + dfIn + " " + minDelta + " "); - double rot = alignRotation(turnType.getTurnAngle(), leftSide, minDelta) / 180 * Math.PI; + double rot = alignRotation(turnType.getTurnAngle(), leftSide, minDelta, out) / 180 * Math.PI; + + float cx = wa / 2 ; + float cy = ha / 2 ; + // align center + float potentialArrowEndX = (float) (Math.sin(rot) * radEndOfArrow); + float potentialArrowEndY = (float) (Math.cos(rot) * radEndOfArrow); + if (potentialArrowEndX > cx) { + cx = potentialArrowEndX; + } else if (potentialArrowEndX < -cx) { + cx = 2 * cx + potentialArrowEndX; + } + if(potentialArrowEndY > cy) { + cy = 2 * cy - potentialArrowEndY; + } else if(potentialArrowEndY < -cy) { + cy = -potentialArrowEndY; + } + if(center != null) { + center.set(cx, cy); + } - RectF qrOut = new RectF(cx - radOut, cy - radOut, cx + radOut, cy + radOut); - RectF qrIn = new RectF(cx - radIn, cy - radIn, cx + radIn, cy + radIn); - if(outlay != null) { + RectF qrOut = new RectF(cx - radOuterCircle, cy - radOuterCircle, cx + radOuterCircle, cy + radOuterCircle); + RectF qrIn = new RectF(cx - radInnerCircle, cy - radInnerCircle, cx + radInnerCircle, cy + radInnerCircle); + if(outlay != null && !mini) { outlay.addArc(qrOut, 0, 360); outlay.addArc(qrIn, 0, -360); // outlay.addOval(qrOut, Direction.CCW); @@ -219,7 +245,7 @@ public class TurnPathHelper { } // move to bottom ring - pathForTurn.moveTo(getProjX(dfOut, cx, cy, radOut), getProjY(dfOut, cx, cy, radOut)); + pathForTurn.moveTo(getProjX(dfOut, cx, cy, radOuterCircle), getProjY(dfOut, cx, cy, radOuterCircle)); if (out <= 1) { showSteps = false; } @@ -235,18 +261,18 @@ public class TurnPathHelper { // double st = (rot - 2 * dfOut ) / (2 * out - 1); // dfStepOut = st; if (showSteps) { - outlay.moveTo(getProjX(dfOut, cx, cy, radOut), getProjY(dfOut, cx, cy, radOut)); + outlay.moveTo(getProjX(dfOut, cx, cy, radOuterCircle), getProjY(dfOut, cx, cy, radOuterCircle)); for (int i = 0; i < out - 1; i++) { outlay.arcTo(qrOut, startArcAngle(dfOut + i * (st + dfStepOut)), sweepArcAngle(st)); arcLineTo(outlay, dfOut + (i + 1) * (st + dfStepOut) - dfStepOut / 2 - dfStepInter / 2, cx, cy, radStepInter); arcLineTo(outlay, dfOut + (i + 1) * (st + dfStepOut) - dfStepOut / 2 + dfStepInter / 2, cx, cy, radStepInter); - arcLineTo(outlay, dfOut + (i + 1) * (st + dfStepOut), cx, cy, radOut); + arcLineTo(outlay, dfOut + (i + 1) * (st + dfStepOut), cx, cy, radOuterCircle); // pathForTurn.arcTo(qr1, startArcAngle(dfOut), sweepArcAngle(rot - dfOut - dfOut)); } outlay.arcTo(qrOut, startArcAngle(rot - dfOut - st), sweepArcAngle(st)); // swipe back - arcLineTo(outlay, rot - dfIn, cx, cy, radIn); + arcLineTo(outlay, rot - dfIn, cx, cy, radInnerCircle); outlay.arcTo(qrIn, startArcAngle(rot - dfIn), -sweepArcAngle(rot - dfIn - dfIn)); } } @@ -257,21 +283,21 @@ public class TurnPathHelper { pathForTurn.arcTo(qrOut, startArcAngle(dfOut), sweepArcAngle(rot - dfOut - dfOut)); // up from arc - arcLineTo(pathForTurn, rot - dfAr, cx, cy, radAr); + arcLineTo(pathForTurn, rot - dfAr, cx, cy, radArrowTriangle1); // left triangle // arcLineTo(pathForTurn, rot - dfAr2, cx, cy, radAr2); // 1. // arcQuadTo(pathForTurn, rot - dfAr2, radAr2, rot, radArrow, 0.9f, cx, cy); // 2. - arcQuadTo(pathForTurn, rot - dfAr, radAr, rot - dfAr2, radAr2, rot, radArrow, 4.5f, cx, cy); // 3. + arcQuadTo(pathForTurn, rot - dfAr, radArrowTriangle1, rot - dfAr2, radArrowTriangle2, rot, radEndOfArrow, 4.5f, cx, cy); // 3. // arcLineTo(pathForTurn, rot, cx, cy, radArrow); // 1. - arcQuadTo(pathForTurn, rot - dfAr2, radAr2, rot, radArrow, rot + dfAr2, radAr2, 4.5f, cx, cy); + arcQuadTo(pathForTurn, rot - dfAr2, radArrowTriangle2, rot, radEndOfArrow, rot + dfAr2, radArrowTriangle2, 4.5f, cx, cy); // right triangle // arcLineTo(pathForTurn, rot + dfAr2, cx, cy, radAr2); // 1. - arcQuadTo(pathForTurn, rot, radArrow, rot + dfAr2, radAr2, rot + dfAr, radAr, 4.5f, cx, cy); + arcQuadTo(pathForTurn, rot, radEndOfArrow, rot + dfAr2, radArrowTriangle2, rot + dfAr, radArrowTriangle1, 4.5f, cx, cy); - arcLineTo(pathForTurn, rot + dfAr, cx, cy, radAr); + arcLineTo(pathForTurn, rot + dfAr, cx, cy, radArrowTriangle1); // down to arc - arcLineTo(pathForTurn, rot + dfIn, cx, cy, radIn); + arcLineTo(pathForTurn, rot + dfIn, cx, cy, radInnerCircle); // arc pathForTurn.arcTo(qrIn, startArcAngle(rot + dfIn), sweepArcAngle(-rot - dfIn - dfIn)); // down @@ -362,24 +388,34 @@ public class TurnPathHelper { } } - private static float alignRotation(float t, boolean leftSide, double minDelta) { - // t between -180, 180 + private static float alignRotation(float t, boolean leftSide, double minDelta, int out) { + // t between ]-180, 180] while(t > 180) { t -= 360; } - while(t < -180) { + while(t <= -180) { t += 360; } + // rot left - ] 0, 360], right ] -360,0] float rot = leftSide ? (t + 180) : (t - 180) ; + if(rot == 0) { + rot = leftSide ? 360 : -360; + } float delta = (float) minDelta; - if(rot > 360 - delta && rot < 360) { + if(rot > 360 - delta && rot <= 360) { rot = 360 - delta; - } else if (rot > 0 && rot < delta) { - rot = delta; - } else if (rot < -360 + delta && rot > -360) { + } else if (rot < -360 + delta && rot >= -360) { rot = -360 + delta; - } else if (rot < 0 && rot > -delta) { + } else if (rot >= 0 && rot < delta) { + rot = delta; + if(out > 2) { + rot = 360 - delta; + } + } else if (rot <= 0 && rot > -delta) { rot = -delta; + if(out > 2) { + rot = -360 + delta; + } } return rot; } @@ -447,8 +483,10 @@ public class TurnPathHelper { Path dp = new Path(); Path pOutlay = new Path(); Path dpOutlay = new Path(); + private boolean mini; - public RouteDrawable(Resources resources){ + public RouteDrawable(Resources resources, boolean mini){ + this.mini = mini; paintRouteDirection = new Paint(); paintRouteDirection.setStyle(Style.FILL_AND_STROKE); paintRouteDirection.setColor(resources.getColor(R.color.nav_arrow_distant)); @@ -457,7 +495,7 @@ public class TurnPathHelper { paintRouteDirectionOutlay.setStyle(Style.STROKE); paintRouteDirectionOutlay.setColor(Color.BLACK); paintRouteDirectionOutlay.setAntiAlias(true); - TurnPathHelper.calcTurnPath(dp, dpOutlay, TurnType.straight(), null); + TurnPathHelper.calcTurnPath(dp, dpOutlay, TurnType.straight(), null, null, mini); } @Override @@ -469,7 +507,7 @@ public class TurnPathHelper { } public void setRouteType(TurnType t){ - TurnPathHelper.calcTurnPath(p, pOutlay, t, null); + TurnPathHelper.calcTurnPath(p, pOutlay, t, null, null, mini); onBoundsChange(getBounds()); } diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java index 2cc8468f60..10eb65eb1d 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java @@ -262,7 +262,7 @@ public class MapInfoWidgetsFactory { settings = app.getSettings(); waypointHelper = app.getWaypointHelper(); updateVisibility(false); - turnDrawable = new NextTurnInfoWidget.TurnDrawable(map); + turnDrawable = new NextTurnInfoWidget.TurnDrawable(map, true); } public boolean updateVisibility(boolean visible) { diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java index 265ecf0ed9..27a28b4d19 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java @@ -5,6 +5,7 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; +import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopTextView; import net.osmand.plus.views.TurnPathHelper; import net.osmand.router.TurnType; import android.app.Activity; @@ -14,10 +15,13 @@ import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Paint; +import android.graphics.Paint.Align; import android.graphics.Paint.Style; import android.graphics.Path; +import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.text.TextPaint; @@ -36,7 +40,7 @@ public class NextTurnInfoWidget extends TextInfoWidget { super(activity); this.app = app; this.horisontalMini = horisontalMini; - turnDrawable = new TurnDrawable(activity); + turnDrawable = new TurnDrawable(activity, horisontalMini); if(horisontalMini) { setImageDrawable(turnDrawable, false); setTopImageDrawable(null, null); @@ -53,11 +57,13 @@ public class NextTurnInfoWidget extends TextInfoWidget { public void setTurnType(TurnType turnType) { boolean vis = updateVisibility(turnType != null); if (turnDrawable.setTurnType(turnType) || vis) { + turnDrawable.setTextPaint(topTextView.getPaint()); if(horisontalMini) { setImageDrawable(turnDrawable, false); } else { - setTopImageDrawable(turnDrawable, turnType == null || turnType.getExitOut() == 0 ? "" : - turnType.getExitOut() + ""); + setTopImageDrawable(turnDrawable, ""); +// setTopImageDrawable(turnDrawable, turnType == null || turnType.getExitOut() == 0 ? "" : +// turnType.getExitOut() + ""); } } } @@ -118,14 +124,20 @@ public class NextTurnInfoWidget extends TextInfoWidget { protected int turnImminent; protected boolean deviatedFromRoute; private Context ctx; + private boolean mini; + private PointF centerText; + private TextPaint textPaint; - public TurnDrawable(Context ctx) { + public TurnDrawable(Context ctx, boolean mini) { this.ctx = ctx; + this.mini = mini; + centerText = new PointF(); paintBlack = new Paint(); paintBlack.setStyle(Style.STROKE); paintBlack.setColor(Color.BLACK); paintBlack.setAntiAlias(true); paintBlack.setStrokeWidth(2.5f); + paintRouteDirection = new Paint(); paintRouteDirection.setStyle(Style.FILL); @@ -137,8 +149,12 @@ public class NextTurnInfoWidget extends TextInfoWidget { @Override protected void onBoundsChange(Rect bounds) { Matrix m = new Matrix(); - m.setScale(bounds.width() / 72f, bounds.height() / 72f); + float scaleX = bounds.width() / 72f; + float scaleY = bounds.height() / 72f; + m.setScale(scaleX, scaleY); pathForTurn.transform(m, pathForTurn); + centerText.x = scaleX * centerText.x; + centerText.y = scaleY * centerText.y; pathForTurnOutlay.transform(m, pathForTurnOutlay); } @@ -166,6 +182,17 @@ public class NextTurnInfoWidget extends TextInfoWidget { canvas.drawPath(pathForTurnOutlay, paintBlack); canvas.drawPath(pathForTurn, paintRouteDirection); canvas.drawPath(pathForTurn, paintBlack); + if(textPaint != null ) { + if (turnType != null && !mini && turnType.getExitOut() > 0) { + canvas.drawText(turnType.getExitOut() + "", centerText.x, + centerText.y + textPaint.getTextSize() / 2, textPaint); + } + } + } + + public void setTextPaint(TextPaint textPaint) { + this.textPaint = textPaint; + this.textPaint.setTextAlign(Align.CENTER); } @Override @@ -186,7 +213,7 @@ public class NextTurnInfoWidget extends TextInfoWidget { public boolean setTurnType(TurnType turnType) { if(turnType != this.turnType) { this.turnType = turnType; - TurnPathHelper.calcTurnPath(pathForTurn, pathForTurnOutlay, turnType, null); + TurnPathHelper.calcTurnPath(pathForTurn, pathForTurnOutlay, turnType, null, centerText, mini); onBoundsChange(getBounds()); return true; } diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java index 6a02cb79be..7e290b957e 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java @@ -734,7 +734,7 @@ public class RouteInfoWidgetsFactory { return bearingControl; } - private static Path getPathFromTurnType(List paths, int laneType, Path defaultType, float coef) { + private static Path getPathFromTurnType(List paths, int laneType, Path defaultType, float coef, boolean mini) { if(laneType == 0) { return defaultType; } @@ -749,7 +749,7 @@ public class RouteInfoWidgetsFactory { Matrix pathTransform = new Matrix(); pathTransform.postScale(coef, coef ); TurnType tp = TurnType.valueOf(laneType, false); - TurnPathHelper.calcTurnPath(p, null, tp, pathTransform); + TurnPathHelper.calcTurnPath(p, null, tp, pathTransform, null, mini); paths.set(laneType, p); return p; } @@ -889,7 +889,7 @@ public class RouteInfoWidgetsFactory { leftSide = settings.DRIVING_REGION.get().leftHandDriving; this.scaleCoefficient = scaleCoefficent; - laneStraight = getPathFromTurnType(paths, TurnType.C, null, scaleCoefficient / miniCoeff); + laneStraight = getPathFromTurnType(paths, TurnType.C, null, scaleCoefficient / miniCoeff, true); laneStraightBitmap = TurnPathHelper.getBitmapFromTurnType(ctx.getResources(), bitmapCache, TurnType.C, 0, 0, TurnPathHelper.FIRST_TURN, scaleCoefficient / miniCoeff, leftSide); paintBlack = new Paint(); paintBlack.setStyle(Style.STROKE); @@ -1016,7 +1016,7 @@ public class RouteInfoWidgetsFactory { paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); turnType = TurnType.getPrimaryTurn(lanes[i]); } - Path p = getPathFromTurnType(paths, turnType, laneStraight, scaleCoefficient / miniCoeff); + Path p = getPathFromTurnType(paths, turnType, laneStraight, scaleCoefficient / miniCoeff, true); canvas.drawPath(p, paintBlack); canvas.drawPath(p, paintRouteDirection); canvas.translate(w, 0); diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/TextInfoWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/TextInfoWidget.java index f399c4632c..508c087d71 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/TextInfoWidget.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/TextInfoWidget.java @@ -23,7 +23,7 @@ public class TextInfoWidget { private TextView smallTextView; private TextView smallTextViewShadow; private ImageView topImageView; - private TextView topTextView; + protected TextView topTextView; private boolean explicitlyVisible; private OsmandApplication app;