Opened 11 years ago

Closed 10 years ago

# [PATCH] spherical computation of angles

Reported by: Owned by: SaschaR framm major Core latest angle Winkel Winkeldings

### Description

The method LatLon#heading(LatLon other) has a bug: It lives
in a plane instead on a sphere.

The methode DrawAction#computeHelperLine() computes the
angle between two way segments by subtraction of two
heading angles. This is incorrect if the segments are
very long.

The following code computes the heading by means of
the spherical sine formular.

```    /** earth radius in metres: 6378135 */
public final static double EARTH_RADIUS = 6378135;

/**
* Returns the heading, in radians, that you have to use to get from
* this lat/lon to another.
*
* @param other the "destination" position
*/
double rv;
double distance = greatCircleDistance(other) / EARTH_RADIUS;
double sinDistance = Math.sin(distance);
if (Math.abs(sinDistance) > 0.0) {
// spherical sine formula: Our triangle consists of
// P0 = north pole = (lat=PI/2, lon=0),
// P1 = this = (lan(), lon()),
// P2 = other = (other.lan(), other.lon()).
// We are looking for the angle rv at P1.
// The distance between north pole and other is PI/2-other.lat().
// The angle at north pole is delta_lon = other.lon()-lon().
// sine formular:
// sin(rv) = sin(delta_lon) * sin(PI/2-other.lat()) / sin(distance)
//         = sin(delta_lon) * cos(other.lat()) / sin(distance).
if (lat() > other.lat()) {
rv = Math.PI - rv;
}
if (rv < 0) {
rv += 2*Math.PI;
}
} else {
rv = Double.NaN;
}
return rv;
}
```

Proposal 2: Method LatLon#angle(LatLon p1, LatLon p2).

```    /**
* Computes the angle between the edges (this, p1) and (this, p2)
* at this by use of cosine law.
* @param p1 other point of first edge
* @param p2 other point of second edge
* @return angle in radians or NaN
*/
public double angle(LatLon p1, LatLon p2) {
double numerator = Math.cos(lenEdge3) - Math.cos(lenEdge1)*Math.cos(lenEdge2);
double denomin = Math.sin(lenEdge1)*Math.sin(lenEdge2);
double angle;
if (denomin != 0) {
angle = Math.acos(numerator / denomin);
} else {
angle = Double.NaN;
}
return angle;
}
```

Computation in DrawAction#computeHelperLine():

```        if (previousNode != null) {
angle = Math.toDegrees(currentBaseNode.coor.angle(
previousNode.coor, mouseLatLon));
}
```

```        if (previousNode != null) {
if (angle < 0) angle += 360;
}
```

With best regards

Sascha Rogmann

### comment:1 Changed 11 years ago by anonymous

Summary: computation of angles → [PATCH] spherical computation of angles

### comment:2 Changed 10 years ago by framm

Resolution: → wontfix new → closed

This is technically true, however we do not usually have segments longer than a few km (and even that is a stretch). We "live on a plane" in other parts of JOSM as well, e.g. when doing "align nodes in circle/line/rectangle" etc.; this patch would introduce half spherical and half planar treatment.

If someone thinks otherwise then please comment and re-open the ticket; I'll set it to wontfix now. Again, Sasche is technically correct, I just doubt that this "bug" has any meaningful consequences for the tasks JOSM is used for.

### Modify Ticket

Change Properties