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 .
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.
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 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.
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).
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.
Entre corchetes, el número indica la posición en el vector:
Clase definida en MapContext para tratar eventos producidos en cualquier tipo de las capas de éste.
En concreto trata eventos de:
ViewPort es la clase utilizada por todas aquellas que deseen realizar una transformación afín 2D entre 2 áreas rectangulares, obteniendo coordenadas de píxel a partir de las de la capa visual (llamémosle mapa).
Así, pues, y aunque se utiliza en otras partes de gvSIG, nos centraremos en el uso que hace la clase MapContext, que se encarga del almacenar la información necesaria para visualizar capas en vistas de gvSIG.
Un objeto de tipo MapContext contendrá una instancia de ViewPort, que servirá para que se pueda visualizar el área rectangular de trabajo seleccionada sobre las capas gráficas, en el área disponible (llamémosle imageSize) que hay para visualizarla en el objeto MapControl que los contiene.
Así pues, tenemos 2 planos: el del mapa, y el de la pantalla; y cada uno puede estar en distinta unidad de medidad. MapContext permitirá realizar la conversión de medidas, entre ambos planos vía su objeto tipo ViewPort, y teniendo en cuenta su proyección. ViewPort define varias unidades de medida: metro, kilómetro, yarda, milla estatutaria internacional, etc.
En ViewPort, al área seleccionada para visualizar del mapa, la llamaremos extent, a la disponible para visualizarla, de la pantalla, dimensionSize, y a la seleccionada ajustada para que sea proporcional en ancho y alto a la disponible, adjustedExtent.
Al realizar el ajuste, el área "extra" se rellenará con el mapa, o, en última instancia, con el color de fondo del objeto ViewPort.
ViewPort almacena en un objeto de tipo ExtentHistory los últimos extents, dando la opción de recargar el previo cada vez.
Para acelerar el dibujado, se busca pintar la menor información necesaria, de manera que si al realizar la transformación mapa a ventana hay puntos muy cercanos que representan el mismo píxel o tres píxels juxtapuestos, se pintará uno. Por ello, cada vez que ViewPort recalcula la tranformación afín, además de recalcular adjustedExtent y la escala entre este e imageSize, se calcula la distancia en el mundo real a que equivalen 1 o 3 píxels juxtapuestos.
Las unidades de medida soportadas, tanto para distancias como para del mapa original son:
Interfaz para la captura y tratamiento de los eventos asociados a un ViewPort, que son:
Diseñada para tener un historial de Rectangle2D que representan áreas rectangulares seleccionadas de capa/s gráfica/s.
Se gestionan de manera que se puede agregar nuevas, pero sólo almacena una cantidad máxima (por defecto 10), elimando las más antiguas, y obteniendo siempre la última agregada.