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