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

FMap

by Grupo gvSIG last modified 2012-09-08 00:35

Es el corazón SIG de la plataforma. Incluye todas las clases necesarias para manejar objetos SIG, así como drivers y adaptadores para manejar los formatos más usados para el almacenamiento de los datos cartográficos. Dentro de esta librería encontramos clases para leer y escribir los formatos soportados, dibujar los mapas a las escalas adecuadas, asignar leyendas, definir simbologías, realizar búsquedas, consultas, análisis, etc.




Introducción

Introducción

Introducción

libFMap es un proyecto software desarrollado en Java como parte del Proyecto gvSIG, con la finalidad de disponer de una librería que permita trabajar con información geográfica, cartográfica, topográfica, ... según estándares internacionales, y a la vez con imágenes, en forma de capas gráficas, tipo raster o vectorial.

Para poder trabajar con dicha información, incluye drivers para el acceso a los múltiples formatos, y ofrece un conjunto de herramientas para trabajar con las capas visuales: zoom in, zoom out, pan (para arrastrar usando el ratón), selección de figuras geométricas, etc.

Soporta edición de capas (aquellas que se puedan editar), con un conjunto propio de herramientas. Trabaja también con índices espaciales, para acelerar el acceso a los datos (esto es recomendable cuando hay muchos en las capas, o incluso están en repartidos en múltiples niveles).

Existen, pues, una amplia variedad de tipos de capas, cada una con su propia estrategia a la hora de dibujarse y recorrer su información.

libFMap agrupa las capas en forma de árbol, de manera que se amplía el horizonte de trabajo, pudiendo servir tanto para obras civiles, medio ambiente, arquitectura, arqueología, etc.

Diagrama
images/introduction/dcpaqueteslibfmap.png

Diagrama 1: Visión estructural de la librería libFMap. Se muestra solo la división al primer nivel para simplificar el diagrama.

Enlaces de Interés
  • FLayers: Información sobre las capas: tipos, estatus, funcionalidad, ...
  • MapControl: Componente gráfico central de libFMap, incorpora las capas, soporte para su dibujado, su comportamiento, herramientas para trabajar con ellas, ...
  • gvSIG: Toda la información pública del Proyecto gvSIG.

MapControl

Behavior

Introducción

Los distintos modos en que un usuario puede interactuar con un objeto de tipo MapControl son lo que se denomina behavior.

Así, en un momento dado, puede ser necesario tener que trabajar seleccionando una polilínea, o un punto, o un rectángulo, o arrastrando el ratón sobre un MapControl, o, porqué no, combinando varios de estos comportamientos individuales (por ej. seleccionando un punto del objeto de tipo MapControl y arrastrando (drag & drop) el ratón) ... Cada uno de estos comportamientos posibles con los que trabajar con MapControl es lo que, en la terminología de libFMap se denomina behavior. De hecho, es común utilizar varios de estos comportamientos básicos combinados para definir la interacción con MapControl vía una herramienta determinada.

Ninguno de los behavior se encargará de tratar la información seleccionada por el usuario sobre MapControl, para esto están las ToolListeners. Behavior se encarga de procesar los eventos que se producen en MapControl, preparando eventos genéricos que enviará a la ToolListener actual, con la información necesaria.

De este modo, se consigue simular distintas herramientas con las que un usuario podrá trabajar con un objeto de tipo MapControl, y a la vez facilitar al desarrollador el incorporar nuevas herramientas, basándonos en el principio de divide y vencerás y una variante del patrón software "Chain-of-responsibility pattern".

Actualmente, todos los eventos que puede recibir cualquier tipo de behavior son producidos por el manejo del ratón sobre el objeto MapControl, y estos pueden ser de tipo MouseEvent, o de tipo MouseWheelEvent, según su naturaleza, atenderá a uno u otro tipo de evento. Por otro lado, cualquiera de las excepciones que puede lanzar son de tipo BehaviorException.

Diagramas

El diagrama 1 muestra cómo se integra en MapControl, y la relación con los tipos de eventos que puede recibir, o excepciones que puede lanzar.

images/mapcontrol/dcbehavior.png

Diagrama 1: Diagrama de clases centrado en Behavior.

Tipos de behavior en libFMap

El diagrama 2 muestra los tipos de comportamientos básicos implementados en la librería libFMap.

images/mapcontrol/dcbehaviortypes.png

Diagrama 2: Tipos de comportamiento implementados en libFMap.

Tipo Proyecto Modo de interacción Eventos hacia la herramienta Herramienta asociada
CADToolAdapter extCAD

Por Ratón:

Haciendo click con el botón derecho del ratón solicita a la herramienta actual que muestre un popup con las opciones de edición actualmente disponibles. Si es con el botón izquierdo agrega un punto en dicha posición. Soltando cualquier botón solicita a MapControl que se repinte. Mientras que, moviéndolo además actualiza las coordenadas en la barra de estado. En caso que esté habilitado el snap, actualizará el icono del cursor conforme el punto de control más cercano en una pequeña área de tolerancia bajo.

Por Teclado:

En caso de escribir un comando por teclado, cambia a una herramienta en modo selección, y según el tipo de comando escrito y el estado actual de la herramienta, puede tomar la información como un nuevo punto, una opción o el valor de una opción. Aplicará cambios, o notificará que el comando no es válido, en la misma consola de edición.

MouseEvent, InputEvent 1 o más CADTool
CircleBehavior libFMap Pulsando el botón izquierdo del ratón, permite definir un área circular: primero se indica centro, y luego un punto de la circunferencia, mediante el botón izquierdo del ratón. MeasureEvent CircleListener
CompoundBehavior libFMap Funciona como una combinación de Behavior de libFMap. El modo de interacción dependerá de los Behavior que lo componen. MouseEvent, MouseWheelEvent 1 o más ToolListener
DraggerBehavior libFMap Arrastrando el ratón y manteniendo pulsado cualquiera de sus botones. Irá actualizando MapControl teniendo en cuenta la variación del punto actual respecto al inicial. Una vez soltado el ratón, el cambio será permanente. MoveEvent PanListener
MouseMovementBehavior libFMap Notifica eventos de movimiento, o arrastre (mantener pulsado un botón del ratón y a la vez moverlo) del ratón sobre MapControl. PointEvent PointListener
MoveBehavior libFMap Igual que DraggedBehavior pero manteniendo pulsado el botón izquierdo del ratón. MoveEvent PanListener
PointBehavior libFMap

Selección de un punto con un click por medio de cualquier botón del ratón.

Pulsando una vez, solicita la cancelación del dibujado actual de MapControl.

Siempre notifica el que un botón haya dejado de estar pulsado, y en caso que se hubiese hecho un click doble, notifica el evento al soltar el botón.

PointEvent PointListener
PolylineBehavior libFMap Con un click de cualquier botón del ratón, notifica y almacena el punto, iniciándose así el modo de dibujado de polilínea. Todos los eventos de movimiento o arrastre del ratón posteriores son tambien notificados, hasta que con 2 clicks se finaliza el modo, enviando todos los vértices seleccionados por el usuario a la ToolListener asociada. MeasureEvent PolylineListener
PolygonBehavior libFMap Igual a PolylineBehavior, pero ahora el primer punto será también el último de la polilínea, y cada nuevo en agregarse será el penúltimo. MeasureEvent PolylineListener
RectangleBehavior libFMap

Notifica el punto donde se hizo click con el botón izquierdo del ratón, a partir de ese momento según se arrastre el ratón se mostrará un rectángulo tomando como segundo vértice en diagonal la posición actual del cursor. Una vez se suelte el botón, quedará definida el área rectangular. Así pues, durante el arrastre y al soltar el botón, se generarán eventos que notifiquen la posición actual del ratón.

Via los puntos inicial y el final se definirá un rectángulo con los lados paralelos a los ejes X e Y de coordenadas.

RectangleEvent RectangleListener
Enlaces de interés

Chain of responsibility Pattern: información acerca de este patrón software, con código fuente de ejemplo.

ToolListeners: herramientas que combinadas con algún comportamiento Behavior permiten trabajar con MapControl.

ToolListener events: eventos que utiliza un Behavior para notificar información a su/s ToolListener asociada.

Eventos relacionados con las ToolListeners

Introduccción

Según el comportamiento que se quiere simular en MapControl, los eventos de ratón que se produzcan en este, serán base para la creacción de algún tipo de evento que complete la información necesaria para que la ToolListener asociada a dicho comportamiento pueda completar la simulación de la herramienta con la que se interactúa con MapControl.

Existen cuatro tipos de estos eventos, todos ellos producidos como consecuencia de eventos de ratón (MouseEvent) al trabajar el usuario sobre dicha vista, que son los únicos que puede recibir cualquiera de los tool listeners.

Así, una herramienta como el pan, que requiere arrastrar con el ratón, necesitará recibir no sólo la información del evento de ratón nativo de Java (MouseEvent), sino también las posiciones inicial y final de dicho arrastre.

Si en cambio se está seleccionando una herramienta que solo requiere información de un punto dado, necesitaré dicho punto. O si es por área, información de dicha área.

Se buscaba tener el mínimo número de eventos posibles, y que sean lo más genéricos para que sirvan para el máximo número de tipos de tool listeners, y así facilitar la programación. Esto hizo que se crearan los 4 tipos de eventos siguientes, que se crearán como consecuencia de alguna acción del ratón sobre MapControl y cuyo evento (MouseEvent) almacenarán internamente. Decir, por último que ninguno de estos eventos se considera de tipo FMapEvent, dado que estos últimos están más relacionados con el dibujado de las capas.

Tipos

MeasureEvent: evento asociado a tool listeners que permiten crear o seleccionar polilíneas abiertas, cerradas, que se corten o no.

Información adicional que aporta:

  • Vector con la coordenada X de todos los puntos seleccionados.
  • Vector con la coordenada Y de todos los puntos seleccionados.
  • Un objeto con toda la geometría dividida en líneas rectas y curvas de Bezier cuadráticas o cúbicas.
  • Evento de ratón producido en MapControl, que fue la causa de que Behavior generase este evento.

MoveEvent: evento asociado a tool listeners que requieren que el usuario realice un movimiento del ratón sobre pantalla, tipo drag & drop (arrastrar y soltar).

Información adicional que aporta:

  • Punto inicial del movimiento de ratón.
  • Punto final del movimiento de ratón.
  • Evento de ratón producido en MapControl, que fue la causa de que Behavior generase este evento.

PointEvent: evento asociado a tool listeners que requieren que el usuario seleccione un punto.

Información adicional que aporta:

  • Punto donde se generó el evento.
  • Evento de ratón producido en MapControl, que fue la causa de que Behavior generase este evento.

RectangleEvent: evento asociado a tool listeners que requieren que el usuario seleccione un área rectangular.

Información adicional que aporta:

  • Rectangulo seleccionado en coordenadas del mundo.
  • Rectangulo seleccionado en coordenadas de pantalla (píxels).
  • Evento de ratón producido en MapControl, que fue la causa de que Behavior generase este evento.
Diagrama
images/mapcontrol/dceventsrelatedtoollisteners.png

Diagrama: Muestra la estructura y las relaciones de este tipo de eventos con las ToolListeners básicas, el resto hereran de ellas, y por tanto mantienen la misma relación con estos eventos.

MapControl

Introducción

MapControl es un componente Java de intefaz gráfica, que pinta un conjunto de capas con información gráfica, vía su objeto MapContext que las contiene, y captura los eventos de ratón que se producen en él vía un Behavior (que puede ser una composición de varios) que define cómo se comporta actualmente, enriqueciendo dichos eventos con la información necesaria para poder simular la herramienta de interacción actual, vía ToolListener, que será la que complete la simulación.

Descripción

Según el tipo de capas visibles y activas, gvSIG nos proporcionará una serie de herramientas con las que el usuario podrá interaccionar con el objeto MapControl que contiene las capas.

Al seleccionar cualquiera de las herramientas disponibles, lo que se está haciendo es seleccionar un comportamiento para trabajar con MapControl, que puede ser el resultado de múltiples comportamientos denominados cada uno Behavior, cada uno con una ToolListener.

La librería libFMap define cada uno de estos comportientos básicos, que procesan los eventos de ratón producidos en MapControl, generando otros eventos con la información necesaria según su naturaleza. Estos eventos serán los que se envíen a la herramienta actualmente seleccionada para interactuar con MapControl.

Dicha herramienta tendrá un icono que verá el usuario en su cursor, y una serie de métodos que serán invocados según el tipo de evento que se produzca.

Las ToolListener incluyen la lógica que complementa a los Behavior para simular una herramienta con la que interactuar con un objeto de tipo MapControl.

En la librería libFMap se definen las ToolListener básicas, pero existen otras muchas que heredan de estas, y están definidas en otros proyectos.

MapControl utiliza un doble-buffer propio para el dibujado, intentando en la medida que sea posible, dibujar en el buffer, y una vez finalizado, enviar esa información a pantalla.

MapControl crea un objeto compartido de tipo Cancellable, con el que notificará a MapContext y a las capas que se estén dibujando el que pueden seguir con el proceso, o deben cancelar el dibujado. (No todas las capas pueden cancelar su dibujado).

Normalmente, cuando se utiliza una instacia de MapControl, se asignan sus posibles comportamientos, identificándolos cada uno con una cadena de texto. Posteriormente, según la herramienta con la que el usuario esté trabajando, se le indicará al objeto MapControl, que utilice como "herramienta activa" uno de ellos.

Pintado de MapControl

Se busca siempre tener el menor tiempo de respuesta en la interacción con el usuario, por ello en caso que el proceso de pintado sea pesado, se actualiza la pantalla con el valor de pintado del buffer cada t milisegundos.

MapControl se encarga de atender sus peticiones de pintado mediante un objeto de tipo Drawer2 que notificará a su hilo trabajador para que ejecute solo una a la vez, manteniendo otra en espera. Si llegase una petición de pintado, habiendo otra en espera, esta segunda se perdería. Por otro lado, si el hilo "trabajador" encargado de pintar, finalizase, quedaría en espera pasiva, hasta nueva notificación por parte de Drawer2.

Para indicar qué es lo que se repintará, MapControl define 3 estados posibles:

  • ACTUALIZADO / UPDATED : refresca la pantalla con el contenido del buffer. Es proceso de pintado rápido.
  • DESACTUALIZADO / OUTDATED : actualizar toda la información visual de todas las capas visibles y disponibles. Puede ser el proceso más pesado de pintado.
  • ONLY_GRAPHICS : actualizar capa/s de simbología y geometrías.
Proceso de pintado

El proceso de pintado de MapControl sigue el siguiente algoritmo:

  • Si el status es ACTUALIZADO:
    • Si hay doble-buffer:
      • Si hay un Behavior para gestionar la instancia de MapControl: delega el proceso de dibujado a dicho Behavior, invocando: behavior_instance.paintComponent(g).
      • Sino, repinta rápidamente la información gráfica actual, invocando: g.drawImage(image,0,0,null).
  • Si el estado es OUTDATED o ONLY_GRAPHICS:
    • Repinta rápidamente la información previa invocando g.drawImage(image,0,0,null), y crea una petición de pintado (PaintingRequest), con la que delegará el proceso pesado de pintado al hilo trabajador de Drawer2, siguiendo el patrón software SingleWorketThread, e iniciando el temporizador con el que actualizará la pantalla cada 360 ms. según se ejecuta el proceso pesado de pintado. Una vez es atendida la petición de dibujado, se invoca a MapContext para que pinte las capas: mapContext.draw(image, g, cancel,mapContext.getScaleView()).

Notas sobre el proceso de pintado:

  • Puede ser cancelado en cualquier momento invocando cancelDrawing().
  • Será en última instancia la implementación de pintado de cada capa la que la pinte, y realice la cancelación, pudiendo haber quienes no cancelen su proceso de pintado.
  • Se puede forzar a pintar todas las capas de MapControl invocando: drawMap(boolean).
  • Se puede forzar a repintar solo las capas sucias invocando: rePaintDirtyLayers().
  • Se puede forzar a repintar solo la capa GraphicLayer invocando: drawGraphics().
Algoritmo de Pintado
  • MapControl al iniciarse crea un objeto Drawer2. Este a su vez crea un hilo de tipo Worker.
  • Cada vez que se invoca a paintComponent(Graphics g) de MapControl, y su estatus es ACTUALIZADO:
    • Si hay doble-buffer:
      • Si hay una herramienta activa: le delega el control para que pinte sobre el front-buffer.
      • Sino, refresca el front-buffer.
  • Cada vez que se invoca a paintComponent(Graphics g) de MapControl, y su estatus es DESACTUALIZADO, o ONLY_GRAPHICS, creará una nueva petición de tipo PaintingRequest que se la asignará al objeto de tipo Drawer2, e iniciará el temporizador. Drawer2 almacenará la petición como waitingRequest, y, en caso que el hilo trabajador estuviese esperando, le notifica que vuelva a ejecución.
  • El hilo trabajador de Drawer2, (Worker), una vez en ejecución, intenta recoger una petición (PaintingRequest).
  • Si no hubiese ninguna, Drawer2 lo pondría en espera pasiva.
  • En caso que hubiese alguna, Drawer2 le asignaría waitingRequest, que pasaría a ser ahora paintingRequest.
  • Si estando el hilo trabajador en ejecución, llegase otra petición, pasaría a ser waitingRequest.
  • El hilo Worker:
    • Si MapControl tiene double-buffer donde pintar:
      • Avisa a MapControl para que cancele cualquier proceso de dibujado previo, invocando cancelDrawing().
      • Ejecuta el algoritmo de pintado de la petición: painting_request_instance.paint():
        • Fuerza la cancelación de procesos de dibujado previos, vía el objeto compartido de tipo CancelDraw.
        • Si status es DESACTUALIZADO:
          • Obtiene el buffer sobre el que pintar: el back-buffer del double-buffer de MapControl: Graphics2D g.
          • Actualiza el back-buffer con el color de fondo del ViewPort, o en blanco, si no hubiese ninguno definido.
          • Pone status = ACTUALIZADO.
          • Avisa a MapContext para que pinte las capas: mapContext.draw(double-buffer, front-buffer, canceldraw_compartido, escala_del_ViewPort).
        • Si status es ONLY_GRAPHICS:
          • Pone status = ACTUALIZADO.
          • Avisa a MapContext para que pinte GraphicLayer: mapContext.drawGraphics(double-buffer, front-buffer, canceldraw_compartido, escala_del_ViewPort).
        • Para el temporizador.
        • Repinta MapControl.
    • Sino, pondrá: status = DESACTUALIZADO
  • Por su parte, cada vez que se dispare el temporizador, mandará refrescar MapControl, de modo que el usuario verá la imagen parcialmente, cada vez más completa.
  • Si se produce alguna excepción ejecutando el código de la petición de pintado (PaintingRequest), parará el temporizador, y la notificará a ExceptionHandlingSupport, para que la notifique a todos los ExceptionListener registrados.
Gestión de Excepciones

MapControl permite registrar listeners, de tipo ExceptionListener, con los que recibir notificación de expcepciones producidas:

  • Atendiendo una petición de pintado.
  • Trabajando con la herramienta activa.
  • O, ejecutando alguna de las operaciones soportadas por defecto por MapControl: zoom in, o zoom out .
Diagrama

El diagrama 1 muestra los principales elementos que intervienen con MapControl.

images/mapcontrol/smalldcmapcontrol.png

Diagrama 1: diagrama de clases simplificado de MapControl. Versión en tamaño reducido.

Pulse aquí para ver el diagrama en grande.

Descripción del diagrama
  • MapControl es un componente Swing que implementa:
    • ComponentListener para atender eventos producidos al moverlo, ocultarlo, redimensionarlo, o mostrarlo. En realidad estos métodos no están implementados, sino que se han dejado por si alguna subclase los necesitase.
    • CommandListener para atender eventos producidos por la ejecución de operaciones de edición de capas.
  • Contiene un doble-buffer propio sobre el que realizar el proceso de pintado: se dibuja en el back-buffer, y una vez completado, o cada cierto tiempo si el proceso es largo, se actualiza el front-buffer con el back-buffer.
  • Crea un objeto (CancelDraw) compartido de tipo Cancellable con el que podrá notificar a todas las capas y MapContext si pueden continuar el proceso de dibujado, o deben cancelarlo.
  • Las distintas capas con información gráfica las almacena en un objeto de tipo MapContext, que servirá para gestionarlas, gestionar los eventos (agrupados en AtomicEvent) que se producen en ellas mediante un buffer (EventBuffer), proyectarlas según una proyección y el puerto de vista (ViewPort) disponible, y controlar su dibujado: calidad, ...
  • Contiene una serie de identificadores que definen su posible comportamiento, cada identificador asociado a un Behavior o una composición de estos. En un momento dado, tendrá como currentMapTool, sólo uno de estos comportamientos posibles.
  • Define un listener: MapToolListener, que será el encargado de procesar cualquier evento de ratón que se produzca en MapControl, y notificarlo a la herramienta activa: currentMapTool. Para el caso del evento por rueda del ratón: MouseWheelEvent, solo notifica un evento por segundo, para dar tiempo a que se pueda cancelar el proceso anterior.
  • La herramienta activa delega el control a la ToolListener asociada, enviándole un evento con la información necesaria para que realice dicho procesamiento. Cualquier excepción durante dicho procesamiento implicará el lanzamiento de alguna BehaviorException.
  • BehaviorException es una simple excepción de Java, que sirve para identificar un problema producido en la ejecución del código de un Behavior.
  • Toda excepción producida atendiendo una petición de pintado, trabajando con la herramienta activa, o, ejecutando alguna de las operaciones soportadas por defecto por MapControl: zoom in, o zoom out, será lanzada por un objeto de tipo ExceptionHandlerSupport a las ExceptionListener que estuviesen registradas.
  • Todos los eventos (de tipo AtomicEvent) que pueda lanzar el objeto interno de tipo MapContext serán capturados y procesados por un listener de tipo MapContextListener definido en MapControl.
  • Siempre que es invocado el método protected void paintComponent(Graphics g) de MapControl, y su estatus es DESACTUALIZADO, o ONLY_GRAPHICS, se creará una nueva petición de pintado: PaintingRequest, que se le notificará el Drawer2, objeto encargado de gestionarlas.
  • El objeto interno de tipo Drawer2 posee un hilo trabajador (Worker) que es el que realiza el pintado implementado en la petición (PaintingRequest). Drawer2 sólo almacena 2 peticiones de pintado, la que está siendo atendida, y una en cola:
    • Si llega una nueva petición, se borra la que estaba en cola.
    • Si el hilo trabador acaba, intenta obtener la petición en cola, en caso que no hubiese, pasa a espera pasiva.
    • Estando el hilo trabajador en espera pasiva, si llega una petición de pintado, se notifica al hilo para que vuelva a ejecución.
  • Contiene un temporizador (Timer) que utilizará para refrescar el front-buffer del double-buffer cada 360 ms. con la información del back-buffer, mientras se está ejecutando un proceso pesado de pintado.
Funcionalidad
  • Cancelación del pintado: permite cancelar el proceso actual de pintado en cualquier momento.
  • Componente Java de GUI: el desarrollador puede incorporar MapControl en la interfaz gráfica de su aplicación como otro JComponent más.
  • Doble buffer: obtener el doble-buffer con el que pinta las capas.
  • Herramientas:
    • Agregar un Behavior, o un conjunto (que será un CompoundBehavior), identificado por un String, como herramienta con las que se podría interactuar con el objeto MapControl.
    • Buscar una herramienta registrada, vía su identificador.
    • Obtener todas las herramientas registradas, junto con su identificador.
    • Obtener sólo los identificadores de las herramientas registradas.
    • Establacer una de las herramientas registradas, como activa, de modo que definirá el comportamiento de MapControl.
    • Obtener la herramienta activa, o su identificador.
    • Averiguar si hay una determinada herramienta registrada.
    • Establecer como activa, la que previamente lo estuvo.
  • Listeners:
    • ExceptionListener : agregar, o eliminar este tipo de listener, o notificar a todos estos listeners registrados de alguna excepción producida:
      • Atendiendo una petición de pintado.
      • Trabajando con la herramienta activa.
      • O, ejecutando alguna de las operaciones soportadas por defecto por MapControl: zoom in, o zoom out .
  • MapContext: establecer u obtener un objeto MapContext. Las distintas capas con información gráfica las almacena en un objeto de tipo MapContext, que servirá para gestionarlas, gestionar los eventos (agrupados en AtomicEvent) que se producen en ellas mediante un buffer (EventBuffer), proyectarlas según una proyección y el puerto de vista (ViewPort) disponible, y controlar su dibujado: calidad, ...
  • Pintado: ofrece distintos mecanismos de pintado ( vea `Pintado de MapControl`_ ):
    • Forzar pintado completo de todas las capas (cancelando el pintado previo que estuviese en marcha):
      • Pintado completo de todas las capas: drawMap(false).
      • Pintado completo de todas las capas, vaciando el front-buffer con el color de fondo del puerto de vista, o a blanco, si no estuviese definido: drawMap(true).
    • Pintar sólo la capa de tipo GraphicLayer existente: drawGraphics().
    • Repintar solo las capas que no estén actualizadas (capas sucias) (cancelando el pintado previo que estuviese en marcha): rePaintDirtyLayers().
  • Proyección: obtener la proyección actual en que se está mostrando la información gráfica de las capas.
  • Puerto de vista: obtener el puerto de vista utilizado para ajustar el extent seleccionado de las capas, al disponible.
  • Zoom: MapControl implementa por defecto las operaciones de zoom in, y zoom out.
Enlaces de interés
  • Behavior: descripción de los comportamientos básicos.
  • Eventos: tipos de eventos que pueden recibir las ToolListener.
  • FLayers: las distintas capas con información gráfica que puede contener MapContext.
  • MapContext: lógica de gestión y pintado de las capas.
  • MapOverview : MapControl que se puede utilizar como vista en miniatura de otro.
  • ToolListener: listeners que completan la simulación de una herramienta con la que interactuar con MapControl.

ToolListener

Introducción

Según el tipo de capas visibles y activas, gvSIG nos proporcionará una serie de herramientas con las que el usuario podrá interaccionar con el objeto MapControl que contiene las capas.

Al seleccionar cualquiera de las herramientas disponibles, lo que se está haciendo es seleccionar un comportamiento para trabajar con MapControl, que puede ser el resultado de múltiples comportamientos denominados cada uno Behavior, cada uno con una ToolListener.

La librería libFMap define cada uno de estos comportientos básicos, que procesan los eventos de ratón producidos en MapControl, generando otros eventos con la información necesaria según su naturaleza. Estos eventos serán los que se envíen a la herramienta actualmente seleccionada para interactuar con MapControl.

Dicha herramienta tendrá un icono que verá el usuario en su cursor, y una serie de métodos que serán invocados según el tipo de evento que se produzca.

Las ToolListener incluyen la lógica que complementa a los Behavior para simular una herramienta con la que interactuar con un objeto de tipo MapControl.

En la librería libFMap se definen las ToolListener básicas, pero existen otras muchas que heredan de estas, y están definidas en otros proyectos. Destacar las que proporciona el proyecto appgvSIG, que, en general, solo agregan como funcionalidad el actualizar las herramientas disponibles en la GUI de gvSIG , una ejecutada la lógica de la herramienta de la que hereda (en libFMap).

Diagramas

Existe multitud de herramientas definidas en la librería libFMap, todas implementan la interfaz ToolListener, y se agrupan en 5 tipos, según se puede observar en el diagrama 1: selección por área circular, rectangular, polinínea, por punto, o de tipo drag & drop (arrastrar y soltar).

Todas reciben eventos fruto de acciones realizadas con el ratón sobre la vista (MapControl) .

Diagrama con las interfaces para todas las herramientas
images/mapcontrol/dcinterfacesbasetoolslibfmap.png

Diagrama 1: diagrama de clases con las interfaces base que implementan todos los listeners de las herramientas definidas en libFMap. El color morado representa un elemento del diagrama global de MapContext.

Diagrama con herramientas que implementan CircleListener

El diagrama 2 muestra los tool listener definidos en la librería libFMap asociados a una selección por área circular.

images/mapcontrol/dclistenersimplcirclelistener.png

Diagrama 2: diagrama de clases: Listeners de herramientas de libFMap que implementan CircleListener.

Tipo Proyecto Descripción Cancelable Eventos a los que responde Icono
CircleMeasureListener appgvSIG Calcula el radio del círculo y lo muestra en el la barra de estado de gvSIG como distancias parcial y total. No. MeasureEvent
images/mapcontrol/toollistenericons/ictlrulercursor.png
Diagrama con herramientas que implementan PanListener

El diagrama 3 muestra los tool listener definidos en la librería libFMap asociados a una selección de tipo drag & drop (arrastrar y soltar).

images/mapcontrol/dclistenerstypepanlistener.png

Diagrama 3: diagrama de clases: Listeners de herramientas de libFMap que implementan PanListener.

Tipo Proyecto Descripción Cancelable Eventos a los que responde Icono
MapOverviewChangeZoomListener appgvSIG

Actualiza el extent del ViewPort del MapControl con el área rectangular seleccionada, o dibuja en el MapOverview asociado un rectángulo delimitando dicha área.

De este segundo modo establece dicha área como el extent a visualizar en el objeto MapControl asociado al MapOverview.

Sí. RectangleEvent, MoveEvent
images/mapcontrol/toollistenericons/ictlzoomincursor.gif
MapOverviewPanListener appgvSIG

Desplaza el área rectangular bajo el cursor del ratón en el objeto MapOverview según se arrastra éste mientras se mantiene pulsado su botón derecho.

De este modo se establece dicha área como el extent a visualizar en el objeto MapControl asociado al MapOverview.

Sí. MoveEvent
images/mapcontrol/toollistenericons/ictlcruxcursor.png
PanListenerImpl libFMap Actualiza el ViewPort del objeto MapControl asociado con un nuevo extent. Sí. MoveEvent
images/mapcontrol/toollistenericons/ictlhand.png
PanListener appgvSIG Igual a PanListenerImpl, actualizando los controles disponibles de la interfaz gráfica de gvSIG para trabajar con la información actual en el objeto MapControl asociado. Sí. MoveEvent
images/mapcontrol/toollistenericons/ictlhand.png
Diagrama con herramientas que implementan PointListener

El diagrama 4 muestra los tool listener definidos en la librería libFMap asociados a una selección por punto.

images/mapcontrol/smalldclistenerstypepointlistener.png

Diagrama 4: diagrama de clases: Listeners de herramientas de libFMap que implementan PointListener.

Pulse aquí para ver el diagrama 4 en tamaño completo.

Tipo Proyecto Descripción Cancelable Eventos a los que responde Icono
DwgEntityListener extDWG Selecciona una geometría que tenga un punto en la posición seleccionada por el cursor, en una capa con información DWG. No. PointEvent Cursor.CROSSHAIR_CURSOR
InfoListener appgvSIG

Muestra la información alfanumérica disponible para el punto seleccionado y un área alrededor de 7 unidades equivalentes en coordenadas del mapa, en todas las capas activas del MapControl asociado.

Dicha información se muestra en forma de tabla.

No. PointEvent
images/mapcontrol/toollistenericons/ictlinfocursor.gif
LinkListener appgvSIG Muestra en un panel información (imagen, texto, etc) asociada a cualquier feature de las capas activas cuya área intersecte con el punto seleccionado. No. PointEvent
images/mapcontrol/toollistenericons/ictllink.png
MapOverviewListener appgvSIG

Crea un rectángulo centrado en el punto seleccionado con el botón izquierdo del ratón sobre el objeto MapOverview asociado.

De este modo se establece dicha área como el extent a visualizar en el objeto MapControl asociado al MapOverview.

Sí. PointEvent
images/mapcontrol/toollistenericons/ictlcruxcursor.png
PointSelectionListener libFMap Selecciona todas las features de capas vectoriales activas del objeto MapControl asociado cuya área intersecte con el punto seleccionado por un simple click de cualquier botón del ratón. No. PointEvent
images/mapcontrol/toollistenericons/ictlpointselectcursor.png
PointSelectListener appgvSIG Igual a PointSelectionListener actualizando los controles disponibles de la interfaz gráfica de gvSIG para trabajar con la información actual en el objeto MapControl asociado. No. PointEvent
images/mapcontrol/toollistenericons/ictlpointselectcursor.png
SelectImageListenerImpl libFMap ToolListener anticuado que permitía tener SelectImageListener en appgvSIG para la selección de capa raster. Sí. PointEvent
images/mapcontrol/toollistenericons/ictlpointselectcursor.png
SelectImageListener appgvSIG

Selecciona la capa raster situada más arriba en el TOC con información en la posición indicada en el objeto MapControl asociado. Dicha capa pasará a estar activa, mientras que el resto estará como no activas.

Posteriormente actualiza los controles disponibles de la interfaz gráfica de gvSIG para trabajar con la información actual en el objeto MapControl asociado.

Esta ToolListener también está anticuada.

Sí. PointEvent
images/mapcontrol/toollistenericons/ictlpointselectcursor.png
StatusBarListener appgvSIG

Muestra en la barra de estado de la interfaz gráfica de gvSIG las coordenadas equivalentes al punto sobre el objeto MapControl asociado, llamémosle m.

Sigue las siguientes reglas para obtener las expresiones de las coordenadas:

Si m no está proyectado, expresa las coordenadas como distancia en píxeles respecto la esquina superior izquierda (0, 0).

Si estando proyectado, las unidades de medida de distancia del ViewPort de m están en grados, calcula las coordenadas geográficas.

En cualquier otro caso expresa las coordenadas como números decimales teniendo en cuenta la proyección actual.

En caso de no estar proyectado m, expresará las coordenadas como latitud: Lat = y longitud: Long =, sino como X: X = e Y: Y =, como prefijo, mientras que como sufijo:

En caso de utilizar números decimales: 8 decimales si la proyección de *m es EPSG: 4230 ó EPSG: 4326, o 2 decimales con cualquier otra proyección.

En caso de no utilizar números decimales, seguirá este patrón:

S?Gº M' S'', con:

  • S?: opcionalmente, el símbolo - en caso de ser negativa.
  • G: grados equivalentes.
  • M: minutos equivalentes.
  • S: segundos equivalentes.
No. PointEvent No utiliza icono.
ToolSelectGraphic extCAD Selecciona ítems de la capa GraphicLayer de objeto MapControl asociado, cuya área intersecta con el punto indicado. No. PointEvent
images/mapcontrol/toollistenericons/ictlpointselectcursor.png
WCSZoomPixelCursorListener extWCS

Realiza una operación de zoom acercar en el objeto MapControl asociado, tomando como centro el punto seleccionado.

El factor de zoom dependerá de la resolución máxima de las capas activas con información WCS

No. PointEvent
images/mapcontrol/toollistenericons/ictlzoompixelcursor.gif
ZoomOutListenerImpl libFMap

Realiza una operación de zoom alejar sobre el objeto MapControl asociado. Para ello calcula el nuevo extent de su ViewPort según las siguientes ecuaciones:

ViewPort vp = mapControl.getMapContext().getViewPort();
Point2D p2 = vp.toMapPoint(event.getPoint());
double factor = 1/MapContext.ZOOMOUTFACTOR;
Rectangle2D.Double r = new Rectangle2D.Double();
double nuevoX = p2.getX() - ((vp.getExtent().getWidth() * factor) / 2.0);
double nuevoY = p2.getY() - ((vp.getExtent().getHeight() * factor) / 2.0);
r.x = nuevoX;
r.y = nuevoY;
r.width = vp.getExtent().getWidth() * factor;
r.height = vp.getExtent().getHeight() * factor;
vp.setExtent(r);

Hay que contar que el extent calculado no tendrá porqué coincidir con el que en última instancia se visualize, dado que ViewPort se encargará de calcular el extent ajustado a partir de éste.

Sí. PointEvent
images/mapcontrol/toollistenericons/ictlzoomoutcursor.gif
ZoomOutListener appgvSIG Igual a ZoomOutListenerImpl actualizando los controles disponibles de la interfaz gráfica de gvSIG para trabajar con la información actual en el objeto MapControl asociado. Sí. PointEvent
images/mapcontrol/toollistenericons/ictlzoomoutcursor.gif
ZoomOutRightButtonListener libFMap Funciona igual que ZoomOutListenerImpl, pero sólo como respuesta al pulsado del botón derecho del ratón. Sí. PointEvent
images/mapcontrol/toollistenericons/ictlzoomoutcursor.gif
ZoomPixelCursorListener appgvSIG Realiza una operación de zoom acercar calculando el nuevo extent del ViewPort del objeto MapControl asociado centrado en su pixel más al punto seleccionado. No. PointEvent
images/mapcontrol/toollistenericons/ictlzoompixelcursor.gif
Diagrama con herramientas que implementan PolylineListener

El diagrama 5 muestra los tool listener definidos en la librería libFMap asociados a una selección por polilínea.

images/mapcontrol/dclistenerstypepolylinelistener.png

Diagrama 5: diagrama de clases: Listeners de herramientas de libFMap que implementan PolylineListener.

Tipo Proyecto Descripción Cancelable Eventos a los que responde Icono
AreaListenerImpl libFMap

Calcula perímetro y área de la selección rectangular definida con dos vértices de una de sus diagonales.

Si el objeto MapControl no está proyectado, toma las coordenadas como geográficas (latitud - longitud), sino, las calcula teniendo en cuenta su proyección y unidades de medida.

No. MeasureEvent
images/mapcontrol/toollistenericons/ictlareacursor.png
AreaListener appgvSIG Igual que AreaListenerImpl actualizando la información de perímetro y área en la barra de estado de la GUI de gvSIG. No. MeasureEvent
images/mapcontrol/toollistenericons/ictlareacursor.png
MeasureListenerImpl libFMap Calcula y muestra por la salida estándar el valor de la longitud total y la del último segmento de la polilínea definida por una serie de puntos. No. MeasureEvent
images/mapcontrol/toollistenericons/ictlrulercursor.png
MeasureListener appgvSIG Calcula y muestra por en el statusbar de gvSIG el valor de la longitud total y la del último segmento de la polilínea definida por una serie de puntos. No. MeasureEvent
images/mapcontrol/toollistenericons/ictlrulercursor.png
PolygonSelectionListener libFMap

Selecciona todas las features de las capas activas y vectoriales que intersecten con el área poligonal definida sobre el objeto MapControl asociado.

La selección se producirá una vez se finalice la creacción de la polilínea.

No. MeasureEvent
images/mapcontrol/toollistenericons/ictlpolygoncursor.png
PolygonSelectListener appgvSIG Igual a PolygonSelectionListener actualizando los controles disponibles de la interfaz gráfica de gvSIG para trabajar con la información actual en el objeto MapControl asociado. No. MeasureEvent
images/mapcontrol/toollistenericons/ictlpolygoncursor.png
Diagrama con herramientas que implementan RectangleListener

El diagrama 6 muestra los tool listener definidos en la librería libFMap asociados a una selección por área rectangular.

images/mapcontrol/dclistenerstyperectanglelistener.png

Diagrama 6: diagrama de clases: Listeners de herramientas de libFMap que implementan RectangleListener.

Tipo Proyecto Descripción Cancelable Eventos a los que responde Icono
MapOverviewChangeZoomListener appgvSIG

Permite realizar un cambio de extent según un área rectangular definida sobre un objeto de tipo MapOverview.

Si la acción es un movimiento, y el objeto asociado es de tipo MapOverview actualiza el extent manteniendo el zoom.

Si la acción es la selección de un área rectangular, y supera los 3x3 píxeles, realiza una operación de zoom in adaptando el ViewPort de MapOverview al extent equivalente en coordenadas del mundo al área seleccionada.

Sí. MoveEvent, RectangleEvent
images/mapcontrol/toollistenericons/ictlzoomincursor.gif
RectangleSelectionListener libFMap De las capas vectoriales que estén activas, selecciona todas las features que intersecten con el área rectangular definida. No. RectangleEvent
images/mapcontrol/toollistenericons/ictlrectselectcursor.gif
RectangleSelectListener appgvSIG Igual a RectangleSelectionListener actualizando los controles disponibles de la interfaz gráfica de gvSIG para trabajar con la información actual en el objeto MapControl asociado. No. RectangleEvent
images/mapcontrol/toollistenericons/ictlrectselectcursor.gif
SaveRasterListenerImpl libFMap, extRasterTools Almacena el área rectangular definida, en coordenadas del mapa y del mundo. Sí. RectangleEvent
images/mapcontrol/toollistenericons/ictlrectselectcursor.gif
SaveRasterListener extRasterTools Permite guardar el área rectangular seleccionada, como un fichero raster, vía un panel cone opciones de salvado. Sí. RectangleEvent
images/mapcontrol/toollistenericons/ictlrectselectcursor.gif
ExportToGeoRasterToolListener extRasterTools El diálogo de recorte raster utiliza esta herramienta para permitir al usuario seleccionar una nueva área y con ello actualizar las coordenadas de recorte. Sí. RectangleEvent
images/mapcontrol/toollistenericons/ictlrectselectcursor.gif
ZoomInListenerImpl libFMap

Realiza una operación de zoom acercar sobre el objeto MapControl asociado. Para ello calcula el nuevo extent de su ViewPort según las siguientes ecuaciones:

double factor = 1/MapContext.ZOOMINFACTOR;
Rectangle2D rect = event.getWorldCoordRect();
Rectangle2D.Double r = new Rectangle2D.Double();
ViewPort vp = mapCtrl.getMapContext().getViewPort()"
double nuevoX = rect.getMaxX() - ((vp.getExtent().getWidth() * factor) / 2.0);
double nuevoY = rect.getMaxY() - ((vp.getExtent().getHeight() * factor) / 2.0);
Rectangle2D.Double r;
r.x = nuevoX;
r.y = nuevoY;
r.width = vp.getExtent().getWidth() * factor;
r.height = vp.getExtent().getHeight() * factor;
vp.setExtent(r);

Hay que contar que el extent calculado no tendrá porqué coincidir con el que en última instancia se visualize, dado que que ViewPort se encargará de calcular el extent ajustado a partir de éste.

Sí. RectangleEvent
images/mapcontrol/toollistenericons/ictlzoomincursor.gif
ZoomInListener appgvSIG Igual a ZoomInListenerImpl actualizando los controles disponibles de la interfaz gráfica de gvSIG para trabajar con la información actual en el objeto MapControl asociado. Sí. RectangleEvent
images/mapcontrol/toollistenericons/ictlzoomincursor.gif

MapContext

MapContext

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

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

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

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.

ViewPort

Introducción

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

ViewPort en el contexto de MapContext

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.

Visión Global
images/mapcontext/dcviewport.png

Diagrama 1: diagrama de clases simplificado de ViewPort en MapContext. Se muestran las clases e interfaces de sus atributos.

Atributos del ViewPort
  • Área seleccionada a visualizar, en coordendas del mapa: extent.
  • Dimensiones en pixels del área disponible para visualizarla: imageSize.
  • Área que se utilizará para visualizar. Esta área es la seleccionada, ajustada al aspecto de la disponible, de forma que ampliará la seleccionada, y en caso que no hubiese suficiente, con el color de fondo: adjustedExtent.
  • Escala entre el área ajustada y la disponible. Esta escala es igual para ancho y alto.
  • Color de fondo por defecto.
  • Transformación afín entre el área a visualizar ajustada (en coordenadas de mapa), y la disponible para visualizarla (en coordenadas de píxel).
  • Proyección que se utiliza para obtener el área a visualizar.
  • Unidad de medida de distancias en el área visualizada: distanceUnits.
  • Unidad de medida en el mapa original: mapUnits.
  • Lista de las últimas áreas visualizadas: extents. Permite ir a vistas previas.
  • Posición del área visible, de la esquina donde empieza a visualizar el mapa: offset.
  • Distancia en coordenadas del mundo equivalente a 1 pixel en la vista con el área a visualizar actual: dist1pixel.
  • Distancia en coordenadas del mundo equivalente a 3 pixels en la vista con el área a visualizar actual: dist3pixel.
  • Lista de listeners de tipo ViewPortListener asociados a este puerto de vista.
Unidades de Medida

Las unidades de medida soportadas, tanto para distancias como para del mapa original son:

  • Kilómetro: unidad métrica o de longitud equivalente a 1000 metros.
  • Metro: unidad de longitud del Sistema Internacional, que originalmente se estableció como la diezmillonésima parte del cuadrante del meridiano terrestre, y hoy, con más precisión, se define como la longitud del trayecto recorrido en el vacío por la luz durante un tiempo de 1/299 792 458 de segundo.
  • Centímetro: centésima parte de un metro.
  • Milímetro: milésima parte de un metro.
  • Millas estatutarias internacionales: the international statute mile is by international agreement. It is defined to be precisely 1,760 international yards (by definition, 0.9144 m each) and is therefore exactly 1,609.344 metres (1.609344 km).
  • Yarda: medida de longitud equivalente a 0,914 m.
  • Pie: antigua unidad de medida que aún se utiliza en algunos países anglosajones, equivalente a 1/3 yardas y a 12 pulgadas.
  • Pulgada: medida inglesa equivalente a 1/12 pies, y a 25,4 mm.
  • Grados: grados según la proyección actual.
Funcionalidad
  • Áreas:
    • Área disponible: indicar y obtener las dimensiones (en pixels) del área disponible de visualización. Está en coordenadas de imagen.
    • Área seleccionada: indicar y obtener sus dimensiones y posición. Está en coordenadas del mundo, con su sistema de medida.
    • Área seleccionada ajustada a una escala de la disponible: permite obtener sus dimensiones y posición. Está en coordenadas del mundo, con su sistema de medida.
  • Configuración:
    • Ajuste de Extent: adaptar o no el área a visualizar a una escala de la disponible antes de calcular la transformación afín.
  • Listeners: lógica a ejecutar cuando se producen ciertos eventos sobre la vista. Permite agregar o eliminar listeners a la capa.
  • Clonación: obtener otra capa idéntica e independiente de la actual.
  • Cálculo de la Transformación: se realiza automáticamente al refrescar el puerto de vista, cambiar de extent, o cambiar de área disponible. Este proceso además recalcula la nueva área ajustada, la escala entre área ajustada y visible, y las distancias equivalentes en coordenadas del mundo a 1 y 3 pixels.
  • Conversiones: ViewPort permite realizar conversiones entre datos (puntos, distancias o Rectangle2D (dimensión + posición de un área rectangular)) en coordenadas del mapa, y coordenadas de la imagen, o viceversa.
  • Offset: indicar y obtener la posición donde empieza a situar el área seleccionada transformada en el área disponible.
  • Persistencia: crear una nueva instancia de ViewPort a partir de una entidad XML.
  • Proyección: indicar y obtener la proyección que se ha usado para obtener el plano a partir de la información gráfica original, del que se visualiza un área.
  • Unidades de medida: explicadas en el apartado Unidades de Medida.
  • Otra funcionalidad:
    • Color de fondo: se puede cambiar y obtener el color de fondo por defecto.
    • Distancias equivalentes a 1 o 3 pixels: obtener la distancia equivalente en unidades de medida del mundo a 1 o 3 pixels en el área de visualización.
    • Obtener los extents previos almacenados.
    • Cambiar al extent previo, recalculando transformación afín, etc.
    • Refrescar, recalculando transformación afín, ...
    • Cálculo de la distancia (en coordenadas del mundo) entre dos puntos de las capas gráficas originales. Para ello se tiene en cuenta la proyección con que se ha obtenido el plano a partir de dichas capas.
ViewPortListener

Interfaz para la captura y tratamiento de los eventos asociados a un ViewPort, que son:

  • ColorEvent: cambio de color de fondo.
  • ExtentEvent: cambio de área seleccionada.
  • ProjectionEvent: cambio de proyección.
ExtentHistory

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.

Ejemplo
images/dirimejviewport/ejviewportim1.png

Imagen 1: Una vista de gvSIG, donde se indica la dimensión del área disponible para visualizar las capas.

images/dirimejviewport/ejviewportim2.png

Imagen 2: La vista de la Imagen 1, sobre la que se ha cargado dos capas. El/la usuario/a selecciona un área de interés, esta será el extent. Así, cuando deje de seleccionar, se recalculará el nuevo adjustedExtent.

images/dirimejviewport/ejviewportim3.png

Imagen 3: La vista de la Imagen 2, donde se visualiza el área de interés seleccionada, adaptada a las dimensiones disponibles. Se puede observar como se ha ampliado el ancho seleccionado, por mantener una proporción al aspecto del área disponible de visualización.


Layers

Estatus de las Capas

Introducción

gvSIG permite trabajar con múltiples y diferentes tipos de capas, de manera que cada una, según su naturaleza, tiene unas propiedades y comportamiento que no tienen porqué coincidir con las de otro tipo. En cambio, todas las capas, al menos teóricamente, pueden estar en un reducido número de estados simultáneos. A cada conjunto posible de estados simultáneos se les denomina estatus.

A nivel genérico, el estatus de una capa está definido en la clase FLayerStatus del proyecto libFMap, como se observa en el diagrama 1.

Así, se observa como la clase abstracta con la implementación común para todas las capas, FLyrDefault, contiene y utiliza una instancia de tipo FLayerStatus que representa el estatus actual en que puede estar cualquier tipo de capa.

En la práctica, una capa dada solo podrá estar en un subconjunto de los posibles estatus, teniendo en cuenta su naturaleza.

images/layers/dcflayerstatus.png

Diagrama de clases que muestra la relación de FLayerStatus con las capas de libFMap.

El estatus de una capa almacena la información de las excepciones que se puedan ir produciendo cuando se utiliza el driver asociado a ella, este tipo de excepción es DriverException.

Estados
  • Activa: la capa está seleccionada en el TOC.
  • Visible: la capa tiene seleccionado su checkbox asociado en el TOC. En caso afirmativo, implica que se intentará pintar la capa a no ser que no estén disponibles los datos necesarios, cosa que sucede a veces con capas de servicios remotos.
  • Disponible: la fuente con los datos de la capa está on-line (el driver ha conectado con ella exitosamente y está lista para que sus datos se puedan acceder sin problemas).
  • Sucia: la capa requiere actualizarse. En el momento que una capa pasa a edición, cambia la transparencia, cambia la visibilidad, se ordena refrescarla, o se le indica por parte de un tipo de capa determinado, cuando, por ejemplo, sus datos han cambiado, la capa pasará a estar sucia, lo que obligará a que se repinte, para luego pasar a "no sucia".
  • En TOC: la capa está registrada en el árbol de capas del TOC.
  • Editándose: el contenido de la capa puede modificarse en este momento.
  • Puede escribirse: hay driver de escritura para esa capa, y tiene permisos para modificarla.
  • Caché de capas dibujadas: almacena varias imágenes para acelerar el pintado.
Status por defecto al crear una capa
Estado Activo [1]
Activa No
Visible
Disponible
Sucia No
En TOC
Editándose No
Puede escribirse No
Caché de capas dibujadas No
[1]"Activo" equivale a "true" a nivel de programación.
Capturas

En este apartado se han colocado unos ejemplos visuales con los que un usuario podría conocer el estado de la capa/s con la que está trabajando en gvSIG:

images/imejsestscapa/ej1estadocapa.png

El usuario tiene esta vista en gvSIG con las capas WFS "embalses" e "hidrografía" en el TOC, visibles ("checkboxs" seleccionados), disponibles (dado que sino no se habrían visualizado sus datos), y estando la capa "embalses" activa.

images/imejsestscapa/ej2estadocapa.png

Igual a la imagen anterior, pero ahora ambas capas están activas (seleccionadas).

images/imejsestscapa/ej3estadocapa.png

Ahora, el usuario ha deseleccionado los "checkbox's" de ambas capas, y, por tanto, no están visibles. Por otro lado, la capa "hidrografía" está activa, y ambas se mantienen disponibles dado que no se nos informa de lo contrario en el icono asociado.

images/imejsestscapa/ej4estadocapa.png

Visible sólo la capa "embalses", y activa sólo "hidrografía".

images/imejsestscapa/ej5estadocapa.png

El usuario ha creado una vista en gvSIG en la que sólo ha cargado una capa (1 capa en TOC), que está activa, pero no disponible (lo indica el aspa roja del icono de la izquierda asociado a la capa). Dado que la capa no está disponible, deja de estar visible.

images/imejsestscapa/ej6estadocapa.png

Cuadro de diálogo que aparece cuando se intenta editar una capa que no tiene permiso de escritura.

images/imejsestscapa/ej7estadocapa.png

El usuario ha intentado cargar una capa en una vista de gvSIG, pero se han producido errores y por tanto deja de estar disponible.

images/imejsestscapa/ej8estadocapa.png

Capa cargada en TOC, disponible, visible, activa, con permiso de escritura, y en edición.

Layers - FLayer, FlyrDefault, FLayers

Introducción

Toda capa utilizada en gvSIG hereda de la clase FlyrDefault, que implementa la declaración genérica y común de capa: el interfaz FLayer .

FlyrDefault, es una clase abstracta, con métodos genéricos para trabajar con capas definidos en la interfaz FLayer, métodos genéricos para trabajar con drivers (para utilizar la capa), definidos en la interfaz Driver, y otros métodos propios.

FLayer, incluye los métodos necesarios para trabajar con proyecciones, definidos en la interfaz Projected, con otros para trabajar con capas.

Por otro lado, es posible tener una colección de capas como nodo de un árbol de capas, y así poder trabajar con distintos niveles. Para ello, se definió la clase FLayers, que hereda de FlyrDefault, e implementa la interfaz LayerCollection con los métodos para trabajar con un conjunto de capas.

Dado que las capas de un mismo nodo pueden ser de distinto tipo, FLayers implementa, por compatibilidad, las interfaces InfoByPoint y VectorialData. Así, es posible que algunas capas trabajen con datos vectoriales, por ello se implementa la interfaz VectorialData; y/o a la vez es posible que soporten la operación de obtención de información a partir de un punto, por ello se implementa la interfaz InfoByPoint.

El siguiente diagrama muestra gráficamente lo explicado, sin entrar en detalles acerca de métodos ni atributos, pero sí listeners que se pueden asociar a una capa, con los correspondientes eventos que pueden recibir, y los tipos de excepciones que se pueden llegar a lanzar en caso de producirse algún error trabajando con una capa:

images/layers/dclayers.png

Diagrama 1: relación entre las clases e interfaces del grupo Layers.

Descripción y funcionalidad
El interfaz Projected

Permite obtener la proyección actual de la capa, o reproyectar a partir de unas coordenadas de transformación.

El interfaz FLayer

Define la funcionalidad básica para trabajar con cualquier tipo de capa:

  • Persistencia: obtener o agregar información completa o solo parcial de la capa.
  • Estado: hay posibilidad de obtener o insertar el estado completo, o solo de algún atributo:
    • Activa: si está o no seleccionada en el TOC.
    • Visible: una capa es visible si está seleccionado su checkbox asociado en el TOC, lo que implica que se intentará pintar la capa a no ser que no estén disponibles los datos necesarios, cosa que sucede a veces con capas de servicios remotos.
    • Disponible: si la fuente de datos está on-line.
    • Sucia: si requiere o no actualizarse.
    • En TOC: si está o no en el árbol de capas del TOC.
    • Editándose: si la capa está siendo o no modificada en este momento.
    • Puede escribirse: si hay o no driver de escritura para esa capa, y tiene permisos para modificarla.
    • Caché de capas dibujadas: si usa o no una imagen con bandas.
  • Identidad: nombre o descripción de la capa.
  • Carga/Recarga: leer la información de la capa y agregarla o actualizarla.
  • Dibujado: lógica de dibujado de la capa.
  • Proyección:
    • Si es o no reproyectable la capa.
    • Uso de coordenadas de transformación, o información de proyección para proyectarla.
    • Uso de la lógica de control para reproyectarla.
  • Listeners: lógica a ejecutar cuando se producen ciertos eventos sobre la capa. Permite agregar, obtener, o eliminar listeners a la capa.
  • Escalas visibles: rango de escalas de zoom en que se verá la capa.
  • Gestión de errores: agregar, u obtener los errores producidos al cargar o trabajar con la capa.
  • Nuevas propiedades: agregar u obtener nuevas propiedades asociadas a la capa.
  • Clonación: obtener otra capa idéntica e independiente de la actual.
  • Otra funcionalidad:
    • Estado correcto.
    • Obtener el modelo de la capa.
    • Obtener posición y dimensiones de la capa.
    • Obtener la imagen de estado en el TOC.
    • Obtener una capa compuesta a partir de esta capa (este método está pensado para utilizarse solo en ciertas capas, de tipo FLayers).
    • Establecer u obtener el nodo padre de esta capa.
    • Establecer u obtener una imagen en el TOC que represente el estado actual de la capa.
El interfaz Driver

Ubicado en la biblioteca libDriverManager, define un método para que todos los drivers puedan devolver su nombre identificativo.

La clase abstracta FlyrDefault

Mientras que FLayer es una definición de funcionalidad genérica para cualquier tipo de capa, FlyrDefault representa la capa genérica de la que se particularizará para WMS, WCS, raster, vectorial, capa de texto, colección de capas, etc.

Posee la misma funcionalidad que FLayer, y además agrega:

  • Estrategia: establecer u obtener la estrategia para recorrer la información de la capa.
  • Transparencia: establecer u obtener el nivel de transparencia.
  • Capas virtuales: gestionar capas virtuales asociadas a la actual.
  • Capa de texto: gestionar una capa de texto asociada a la actual.
  • Otra funcionalidad:
    • Notificar a la capa que va a ser añadida.
    • Establecer la imagen de estado de la capa en el TOC.
El interfaz LayerCollection

Define métodos para trabajar con una colección de capas:

  • Agregar, eliminar, mover, u obtener capas.
  • Agregar, o eliminar listeners de eventos producidos sobre la colección de capas.
  • Cambiar la visibilidad de todas las capas de la colección.
  • Activar / desativar todas las capas de la colección.
  • Obtener las capas visibles.
El interfaz InfoByPoint

Define un método para obtener información de un área de tolerancia centrada en un punto de la capa o capas.

El interfaz VectorialData

Permite utilizar el patrón software Visitor con la lógica que indica cómo procesar datos vectoriales. Además permite procesar todas las geometrías, solo aquellas indicadas, o solo aquellas que corten el perímetro de un rectángulo determinado.

La clase FLayers

Representa un conjunto genérico de capas (FLayer). Posee el mismo comportamiento que FLyrDefault, pero adaptándolo para soportar un árbol de nodos que puede ser cada uno, una sola capa, u otro conjunto (otro nodo de tipo FLayers). Además, incluye la funcionalidad de LayerCollection, InfoByPoint, y VectorialData, y permite:

  • Agregar, reemplazar, o eliminar una capa del conjunto.
  • Agregar una capa a partir de una entidad XML.
  • Dibujar un conjunto de capas, o una capa compuesta.
Excepciones

El diagrama anterior nos muestra los tipos de excepciones que puede lanzar por defecto cualquier tipo de capa, siempre que se haya producido algún tipo de error. Se indica aquí un breve resumen de cada uno de ellas:

  • CancelationException: problema cuando el usuario cancela una tarea.
  • DriverException: problema en el código encargado de trabajar con un tipo de fuente de datos determinada.
  • DriverIOException: similar a DriverException, pero particularizado a cuando se realiza una operación de lectura o escritura sobre la fuente de datos.
  • EditionException: problema cuando una capa o tabla está en estado editable.
  • Exception: cualquier tipo de exceptión producida.
  • VisitException: problema utilizando el patrón software Visitor accediendo a la información las capas.
  • XMLException: problema realizando el proceso un marshall [1] o unmarshall.
[1]Marshall es como se denomina al proceso por el que un objecto se serializa usando XML, es decir, devuelve su información de modo que se pueda transmitir por una conexión, o persistir en un fichero o memoria, siguiendo el estándar XML para estructurar dicha información. Al proceso inverso se le denomina Unmarshall.
Enlaces relacionados
  • En este enlace se muestran unas capturas de gvSIG con las que un usuario puede conocer el estatus de una capa.
  • Este otro enlace es una recopilación de los tipos de capas que se utilizan en gvSIG, o en proyectos relacionados, con una explicación de cada una.
  • Visitor: información de este tipo de patrón software.

Pintado y escritura de capas

Pintado

gvSIG pinta usando el patrón "SingleWorketThread".

Las peticiones de dibujado se encolan y se envían a un único thread que lanza el dibujado con un objeto de tipo Cancellable para permitir interrumpir ese dibujado.

El thread de pintado va recibiendo comandos de pintado e inmediatamente se pone a pintar en segundo plano sobre una imagen en memoria. Frecuentemente, y para observar el progreso (porque puede llegar a tardar varios segundos en terminarlo) MapContext renderiza esa imagen y se muestra en pantalla. Esto es cada 400 milisegundos (y a partir de v1.2 será configurable de manera que se puede ver el progreso en tiempo real) y en el momento en que el thread ha terminado de pintar.

El dibujado de las capas lo hace MapContext. MapContext puede pintar sobre un Graphics2D que provenga de una imagen (caso de las peticiones del MapControl) o sobre un Graphics2D que venga de otro sitio (por ejemplo al imprimir). MapContext tiene una colección FLayers, y cada capa tiene un método draw. Para terminar, existe un "StrategyManager" que, en función del tipo de capa, escoge una estrategia de pintado u otra (patrón "Strategy"). Las estrategias de pintado están en el paquete "operations", dentro de libFMap, y las más interesantes son ShpStrategy y DBStrategy.

Por otra parte, si se observa el interfaz de las capas (FLayers) se verá que el método draw (que dibuja cada capa) tiene un argumento Cancellable que tiene un método isCanceled(). Cuando se ha cancelado el pintado (sea por un zoom, un pan o cualquier otro evento que comporte que lo que hay actualmente ya no es válido y debe de recalcularse) entonces isCanceled() devuelve true. En cualquier otro caso devuelve false.

La agilización de la cancelación se realiza dentro de cada una de las iteraciones que se hace en el método draw y posteriores llamadas internas, comprobando que isCanceled() es true, y si lo es, se aborta todo el proceso y entonces se sale del método del draw, si no lo es, se continua con el renderizando. Si se cancela el pintado de todas las capas de manera encadenada, la petición de draw del MapContext se termina, haciendo que se atienda a la siguiente (la que ha provocado que Mapcontext se invalide y que cancel.isCanceled() devuelva true).

Que el cancelado sea inmediato o no, depende del tipo de capas y de la implementación del método draw de ellas. La mayor parte de las capas tienen en cuenta el Cancelable, pero hay algunas que no lo pueden comprobar e inevitablemente ejecutan su método draw íntegro aunque el resultado no se llegue a mostrar en pantalla.

Escritura de una capa

El método isWritable() de una capa devuelve true si el driver en el que se apoya la capa devuelve true:

  • Para el caso vectorial:
public boolean isWritable() {
  VectorialDriver drv = getSource().getDriver();

  if (!drv.isWritable())
    return false;

  // VectorialEditableAdapter vea = (VectorialEditableAdapter) lyrVect
  // .getSource();
  if (drv instanceof IWriteable)
  {
    IWriter writer = ((IWriteable)drv).getWriter();
    if (writer != null)
    {
      if (writer instanceof ISpatialWriter)
        return true;
    }
  }
  return false;
}
  • Para el caso de los shape: devuelve true si el fichero tiene permiso de escritura. El resto (instanceof IWriteable) es por si tenemos solo capas con driver de lectura. Si el driver implementa la escritura, se podrá editar y guardar la capa en ese formato. Si no, la capa se puede poner en edición, pero no se puede salvar a ese formato, solo se puede guardar como .
Enlaces relacionados
  • Strategy : explicación detallada en inglés acerca de este patrón sofware.
  • WorkerThreadPattern : código Java con un ejemplo donde se implementa este patrón software.
  • Painting in AWT and Swing : descripción detallada en inglés de los mecanismos y filosofía de pintado de la biblioteca Swing y el kit de herramientas AWT en Java.
  • Pintando en AWT : descripción detallada en castellano de los mecanismos y filosofía de pintado en Java con la biblioteca AWT.
  • Pintando en Swing : descripción detallada en castellano de los mecanismos y filosofía de pintado en Java con la biblioteca Swing.

Tipos de capas

Principales tipos de capas

En este apartado se describe brevemente los principales tipos de capas que, heredando de FLayer, FLyrDefault, o, FLayers, se implementan en la librería libFMap o en algún otro proyecto de gvSIG . Pulsa aquí para visualizar el diagrama 2 en grande.

images/layers/smalldctypesoflayers.png

Diagrama 2: Diagrama simplificado que muestra los principales tipos de capas declaradas en la librería libFMap u otro proyecto de gvSIG.

Nombre Ubicación [1] Descripción
FFeatureLyrArcIMS extArcIMS Capa de tipo FLyrVect con soporte de cancelación de proceso de cargado, reimplementada para soportar las particularidades del servicio ArcIMS (Arc Internet Map Server): protocolo, estructura de datos, y su manipulación, teniendo una capa de tipo vectorial.
FFeatureLyrArcIMSCollection extArcIMS Capa de tipo FLayers que la reimplementa para soportar un conjunto de capas de tipo FFeatureLyrArcIMS.
FLayers libFMap Capa que representa una colección genérica de capas, e implementa el código necesario para trabajar con ellas.
FLayerFileVectorial libFMap Capa de tipo FLyrVect utilizada para cargar ficheros con información vectorial.
FLayerGenericVectorial libFMap Capa de tipo FLyrVect con un driver asociado.
FLayerVectorialDB libFMap Capa que extiende de FLyrVect utilizada para capas que utilicen JDBC, como son PostGIS, MySQL, Oracle Spatial, etc ...
FLyrAnnotation libFMap Capa de tipo FLyrVect utilizada para representar anotaciones textuales. Mantiene el tamaño de las geometrías dibujadas independientemente del zoom.
FLyrGT2 libFMap Capa de tipo FlyrSecuential utilizada para pruebas.
FLyrGT2_old libFMap Capa de tipo FLyrDefault utilizada para pruebas.
FLyrRaster libFMap

Antigua capa para trabajar con imágenes raster, que era ofrecida por la librería libFMap. De tipo FLyrDefault reimplementada para soportar operaciones propias de imágenes raster. Permite además:

  • Indicarle u obtener su estatus.
  • Agregar o eliminar ficheros a la capa raster.
  • Indicar u conocer si será destruida la memoria del raster al eliminarlo del TOC.
  • Conocer si la imagen está o no georreferenciada.
  • Obtener el grid asociado.
  • Crear un buffer para tener un driver raster de memoria.
  • Indicar el extent (área seleccionada de trabajo de la capa).
FLyrRasterSE extRasterTools-SE Sustituye a la antigua FlyrRaster, y deja de estar en la librería libFMap. Aporta multitud de mejoras para dar soporte a la gran cantidad de formatos raster existentes.
FLyrSecuential libFMap Definición abstracta de capa con soporte para datos vectoriales, y con una tabla de datos alfanuméricos asociada.
FLyrText libFMap Capa de tipo FLyrDefault que acaba dibujando una serie de FShape's de formas geométricas creados a partir de la información de alto, ancho, posición, y rotación del contenido de una capa vectorial de tipo FLyrVect.
FLyrVect libFMap Capa vectorial genérica: tiene soporte para edición, selección, reproyección, índices vectoriales, leyendas, datos alfanuméricos, acceso aleatorio a datos vectoriales, información por punto, e impresión. Además se le puede establecer la estrategia de recorrido, manipulación y pintado de sus features, y consultar por área rectangular, punto y shape. También realiza un ''marshall''[2] de su información, para poder ser salvarda en un fichero ".gvp" de gvSIG y así restaurarla posteriormente.
FLyrWCS extWCS Capa de tipo FLyrDefault adaptada a las particularidades de WCS (Web Coverage Service), y comportándose como una capa de tipo raster.
FLyrWFS extWFS2 Capa de tipo FLyrDefault adaptada a las particularidades de WFS (Web Feature Service), y comportándose como una capa de tipo vectorial.
FLyrWMS extWMS Capa de tipo FLyrDefault adaptada a las particularidades de WMS (Web Map Service), y comportándose como una capa de tipo raster.
FRasterLyrArcIMS extArcIMS Capa de tipo FLyrDefault con soporte de cancelación de proceso de cargado, reimplementada para soportar las particularidades del servicio ArcIMS (Arc Internet Map Server): protocolo, estructura de datos, y su manipulación, teniendo una capa de tipo raster.
GraphicLayer libFMap

Capa con ítems gráficos, que son geometrías con un símbolo y manejadores asociados.

Los ítems internos son independientes entre sí, y pueden ser seleccionados separadamente. Utiliza un bit set para definir los ítems que se seleccionan. Y aquellos que sean seleccionados, se dibujarán con manejadores, que según la implementación particular de cada uno, pueden mover el ítem, centrarlo, hacer pinzamientos sobre puntos, etc.

[1]La columna "Ubicación" indica en qué proyecto está declarada la capa.
[2]Marshall es como se denomina al proceso por el que un objecto se serializa usando XML, es decir, devuelve su información de modo que se pueda transmitir por una conexión, o persistir en un fichero o memoria, siguiendo el estándar XML para estructurar dicha información. Al proceso inverso se le denomina Unmarshall.

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: