Saltar al contenido

Convertir de latitud, longitud ax, y

Intenta entender el código bien antes de usarlo a tu proyecto si ttienes algo que aportar puedes comentarlo.

Solución:

No existe una solución exacta

No hay mapa isométrico de la esfera al plano. Cuando convierte las coordenadas lat / lon de la esfera a coordenadas x / y en el plano, no puede esperar que esta operación conserve todas las longitudes. Tienes que aceptar algún tipo de deformación. Existen muchas proyecciones de mapas diferentes, que pueden lograr diferentes compromisos entre la preservación de longitudes, ángulos y áreas. Para las partes más pequeñas de la superficie terrestre, el Mercator transversal es bastante común. Es posible que haya oído hablar de UTM. Pero hay muchos más.

Las fórmulas que cita calculan x / y / z, es decir, un punto en el espacio 3D. Pero incluso allí no obtendría las distancias correctas automáticamente. La distancia más corta entre dos puntos en la superficie de la esfera atravesaría esa esfera, mientras que las distancias en la tierra son en su mayoría longitudes geodésicas que siguen la superficie. Entonces serán más largos.

Aproximación para áreas pequeñas

Si la parte de la superficie de la tierra que desea dibujar es relativamente pequeña, puede usar una aproximación muy simple. Simplemente puede usar el eje horizontal X para denotar la longitud λ, el eje vertical y para denotar latitud φ. Sin embargo, la relación entre estos no debe ser de 1: 1. En su lugar, debería utilizar cos (φ0) como la relación de aspecto, donde φ0 denota una latitud cercana al centro de su mapa. Además, para convertir de ángulos (medidos en radianes) a longitudes, se multiplica por el radio de la Tierra (que en este modelo se supone que es una esfera).

  • X = r λ cos (φ0)
  • y = r φ

Esta es una proyección equirrectangular simple. En la mayoría de los casos, podrá calcular cos (φ0) solo una vez, lo que hace que los cálculos posteriores de un gran número de puntos sean realmente económicos.

Quiero compartir con ustedes cómo manejé el problema. He usado la proyección equirrectangular como dijo @MvG, pero este método le brinda posiciones X e Y relacionadas con el mundo (o el mapa completo), esto significa que obtiene posiciones globales. En mi caso, quería convertir coordenadas en un área pequeña (alrededor de 500 m cuadrados), por lo que relacioné el punto de proyección con otros 2 puntos, obteniendo las posiciones globales y relacionándome con las posiciones locales (en pantalla), así:

Primero, elijo 2 puntos (arriba a la izquierda y abajo a la derecha) alrededor del área donde quiero proyectar, como esta imagen:

ingrese la descripción de la imagen aquí

Una vez que tengo el área de referencia global en lat y lng, hago lo mismo para las posiciones de la pantalla. Los objetos que contienen estos datos se muestran a continuación.

//top-left reference point
var p0 = 
    scrX: 23.69,        // Minimum X position on screen
    scrY: -0.5,         // Minimum Y position on screen
    lat: -22.814895,    // Latitude
    lng: -47.072892     // Longitude

//bottom-right reference point
var p1 = 
    scrX: 276,          // Maximum X position on screen
    scrY: 178.9,        // Maximum Y position on screen
    lat: -22.816419,    // Latitude
    lng: -47.070563     // Longitude

var radius = 6.371;     //Earth Radius in Km

//## Now I can calculate the global X and Y for each reference point ##\

// This function converts lat and lng coordinates to GLOBAL X and Y positions
function latlngToGlobalXY(lat, lng)
    //Calculates x based on cos of average of the latitudes
    let x = radius*lng*Math.cos((p0.lat + p1.lat)/2);
    //Calculates y based on latitude
    let y = radius*lat;
    return x: x, y: y

// Calculate global X and Y for top-left reference point
p0.pos = latlngToGlobalXY(p0.lat, p0.lng);
// Calculate global X and Y for bottom-right reference point
p1.pos = latlngToGlobalXY(p1.lat, p1.lng);

/*
* This gives me the X and Y in relation to map for the 2 reference points.
* Now we have the global AND screen areas and then we can relate both for the projection point.
*/

// This function converts lat and lng coordinates to SCREEN X and Y positions
function latlngToScreenXY(lat, lng)
    //Calculate global X and Y for projection point
    let pos = latlngToGlobalXY(lat, lng);
    //Calculate the percentage of Global X position in relation to total global width
    pos.perX = ((pos.x-p0.pos.x)/(p1.pos.x - p0.pos.x));
    //Calculate the percentage of Global Y position in relation to total global height
    pos.perY = ((pos.y-p0.pos.y)/(p1.pos.y - p0.pos.y));

    //Returns the screen position based on reference points
    return 
        x: p0.scrX + (p1.scrX - p0.scrX)*pos.perX,
        y: p0.scrY + (p1.scrY - p0.scrY)*pos.perY
    


//# The usage is like this #\

var pos = latlngToScreenXY(-22.815319, -47.071718);
$point = $("#point-to-project");
$point.css("left", pos.x+"em");
$point.css("top", pos.y+"em");

Como puede ver, hice esto en javascript, pero los cálculos se pueden traducir a cualquier idioma.

PD: Estoy aplicando las posiciones convertidas a un elemento html cuya identificación es “punto a proyecto”. Para usar este fragmento de código en su proyecto, debe crear este elemento (diseñado como posición absoluta) o cambiar el bloque “uso”.

Dado que esta página aparece en la parte superior de Google mientras buscaba este mismo problema, me gustaría proporcionar respuestas más prácticas. La respuesta de MVG es correcta pero más bien teórica.

He creado una aplicación de trazado de pistas para el fitbit ionic en javascript. El siguiente código es cómo abordé el problema.

//LOCATION PROVIDER
index.js
var gpsFix = false;
var circumferenceAtLat = 0;
function locationSuccess(pos)
  if(!gpsFix)
    gpsFix = true;
    circumferenceAtLat = Math.cos(pos.coords.latitude*0.01745329251)*111305;
  
  pos.x:Math.round(pos.coords.longitude*circumferenceAtLat),
  pos.y:Math.round(pos.coords.latitude*110919), 
  plotTrack(pos);

plotting.js

plotTrack(position)

let x = Math.round((this.segments[i].start.x - this.bounds.minX)*this.scale);
let y = Math.round(this.bounds.maxY - this.segments[i].start.y)*this.scale; //heights needs to be inverted

//redraw?
let redraw = false;

//x or y bounds?
 if(position.x>this.bounds.maxX)
   this.bounds.maxX = (position.x-this.bounds.minX)*1.1+this.bounds.minX; //increase by 10%
   redraw = true;
 
 if(position.xthis.bounds.maxY)
   this.bounds.maxY = (position.y-this.bounds.minY)*1.1+this.bounds.minY; //increase by 10%
    redraw = true;
 
 if(position.y

Si eres capaz, eres capaz de dejar un ensayo acerca de qué te ha impresionado de esta división.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *