001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.data.projection.datum;
003    
004    import org.openstreetmap.josm.data.coor.LatLon;
005    import 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     */
018    public 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, double rx, double ry, double rz, double s) {
036            super(name, proj4Id, ellps);
037            this.dx = dx;
038            this.dy = dy;
039            this.dz = dz;
040            this.rx = Math.toRadians(rx / 3600);
041            this.ry = Math.toRadians(ry / 3600);
042            this.rz = Math.toRadians(rz / 3600);
043            this.s = s / 1e6;
044        }
045    
046        @Override
047        public LatLon toWGS84(LatLon ll) {
048            double[] xyz = ellps.latLon2Cart(ll);
049            double x = dx + xyz[0]*(1+s) + xyz[2]*ry - xyz[1]*rz;
050            double y = dy + xyz[1]*(1+s) + xyz[0]*rz - xyz[2]*rx;
051            double z = dz + xyz[2]*(1+s) + xyz[1]*rx - xyz[0]*ry;
052            return Ellipsoid.WGS84.cart2LatLon(new double[] { x, y, z });
053        }
054    
055        @Override
056        public LatLon fromWGS84(LatLon ll) {
057            double[] xyz = Ellipsoid.WGS84.latLon2Cart(ll);
058            double x = (1-s)*(-dx + xyz[0] + ((-dz+xyz[2])*(-ry) - (-dy+xyz[1])*(-rz)));
059            double y = (1-s)*(-dy + xyz[1] + ((-dx+xyz[0])*(-rz) - (-dz+xyz[2])*(-rx)));
060            double z = (1-s)*(-dz + xyz[2] + ((-dy+xyz[1])*(-rx) - (-dx+xyz[0])*(-ry)));
061            return this.ellps.cart2LatLon(new double[] { x, y, z });
062        }
063        
064    }