Add next next turn. Fix small issues

This commit is contained in:
Victor Shcherb 2012-04-23 00:59:39 +02:00
parent 078bf3fc4b
commit 37bfd39b0e
9 changed files with 230 additions and 67 deletions

View file

@ -20,7 +20,7 @@
<folderInfo id="com.android.toolchain.gcc.128294115.2018451624" name="/" resourcePath="">
<toolChain id="com.android.toolchain.gcc.88177390" name="com.android.toolchain.gcc" superClass="com.android.toolchain.gcc">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.android.targetPlatform.998053113" name="Android Platform" osList="all" superClass="com.android.targetPlatform"/>
<builder arguments="${ANDROID_NDK}/ndk-build -j 8" command="sh" enableCleanBuild="false" enabledIncrementalBuild="true" id="com.android.builder.1130188873" incrementalBuildTarget="V=1" keepEnvironmentInBuildfile="false" managedBuildOn="false" superClass="com.android.builder">
<builder arguments="${ANDROID_NDK}/ndk-build" command="sh" enableCleanBuild="false" enabledIncrementalBuild="true" id="com.android.builder.1130188873" incrementalBuildTarget="V=1" keepEnvironmentInBuildfile="false" managedBuildOn="false" superClass="com.android.builder">
<outputEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="libs"/>
</outputEntries>

View file

@ -23,7 +23,7 @@
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value>${ANDROID_NDK}/ndk-build -j 8</value>
<value>${ANDROID_NDK}/ndk-build</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>

View file

@ -593,7 +593,7 @@ public class OsmandSettings {
{
ROTATE_MAP.setModeDefaultValue(ApplicationMode.CAR, ROTATE_MAP_BEARING);
ROTATE_MAP.setModeDefaultValue(ApplicationMode.BICYCLE, ROTATE_MAP_BEARING);
ROTATE_MAP.setModeDefaultValue(ApplicationMode.PEDESTRIAN, ROTATE_MAP_COMPASS);
ROTATE_MAP.setModeDefaultValue(ApplicationMode.PEDESTRIAN, ROTATE_MAP_BEARING);
}
// this value string is synchronized with settings_pref.xml preference name

View file

@ -126,8 +126,6 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
private Dialog progressDlg = null;
// App settings
private OsmandSettings settings;
// Store previous map rotation settings for rotate button
private Integer previousMapRotate = null;
private RouteAnimation routeAnimation = new RouteAnimation();
@ -938,14 +936,12 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
public void switchRotateMapMode(){
if(settings.ROTATE_MAP.get() != OsmandSettings.ROTATE_MAP_COMPASS){
previousMapRotate = settings.ROTATE_MAP.get();
settings.ROTATE_MAP.set(OsmandSettings.ROTATE_MAP_COMPASS);
} else if(previousMapRotate != null){
settings.ROTATE_MAP.set(previousMapRotate);
} else {
settings.ROTATE_MAP.set(settings.ROTATE_MAP.getProfileDefaultValue());
int vl = (settings.ROTATE_MAP.get() + 1) % 3;
Location loc = getLastKnownLocation();
if(vl == OsmandSettings.ROTATE_MAP_BEARING && (loc == null || !loc.hasBearing())){
vl = (vl + 1) % 3;
}
settings.ROTATE_MAP.set(vl);
registerUnregisterSensor(getLastKnownLocation());
if(settings.ROTATE_MAP.get() != OsmandSettings.ROTATE_MAP_COMPASS){
mapView.setRotate(0);

View file

@ -74,7 +74,6 @@ public class RoutingHelper {
// TODO vshcherb review !
private boolean makeUturnWhenPossible = false;
private boolean suppressTurnPrompt = false;
private int turnImminent = 0;
private long makeUTwpDetected = 0;
public boolean makeUturnWhenPossible() {
@ -85,11 +84,6 @@ public class RoutingHelper {
return suppressTurnPrompt;
}
public int turnImminent() {
return turnImminent;
}
public RoutingHelper(OsmandSettings settings, Context context, CommandPlayer player){
this.settings = settings;
@ -124,7 +118,6 @@ public class RoutingHelper {
listDistance = null;
directionInfo = null;
makeUturnWhenPossible = false;
turnImminent = 0;
evalWaitInterval = 3000;
uiHandler.post(new Runnable() {
@Override
@ -223,7 +216,6 @@ public class RoutingHelper {
if(finalLocation == null || currentLocation == null){
makeUturnWhenPossible = false;
suppressTurnPrompt = false;
turnImminent = 0;
return;
}
@ -373,7 +365,6 @@ public class RoutingHelper {
makeUturnWhenPossible = false;
suppressTurnPrompt = false;
if(finalLocation == null || currentLocation == null){
turnImminent = 0;
return;
}
// 6. + 7. Direction detection, by Hardy, Feb 2012
@ -399,7 +390,6 @@ public class RoutingHelper {
// require 5 sec since first detection, to avoid false positive announcements
} else if ((System.currentTimeMillis() - makeUTwpDetected > 5000)) {
makeUturnWhenPossible = true;
turnImminent = 1;
//log.info("bearingMotion is opposite to bearingRoute"); //$NON-NLS-1$
}
}
@ -503,7 +493,7 @@ public class RoutingHelper {
return Collections.emptyList();
}
public int getDistanceToNextRouteDirection() {
public synchronized int getDistanceToNextRouteDirection() {
if (directionInfo != null && currentDirectionInfo < directionInfo.size()) {
int dist = listDistance[currentRoute];
if (currentDirectionInfo < directionInfo.size() - 1) {
@ -512,25 +502,56 @@ public class RoutingHelper {
if (lastFixedLocation != null) {
dist += lastFixedLocation.distanceTo(routeNodes.get(currentRoute));
}
if (dist <= 100 || makeUturnWhenPossible == true) {
turnImminent = 1;
} else if (dist <= 3000) {
turnImminent = 0;
} else {
turnImminent = -1;
return dist;
}
return 0;
}
public synchronized int getNextTurnImminent() {
if (directionInfo != null && currentDirectionInfo < directionInfo.size()) {
if (makeUturnWhenPossible) {
return 1;
}
int dist = getDistanceToNextRouteDirection();
// Show turnImminent for at least 5 sec (changed to 6 for device delay) if moving, cut off at 300m to avoid speed artifacts
if (lastFixedLocation != null && lastFixedLocation.hasSpeed()) {
if ((dist < (lastFixedLocation.getSpeed() * 6f)) && (dist < 300)) {
turnImminent = 1;
return 1;
}
}
if (dist <= 140) {
return 1;
} else if (dist <= 3000) {
return 0;
} else {
return -1;
}
}
return 0;
}
public synchronized int getNextNextTurnImminent() {
if (directionInfo != null && currentDirectionInfo < directionInfo.size() - 1) {
int dist = getDistanceToNextNextRouteDirection();
if (dist <= 140) {
return 1;
} else if (dist <= 3000) {
return 0;
} else {
return -1;
}
}
return 0;
}
public synchronized int getDistanceToNextNextRouteDirection() {
if (directionInfo != null && currentDirectionInfo < directionInfo.size() - 1) {
int dist = listDistance[directionInfo.get(currentDirectionInfo + 1).routePointOffset];
if (currentDirectionInfo < directionInfo.size() - 2) {
dist -= listDistance[directionInfo.get(currentDirectionInfo + 2).routePointOffset];
}
return dist;
}
turnImminent = 0;
return 0;
}
@ -692,9 +713,11 @@ public class RoutingHelper {
public static final String TR = "TR"; // turn right //$NON-NLS-1$
public static final String TSLR = "TSLR"; // turn slightly right //$NON-NLS-1$
public static final String TSHR = "TSHR"; // turn sharply right //$NON-NLS-1$
public static final String KL = "KL"; // keep left //$NON-NLS-1$
public static final String KR = "KR"; // keep right//$NON-NLS-1$
public static final String TU = "TU"; // U-turn //$NON-NLS-1$
public static final String TRU = "TRU"; // Right U-turn //$NON-NLS-1$
public static String[] predefinedTypes = new String[] {C, TL, TSLL, TSHL, TR, TSLR, TSHR, TU, TRU};
public static String[] predefinedTypes = new String[] {C, KL, KR, TL, TSLL, TSHL, TR, TSLR, TSHR, TU, TRU};
public static TurnType valueOf(String s){

View file

@ -41,6 +41,8 @@ public class MapInfoLayer extends OsmandMapLayer {
private Paint paintText;
private Paint paintSubText;
private Paint paintSmallText;
private Paint paintSmallSubText;
private Paint paintImg;
private float cachedRotate = 0;
@ -61,6 +63,8 @@ public class MapInfoLayer extends OsmandMapLayer {
private ViewGroup statusBar;
public MapInfoLayer(MapActivity map, RouteLayer layer){
this.map = map;
this.routeLayer = layer;
@ -89,9 +93,21 @@ public class MapInfoLayer extends OsmandMapLayer {
paintSubText.setStyle(Style.FILL_AND_STROKE);
paintSubText.setColor(Color.BLACK);
paintSubText.setTextSize(15 * scaleCoefficient);
paintSubText.setAntiAlias(true);
paintSmallText = new Paint();
paintSmallText.setStyle(Style.FILL_AND_STROKE);
paintSmallText.setColor(Color.BLACK);
paintSmallText.setTextSize(15 * scaleCoefficient);
paintSmallText.setAntiAlias(true);
paintSmallText.setStrokeWidth(4);
paintSmallSubText = new Paint();
paintSmallSubText.setStyle(Style.FILL_AND_STROKE);
paintSmallSubText.setColor(Color.BLACK);
paintSmallSubText.setTextSize(12 * scaleCoefficient);
paintSmallSubText.setAntiAlias(true);
paintImg = new Paint();
paintImg.setDither(true);
paintImg.setFilterBitmap(true);
@ -139,6 +155,7 @@ public class MapInfoLayer extends OsmandMapLayer {
leftStack = new MapStackControl(view.getContext());
leftStack.addStackView(createNextInfoControl());
leftStack.addStackView(createMiniMapControl());
leftStack.addStackView(createNextNextInfoControl());
// 2. Preparations
Rect topRectPadding = new Rect();
@ -401,7 +418,7 @@ public class MapInfoLayer extends OsmandMapLayer {
}
private MiniMapControl createMiniMapControl() {
MiniMapControl miniMapControl = new MiniMapControl(map, view) {
final MiniMapControl miniMapControl = new MiniMapControl(map, view) {
@Override
public boolean updateInfo() {
boolean visible = false;
@ -420,17 +437,81 @@ public class MapInfoLayer extends OsmandMapLayer {
@Override
public void onClick(View v) {
showMiniMap = false;
miniMapControl.invalidate();
view.refreshMap();
}
});
return miniMapControl;
}
private NextTurnInfoControl createNextNextInfoControl() {
final RoutingHelper routingHelper = routeLayer.getHelper();
final NextTurnInfoControl nextTurnInfo = new NextTurnInfoControl(map, paintSmallText, paintSmallSubText, true) {
@Override
public boolean updateInfo() {
boolean visible = false;
if (routeLayer != null && routingHelper.isRouterEnabled() && routingHelper.isFollowingMode()) {
int d = routingHelper.getDistanceToNextNextRouteDirection();
if (d > 0 && !showMiniMap) {
visible = true;
RouteDirectionInfo next = routingHelper.getNextNextRouteDirectionInfo();
if (next == null) {
if (turnType != null) {
turnType = null;
invalidate();
}
} else if (!Algoritms.objectEquals(turnType, next.turnType)) {
turnType = next.turnType;
TurnPathHelper.calcTurnPath(pathForTurn, turnType, pathTransform);
invalidate();
}
if (distChanged(d, nextTurnDirection)) {
invalidate();
nextTurnDirection = d;
}
if (turnImminent != routingHelper.getNextNextTurnImminent()) {
turnImminent = routingHelper.getNextNextTurnImminent();
invalidate();
}
}
}
updateVisibility(visible);
return true;
}
};
nextTurnInfo.setOnClickListener(new View.OnClickListener() {
// int i = 0;
@Override
public void onClick(View v) {
// uncomment to test turn info rendering
// final int l = TurnType.predefinedTypes.length;
// final int exits = 5;
// i++;
// if (i % (l + exits) >= l ) {
// nextTurnInfo.turnType = TurnType.valueOf("EXIT" + (i % (l + exits) - l + 1));
// nextTurnInfo.exitOut = (i % (l + exits) - l + 1)+"";
// float a = 180 - (i % (l + exits) - l + 1) * 50;
// nextTurnInfo.turnType.setTurnAngle(a < 0 ? a + 360 : a);
// } else {
// nextTurnInfo.turnType = TurnType.valueOf(TurnType.predefinedTypes[i % (TurnType.predefinedTypes.length + exits)]);
// nextTurnInfo.exitOut = "";
// }
// nextTurnInfo.turnImminent = (nextTurnInfo.turnImminent + 1) % 3;
// nextTurnInfo.nextTurnDirection = 580;
// TurnPathHelper.calcTurnPath(nextTurnInfo.pathForTurn, nextTurnInfo.turnType,nextTurnInfo.pathTransform);
showMiniMap = true;
view.refreshMap();
}
});
// initial state
nextTurnInfo.setVisibility(View.GONE);
return nextTurnInfo;
}
private NextTurnInfoControl createNextInfoControl() {
final RoutingHelper routingHelper = routeLayer.getHelper();
final NextTurnInfoControl nextTurnInfo = new NextTurnInfoControl(map, paintText, paintSubText) {
final NextTurnInfoControl nextTurnInfo = new NextTurnInfoControl(map, paintText, paintSubText, false) {
@Override
public boolean updateInfo() {
boolean visible = false;
@ -468,8 +549,8 @@ public class MapInfoLayer extends OsmandMapLayer {
invalidate();
nextTurnDirection = d;
}
if(turnImminent != routingHelper.turnImminent()){
turnImminent = routingHelper.turnImminent();
if(turnImminent != routingHelper.getNextTurnImminent()){
turnImminent = routingHelper.getNextTurnImminent();
invalidate();
}
}
@ -491,10 +572,14 @@ public class MapInfoLayer extends OsmandMapLayer {
// nextTurnInfo.turnType = TurnType.valueOf("EXIT" + (i % (l + exits) - l + 1));
// float a = 180 - (i % (l + exits) - l + 1) * 50;
// nextTurnInfo.turnType.setTurnAngle(a < 0 ? a + 360 : a);
// nextTurnInfo.exitOut = (i % (l + exits) - l + 1)+"";
// } else {
// nextTurnInfo.turnType = TurnType.valueOf(TurnType.predefinedTypes[i % (TurnType.predefinedTypes.length + exits)]);
// nextTurnInfo.exitOut = "";
// }
nextTurnInfo.invalidate();
// nextTurnInfo.turnImminent = (nextTurnInfo.turnImminent + 1) % 3;
// nextTurnInfo.nextTurnDirection = 580;
// TurnPathHelper.calcTurnPath(nextTurnInfo.pathForTurn, nextTurnInfo.turnType,nextTurnInfo.pathTransform);
showMiniMap = true;
view.refreshMap();
}

View file

@ -137,8 +137,9 @@ public class MapStackControl extends ViewGroup {
int cacheStack = 0;
if (stackViews != null) {
for (MapInfoControl c : stackViews) {
cacheStack++;
if (c.getVisibility() != View.GONE) {
c.setBackgroundDrawable(first ? topDrawable : getStackDrawable(cacheStack++ ));
c.setBackgroundDrawable(first ? topDrawable : getStackDrawable(cacheStack));
first = false;
c.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
w = Math.max(w, c.getMeasuredWidth());
@ -152,10 +153,11 @@ public class MapStackControl extends ViewGroup {
}
isCollapsible = false;
for (MapInfoControl c : collapsedViews) {
cacheStack++;
if (c.getVisibility() != View.GONE) {
isCollapsible = true;
if (!isCollapsed) {
c.setBackgroundDrawable(first ? topDrawable : getStackDrawable(cacheStack++ ));
c.setBackgroundDrawable(first ? topDrawable : getStackDrawable(cacheStack));
first = false;
c.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
w = Math.max(w, c.getMeasuredWidth());

View file

@ -1,9 +1,7 @@
package net.osmand.plus.views;
import net.osmand.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.TurnType;
import android.content.Context;
import android.graphics.Canvas;
@ -18,8 +16,9 @@ import android.graphics.Path;
public class NextTurnInfoControl extends MapInfoControl {
private float scaleCoefficient = MapInfoLayer.scaleCoefficient;
private final float width = 72 * scaleCoefficient;
private final float height = 75 * scaleCoefficient;
private final float width;
private final float height ;
private static final float miniCoeff = 2.5f;
protected Path pathForTurn = new Path();
@ -27,6 +26,7 @@ public class NextTurnInfoControl extends MapInfoControl {
protected String exitOut = null;
protected int nextTurnDirection = 0;
private final Paint textPaint;
private final Paint subtextPaint;
private Paint paintBlack;
@ -34,11 +34,13 @@ public class NextTurnInfoControl extends MapInfoControl {
protected boolean makeUturnWhenPossible;
protected int turnImminent;
private final boolean horisontalMini;
public NextTurnInfoControl(Context ctx, Paint textPaint, Paint subtextPaint) {
public NextTurnInfoControl(Context ctx, Paint textPaint, Paint subtextPaint, boolean horisontalMini) {
super(ctx);
this.textPaint = textPaint;
this.subtextPaint = subtextPaint;
this.horisontalMini = horisontalMini;
paintBlack = new Paint();
paintBlack.setStyle(Style.STROKE);
@ -52,15 +54,31 @@ public class NextTurnInfoControl extends MapInfoControl {
paintRouteDirection.setAntiAlias(true);
pathTransform = new Matrix();
if (horisontalMini) {
pathTransform.postScale(scaleCoefficient / miniCoeff, scaleCoefficient / miniCoeff);
width = 72 * scaleCoefficient / miniCoeff;
height = 72 * scaleCoefficient / miniCoeff;
} else {
pathTransform.postScale(scaleCoefficient, scaleCoefficient);
width = 72 * scaleCoefficient;
height = 72 * scaleCoefficient;
}
}
protected Matrix pathTransform = new Matrix();
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int h = (int) (5 * scaleCoefficient + Math.max(textPaint.getTextSize(), subtextPaint.getTextSize()));
setWDimensions((int) width, (int) height + h);
int h = 0;
int w = 0;
if (!horisontalMini) {
h = (int) (8 * scaleCoefficient + Math.max(textPaint.getTextSize(), subtextPaint.getTextSize()));
} else {
h = (int) (6 * scaleCoefficient);
w = (int) textPaint.measureText(OsmAndFormatter.getFormattedDistance(nextTurnDirection, getContext()));
}
setWDimensions((int) width + w, (int) height + h);
}
@Override
@ -78,7 +96,7 @@ public class NextTurnInfoControl extends MapInfoControl {
canvas.translate(0, 3 * scaleCoefficient);
canvas.drawPath(pathForTurn, paintRouteDirection);
canvas.drawPath(pathForTurn, paintBlack);
if (exitOut != null) {
if (exitOut != null && !horisontalMini) {
drawShadowText(canvas, exitOut, (getWWidth()) / 2 - 7 * scaleCoefficient,
getWHeight() / 2 - textPaint.getTextSize() / 2 + 3 * scaleCoefficient, textPaint);
}
@ -97,11 +115,20 @@ public class NextTurnInfoControl extends MapInfoControl {
st = textPaint.measureText(subtext);
}
float mt = textPaint.measureText(text);
if (!horisontalMini) {
float startX = Math.max((getWWidth() - st - mt) / 2, 2 * scaleCoefficient);
drawShadowText(canvas, text, startX, getWHeight() - 5 * scaleCoefficient, textPaint);
if (subtext != null) {
drawShadowText(canvas, subtext, startX + 2 * scaleCoefficient + mt, getWHeight() - 5 * scaleCoefficient, subtextPaint);
}
} else {
drawShadowText(canvas, text, 72 * scaleCoefficient / miniCoeff + 2 * scaleCoefficient,
height / 2 + 5 * scaleCoefficient, textPaint);
if (subtext != null) {
drawShadowText(canvas, subtext, 72 * scaleCoefficient / miniCoeff + mt
+ 2 * scaleCoefficient, height / 2 + 5 * scaleCoefficient, subtextPaint);
}
}
}
}

View file

@ -27,7 +27,7 @@ public class TurnPathHelper {
int th = 12; // thickness
pathForTurn.moveTo(wa / 2, ha - 1);
float sarrowL = 23; // side of arrow ?
float sarrowL = 22; // side of arrow ?
float harrowL = (float) Math.sqrt(2) * sarrowL; // hypotenuse of arrow
float spartArrowL = (float) ((sarrowL - th / Math.sqrt(2)) / 2);
float hpartArrowL = (float) (harrowL - th) / 2;
@ -43,8 +43,8 @@ public class TurnPathHelper {
pathForTurn.rLineTo(0, h);
} else if (TurnType.TR.equals(turnType.getValue())|| TurnType.TL.equals(turnType.getValue())) {
int b = TurnType.TR.equals(turnType.getValue())? 1 : -1;
float quadShiftX = 22;
float quadShiftY = 22;
float quadShiftX = 18;
float quadShiftY = 18;
int wl = 10; // width
int h = (int) (ha - quadShiftY - harrowL + hpartArrowL - 5);
int sl = wl + th / 2;
@ -62,6 +62,36 @@ public class TurnPathHelper {
pathForTurn.rLineTo(-b * wl, 0);
pathForTurn.rQuadTo(-b * (quadShiftX + th), 0, -b * (quadShiftX + th), quadShiftY + th);
pathForTurn.rLineTo(0, h);
} else if (TurnType.KL.equals(turnType.getValue()) || TurnType.KR.equals(turnType.getValue())) {
int b = TurnType.KR.equals(turnType.getValue())? 1 : -1;
float quadShiftX = 14;
float quadShiftY = 14;
th = 10;
spartArrowL = (float) ((sarrowL - th / Math.sqrt(2)) / 2);
hpartArrowL = (float) (harrowL - th) / 2;
int h = 12;
int lh = 15;
int sl = th / 2;
pathForTurn.rMoveTo(-b * (sl + 10), 0);
pathForTurn.rLineTo(0, -lh);
// 1st arc
pathForTurn.rQuadTo(0, -quadShiftY, b * quadShiftX, -quadShiftY);
// 2nd arc
pathForTurn.rQuadTo(b * quadShiftX, 0, b * quadShiftX, -quadShiftY);
// center
pathForTurn.rLineTo(0, -h);
pathForTurn.rLineTo(b*hpartArrowL, 0);
pathForTurn.rLineTo(-b*harrowL / 2, -harrowL / 2); // center
pathForTurn.rLineTo(-b*harrowL / 2, harrowL / 2);
pathForTurn.rLineTo(b*hpartArrowL, 0);
pathForTurn.rLineTo(0, h );
// 2nd arc
pathForTurn.rQuadTo(0, quadShiftY - th, -b * (quadShiftX - th), quadShiftY- th);
//1st arc
pathForTurn.rQuadTo(-b * (quadShiftX + th), 0, -b * (quadShiftX + th ), quadShiftY + th);
pathForTurn.rLineTo(0, lh );
} else if (TurnType.TSLR.equals(turnType.getValue()) || TurnType.TSLL.equals(turnType.getValue())) {
int b = TurnType.TSLR.equals(turnType.getValue()) ? 1 : -1;
int h = 24;