Ticket #12524: LatLonHeadingFix.patch

File LatLonHeadingFix.patch, 6.9 KB (added by kolesar, 10 years ago)
  • src/org/openstreetmap/josm/data/coor/LatLon.java

    diff --git a/src/org/openstreetmap/josm/data/coor/LatLon.java b/src/org/openstreetmap/josm/data/coor/LatLon.java
    index fcb9435..c963f26 100644
    a b public class LatLon extends Coordinate {  
    326326    }
    327327
    328328    /**
    329      * Returns the heading, in radians, that you have to use to get from this lat/lon to another.
     329     * Returns the heading that you have to use to get from this lat/lon to another.
     330     *
     331     * Angle starts from north and increases counterclockwise (!), PI/2 means west.
     332     * You can get usual clockwise angle from {@link #bearing(LatLon)} method.
     333     * This method is kept as deprecated because it is called from many plugins.
    330334     *
    331335     * (I don't know the original source of this formula, but see
    332336     * <a href="https://math.stackexchange.com/questions/720/how-to-calculate-a-heading-on-the-earths-surface">this question</a>
    333337     * for some hints how it is derived.)
    334338     *
     339     * @deprecated see bearing method
    335340     * @param other the "destination" position
    336      * @return heading in the range 0 &lt;= hd &lt; 2*PI
     341     * @return heading in radians in the range 0 &lt;= hd &lt; 2*PI
    337342     */
     343    @Deprecated
    338344    public double heading(LatLon other) {
    339345        double hd = atan2(sin(toRadians(this.lon() - other.lon())) * cos(toRadians(other.lat())),
    340346                cos(toRadians(this.lat())) * sin(toRadians(other.lat())) -
    public class LatLon extends Coordinate {  
    347353    }
    348354
    349355    /**
     356     * Returns bearing from this point to another.
     357     *
     358     * Angle starts from north and increases clockwise, PI/2 means east.
     359     * Old deprecated method {@link #heading(LatLon)} used unusual reverse angle.
     360     *
     361     * Please note that reverse bearing (from other point to this point) should NOT be
     362     * calculated from return value of this method, because great circle path
     363     * between the two points have different bearings at each position.
     364     *
     365     * To get bearing from another point to this point call other.bearing(this)
     366     *
     367     * @param other the "destination" position
     368     * @return heading in radians in the range 0 &lt;= hd &lt; 2*PI
     369     */
     370    public double bearing(LatLon other) {
     371        double lat1 = toRadians(this.lat());
     372        double lat2 = toRadians(other.lat());
     373        double dlon = toRadians(other.lon() - this.lon());
     374        double bearing = atan2(
     375            sin(dlon) * cos(lat2),
     376            cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon)
     377        );
     378        bearing %= 2 * PI;
     379        if (bearing < 0) {
     380            bearing += 2 * PI;
     381        }
     382        return bearing;
     383    }
     384
     385    /**
    350386     * Returns this lat/lon pair in human-readable format.
    351387     *
    352388     * @return String in the format "lat=1.23456 deg, lon=2.34567 deg"
  • src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java b/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
    index ed925af..2ca6174 100644
    a b public class GpxDrawHelper {  
    8888    private static final int sl4 = 5;
    8989    private static final int sl9 = 3;
    9090    private static final int[][] dir = {
    91         {+sl4, +ll0, +ll0, +sl4}, {-sl9, +ll0, +sl9, +ll0}, {-ll0, +sl4, -sl4, +ll0},
    92         {-ll0, -sl9, -ll0, +sl9}, {-sl4, -ll0, -ll0, -sl4}, {+sl9, -ll0, -sl9, -ll0},
    93         {+ll0, -sl4, +sl4, -ll0}, {+ll0, +sl9, +ll0, -sl9}, {+sl4, +ll0, +ll0, +sl4},
    94         {-sl9, +ll0, +sl9, +ll0}, {-ll0, +sl4, -sl4, +ll0}, {-ll0, -sl9, -ll0, +sl9}};
     91        {+sl4, +ll0, +ll0, +sl4}, {-sl9, +ll0, +sl9, +ll0},
     92        {-ll0, +sl4, -sl4, +ll0}, {-ll0, -sl9, -ll0, +sl9},
     93        {-sl4, -ll0, -ll0, -sl4}, {+sl9, -ll0, -sl9, -ll0},
     94        {+ll0, -sl4, +sl4, -ll0}, {+ll0, +sl9, +ll0, -sl9}
     95    };
    9596
    9697    private void setupColors() {
    9798        hdopAlpha = Main.pref.getInteger("hdop.color.alpha", -1);
    public class GpxDrawHelper {  
    332333                        }
    333334                        break;
    334335                    case DIRECTION:
    335                         double dirColor = oldWp.getCoor().heading(trkPnt.getCoor());
     336                        double dirColor = oldWp.getCoor().bearing(trkPnt.getCoor());
    336337                        color = directionScale.getColor(dirColor);
    337338                        break;
    338339                    case TIME:
    public class GpxDrawHelper {  
    347348                    }
    348349                    if (!noDraw && (maxLineLength == -1 || dist <= maxLineLength)) {
    349350                        trkPnt.drawLine = true;
    350                         trkPnt.dir = (int) oldWp.getCoor().heading(trkPnt.getCoor());
     351                        double bearing = oldWp.getCoor().bearing(trkPnt.getCoor());
     352                        trkPnt.dir = ((int) (bearing / Math.PI * 4 + 1.5)) % 8;
    351353                    } else {
    352354                        trkPnt.drawLine = false;
    353355                    }
  • src/org/openstreetmap/josm/tools/ColorScale.java

    diff --git a/src/org/openstreetmap/josm/tools/ColorScale.java b/src/org/openstreetmap/josm/tools/ColorScale.java
    index ea3b5ac..f2e482c 100644
    a b public final class ColorScale {  
    4444        sc.colors = new Color[count];
    4545        for (int i = 0; i < sc.colors.length; i++) {
    4646
    47             float angle = 4 - i / 256f * 4;
     47            float angle = i / 256f * 4;
    4848            int quadrant = (int) angle;
    4949            angle -= quadrant;
    5050            quadrant = Utils.mod(quadrant+1, 4);
  • test/unit/org/openstreetmap/josm/data/coor/LatLonTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/coor/LatLonTest.java b/test/unit/org/openstreetmap/josm/data/coor/LatLonTest.java
    index 74cdcf0..a0ef2d0 100644
    a b import org.junit.Test;  
    1010 */
    1111public class LatLonTest {
    1212
     13    private static final double EPSILON = 1e-6;
     14
    1315    public static final double[] SAMPLE_VALUES = new double[]{
    1416            -180.0, -179.9, -179.6, -179.5, -179.4, -179.1, -179.0, -100.0, -99.9, -10.0, -9.9, -1.0, -0.1,
    1517            180.0,  179.9,  179.6,  179.5,  179.4,  179.1,  179.0,  100.0,  99.9,  10.0,  9.9,  1.0,  0.1,
    public class LatLonTest {  
    123125            assertEquals(a.hashCode(), b.hashCode());
    124126        }
    125127    }
     128
     129    /**
     130     * Test of {@link LatLon#bearing}
     131     */
     132    @Test
     133    public void testBearing() {
     134        LatLon c = new LatLon(47.000000, 19.000000);
     135        LatLon e = new LatLon(47.000000, 19.000001);
     136        LatLon n = new LatLon(47.000001, 19.000000);
     137        assertEquals(  0, Math.toDegrees(c.bearing(n)), EPSILON);
     138        assertEquals( 90, Math.toDegrees(c.bearing(e)), EPSILON);
     139        assertEquals(180, Math.toDegrees(n.bearing(c)), EPSILON);
     140        assertEquals(270, Math.toDegrees(e.bearing(c)), EPSILON);
     141    }
    126142}