aboutsummaryrefslogtreecommitdiffstats
path: root/src/cgeo/geocaching/cgCompass.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgeo/geocaching/cgCompass.java')
-rw-r--r--src/cgeo/geocaching/cgCompass.java157
1 files changed, 50 insertions, 107 deletions
diff --git a/src/cgeo/geocaching/cgCompass.java b/src/cgeo/geocaching/cgCompass.java
index 4a004b3..7ecee4b 100644
--- a/src/cgeo/geocaching/cgCompass.java
+++ b/src/cgeo/geocaching/cgCompass.java
@@ -15,18 +15,16 @@ import android.view.View;
public class cgCompass extends View {
private changeThread watchdog = null;
- private boolean wantStop = false;
- private boolean lock = false;
- private boolean drawing = false;
+ private volatile boolean wantStop = false;
private Context context = null;
private Bitmap compassUnderlay = null;
private Bitmap compassRose = null;
private Bitmap compassArrow = null;
private Bitmap compassOverlay = null;
- private Double azimuth = Double.valueOf(0);
- private Double heading = Double.valueOf(0);
- private Double cacheHeading = Double.valueOf(0);
- private Double northHeading = Double.valueOf(0);
+ private double azimuth = 0.0;
+ private double heading = 0.0;
+ private double cacheHeading = 0.0;
+ private double northHeading = 0.0;
private PaintFlagsDrawFilter setfil = null;
private PaintFlagsDrawFilter remfil = null;
private int compassUnderlayWidth = 0;
@@ -105,11 +103,40 @@ public class cgCompass extends View {
}
}
- protected void updateNorth(Double northHeadingIn, Double cacheHeadingIn) {
+ protected synchronized void updateNorth(double northHeadingIn, double cacheHeadingIn) {
northHeading = northHeadingIn;
cacheHeading = cacheHeadingIn;
}
+ /**
+ * Compute the new value, moving by small increments.
+ * @param goal the goal to reach
+ * @param actual the actual value
+ * @return the new value
+ */
+ static protected double smoothUpdate(double goal, double actual) {
+ double diff = goal - actual;
+ final boolean largeDiff = Math.abs(diff) > 5;
+
+ double offset = 0.0;
+
+ if (diff < 0.0) {
+ diff = diff + 360.0;
+ } else if (diff >= 360.0) {
+ diff = diff - 360.0;
+ }
+
+ // If the difference is smaller than 1 degree, do nothing as it
+ // causes the arrow to vibrate.
+ if (diff > 1.0 && diff <= 180.0) {
+ offset = largeDiff ? 2.0 : 1.0;
+ } else if (diff > 180.0 && diff < 359.0) {
+ offset = largeDiff ? -2.0 : -1.0;
+ }
+
+ return actual + offset;
+ }
+
private class changeThread extends Thread {
@Override
@@ -121,93 +148,11 @@ public class cgCompass extends View {
// nothing
}
- if (Math.abs(azimuth - northHeading) < 2 && Math.abs(heading - cacheHeading) < 2) {
- continue;
- }
-
- lock = true;
-
- Double diff = Double.valueOf(0);
- Double diffAbs = Double.valueOf(0);
- Double tempAzimuth = Double.valueOf(0);
- Double tempHeading = Double.valueOf(0);
-
- Double actualAzimuth = azimuth;
- Double actualHeading = heading;
-
- diff = northHeading - actualAzimuth;
- diffAbs = Math.abs(northHeading - actualAzimuth);
- if (diff < 0) {
- diff = diff + 360;
- } else if (diff >= 360) {
- diff = diff - 360;
- }
-
- if (diff > 0 && diff <= 180) {
- if (diffAbs > 5) {
- tempAzimuth = actualAzimuth + 2;
- } else if (diffAbs > 1) {
- tempAzimuth = actualAzimuth + 1;
- } else {
- tempAzimuth = actualAzimuth;
- }
- } else if (diff > 180 && diff < 360) {
- if (diffAbs > 5) {
- tempAzimuth = actualAzimuth - 2;
- } else if (diffAbs > 1) {
- tempAzimuth = actualAzimuth - 1;
- } else {
- tempAzimuth = actualAzimuth;
- }
- } else {
- tempAzimuth = actualAzimuth;
+ synchronized(cgCompass.this) {
+ azimuth = smoothUpdate(northHeading, azimuth);
+ heading = smoothUpdate(cacheHeading, heading);
}
- diff = cacheHeading - actualHeading;
- diffAbs = Math.abs(cacheHeading - actualHeading);
- if (diff < 0) {
- diff = diff + 360;
- } else if (diff >= 360) {
- diff = diff - 360;
- }
-
- if (diff > 0 && diff <= 180) {
- if (diffAbs > 5) {
- tempHeading = actualHeading + 2;
- } else if (diffAbs > 1) {
- tempHeading = actualHeading + 1;
- } else {
- tempHeading = actualHeading;
- }
- } else if (diff > 180 && diff < 360) {
- if (diffAbs > 5) {
- tempHeading = actualHeading - 2;
- } else if (diffAbs > 1) {
- tempHeading = actualHeading - 1;
- } else {
- tempHeading = actualHeading;
- }
- } else {
- tempHeading = actualHeading;
- }
-
- if (tempAzimuth >= 360) {
- tempAzimuth = tempAzimuth - 360;
- } else if (tempAzimuth < 0) {
- tempAzimuth = tempAzimuth + 360;
- }
-
- if (tempHeading >= 360) {
- tempHeading = tempHeading - 360;
- } else if (tempHeading < 0) {
- tempHeading = tempHeading + 360;
- }
-
- azimuth = tempAzimuth;
- heading = tempHeading;
-
- lock = false;
-
changeHandler.sendMessage(new Message());
}
}
@@ -215,15 +160,16 @@ public class cgCompass extends View {
@Override
protected void onDraw(Canvas canvas) {
- if (lock) {
- return;
- }
- if (drawing) {
- return;
+ double currentAzimuth;
+ double currentHeading;
+
+ synchronized(this) {
+ currentAzimuth = azimuth;
+ currentHeading = heading;
}
- Double azimuthTemp = azimuth;
- Double azimuthRelative = azimuthTemp - heading;
+ double azimuthTemp = currentAzimuth;
+ double azimuthRelative = azimuthTemp - currentHeading;
if (azimuthRelative < 0) {
azimuthRelative = azimuthRelative + 360;
} else if (azimuthRelative >= 360) {
@@ -237,7 +183,6 @@ public class cgCompass extends View {
int marginLeftTemp = 0;
int marginTopTemp = 0;
- drawing = true;
super.onDraw(canvas);
canvas.save();
@@ -251,16 +196,16 @@ public class cgCompass extends View {
marginLeftTemp = (getWidth() - compassRoseWidth) / 2;
marginTopTemp = (getHeight() - compassRoseHeight) / 2;
- canvas.rotate(-(azimuthTemp.floatValue()), canvasCenterX, canvasCenterY);
+ canvas.rotate((float) -azimuthTemp, canvasCenterX, canvasCenterY);
canvas.drawBitmap(compassRose, marginLeftTemp, marginTopTemp, null);
- canvas.rotate(azimuthTemp.floatValue(), canvasCenterX, canvasCenterY);
+ canvas.rotate((float) azimuthTemp, canvasCenterX, canvasCenterY);
marginLeftTemp = (getWidth() - compassArrowWidth) / 2;
marginTopTemp = (getHeight() - compassArrowHeight) / 2;
- canvas.rotate(-(azimuthRelative.floatValue()), canvasCenterX, canvasCenterY);
+ canvas.rotate((float) -azimuthRelative, canvasCenterX, canvasCenterY);
canvas.drawBitmap(compassArrow, marginLeftTemp, marginTopTemp, null);
- canvas.rotate(azimuthRelative.floatValue(), canvasCenterX, canvasCenterY);
+ canvas.rotate((float) azimuthRelative, canvasCenterX, canvasCenterY);
marginLeftTemp = (getWidth() - compassOverlayWidth) / 2;
marginTopTemp = (getHeight() - compassOverlayHeight) / 2;
@@ -269,8 +214,6 @@ public class cgCompass extends View {
canvas.setDrawFilter(remfil);
canvas.restore();
-
- drawing = false;
}
@Override