Personal tools
You are here: Home Development Documents gvSIG desktop 1.0 / 1.1 FMap MapContext MapContext
Document Actions

MapContext

by Pablo Piqueras last modified 2010-06-01 22:46

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.

.. figure:: ../images/mapcontext/dcmapcontext.png
   :width: 786
   :height: 480
   :align: center

   *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*.

.. figure:: images/mapcontext/smalldceventbuffer.png
   :height: 420
   :width: 800
   :align: center

   *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*).

.. figure:: images/mapcontext/dcgroupsreglists.png
   :height: 374
   :width: 641
   :align: center

   *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.


.. _aquí: ../images/mapcontext/dceventbuffer.png
.. _libFMap: ../introduccion/introduccion
.. _FLayer: ../dirlayers/layers
.. _FLayers: ../dirlayers/layers
.. _ViewPort: ./viewport
.. _MapControl: ../dirmapcontrol/mapcontrol/

View source document


Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: