Convertir la latitude et la longitude en un point 2D en Java

1. Vue d'ensemble

Lors de la mise en œuvre d'applications utilisant des cartes, nous nous heurterons généralement au problème de la conversion des coordonnées. La plupart du temps, nous devons convertir la latitude et la longitude en un point 2D à afficher . Heureusement, pour résoudre ce problème, nous pouvons utiliser les formules de la projection Mercator.

Dans ce tutoriel, nous aborderons la projection de Mercator et apprendrons à implémenter ses deux variantes.

2. Projection de Mercator

La projection Mercator est une projection cartographique introduite par le cartographe flamand Gerardus Mercator en 1569. Une projection cartographique convertit les coordonnées de latitude et de longitude sur la Terre en un point sur une surface plane. En d'autres termes, il traduit un point à la surface de la terre en un point sur une carte plane .

Il existe deux manières d'implémenter la projection Mercator. La pseudo projection de Mercator traite la Terre comme une sphère. La véritable projection de Mercator modélise la Terre comme un ellipsoïde . Nous implémenterons les deux versions.

Commençons par une classe de base pour les deux implémentations de projection Mercator:

abstract class Mercator { final static double RADIUS_MAJOR = 6378137.0; final static double RADIUS_MINOR = 6356752.3142; abstract double yAxisProjection(double input); abstract double xAxisProjection(double input); }

Cette classe fournit également le grand et le petit rayon de la Terre mesurés en mètres. Il est bien connu que la Terre n'est pas exactement une sphère. Pour cette raison, nous avons besoin de deux rayons. Premièrement, le rayon majeur est la distance entre le centre de la terre et l'équateur . Deuxièmement, le rayon mineur est la distance entre le centre de la terre et les pôles nord et sud .

2.1. Projection sphérique de Mercator

Le modèle de pseudo-projection traite la terre comme une sphère. Contrairement à la projection elliptique où la Terre serait projetée sur une forme plus précise. Cette approche nous permet une estimation rapide de la projection elliptique plus précise, mais plus lourde de calcul. En conséquence, les mesures directes des distances dans cette projection seront approximatives.

De plus, les proportions des formes sur la carte seront légèrement modifiées. En raison de cette latitude et des rapports de formes d'objets sur la carte comme les pays, les lacs, les rivières, etc. ne sont pas précisément préservés .

Cela s'appelle également la projection Web Mercator - couramment utilisée dans les applications Web, y compris Google Maps.

Implémentons cette approche:

public class SphericalMercator extends Mercator { @Override double xAxisProjection(double input) { return Math.toRadians(input) * RADIUS_MAJOR; } @Override double yAxisProjection(double input) { return Math.log(Math.tan(Math.PI / 4 + Math.toRadians(input) / 2)) * RADIUS_MAJOR; } }

La première chose à noter sur cette approche est le fait que cette approche représente le rayon de la Terre par une constante et non par deux tel qu'il est réellement. Deuxièmement, nous pouvons voir que nous avons implémenté deux fonctions à utiliser pour la conversion en projection sur l'axe des x et en projection sur l'axe des y . Dans la classe ci-dessus, nous avons utilisé la bibliothèque Math fournie par java pour nous aider à simplifier notre code.

Testons une conversion simple:

Assert.assertEquals(2449028.7974520186, sphericalMercator.xAxisProjection(22)); Assert.assertEquals(5465442.183322753, sphericalMercator.yAxisProjection(44));

Il est à noter que cette projection mappera les points dans une boîte englobante (gauche, bas, droite, haut) de (-20037508.34, -23810769.32, 20037508.34, 23810769.32).

2 .2. Projection elliptique de Mercator

La vraie projection modélise la terre comme un ellipsoïde. Cette projection donne des ratios précis pour les objets n'importe où sur Terre . Certes, il respecte les objets sur la carte mais n'est pas précis à 100% . Cependant, cette approche n'est pas la plus fréquemment utilisée car elle est complexe en termes de calcul.

Implémentons cette approche:

class EllipticalMercator extends Mercator { @Override double yAxisProjection(double input) { input = Math.min(Math.max(input, -89.5), 89.5); double earthDimensionalRateNormalized = 1.0 - Math.pow(RADIUS_MINOR / RADIUS_MAJOR, 2); double inputOnEarthProj = Math.sqrt(earthDimensionalRateNormalized) * Math.sin( Math.toRadians(input)); inputOnEarthProj = Math.pow(((1.0 - inputOnEarthProj) / (1.0+inputOnEarthProj)), 0.5 * Math.sqrt(earthDimensionalRateNormalized)); double inputOnEarthProjNormalized = Math.tan(0.5 * ((Math.PI * 0.5) - Math.toRadians(input))) / inputOnEarthProj; return (-1) * RADIUS_MAJOR * Math.log(inputOnEarthProjNormalized); } @Override double xAxisProjection(double input) { return RADIUS_MAJOR * Math.toRadians(input); } }

Ci-dessus, nous pouvons voir à quel point cette approche est complexe concernant la projection sur l'axe des y. En effet, il doit prendre en compte la forme de la terre non ronde. Bien que la véritable approche de Mercator semble complexe, elle est plus précise que l'approche sphérique car elle utilise un rayon pour représenter la Terre un mineur et un majeur.

Testons une conversion simple:

Assert.assertEquals(2449028.7974520186, ellipticalMercator.xAxisProjection(22)); Assert.assertEquals(5435749.887511954, ellipticalMercator.yAxisProjection(44));

Cette projection mappera les points dans une boîte englobante de (-20037508.34, -34619289.37, 20037508.34, 34619289.37).

3 . Conclusion

Si nous devons convertir les coordonnées de latitude et de longitude sur une surface 2D, nous pouvons utiliser la projection Mercator. En fonction de la précision dont nous avons besoin pour notre implémentation, nous pouvons utiliser l'approche sphérique ou elliptique.

Comme toujours, nous pouvons retrouver le code de cet article sur GitHub.