MapContext
Modelo con algo de control y vista según el patrón Modelo-Vista-Controlador, usado por MapControl para almacenar, gestionar y visualizar capas con información gráfica.
Introducción
MapContext es una clase utilizada por MapControl para almacenar, gestionar y dibujar capas con información gráfica, así como los manejadores de eventos que se producen en ellas.
Contiene un ViewPort con la información necesaria para visualizar un área seleccionada de las capas en el área disponible para ello. Y contiene la conversión de las unidades definidas en el ViewPort, a metros o a centímetros. Véase el apartado Conversión de Unidades de Medida .
Descripción
La librería libFMap permite trabajar con capas gráficas.
Estas capas gráficas se visualizarán de manera que un usuario pueda trabajar con ellas gracias a MapControl, que, siguiendo el patrón Modelo-Vista-Controlador, se desentiende de su almacenamiento (modelo), la gestión de eventos sobre ellas (parte del control), ni la transformación entre la parte que se quiere visualizar y la parte disponible para ello (otra parte del control, esta se encarga ViewPort), para encargarse solo de su visualización y la interacción con herramientas gráficas (vista, y parte del control).
Así pues, será MapContext quien se encargue de proporcionar a MapControl la lógica necesaria para almacenamiento de capas, la gestión de eventos en ellas y su dibujado, utilizando para ello un puerto de vista (ViewPort) y una proyección. Tal es así, que MapContext no puede existir fuera del contexto de MapControl .
MapContext soporta dibujado de las capas que almacena, estableciendo la calidad mediante antialiasing de texto e imágenes, y de renderizado, pero la lógica de dibujado está contenida en cada capa.
El diagrama 1 nos muestra una visión en conjunto de las principales clases e interfaces relacionadas con MapContext. Se puede así observar como MapContext, que implementa la funcionalidad definida en el interfaz Projected, es parte intrínseca de MapControl. También las relaciones con las capas que almacena (FLayers, y GraphicLayer), la información para dibujar el área seleccionada de las capas en el espacio disponible para ello (ViewPort), el buffer (EventBuffer) para tratar conjuntos de eventos recibidos de manera atómica, así como una clase interna para la manipulación genérica de los eventos en cualquier tipo de capa de éste (LayerEventListener).
Tenemos pues, una capa, GraphicLayer, propia de MapContext para los símbolos y geometrías editables, y un árbol con distinto tipo de capas gráficas. Ambas son opcionales, de manera que no es necesario que haya ambos tipos de capas a la vez.
Por último el diagrama se completa con los tipos de excepciones que puede lanzar trabajando con los eventos de las capas que contiene.
![../images/mapcontext/dcmapcontext.png](../../images/mapcontext/dcmapcontext.png)
Diagrama 1: diagrama de clases de MapContext. El paquete "Groups of Registered Listeners" representa un conjunto de listeners que MapContext puede registrar, y lanzar cuando recibe algún evento de los soportados por alguna de ellas.
Se puede ver en el diagrama 2 como EventBuffer implementa interfaces para soportar eventos en una capa (LayerListener), en un conjunto de capas (LayerCollectionListener), del puerto de vista (ViewPortListener), de leyendas en capas (LegendListener), y producidos por la selección en una capa vectorial (SelectionListener).
Los eventos que recibe, los irá almacenando hasta que se le indique que los lance, lo cual aparentará externamente que se ha ejecutado un solo evento atómico.
EventBuffer lanzará un tipo de evento denominado AtomicEvent que contendrá una lista con todos los eventos almacenados entre las operaciones: beginAtomicEvent() y endAtomicEvent(). Además, se pueden registrar *listeners de tipo AtomicEventListener que permitirán realizar el tratamiento que se desee con este tipo de eventos. También, es posible cancelar en tiempo de ejecución el tratamiento de un evento de tipo AtomicEvent, en caso de producirse un error, se lanzaría una excepción de tipo CancelableException.
AtomicEvent
AtomicEvent es muy útil para invocar listeners una vez realizadas una serie de operaciones, evitando que se pudiesen invocar más veces, y que en el ejecución de alguna de estas, se llegase a algún estado inestable. Con ello evitamos también que puedan interferir o ralentizar el proceso de dibujado de capas, y a su vez, mejorar la interactividad.
Antes de empezar a recibir los eventos se debe activar el modo buffer en la instancia de EventBuffer invocando el método beginAtomicEvent(), y una vez se considere que ya no se van a recibir más eventos atómicos, se le debe de indicar que acabe el modo, invocando endAtomicEvent().
AtomicEvent es un tipo de evento propio de la librería libFMap, este tipo de eventos se define genéricamente en la clase FMapEvent.
![images/mapcontext/smalldceventbuffer.png](../images/mapcontext/smalldceventbuffer.png)
Diagrama 2: diagrama donde se muestra la clase EventBuffer, que usa MapContext para trabajar con conjuntos de eventos como atómicos, y donde se muestran los interfaces que implementa.
Pulse aquí si desea ver el diagrama 2 ampliado.
MapContext, por otro lado, permite registrar listeners de eventos de recepción de cambios en las leyendas de las capas (LegendListener), notificación que se ha pintado o se va a pintar una capa (LayerDrawingListener), o de eventos de errores producidos en cualquier operación de los componentes de MapContext (ErrorListener).
![images/mapcontext/dcgroupsreglists.png](../images/mapcontext/dcgroupsreglists.png)
Diagrama 3: conjunto de listeners que puede registrar MapContext y lanzar cuando recibe algún evento de los soportados por alguna de ellas.
Atributos de MapContext
- Nodo raíz opcional de tipo FLayers para el árbol con las capas.
- Capa (GraphicLayer) opcional para geometrías y símbolos editables.
- ViewPort con información para que pueda dibujar MapControl la información seleccionada de las capas.
- Lista de listeners de tipo LegendListener, que se utilizan con los cambios en las leyendas de las capas.
- Lista de listeners de tipo LayerDrawingListener, que se utilizan para notificar que se ha pintado o se va a pintar una capa.
- Un buffer (EventBuffer) para almacenar una serie de eventos, y luego lanzarlos todos de una vez. Estos eventos pueden ser:
- Producidos en una capa (FLayer): LayerEvent.
- Producidos en un colección de capas (FLayers): LayerCollectionEvent, LayerPositionEvent.
- Producidos en leyendas de una capa de tipo clasificable: LegendChangedEvent, LegendEvent.
- Producidos en el puerto de vista (ViewPort): ExtentEvent, ColorEvent, ProjectionEvent.
- Producidos por la selección en una capa alfanumérica: SelectionEvent.
- Eventos atómicos: AtomicEvent.
- Un listener de tipo LayerEventListener, para la notificación de eventos en cualquier tipo de capa de las que contiene MapContext. El tipo de eventos es:
- Se ha añadido, movido o eliminado una capa del árbol de capas.
- Una capa está a punto de añadirse, moverse o eliminarse del árbol de capas.
- Ha cambiado la visibilidad de una capa.
- Ha cambiado la selección de capas en el árbol.
- Una lista con los errores producidos en cualquier capa.
- Una lista con los errores producidos en el mapa.
Conversión de Unidades de Medida
MapContext define dos vectores públicos (uno para metros y otro para centímetros) con los valores con que habría de dividirse un valor dado en una de las medidas soportadas (véase ViewPort) para obtener el equivalente en metros, o en centímetros.
- Vector para conversión a metros: MapContext.CHANGEM .
- Vector para conversión a centímetros: MapContext.CHANGE .
Medidas soportadas
Entre corchetes, el número indica la posición en el vector:
- [0]: kilómetro
- [1]: metro
- [2]: centímetro
- [3]: milímetro
- [4]: milla internacional estatutaria
- [5]: yarda
- [6]: pie
- [7]: pulgada
- [8]: grado - Esta unidad es calculada así: sabiendo que el radio aproximado de la Tierra es de R=6.37846082678100774672e6, queremos medir la distancia en línea recta entre dos puntos en su superfície. Si partimos de tener 2 puntos en la superfície de la Tierra que están a un grado entre ellos, la unión entre estos tres puntos (radio y los 2 puntos en la superfície) nos da un triángulo isósceles, que si lo dividimos por la mitad, nos dará 2 triángulos rectángulos, donde el ángulo menor es de 0.5 grados, y un cateto es el radio terrestre, y el otro la mitad de la distancia (D) que queremos calcular. Aplicando trigonometría y despejando D, tenemos que: D = 2 * (sin (1)) * R. Luego si invertimos este valor, sabremos cuántos grados equivalen a un metro, y éste es el valor que está almacenado en el vector. Idem para la conversión centímetros. Posteriormente, cuando se utilice este valor, se debe tener en cuenta la proyección que se está usando en el mapa, para obtener los grados según dicha proyección.
Ejemplos de uso
- 1 milla estatutaria internacional / MapContext.CHANGEM[4] = M1 metros
- 1 kilómetro / MapContext.CHANGEM[0] = M2 metros
- 1 grado / MapContext.CHANGEM[8] = M3 metros
- 1 milla estatutaria internacional / MapContext.CHANGE[4] = C1 centímetros
- 1 kilómetro / MapContext.CHANGE[0] = C2 centímetros
- 1 grado / MapContext.CHANGE[8] = C3 centímetros
Funcionalidad
- Atomicidad: iniciar o terminar un evento atómico usando EventBuffer, y agregar o eliminar listeners de tipo AtomicEventListener para manejar este tipo de eventos.
- Clonación: soporta dos modos, una clonación total, o una copia parcial con lo necesario para el pintado.
- Dibujado de capas: en principio, el dibujado que soporta es solo de las capas que almacena MapContext, con la lógica de dibujado de cada una. Para acelerar el proceso de dibujado, solo se dibujan o redibujan aquellas capas "sucias", por eso, MapContext soporta tres tipos de dibujado:
- Solo la capa con símbolos y geometrías.
- Dibujado de todas las capas que lo requieran (estén sucias).
- Dibujado de todas las capas. En este caso y en el anterior puede establecer la calidad de dibujado mediante antialiasing de texto y símbolos, y mediante la calidad del renderizado.
- Escala de la vista: obtener o establecer la escala del puerto de vista teniendo en cuenta la resolución en puntos por pulgada en la pantalla.
- Gestión de errores: agregar, obtener o borrar los mensajes de errores producidos.
- Gestión de las capas:
- Obtener, establecer o dibujar la capa de tipo GraphicLayer.
- Obtener las capas, asociar listeners o el buffer de eventos, o dibujarlas.
- Listeners: permite trabajar con distintos tipos de listeners:
- ErrorListener: agregar este tipo de listener, o notificar a todos estos listeners registrados de un conjunto de eventos de error producidos durante una transacción atómica.
- LayerDrawingListener y LegendListener: agregar, eliminar o invocar un listener de alguno de estos tipos.
- Persistencia: crear una nueva instancia de MapContext a partir de una entidad XML, o devolver una entidad XML que represente el objeto MapContext actual (con la menor información necesaria), esta entidad tendrá:
- className: el nombre completo de la clase.
- 1 rama que será la entidad XML del ViewPort interno.
- 1 rama que será la entidad XML a partir del nodo raíz del FLayers interno.
- Comparar con otro objeto MapContext: considerará igual al objeto actual si:
- Ambos objetos son igual según el método equals de la clase Object.
- Si tienen las mismas capas.
- O, si tienen el mismo número de capas, y con el mismo nombre.
- Proyección: establecer u obtener la proyección que se utilizará con todas la capas que almacena MapContext.
- Puerto de vista: establecer u obtener el puerto de vista (ViewPort) actual de MapContext.
- Otra funcionalidad:
- Crear un objeto MapContext a partir de un puerto de vista, y el árbol de capas actual.
- Obtener el extent (dimensión y posición del área) unión del de todas las capas.
- Obtener el extent seleccionado.
- Registar el LayerEventListener del MapContext a un nodo de tipo FLayers .
- Redibujado de todas las capas.
- Define el factor de zoom por defecto para alejar o acercar el encuadre del área visible:
- Factor de Zoom In (acercar): 2
- Factor de Zoom Out (alejar): 0.5
LayerEventListener
Clase definida en MapContext para tratar eventos producidos en cualquier tipo de las capas de éste.
En concreto trata eventos de:
- Se ha añadido, movido o eliminado capa.
- Se está a punto de a añadir, mover o eliminar capa.
- Ha cambiado la visibilidad de alguna capa.