web-dev-qa-db-fra.com

Vers l'est vers le nord jusqu'à la longitude de latitude

J'ai des coordonnées de localisation au format est/nord mais je dois le convertir en lat approprié pour le centrer dans les cartes bing. Une formule ou des détails sur la conversion de l'abscisse/ordonnée en lat/lon?

EDIT: Pour être plus précis, j'ai besoin de convertir les coordonnées SVY21 en WGS84

14
Bahamut

Les abscisses et les ordonnées sont les distances à l'est et au nord, respectivement, d'un point de base. Le point de base est généralement une latitude et une longitude, et les abscisses et les ordonnées sont normalement exprimées en mètres ou en pieds. L'abscisse et l'ordonnée, cependant, sont généralement compensées par une valeur particulière pour les rendre positives et leur permettre d'exprimer des endroits à l'ouest et au sud du point de base.

En général, la conversion d'un système de coordonnées à un autre n'est pas simple, car les deux peuvent avoir des ellipsoïdes (modèles terrestres) et des datums différents. Si je comprends bien, les formules de conversion d'un système de coordonnées à un autre sont assez complexes.

SVY21 , cependant, utilise exactement le même datum et ellipsoïde que WGS84, ce qui rend la tâche plus simple. Dans SVY21, le point de base pour les abscisses et les ordonnées est Base 7 au réservoir Pierce , 1 deg. 22 min. 02.9154 sec. nord et 103 deg. 49 min 31.9752 sec. est (c'est-à-dire une latitude d'environ 1,3674765 degrés et une longitude d'environ 103,8255487 degrés; le texte bien connu, cependant, utilise 1,3666 ... degrés et 103,8333 ... degrés, respectivement). Le décalage pour l'abscisse est de 28001,642 mètres et le décalage pour l'ordonnée est de 38744,572 mètres. Le code EPSG est 3414. Je suppose que vos abscisses et ordonnées sont exprimées en mètres.

Étant donné que SVY21 utilise le même système que WGS84, tout ce que vous avez à faire est de:

  • Soustrayez l'abscisse et l'ordonnée par leurs valeurs de décalage respectives. (Les valeurs seront en mètres.)
  • Trouvez la longitude du point donné en trouvant le point de destination étant donné le point de base, la valeur absolue de l'abscisse et le relèvement de 90 degrés si l'abscisse est positive, ou 270 degrés si elle est négative. Ce lien contient les formules pertinentes. (Pour ce calcul, vous pouvez utiliser soit la loi sphérique des cosinus, comme indiqué dans la section "Point de destination étant donné la distance et le relèvement par rapport au point de départ", soit la plus précise formule directe de Vincenty . Le premier lien Cependant, la page n'utilise pas la formule Haversine pour ce calcul.)
  • Trouvez la latitude du point donné en trouvant le point de destination étant donné le point de base, la valeur absolue de l'ordonnée et le relèvement de 0 degrés si l'ordonnée est positive ou de 180 degrés si elle est négative.
14
Peter O.

Il existe des centaines de systèmes de coordonnées différents - Est/Nord et Lat/Long sont types de coordonnées, mais ils ne sont pas suffisants pour identifier de manière unique le système à partir duquel ces coordonnées sont obtenues.

Vous devez avoir un code EPSG (par exemple 4326, 4269, 27700, 32701) ou, alternativement, les détails du système de référence spatiale (le datum, la projection, le méridien principal et l'unité de mesure) pour votre source et le format de destination choisi . Vous mentionnez "GPS" dans le titre de votre question, je suppose donc que le lat/lon dont vous avez besoin est défini par rapport au datum WGS84 utilisé par les systèmes de positionnement global, mais il existe encore de nombreuses projections de ce datum qui pourraient conduire à des abaissements différents./Valeurs d'ordonnée.

Une fois que vous avez les détails de la projection utilisée, vous pouvez effectuer la transformation en code en utilisant quelque chose comme la bibliothèque Proj.4 (http://trac.osgeo.org/proj/)

3
Alastair Aitchison

J'ai converti une implémentation Javascript en fonctions T-SQL pour le WGS84 en valeurs Latitude/Longitude. N'hésitez pas à l'utiliser comme bon vous semble. Si vous avez besoin d'un système de coordonnées différent, consultez la page Web de l'Université du Wisconsin - Green Bay que j'ai utilisée comme source et obtenez les constantes mises à jour.

    drop function UF_utm_to_lat
go
create function UF_utm_to_lat(@utmz float, @x float, @y float) returns float
as
begin
    --Based on code from this page: http://www.uwgb.edu/dutchs/usefuldata/ConvertUTMNoOZ.HTM
    declare @latitude float;
    declare @longitude float;
    set @latitude = 0.00;
    set @longitude = 0.00;

    --Declarations
    declare @a float;
    declare @f float;
    declare @drad float;
    declare @k0 float;
    declare @b float;
    declare @e float;
    declare @e0 float;
    declare @esq float;
    declare @e0sq float;
    declare @zcm float;
    declare @e1 float;
    declare @M float;
    declare @mu float;
    declare @phi1 float;
    declare @C1 float;
    declare @T1 float;
    declare @N1 float;
    declare @R1 float;
    declare @D float;
    declare @phi float;
    declare @lng float;
    declare @lngd float;

    --Datum Info here: Name, a, b, f, 1/f
    --WGS 84    6,378,137.0 6356752.314 0.003352811 298.2572236

    set @a = 6378137.0;
    set @b = 6356752.314;
    set @f = 0.003352811;
    set @drad = PI()/180.0;
    set @k0 = 0.9996; --scale on central meridian

    set @e = SQRT(1.0 - (@b/@a)*(@b/@a)); --Eccentricity
    --e = Math.sqrt(1 - (b/a)*(b/a));//eccentricity
    set @e0 = @e/SQRT(1.0 - @e*@e); --Called e prime in reference
    --e0 = e/Math.sqrt(1 - e*e);//Called e prime in reference
    set @esq = (1.0 - (@b/@a)*(@b/@a)); --e squared for use in expansions
    --esq = (1 - (b/a)*(b/a));//e squared for use in expansions
    set @e0sq = @e*@e/(1.0-@e*@e); --e0 squared - always even powers
    --e0sq = e*e/(1-e*e);// e0 squared - always even powers
    set @zcm = 3.0 + 6.0*(@utmz-1.0) - 180.0; --Central meridian of zone
    --zcm = 3 + 6*(utmz-1) - 180;//Central meridian of zone
    set @e1 = (1.0 - SQRT(1.0 - @e*@e))/(1.0 + SQRT(1.0 - @e*@e)); --Called e1 in USGS PP 1395 also
    --e1 = (1 - Math.sqrt(1 - e*e))/(1 + Math.sqrt(1 - e*e));//Called e1 in USGS PP 1395 also
    set @M = 0.0 + @y / @k0; --Arc length along standard meridian
    --M = M0 + y/k0;//Arc length along standard meridian. 
    set @mu = @M/(@a*(1.0 - @esq*(1.0/4.0 + @esq*(3.0/64.0 + 5.0*@esq/256.0))));
    --mu = M/(a*(1 - esq*(1/4 + esq*(3/64 + 5*esq/256))));
    set @phi1 = @mu + @e1*(3.0/2.0 - 27.0*@e1*@e1/32.0)*SIN(2.0*@mu) + @e1*@e1*(21.0/16.0 - 55.0*@e1*@e1/32.0)*SIN(4.0*@mu); --Footprint Latitude
    --phi1 = mu + e1*(3/2 - 27*e1*e1/32)*Math.sin(2*mu) + e1*e1*(21/16 -55*e1*e1/32)*Math.sin(4*mu);//Footprint Latitude
    set @phi1 = @phi1 + @e1*@e1*@e1*(SIN(6.0*@mu)*151.0/96.0 + @e1*SIN(8.0*@mu)*1097.0/512.0);
    --phi1 = phi1 + e1*e1*e1*(Math.sin(6*mu)*151/96 + e1*Math.sin(8*mu)*1097/512);
    set @C1 = @e0sq*POWER(COS(@phi1),2.0);
    --C1 = e0sq*Math.pow(Math.cos(phi1),2);
    set @T1 = POWER(TAN(@phi1),2.0);
    --T1 = Math.pow(Math.tan(phi1),2);
    set @N1 = @a/SQRT(1.0-POWER(@e*SIN(@phi1),2.0));
    --N1 = a/Math.sqrt(1-Math.pow(e*Math.sin(phi1),2));
    set @R1 = @N1*(1.0-@e*@e)/(1.0-POWER(@e*SIN(@phi1),2.0));
    --R1 = N1*(1-e*e)/(1-Math.pow(e*Math.sin(phi1),2));
    set @D = (@x-500000.0)/(@N1*@k0);
    --D = (x-500000)/(N1*k0);
    set @phi = (@D*@D)*(1.0/2.0 - @D*@D*(5.0 + 3.0*@T1 + 10.0*@C1 - 4.0*@C1*@C1 - 9.0*@e0sq)/24.0);
    --phi = (D*D)*(1/2 - D*D*(5 + 3*T1 + 10*C1 - 4*C1*C1 - 9*e0sq)/24);
    set @phi = @phi + POWER(@D,6.0)*(61.0 + 90.0*@T1 + 298.0*@C1 + 45.0*@T1*@T1 - 252.0*@e0sq - 3.0*@C1*@C1)/720.0;
    --phi = phi + Math.pow(D,6)*(61 + 90*T1 + 298*C1 + 45*T1*T1 -252*e0sq - 3*C1*C1)/720;
    set @phi = @phi1 - (@N1*TAN(@phi1)/@R1)*@phi;
    --phi = phi1 - (N1*Math.tan(phi1)/R1)*phi;


    set @latitude = FLOOR(1000000.0*@phi/@drad)/1000000.0;

    set @lng = @D*(1.0 + @D*@D*((-1.0 - 2.0*@T1 - @C1)/6.0 + @D*@D*(5.0 - 2.0*@C1 + 28.0*@T1 - 3.0*@C1*@C1 + 8.0*@e0sq + 24.0*@T1*@T1)/120))/COS(@phi1);
    set @lngd = @zcm+@lng/@drad;
    set @longitude = FLOOR(1000000.0*@lngd)/1000000.0;


    return @latitude;
end
go
drop function UF_utm_to_long
go
create function UF_utm_to_long(@utmz float, @x float, @y float) returns float
as
begin
    --Based on code from this page: http://www.uwgb.edu/dutchs/usefuldata/ConvertUTMNoOZ.HTM
    declare @latitude float;
    declare @longitude float;
    set @latitude = 0.00;
    set @longitude = 0.00;

    --Declarations
    declare @a float;
    declare @f float;
    declare @drad float;
    declare @k0 float;
    declare @b float;
    declare @e float;
    declare @e0 float;
    declare @esq float;
    declare @e0sq float;
    declare @zcm float;
    declare @e1 float;
    declare @M float;
    declare @mu float;
    declare @phi1 float;
    declare @C1 float;
    declare @T1 float;
    declare @N1 float;
    declare @R1 float;
    declare @D float;
    declare @phi float;
    declare @lng float;
    declare @lngd float;

    --Datum Info here: Name, a, b, f, 1/f
    --WGS 84    6,378,137.0 6356752.314 0.003352811 298.2572236

    set @a = 6378137.0;
    set @b = 6356752.314;
    set @f = 0.003352811;
    set @drad = PI()/180.0;
    set @k0 = 0.9996; --scale on central meridian

    set @e = SQRT(1.0 - (@b/@a)*(@b/@a)); --Eccentricity
    --e = Math.sqrt(1 - (b/a)*(b/a));//eccentricity
    set @e0 = @e/SQRT(1.0 - @e*@e); --Called e prime in reference
    --e0 = e/Math.sqrt(1 - e*e);//Called e prime in reference
    set @esq = (1.0 - (@b/@a)*(@b/@a)); --e squared for use in expansions
    --esq = (1 - (b/a)*(b/a));//e squared for use in expansions
    set @e0sq = @e*@e/(1.0-@e*@e); --e0 squared - always even powers
    --e0sq = e*e/(1-e*e);// e0 squared - always even powers
    set @zcm = 3.0 + 6.0*(@utmz-1.0) - 180.0; --Central meridian of zone
    --zcm = 3 + 6*(utmz-1) - 180;//Central meridian of zone
    set @e1 = (1.0 - SQRT(1.0 - @e*@e))/(1.0 + SQRT(1.0 - @e*@e)); --Called e1 in USGS PP 1395 also
    --e1 = (1 - Math.sqrt(1 - e*e))/(1 + Math.sqrt(1 - e*e));//Called e1 in USGS PP 1395 also
    set @M = 0.0 + @y / @k0; --Arc length along standard meridian
    --M = M0 + y/k0;//Arc length along standard meridian. 
    set @mu = @M/(@a*(1.0 - @esq*(1.0/4.0 + @esq*(3.0/64.0 + 5.0*@esq/256.0))));
    --mu = M/(a*(1 - esq*(1/4 + esq*(3/64 + 5*esq/256))));
    set @phi1 = @mu + @e1*(3.0/2.0 - 27.0*@e1*@e1/32.0)*SIN(2.0*@mu) + @e1*@e1*(21.0/16.0 - 55.0*@e1*@e1/32.0)*SIN(4.0*@mu); --Footprint Latitude
    --phi1 = mu + e1*(3/2 - 27*e1*e1/32)*Math.sin(2*mu) + e1*e1*(21/16 -55*e1*e1/32)*Math.sin(4*mu);//Footprint Latitude
    set @phi1 = @phi1 + @e1*@e1*@e1*(SIN(6.0*@mu)*151.0/96.0 + @e1*SIN(8.0*@mu)*1097.0/512.0);
    --phi1 = phi1 + e1*e1*e1*(Math.sin(6*mu)*151/96 + e1*Math.sin(8*mu)*1097/512);
    set @C1 = @e0sq*POWER(COS(@phi1),2.0);
    --C1 = e0sq*Math.pow(Math.cos(phi1),2);
    set @T1 = POWER(TAN(@phi1),2.0);
    --T1 = Math.pow(Math.tan(phi1),2);
    set @N1 = @a/SQRT(1.0-POWER(@e*SIN(@phi1),2.0));
    --N1 = a/Math.sqrt(1-Math.pow(e*Math.sin(phi1),2));
    set @R1 = @N1*(1.0-@e*@e)/(1.0-POWER(@e*SIN(@phi1),2.0));
    --R1 = N1*(1-e*e)/(1-Math.pow(e*Math.sin(phi1),2));
    set @D = (@x-500000.0)/(@N1*@k0);
    --D = (x-500000)/(N1*k0);
    set @phi = (@D*@D)*(1.0/2.0 - @D*@D*(5.0 + 3.0*@T1 + 10.0*@C1 - 4.0*@C1*@C1 - 9.0*@e0sq)/24.0);
    --phi = (D*D)*(1/2 - D*D*(5 + 3*T1 + 10*C1 - 4*C1*C1 - 9*e0sq)/24);
    set @phi = @phi + POWER(@D,6.0)*(61.0 + 90.0*@T1 + 298.0*@C1 + 45.0*@T1*@T1 - 252.0*@e0sq - 3.0*@C1*@C1)/720.0;
    --phi = phi + Math.pow(D,6)*(61 + 90*T1 + 298*C1 + 45*T1*T1 -252*e0sq - 3*C1*C1)/720;
    set @phi = @phi1 - (@N1*TAN(@phi1)/@R1)*@phi;
    --phi = phi1 - (N1*Math.tan(phi1)/R1)*phi;

    set @latitude = FLOOR(1000000.0*@phi/@drad)/1000000.0;

    set @lng = @D*(1.0 + @D*@D*((-1.0 - 2.0*@T1 - @C1)/6.0 + @D*@D*(5.0 - 2.0*@C1 + 28.0*@T1 - 3.0*@C1*@C1 + 8.0*@e0sq + 24.0*@T1*@T1)/120))/COS(@phi1);
    set @lngd = @zcm+@lng/@drad;
    set @longitude = FLOOR(1000000.0*@lngd)/1000000.0;


    return @longitude;
end
2
SQLGuru

Il existe une solution relativement simple en Perl:

Donc, tout d'abord, assurez-vous que Perl est installé. Ensuite, installez les quatre modules suivants:

Géo :: HelmertTransform Geography :: NationalGrid CAM :: DBF mySociety :: GeoUtil

Vous pouvez le faire de plusieurs manières. Voici comment je l'ai fait:

# Geo::HelmertTransform 
wget http://search.cpan.org/CPAN/authors/id/M/MY/MYSOCIETY/Geo-HelmertTransform-1.13.tar.gz 
tar xzf Geo-HelmertTransform-1.13.tar.gz  
Perl Makefile.PL 
make 
make install

# Geography::NationalGrid 
http://search.cpan.org/CPAN/authors/id/P/PK/PKENT/Geography-NationalGrid-1.6.tar.gz 
tar xzf Geography-NationalGrid-1.6.tar.gz 
Perl Makefile.PL 
make 
make install

# CAM::DBF 
wget http://search.cpan.org/CPAN/authors/id/C/CL/CLOTHO/CAM-DBF-1.02.tgz 
tar xzf CAM-DBF-1.02.tgz 
Perl Makefile.PL 
make 
make install

# mySociety::GeoUtil
# See: http://parlvid.mysociety.org:81/os/ -> https://github.com/mysociety/commonlib/blob/master/perllib/mySociety/GeoUtil.pm
mkdir -p mySociety 
wget -O mySociety/GeoUtil.pm 'https://raw.githubusercontent.com/mysociety/commonlib/master/perllib/mySociety/GeoUtil.pm'
  1. Obtenez des données GB.

Téléchargez l'ensemble de données "Code-Point® Open" de Grande-Bretagne en cliquant ici et en suivant les instructions. Une fois que vous avez téléchargé codepo_gb.Zip, vous pouvez l'extraire comme suit:

décompressez codepo_gb.Zip

En supposant que les fichiers décompressés se trouvent maintenant dans le répertoire en cours, vous pouvez ensuite exécuter le perlscript suivant afin d'analyser les données, d'extraire les abscisses/ordonnées du Go et de les convertir en latitude/longitude.

use strict;
use mySociety::GeoUtil qw/national_grid_to_wgs84/;

while (<>) {
    my @x=split(/,/); # split csv
    my ($pc, $east, $north) = ($x[0], $x[10], $x[11]);
    $pc=~s/\"//g; # remove quotes around postcode
    my ($lat, $lng) = national_grid_to_wgs84($east, $north, "G"); # "G" means Great Britain
    print "$pc,$lat,$lng\n";
}

(Pour appeler, enregistrez le dernier bloc de code dans un fichier .pl, puis appelez Perl script.pl your.csv ... rappelez-vous également que $ x [0], $ x [10] et $ x [11] doivent être les numéros de colonne du code postal, de l'abscisse et de l'ordonnée respectivement.

Crédit complet à http://baroque.posterous.com/uk-postcode-latitudelongitude

2
rickyduck