001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.projection.datum;
003
004import org.openstreetmap.josm.data.coor.LatLon;
005import org.openstreetmap.josm.data.projection.Ellipsoid;
006import org.openstreetmap.josm.tools.Utils;
007
008/**
009 * Datum provides general conversion from one ellipsoid to another.
010 *
011 * Seven parameters can be specified:
012 * - 3D offset
013 * - general rotation
014 * - scale
015 *
016 * This method is described by EPSG as EPSG:9606.
017 * Also known as Bursa-Wolf.
018 * @since 4285
019 */
020public class SevenParameterDatum extends AbstractDatum {
021
022    protected double dx, dy, dz, rx, ry, rz, s;
023
024    /**
025     * Constructs a new {@code SevenParameterDatum}
026     * @param name name of the datum
027     * @param proj4Id Proj.4 identifier for this datum (or null)
028     * @param ellps the ellipsoid used
029     * @param dx x offset in meters
030     * @param dy y offset in meters
031     * @param dz z offset in meters
032     * @param rx rotational parameter in seconds of arc
033     * @param ry rotational parameter in seconds of arc
034     * @param rz rotational parameter in seconds of arc
035     * @param s scale change in parts per million
036     */
037    public SevenParameterDatum(String name, String proj4Id, Ellipsoid ellps, double dx, double dy, double dz,
038            double rx, double ry, double rz, double s) {
039        super(name, proj4Id, ellps);
040        this.dx = dx;
041        this.dy = dy;
042        this.dz = dz;
043        this.rx = Utils.toRadians(rx / 3600);
044        this.ry = Utils.toRadians(ry / 3600);
045        this.rz = Utils.toRadians(rz / 3600);
046        this.s = s / 1e6;
047    }
048
049    @Override
050    public LatLon toWGS84(LatLon ll) {
051        double[] xyz = ellps.latLon2Cart(ll);
052        double x = dx + xyz[0]*(1+s) + xyz[2]*ry - xyz[1]*rz;
053        double y = dy + xyz[1]*(1+s) + xyz[0]*rz - xyz[2]*rx;
054        double z = dz + xyz[2]*(1+s) + xyz[1]*rx - xyz[0]*ry;
055        return Ellipsoid.WGS84.cart2LatLon(x, y, z);
056    }
057
058    @Override
059    public LatLon fromWGS84(LatLon ll) {
060        double[] xyz = Ellipsoid.WGS84.latLon2Cart(ll);
061        double x = (1-s)*(-dx + xyz[0] + ((-dz+xyz[2])* -ry - (-dy+xyz[1])* -rz));
062        double y = (1-s)*(-dy + xyz[1] + ((-dx+xyz[0])* -rz - (-dz+xyz[2])* -rx));
063        double z = (1-s)*(-dz + xyz[2] + ((-dy+xyz[1])* -rx - (-dx+xyz[0])* -ry));
064        return this.ellps.cart2LatLon(x, y, z);
065    }
066}