diff --git a/src/org/openstreetmap/josm/actions/CreateCircleAction.java b/src/org/openstreetmap/josm/actions/CreateCircleAction.java
index a8488ae92e..6ecbefdf72 100644
--- a/src/org/openstreetmap/josm/actions/CreateCircleAction.java
+++ b/src/org/openstreetmap/josm/actions/CreateCircleAction.java
@@ -191,10 +191,9 @@ public final class CreateCircleAction extends JosmAction {
         double r = n1.distance(center);
 
         // see #10777
-        LatLon ll1 = ProjectionRegistry.getProjection().eastNorth2latlon(n1);
         LatLon ll2 = ProjectionRegistry.getProjection().eastNorth2latlon(center);
 
-        double radiusInMeters = ll1.greatCircleDistance(ll2);
+        double radiusInMeters = nodes.get(0).greatCircleDistance(ll2);
 
         int numberOfNodesInCircle = (int) Math.ceil(6.0 * Math.pow(radiusInMeters, 0.5));
         // an odd number of nodes makes the distribution uneven
diff --git a/src/org/openstreetmap/josm/actions/mapmode/DrawSnapHelper.java b/src/org/openstreetmap/josm/actions/mapmode/DrawSnapHelper.java
index 59992ac1eb..f09960ebbd 100644
--- a/src/org/openstreetmap/josm/actions/mapmode/DrawSnapHelper.java
+++ b/src/org/openstreetmap/josm/actions/mapmode/DrawSnapHelper.java
@@ -388,7 +388,7 @@ class DrawSnapHelper {
 
         // find out the distance, in metres, between the base point and projected point
         LatLon mouseLatLon = mapView.getProjection().eastNorth2latlon(snapPoint);
-        double distance = this.drawAction.getCurrentBaseNode().getCoor().greatCircleDistance(mouseLatLon);
+        double distance = this.drawAction.getCurrentBaseNode().greatCircleDistance(mouseLatLon);
         double hdg = Utils.toDegrees(p0.heading(snapPoint));
         // heading of segment from current to calculated point, not to mouse position
 
diff --git a/src/org/openstreetmap/josm/command/MoveCommand.java b/src/org/openstreetmap/josm/command/MoveCommand.java
index b2bf3a2d02..9d8a333627 100644
--- a/src/org/openstreetmap/josm/command/MoveCommand.java
+++ b/src/org/openstreetmap/josm/command/MoveCommand.java
@@ -15,6 +15,7 @@ import java.util.function.Predicate;
 import javax.swing.Icon;
 
 import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.ILatLon;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
@@ -313,12 +314,12 @@ public class MoveCommand extends Command {
     public double getDistance(Predicate<Node> predicate) {
         return nodes.stream()
                 .filter(predicate)
-                .filter(node -> node.getCoor() != null && node.getEastNorth() != null)
+                .filter(ILatLon::isLatLonKnown /* If the node latlon is known, then the eastnorth cannot be null */)
                 .findFirst()
                 .map(node -> {
                     final Node old = new Node(node);
                     old.setEastNorth(old.getEastNorth().add(-x, -y));
-                    return node.getCoor().greatCircleDistance(old.getCoor());
+                    return node.greatCircleDistance(old);
                 }).orElse(Double.NaN);
     }
 
diff --git a/src/org/openstreetmap/josm/data/coor/ILatLon.java b/src/org/openstreetmap/josm/data/coor/ILatLon.java
index 45498b5cf6..3891ad57b7 100644
--- a/src/org/openstreetmap/josm/data/coor/ILatLon.java
+++ b/src/org/openstreetmap/josm/data/coor/ILatLon.java
@@ -1,7 +1,17 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.data.coor;
 
+import static java.lang.Math.PI;
+import static java.lang.Math.asin;
+import static java.lang.Math.atan2;
+import static java.lang.Math.cos;
+import static java.lang.Math.sin;
+import static java.lang.Math.sqrt;
+import static org.openstreetmap.josm.data.projection.Ellipsoid.WGS84;
+import static org.openstreetmap.josm.tools.Utils.toRadians;
+
 import org.openstreetmap.josm.data.projection.Projecting;
+import org.openstreetmap.josm.tools.Logging;
 
 /**
  * This interface represents a coordinate in LatLon space.
@@ -80,4 +90,57 @@ public interface ILatLon {
         double p = precision / 2;
         return Math.abs(lat() - other.lat()) <= p && Math.abs(lon() - other.lon()) <= p;
     }
+
+    /**
+     * Computes the distance between this lat/lon and another point on the earth.
+     * Uses <a href="https://en.wikipedia.org/wiki/Haversine_formula">Haversine formula</a>.
+     * @param other the other point.
+     * @return distance in metres.
+     * @since xxx (extracted from {@link LatLon})
+     */
+    default double greatCircleDistance(ILatLon other) {
+        double sinHalfLat = sin(toRadians(other.lat() - this.lat()) / 2);
+        double sinHalfLon = sin(toRadians(other.lon() - this.lon()) / 2);
+        double d = 2 * WGS84.a * asin(
+                sqrt(sinHalfLat*sinHalfLat +
+                        cos(toRadians(this.lat()))*cos(toRadians(other.lat()))*sinHalfLon*sinHalfLon));
+        // For points opposite to each other on the sphere,
+        // rounding errors could make the argument of asin greater than 1
+        // (This should almost never happen.)
+        if (Double.isNaN(d)) {
+            Logging.error("NaN in greatCircleDistance: {0} {1}", this, other);
+            d = PI * WGS84.a;
+        }
+        return d;
+    }
+
+    /**
+     * Returns bearing from this point to another.
+     *
+     * Angle starts from north and increases clockwise, PI/2 means east.
+     *
+     * Please note that reverse bearing (from other point to this point) should NOT be
+     * calculated from return value of this method, because great circle path
+     * between the two points have different bearings at each position.
+     *
+     * To get bearing from another point to this point call other.bearing(this)
+     *
+     * @param other the "destination" position
+     * @return heading in radians in the range 0 &lt;= hd &lt; 2*PI
+     * @since xxx (extracted from {@link LatLon}, added in 9796)
+     */
+    default double bearing(ILatLon other) {
+        double lat1 = toRadians(this.lat());
+        double lat2 = toRadians(other.lat());
+        double dlon = toRadians(other.lon() - this.lon());
+        double bearing = atan2(
+                sin(dlon) * cos(lat2),
+                cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon)
+        );
+        bearing %= 2 * PI;
+        if (bearing < 0) {
+            bearing += 2 * PI;
+        }
+        return bearing;
+    }
 }
diff --git a/src/org/openstreetmap/josm/data/coor/LatLon.java b/src/org/openstreetmap/josm/data/coor/LatLon.java
index 43d12f6336..3d7fafdf55 100644
--- a/src/org/openstreetmap/josm/data/coor/LatLon.java
+++ b/src/org/openstreetmap/josm/data/coor/LatLon.java
@@ -1,15 +1,6 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.data.coor;
 
-import static java.lang.Math.PI;
-import static java.lang.Math.asin;
-import static java.lang.Math.atan2;
-import static java.lang.Math.cos;
-import static java.lang.Math.sin;
-import static java.lang.Math.sqrt;
-import static org.openstreetmap.josm.data.projection.Ellipsoid.WGS84;
-import static org.openstreetmap.josm.tools.Utils.toRadians;
-
 import java.awt.geom.Area;
 import java.text.DecimalFormat;
 import java.text.NumberFormat;
@@ -19,7 +10,6 @@ import java.util.Objects;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.projection.ProjectionRegistry;
-import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -228,21 +218,11 @@ public class LatLon extends Coordinate implements ILatLon {
      * Uses <a href="https://en.wikipedia.org/wiki/Haversine_formula">Haversine formula</a>.
      * @param other the other point.
      * @return distance in metres.
+     * @deprecated since xxx (use {@link ILatLon#greatCircleDistance(ILatLon)} instead)
      */
+    @Deprecated
     public double greatCircleDistance(LatLon other) {
-        double sinHalfLat = sin(toRadians(other.lat() - this.lat()) / 2);
-        double sinHalfLon = sin(toRadians(other.lon() - this.lon()) / 2);
-        double d = 2 * WGS84.a * asin(
-                sqrt(sinHalfLat*sinHalfLat +
-                        cos(toRadians(this.lat()))*cos(toRadians(other.lat()))*sinHalfLon*sinHalfLon));
-        // For points opposite to each other on the sphere,
-        // rounding errors could make the argument of asin greater than 1
-        // (This should almost never happen.)
-        if (Double.isNaN(d)) {
-            Logging.error("NaN in greatCircleDistance: {0} {1}", this, other);
-            d = PI * WGS84.a;
-        }
-        return d;
+        return ILatLon.super.greatCircleDistance(other);
     }
 
     /**
@@ -259,20 +239,11 @@ public class LatLon extends Coordinate implements ILatLon {
      * @param other the "destination" position
      * @return heading in radians in the range 0 &lt;= hd &lt; 2*PI
      * @since 9796
+     * @deprecated since xxx (use {@link ILatLon#bearing(ILatLon)} instead)
      */
+    @Deprecated
     public double bearing(LatLon other) {
-        double lat1 = toRadians(this.lat());
-        double lat2 = toRadians(other.lat());
-        double dlon = toRadians(other.lon() - this.lon());
-        double bearing = atan2(
-            sin(dlon) * cos(lat2),
-            cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon)
-        );
-        bearing %= 2 * PI;
-        if (bearing < 0) {
-            bearing += 2 * PI;
-        }
-        return bearing;
+        return ILatLon.super.bearing(other);
     }
 
     /**
diff --git a/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java b/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
index c3ede940b6..bcd175ecf0 100644
--- a/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
+++ b/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
@@ -91,7 +91,7 @@ public final class GpxImageCorrelation {
                             double totalDist = 0;
                             List<Pair<Double, WayPoint>> nextWps = new ArrayList<>();
                             for (int j = i; j < size; j++) {
-                                totalDist += wps.get(j - 1).getCoor().greatCircleDistance(wps.get(j).getCoor());
+                                totalDist += wps.get(j - 1).greatCircleDistance(wps.get(j));
                                 nextWps.add(new Pair<>(totalDist, wps.get(j)));
                                 if (wps.get(j).hasDate()) {
                                     // ...if yes, interpolate everything in between
@@ -120,7 +120,7 @@ public final class GpxImageCorrelation {
                             firstSegment = false;
                             if (!trkInt || isFirst || prevWp == null ||
                                     Math.abs(curWpTime - prevWpTime) > TimeUnit.MINUTES.toMillis(trkTime) ||
-                                    prevWp.getCoor().greatCircleDistance(curWp.getCoor()) > trkDist) {
+                                    prevWp.greatCircleDistance(curWp) > trkDist) {
                                 isFirst = false;
                                 interpolate = false;
                                 if (trkTag) {
@@ -131,7 +131,7 @@ public final class GpxImageCorrelation {
                             // Apply settings for segments
                             if (!segInt || prevWp == null ||
                                     Math.abs(curWpTime - prevWpTime) > TimeUnit.MINUTES.toMillis(segTime) ||
-                                    prevWp.getCoor().greatCircleDistance(curWp.getCoor()) > segDist) {
+                                    prevWp.greatCircleDistance(curWp) > segDist) {
                                 interpolate = false;
                                 if (segTag) {
                                     tagTime = segTagTime;
@@ -237,7 +237,7 @@ public final class GpxImageCorrelation {
         Double prevElevation = null;
 
         if (prevWp != null && interpolate) {
-            double distance = prevWp.getCoor().greatCircleDistance(curWp.getCoor());
+            double distance = prevWp.greatCircleDistance(curWp);
             // This is in km/h, 3.6 * m/s
             if (curWpTime > prevWpTime) {
                 speed = 3600 * distance / (curWpTime - prevWpTime);
@@ -266,7 +266,7 @@ public final class GpxImageCorrelation {
                         curTmp.setPos(curWp.getCoor());
                     }
                     if (nextWp != null && dirpos.isSetImageDirection()) {
-                        double direction = curWp.getCoor().bearing(nextWp.getCoor());
+                        double direction = curWp.bearing(nextWp);
                         curTmp.setExifImgDir(computeDirection(direction, dirpos.getImageDirectionAngleOffset()));
                     }
                     curTmp.setGpsTime(curImg.getExifInstant().minusMillis(offset));
diff --git a/src/org/openstreetmap/josm/data/gpx/GpxTrackSegment.java b/src/org/openstreetmap/josm/data/gpx/GpxTrackSegment.java
index 02fa8f12c3..df0993eda5 100644
--- a/src/org/openstreetmap/josm/data/gpx/GpxTrackSegment.java
+++ b/src/org/openstreetmap/josm/data/gpx/GpxTrackSegment.java
@@ -46,7 +46,7 @@ public class GpxTrackSegment extends WithAttributes implements IGpxTrackSegment
         WayPoint last = null;
         for (WayPoint tpt : wayPoints) {
             if (last != null) {
-                Double d = last.getCoor().greatCircleDistance(tpt.getCoor());
+                Double d = last.greatCircleDistance(tpt);
                 if (!d.isNaN() && !d.isInfinite()) {
                     result += d;
                 }
diff --git a/src/org/openstreetmap/josm/data/osm/Way.java b/src/org/openstreetmap/josm/data/osm/Way.java
index b746a98891..ebea83125e 100644
--- a/src/org/openstreetmap/josm/data/osm/Way.java
+++ b/src/org/openstreetmap/josm/data/osm/Way.java
@@ -12,7 +12,7 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
-import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.coor.ILatLon;
 import org.openstreetmap.josm.data.osm.visitor.OsmPrimitiveVisitor;
 import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -630,7 +630,7 @@ public final class Way extends OsmPrimitive implements IWay<Node> {
     }
 
     /**
-     * Replies the length of the way, in metres, as computed by {@link LatLon#greatCircleDistance}.
+     * Replies the length of the way, in metres, as computed by {@link ILatLon#greatCircleDistance}.
      * @return The length of the way, in metres
      * @since 4138
      */
@@ -638,12 +638,8 @@ public final class Way extends OsmPrimitive implements IWay<Node> {
         double length = 0;
         Node lastN = null;
         for (Node n:nodes) {
-            if (lastN != null) {
-                LatLon lastNcoor = lastN.getCoor();
-                LatLon coor = n.getCoor();
-                if (lastNcoor != null && coor != null) {
-                    length += coor.greatCircleDistance(lastNcoor);
-                }
+            if (lastN != null && lastN.isLatLonKnown() && n.isLatLonKnown()) {
+                length += n.greatCircleDistance(lastN);
             }
             lastN = n;
         }
@@ -651,7 +647,7 @@ public final class Way extends OsmPrimitive implements IWay<Node> {
     }
 
     /**
-     * Replies the length of the longest segment of the way, in metres, as computed by {@link LatLon#greatCircleDistance}.
+     * Replies the length of the longest segment of the way, in metres, as computed by {@link ILatLon#greatCircleDistance}.
      * @return The length of the segment, in metres
      * @since 8320
      */
@@ -659,14 +655,10 @@ public final class Way extends OsmPrimitive implements IWay<Node> {
         double length = 0;
         Node lastN = null;
         for (Node n:nodes) {
-            if (lastN != null) {
-                LatLon lastNcoor = lastN.getCoor();
-                LatLon coor = n.getCoor();
-                if (lastNcoor != null && coor != null) {
-                    double l = coor.greatCircleDistance(lastNcoor);
-                    if (l > length) {
-                        length = l;
-                    }
+            if (lastN != null && lastN.isLatLonKnown() && n.isLatLonKnown()) {
+                double l = n.greatCircleDistance(lastN);
+                if (l > length) {
+                    length = l;
                 }
             }
             lastN = n;
diff --git a/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java b/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java
index 0e6612d0d7..60da76e165 100644
--- a/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java
+++ b/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java
@@ -28,7 +28,6 @@ import java.util.regex.PatternSyntaxException;
 import java.util.stream.Collectors;
 
 import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
@@ -1808,9 +1807,8 @@ public class SearchCompiler {
             if (!osm.isUsable())
                 return false;
             else if (osm instanceof Node) {
-                LatLon coordinate = ((Node) osm).getCoor();
                 Collection<Bounds> allBounds = getBounds(osm);
-                return coordinate != null && allBounds != null && allBounds.stream().anyMatch(bounds -> bounds.contains(coordinate));
+                return ((Node) osm).isLatLonKnown() && allBounds != null && allBounds.stream().anyMatch(bounds -> bounds.contains((Node) osm));
             } else if (osm instanceof Way) {
                 Collection<Node> nodes = ((Way) osm).getNodes();
                 return all ? nodes.stream().allMatch(this) : nodes.stream().anyMatch(this);
diff --git a/src/org/openstreetmap/josm/data/validation/tests/Addresses.java b/src/org/openstreetmap/josm/data/validation/tests/Addresses.java
index 11170dee89..98a3fbc25c 100644
--- a/src/org/openstreetmap/josm/data/validation/tests/Addresses.java
+++ b/src/org/openstreetmap/josm/data/validation/tests/Addresses.java
@@ -22,6 +22,7 @@ import java.util.stream.Stream;
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.command.DeleteCommand;
 import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.ILatLon;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -361,6 +362,9 @@ public class Addresses extends Test {
      * @return distance of center of bounding boxes in meters
      */
     static double getDistance(OsmPrimitive a, OsmPrimitive b) {
+        if (a instanceof ILatLon && b instanceof ILatLon) {
+            return ((ILatLon) a).greatCircleDistance((ILatLon) b);
+        }
         LatLon centerA = a.getBBox().getCenter();
         LatLon centerB = b.getBBox().getCenter();
         return centerA.greatCircleDistance(centerB);
diff --git a/src/org/openstreetmap/josm/data/validation/tests/LongSegment.java b/src/org/openstreetmap/josm/data/validation/tests/LongSegment.java
index cac2453184..d09f1a0f40 100644
--- a/src/org/openstreetmap/josm/data/validation/tests/LongSegment.java
+++ b/src/org/openstreetmap/josm/data/validation/tests/LongSegment.java
@@ -8,7 +8,6 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
-import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
@@ -91,11 +90,11 @@ public class LongSegment extends Test {
     }
 
     private void visitWaySegment(Way w, int i) {
-        LatLon coor1 = w.getNode(i).getCoor();
-        LatLon coor2 = w.getNode(i + 1).getCoor();
+        Node oneI = w.getNode(i);
+        Node twoI = w.getNode(i + 1);
 
-        if (coor1 != null && coor2 != null) {
-            Double length = coor1.greatCircleDistance(coor2);
+        if (oneI.isLatLonKnown() && twoI.isLatLonKnown()) {
+            double length = oneI.greatCircleDistance(twoI);
             if (length > maxlength) {
                 addErrorForSegment(new WaySegment(w, i), length / 1000.0);
             }
diff --git a/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java b/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java
index 007eba11bf..5665106a1a 100644
--- a/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java
+++ b/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java
@@ -468,7 +468,7 @@ public abstract class UnconnectedWays extends Test {
                 Node uncon = visited.iterator().next();
                 LatLon cl = ProjectionRegistry.getProjection().eastNorth2latlon(calcClosest(uncon));
                 // calculate real detour length, closest point might be somewhere between n1 and n2
-                double detourLen = len + node.getCoor().greatCircleDistance(cl);
+                double detourLen = len + node.greatCircleDistance(cl);
                 if (detourLen > maxLen)
                     return false;
                 // see #17914: flag also nodes which are very close
@@ -500,7 +500,7 @@ public abstract class UnconnectedWays extends Test {
                         final boolean containsN = visited.contains(next);
                         visited.add(next);
                         if (!containsN && isConnectedTo(next, visited,
-                                len + node.getCoor().greatCircleDistance(next.getCoor()), way)) {
+                                len + node.greatCircleDistance(next), way)) {
                             return true;
                         }
                     }
@@ -515,7 +515,7 @@ public abstract class UnconnectedWays extends Test {
 
         double getDist(Node n) {
             EastNorth closest = calcClosest(n);
-            return n.getCoor().greatCircleDistance(ProjectionRegistry.getProjection().eastNorth2latlon(closest));
+            return n.greatCircleDistance(ProjectionRegistry.getProjection().eastNorth2latlon(closest));
         }
 
         private boolean nearby(Node n, double dist) {
@@ -526,15 +526,15 @@ public abstract class UnconnectedWays extends Test {
         }
 
         private BBox getBounds(double fudge) {
-            double x1 = n1.getCoor().lon();
-            double x2 = n2.getCoor().lon();
+            double x1 = n1.lon();
+            double x2 = n2.lon();
             if (x1 > x2) {
                 double tmpx = x1;
                 x1 = x2;
                 x2 = tmpx;
             }
-            double y1 = n1.getCoor().lat();
-            double y2 = n2.getCoor().lat();
+            double y1 = n1.lat();
+            double y2 = n2.lat();
             if (y1 > y2) {
                 double tmpy = y1;
                 y1 = y2;
diff --git a/src/org/openstreetmap/josm/gui/MapStatus.java b/src/org/openstreetmap/josm/gui/MapStatus.java
index e7d71b7df8..83ba6364bc 100644
--- a/src/org/openstreetmap/josm/gui/MapStatus.java
+++ b/src/org/openstreetmap/josm/gui/MapStatus.java
@@ -61,6 +61,7 @@ import javax.swing.event.PopupMenuListener;
 
 import org.openstreetmap.josm.data.SystemOfMeasurement;
 import org.openstreetmap.josm.data.SystemOfMeasurement.SoMChangeListener;
+import org.openstreetmap.josm.data.coor.ILatLon;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.coor.conversion.CoordinateFormatManager;
 import org.openstreetmap.josm.data.coor.conversion.DMSCoordinateFormat;
@@ -70,7 +71,6 @@ import org.openstreetmap.josm.data.osm.DataSelectionListener;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
 import org.openstreetmap.josm.data.osm.IPrimitive;
-import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
@@ -1220,13 +1220,9 @@ public final class MapStatus extends JPanel implements
             OsmPrimitive n1 = it.next();
             OsmPrimitive n2 = it.next();
             // show distance between two selected nodes with coordinates
-            if (n1 instanceof Node && n2 instanceof Node) {
-                LatLon c1 = ((Node) n1).getCoor();
-                LatLon c2 = ((Node) n2).getCoor();
-                if (c1 != null && c2 != null) {
-                    setDist(c1.greatCircleDistance(c2));
-                    return;
-                }
+            if (n1 instanceof ILatLon && n2 instanceof ILatLon && ((ILatLon) n1).isLatLonKnown() && ((ILatLon) n2).isLatLonKnown()) {
+                setDist(((ILatLon) n1).greatCircleDistance((ILatLon) n2));
+                return;
             }
         }
         setDist(new SubclassFilteredCollection<OsmPrimitive, Way>(newSelection, Way.class::isInstance));
diff --git a/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java b/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
index 60292441a8..c2854f9a7c 100644
--- a/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
+++ b/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
@@ -566,7 +566,7 @@ public class GpxDrawHelper implements SoMChangeListener, MapViewPaintable.LayerP
                             continue;
                         }
                         if (oldWp != null && trkPnt.getTimeInMillis() > oldWp.getTimeInMillis()) {
-                            double vel = trkPnt.getCoor().greatCircleDistance(oldWp.getCoor())
+                            double vel = trkPnt.greatCircleDistance(oldWp)
                                     / (trkPnt.getTime() - oldWp.getTime());
                             velocities.add(vel);
                         }
@@ -623,9 +623,8 @@ public class GpxDrawHelper implements SoMChangeListener, MapViewPaintable.LayerP
                 oldWp = null;
             }
             for (WayPoint trkPnt : segment) {
-                LatLon c = trkPnt.getCoor();
                 trkPnt.customColoring = segment.getColor();
-                if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
+                if (Double.isNaN(trkPnt.lat()) || Double.isNaN(trkPnt.lon())) {
                     continue;
                 }
                 // now we are sure some color will be assigned
@@ -645,7 +644,7 @@ public class GpxDrawHelper implements SoMChangeListener, MapViewPaintable.LayerP
                     }
                 }
                 if (oldWp != null) { // other coloring modes need segment for calcuation
-                    double dist = c.greatCircleDistance(oldWp.getCoor());
+                    double dist = trkPnt.greatCircleDistance(oldWp);
                     boolean noDraw = false;
                     switch (colored) {
                     case VELOCITY:
@@ -657,7 +656,7 @@ public class GpxDrawHelper implements SoMChangeListener, MapViewPaintable.LayerP
                         }
                         break;
                     case DIRECTION:
-                        double dirColor = oldWp.getCoor().bearing(trkPnt.getCoor());
+                        double dirColor = oldWp.bearing(trkPnt);
                         color = directionScale.getColor(dirColor);
                         break;
                     case TIME:
@@ -673,7 +672,7 @@ public class GpxDrawHelper implements SoMChangeListener, MapViewPaintable.LayerP
                     }
                     if (!noDraw && (!segment.isUnordered() || !data.fromServer) && (maxLineLength == -1 || dist <= maxLineLength)) {
                         trkPnt.drawLine = true;
-                        double bearing = oldWp.getCoor().bearing(trkPnt.getCoor());
+                        double bearing = oldWp.bearing(trkPnt);
                         trkPnt.dir = ((int) (bearing / Math.PI * 4 + 1.5)) % 8;
                     } else {
                         trkPnt.drawLine = false;
diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/AddNodeHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/AddNodeHandler.java
index 632e9db390..e05361a7d7 100644
--- a/src/org/openstreetmap/josm/io/remotecontrol/handler/AddNodeHandler.java
+++ b/src/org/openstreetmap/josm/io/remotecontrol/handler/AddNodeHandler.java
@@ -91,7 +91,7 @@ public class AddNodeHandler extends RequestHandler {
             MapView mapView = MainApplication.getMap().mapView;
             Point p = mapView.getPoint(ll);
             node = mapView.getNearestNode(p, OsmPrimitive::isUsable);
-            if (node != null && node.getCoor().greatCircleDistance(ll) > Config.getPref().getDouble("remotecontrol.tolerance", 0.1)) {
+            if (node != null && node.greatCircleDistance(ll) > Config.getPref().getDouble("remotecontrol.tolerance", 0.1)) {
                 node = null; // node is too far
             }
         }
diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/AddWayHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/AddWayHandler.java
index f2b54f02d9..dbd27e0e91 100644
--- a/src/org/openstreetmap/josm/io/remotecontrol/handler/AddWayHandler.java
+++ b/src/org/openstreetmap/josm/io/remotecontrol/handler/AddWayHandler.java
@@ -128,7 +128,7 @@ public class AddWayHandler extends RequestHandler {
         if (MainApplication.isDisplayingMapView()) {
             MapView mapView = MainApplication.getMap().mapView;
             nd = mapView.getNearestNode(mapView.getPoint(ll), OsmPrimitive::isUsable);
-            if (nd != null && nd.getCoor().greatCircleDistance(ll) > Config.getPref().getDouble("remote.tolerance", 0.1)) {
+            if (nd != null && nd.greatCircleDistance(ll) > Config.getPref().getDouble("remote.tolerance", 0.1)) {
                 nd = null; // node is too far
             }
         }
diff --git a/src/org/openstreetmap/josm/tools/Geometry.java b/src/org/openstreetmap/josm/tools/Geometry.java
index 6eca937e72..ad7eeb5016 100644
--- a/src/org/openstreetmap/josm/tools/Geometry.java
+++ b/src/org/openstreetmap/josm/tools/Geometry.java
@@ -1400,8 +1400,8 @@ public final class Geometry {
         double rValue = Double.MAX_VALUE;
         if (one == null || two == null || one.isIncomplete()
                 || two.isIncomplete()) return Double.NaN;
-        if (one instanceof Node && two instanceof Node) {
-            rValue = ((Node) one).getCoor().greatCircleDistance(((Node) two).getCoor());
+        if (one instanceof ILatLon && two instanceof ILatLon) {
+            rValue = ((ILatLon) one).greatCircleDistance(((ILatLon) two));
         } else if (one instanceof Node && two instanceof Way) {
             rValue = getDistanceWayNode((Way) two, (Node) one);
         } else if (one instanceof Way && two instanceof Node) {
