Fundamentos de Programación > Clases > Ejercicios > ejercicio 1
Puede descargar AgenciaViaje.jar para ver cómo funciona.
Para ejecutar, necesitará un mapa de la Tierra:
mapa ortográfico, centrado en España
El problema consiste en calcular rutas geodésicas (mínina distancia) entre dos puntos sobre la superficie de una esfera.
El alumno debe presentar las siguientes clases:
Para calcular las coordenadas a partir de la longitud y latitud, use trigonometría:
Como radio de la tierra, use R = 1.
Para interpretar las coordenadas de un punto, por ejemplo "40 26 N 3 42 W", debe
Más precisamente:
private double extraeLongitud(String coordenadas) { String[] part = coordenadas.split(" "); if (part.length != 6) throw new IllegalArgumentException("notacion: grados minutos N|S grados minutos E|W"); // angulo horizontal double longitud = Math.toRadians(Integer.parseInt(part[3]) + Integer.parseInt(part[4]) / 60.0); if (part[5].equalsIgnoreCase("W")) longitud = -longitud; return longitud; } private double extraeLatitud(String coordenadas) { String[] part = coordenadas.split(" "); if (part.length != 6) throw new IllegalArgumentException("notacion: grados minutos N|S grados minutos E|W"); // angulo vertical double latitud = Math.toRadians(Integer.parseInt(part[0]) + Integer.parseInt(part[1]) / 60.0); if (part[2].equalsIgnoreCase("S")) latitud = -latitud; return latitud; }
Para pasar de un punto en 3D a un punto en el plano de proyección, necesitamos conocer la posición del plano de proyección respecto de la esfera.
Siendo
Para este ejercicio, considere R = 1.
Un detalle importante es saber cuándo un punto está en el lado visible o en el otro lado. La siguiente fórmula da valores positivos si el punto está de este lado, y negativos si está del otro lado
Para el ejercicio, si el punto está del otro lado, getProyeccion(Punto3D punto) debe devolver NULL.
En Internet puede encontrar numerosas imágenes de la Tierra. Las fotografías desde un punto suficientemente lejano (desde cerca del infinito), son proyecciones ortográfinas son prácticamente proyecciones ortográficas. A veces las imágenes indican el punto central de la proyección; en otras ocasiones, tendrá que determinarlo usted mismo.
Por ejemplo, la imagen del prncipio de esta página web tiene como centro de proyección el punto situado en "55 0 N 20 0 E".
public static void main(String[] args)
Sirve para arrancar el programa. Internamente debe
Necesita disponer de un constructor de AgenciaViajes, que será PRIVATE. Internamente, este constructor se limita a crear un objeto de clase MapaOrtografico y guardarlo en un campo privado de AgenciaViajes.
public void viaje(String ciudadOrigen, String ciudadDestino)
Este método pinta la ruta en pantalla usando la clase Ventana que se preparó en el constructor.
Lo primero que necesitamos es conocer las coordenadas 3D de los puntos A (origen) y B (destino). Para ello usaremos el método getCoordenadas(String) de la clase Ciudades. Esta clase tiene registradas una serie de ciudades del planeta. Puede añadir otras ciudades. Es fácil encontrar en Internet la coordenadas de las principales ciudades del Mundo.
Necesitará un objeto de clase ProyeccionOrtografica. Construya uno. No necesita guardarlo en un campo, basta que sea una variable local.
Usando este objeto, es fácil calcular las coordenadas de los puntos A y B. Calcúlelas y marque el punto en la Ventana, algo así
mapa.punto(proyeccion.getProyeccion(A), Color.RED);
Para trazar la ruta necesitamos navegar por la superficie de la Tierra a lo largo del corte de la superficie de la esfera y un plano que pase por 3 puntos: A, B y en centro C de la Tierra.
El centro C de la esfera tiene como coordenadas 3D los valores (0, 0, 0). Construya el punto C y el plano 3D que pasa por los 3 puntos.
Para identificar una serie de puntos de la ruta, se sugiere el siguiente algoritmo
Vector3D interseccion = new Vector3D(plano1.getVectorNormal(), plano2.getVectorNormal());el punto de la superficie de la Tierra será un punto de la intersección de la esfera de radio 1 y una línea a lo largo del vector intersección anterior;
double t = 1 / Math.sqrt(interseccion.getVx() * interseccion.getVx() + interseccion.getVy() * interseccion.getVy() + interseccion.getVz() * interseccion.getVz()); // puntos de interseccion de la linea y la esfera Punto3D s1 = new Punto3D( interseccion.getVx() * t, interseccion.getVy() * t, interseccion.getVz() * t); Punto3D s2 = new Punto3D( -interseccion.getVx() * t, -interseccion.getVy() * t, -interseccion.getVz() * t);
mapa.punto(proyeccion.getProyeccion(s), Color.BLUE); ultimo = s; mapa.pinta();
private double seleccionaDelta(double longitudA, double longitudB)
Se recomienda hacer un método privado para calcular los incrementos de longitud entre pasos de ruta.
Normalmente debe devolver la diferencia de longitud entre A y B, dividida por el número de pasos. Dando un resultado positivo si viajamos hacia el Este, y negativo si viajamos hacia el Oeste.
Tenga en cuanta que debe elegir la ruta más corta, lo que a veces supone cruzar al meridiano internacional de cambio de fecha (opuesto al meridiano 0 de Greenwich). Para ello, tenga en cuenta que si la diferencia de longitud entre A y B es, en valor absoluto, mayor que PI, es que está haciendo una ruta demasiado larga y debe viajar en dirección opuesta.
Para que ponga a punto este pequeño método, la siguiente tabla facilita algunos puntos de prueba:
A B delta Santiago Amsterdam 0.066 Amsterdam Santiago -0.066 Santiago Auckland -0.100 Auckland Santiago 0.100
Se han usado ciudades de la clase Ciudades y PASOS = 20.