viernes, 21 de noviembre de 2014

Uso de servicios OCG

Introducción
En los módulos anteriores, hemos aprendido a programar herramientas SIG utilizando siempre la cartografía que acompañaba a la aplicación: en el caso de GoogleMaps, los cuatro tipos de mapa que nos ofrece su API, y en el caso de gvSIG, los mapas que habíamos obtenido previamente de algun servidor de mapas.

Sin embargo, la proliferación de los servicios de cartografía en línea ha hecho posible una nueva forma de trabajar en la que el cliente no dispone ya de una copia propia de los datos, sino que accede continuamente a servicios en línea que mantienen una copia actualizada de esos datos.
En esta parte, aprenderemos a utilizar la cartografía disponible en línea, es decir, a interaccionar con los servicios OGC desde nuestro código para obtener todo tipo de mapas e incorporarlos a nuestra aplicación SIG.

1. Google Maps y WMS
1.1. Anatomía de un mapa: los tiles
 Todos los mapas de Google Maps estan divididos en porciones de 256 X 256 píxeles llamadas tiles. Cuando se solicita un mapa, Google Maps descarga del servidor las distintas porciones por separado y las junta, creando la ilusión de una única imagen:
  

 El objetivo de reducir el mapa en porciones no es otro que minimizar el tamaño de los datos que el servidor tiene que enviar a las distintas aplicaciones. Debemos pensar que si bien en niveles de zoom pequeños sí que sería factible tener todo el mapa en una única imagen (cuyo tamaño sería de alrededor de unos pocos kilobytes), no sucede lo mismo con los niveles de zoom grandes, en los que sería prácticamente imposible enviar el mapa entero (cuyo tamaño sería de gigabytes).

En el nivel de zoom más pequeño (el nivel 0), el planeta entero está representado en una única porción. Cada nivel subsiguiente de zoom divide cada porción en cuatro subporciones, de manera que el número total de porciones responde a la fórmula 4N, donde N es el nivel de zoom. Así pues, en el nivel 1 habrá cuatro porciones (que formarán una rejilla de 2 x 2), en el nivel 2, dieciséis (que  formarán una rejilla de 4 x 4), y así sucesivamente.

1.2. Mapas personalizados
La API de Google Maps nos permite definir mapas personalizados, cuyo contenido (el contenido de cada una de las porciones) podemos elegir arbitrariamente. Una vez creados, estos mapas se pueden agregar a la vista mediante dos mecanismos diferenciados:
• como una capa del mapa actual, o
• como un mapa independiente.
Aunque existan dos formas de agregar mapas personalizados a una vista, la forma de implementarlos es siempre la misma: crear un objeto “GTileLayer” y sobrecargar las funciones siguientes:

• getTileUrl. Devuelve la dirección (URL) que contiene la imagen de la porción (tile) del mapa, dadas las coordenadas de la porción y el nivel de zoom.
• isPng. Devuelve un valor booleano indicando si la imagen de la porción está en formato PNG*, en cuyo caso puede contener transparencias.
• getOpacity. Devuelve un valor entre 0,0 y 1,0 indicando el nivel de opacidad del mapa. 0,0 es completamente transparente, y 1,0, completamente opaco.

Ejemplo 1: añadir una marca de agua a un mapa

 Veamos un ejemplo sencillo de implementación de un mapa personalizado. Supongamos que deseamos mostrar los mapas de Google con el logotipo de la UOC sobreimpreso a modo de marca de agua*.
La idea es que la marca de agua se vaya repitiendo a lo largo y ancho del mapa, a intervalos regulares. Para lograr este objetivo, emplazaremos una misma imagen —el logotipo cualquiera— en todas y cada una de las porciones que, recordemos, dividen el mapa en áreas de 256 x 256 píxeles. A todos los efectos, es como si creásemos un mosaico con el logotipo de la UOC. Para crear el efecto de marca de agua, estableceremos el nivel de opacidad del mapa en el 50%.

Suponiendo que tenemos el logotipo de la UOC en un fichero llamado “logo.png”(de 256 x 256 píxeles), el código que crea el mapa nos quedaría así:

var capaLogo;
capaLogo = new GTileLayer(null, 0, 19);
// el nombre del fichero que contiene la imagen
capaLogo.getTileUrl = function() { return "logo.png"; }
// opacidad del 50%, expresada en tanto por uno
capaLogo.getOpacity = function() { return 0.5; }
// el fichero que contiene la imagen está en formato PNG
capaLogo.isPng = function() { return true; }


Como podemos observar, el código sobrecarga las tres funciones de la clase “GTileLayer” antes descritas: getTileUrl, getOpacity e isPng. La función getTileUrl siempre devuelve la misma imagen (“logo-uoc.png”), que es la que queremos mostrar en todas las porciones del mapa; getOpacity, siempre la misma transparencia (del 50%), e isPng, siempre true, puesto que sabemos que la imagen que se devuelve está en formato PNG. Por otro lado, el constructor de la clase “GTileLayer” espera tres parámetros: 

• una colección de textos de copyright que se mostrarán en la parte inferior derecha del
mapa,
• el nivel de zoom mínimo del mapa (ampliación mínima del mapa) y
• el nivel de zoom máximo del mapa (ampliación máxima del mapa).
En el ejemplo, no se ha proporcionado ninguna colección de textos de copyright (“null”) y se han establecido los niveles de zoom mínimo y máximo permitidos por Google Maps.
1.2.1. Tile layer overlays

Una forma de agregar un mapa personalizado a la vista es mediante el mecanismo de las capas. Google llama a las capas que contienen mapas tile layer overlays. Por medio de este mecanismo, situaremos el mapa en la capa más superficial de la vista, de manera que quede por encima de las demás. Dada su posición predominante, debemos jugar con su opacidad para que revele, en mayor o menor medida, las capas inferiores. Los pasos que se habrán de seguir serán dos:
1) crear una capa a partir del objeto "GTileLayer" que contiene el mapa, y
2) agregar dicha capa a la vista.

Siguiendo con el ejemplo anterior, el código siguiente:

mapa.addOverlay(new GTileLayerOverlay(capaLogo));

crea una capa a partir del mapa “capaLogo” y lo agrega a la vista del mapa.
Como se puede observar, el primer paso se realiza instanciando un objeto "GTile-LayerOverlay", cuyo constructor espera un objeto "GTileLayer", es decir, el mapa personalizado ("capaLogo"). El segundo paso se alcanza mediante una llamada a la función addOverlay de la clase "GMap2", cuyo único parámetro debe ser un objeto "GTileLayerOverlay", es decir, la capa que se desea agregar a la vista.

1.3. Mapas WMS

Hasta ahora hemos aprendido a crear mapas personalizados y a agregarlos, como capas o como mapas aislados, a la vista de mapa. Sin embargo, el contenido que mostrábamos era muy poco interesante: tan sólo una imagen que se repetía una y otra vez.

Ahora utilizaremos esta base para crear mapas personalizados que muestren datos obtenidos de un servicio OGC/WMS. La idea que reside en el fondo de esta técnica es relativamente simple: obtener la imagen de cada porción de un servicio OGC/WMS y proporcionarla a Google Maps.

El servicio OGC/WMS, en adelante WMS (por Web Map Service, servicio de mapas de la Web), proporciona mapas georeferenciados a partir de datos geográficos. Los mapas se generan a petición de un cliente, que especifica, mediante un protocolo estándar, los datos que quiere obtener, la zona geográfica en la que se limita la petición, el formato del mapa obtenido, etc. Al final, el cliente obtiene una imagen georeferenciada que concentra y representa toda la información que esperaba obtener. 
Es importante destacar que el cliente no recibe nunca los datos en sí: tan sólo una imagen apta (hablando en términos de resolución) para ser mostrada en la pantalla de un ordenador.

El estándar define dos operaciones obligatorias que debe soportar el servicio (GetCapabilities y GetMap) y otra optativa (GetFeatureInfo): 
• GetCapabilities. Proporciona información acerca de los datos ofrecidos por el servidor y sus características, los sistemas de referencia soportados, el ámbito geográfico, etc. 
• GetMap. Proporciona una imagen georeferenciada que contiene los datos solicitados. El estándar nos permite definir el área del mapa, las capas mostradas, el formato de la imagen, etc.
• GetFeatureInfo. Proporciona información acerca de características particulares mostradas en el mapa.

La información que se puede obtener por medio del servicio WMS gira en torno a las capas de información. Es decir, el proveedor proporciona una o más capas, que se pueden obtener aisladas o combinadas mediante la operación GetMap. Es importante remarcar que siempre se obtiene una única imagen como respuesta a una operación GetMap.

A continuación, se detallan los parámetros obligatorios que espera la operación GetMap y el significado de cada uno de ellos:

• VERSION=1.1.1. Especifica el número de versión del protocolo. En otras palabras, especifica la versión del servicio a la que se espera acceder. Dependiendo de la versión, el proveedor aceptará unos parámetros u otros. Estos materiales se basan exclusivamente en la versión 1.1.1 del estándar.
• REQUEST=GetMap. Especifica la operación a la que se quiere acceder. Para la operación GetMap, el valor de REQUEST siempre será GetMap.
• LAYERS (capas). Especifica las capas de información que se desean obtener, separadas por comas. Las capas se deben listar desde la más profunda hasta la más superficial.
• STYLES (estilos). Especifica el estilo con el que se dibujará cada capa. Igual que en el parámetro anterior, los nombres de los estilos deben ir separados por comas.
• SRS (de Source Reference System, ‘sistema de referencia de la fuente’). Especifica el sistema de referencia de la petición. Todas las coordenadas especificadas en los demás parámetros se suponen escritas en este sistema de referencia.
• BBOX (de Bounding BOX, ‘cuadro delimitador’). Especifica los límites del mapa que se desea obtener. Se trata de una lista separada por comas de las coordenadas suroeste y noreste del mapa. Las coordenadas deben especificarse de acuerdo al sistema de referencia indicado en el parámetro SRS.
• WIDTH (ancho). Especifica la anchura, medida en píxeles, que debe tener la imagen resultante.
• HEIGHT (alto). Especifica la altura, medida en píxeles, que debe tener la imagen resultante.
• FORMAT (formato). Especifica el formato (PNG, JPEF, GIF, etc.) que debe tener la imagen resultante.

En resumen, mediante la operación GetMap podemos obtener una porción de cualquier mapa que nos ofrezca el proveedor, en el formato y en las dimensiones que deseemos.

1.4. Mapas personalizados
Partiendo del código desarrollado en el apartado anterior, a continuación mostraremos algunos ejemplos que combinan los mapas de Google con mapas WMS, o que incluso prescinden de los mapas de Google para mostrar un único mapa WMS o un par de ellos combinados. Para ilustrar estos ejemplos, hemos utilizado los servicios WMS que ofrecen el ICC* i el CREAF**
Ejemplo 2: un único mapa WMS
En este ejemplo, se crea un mapa personalizado que contiene un único mapa topográfico
a escala 1:250000 procedente del servicio WMS del ICC:

<!DOCTYPE html "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type"
content="text/html;charset=utf-8"/>
<title>Ejemplo 2</title>
<script src="http://maps.google.com/maps?file=api&amp;v=2"
type="text/javascript"></script>
<script type="text/javascript">
function initialize() {
var mapa;
var capaTopo;
var mapaTopo;
if (GBrowserIsCompatible()) {
mapa = new GMap2(document.getElementById("elemento_mapa"));
mapa.setCenter(new GLatLng(41.5580, 1.5906), 7);
mapa.setUIToDefault();
// crea la capa WMS
capaTopo = crearCapaWms(7, 12, 1.0,
"http://shagrat.icc.es/lizardtech/iserv/ows?",
"mtc250m,");
// crea un mapa personalizado a partir de la capa WMS
mapaTopo = new GMapType(
[capaTopo],
G_NORMAL_MAP.getProjection(),
"WMS");
// agrega el mapa personalizado al visor
mapa.addMapType(mapaTopo);
}
}
function crearCapaWms(zoomMin, zoomMax, opacidad, url, capas,
estilos, formato, colorFondo, version, srs) {
var capaWms;
capaWms = new GTileLayer(null, zoomMin, zoomMax);
// rellena los parámetros no especificados
if (! estilos) { estilos = ""; }
if (! formato) { formato = "image/png"; }
if (! version) { version = "1.1.1"; }
if (! colorFondo) { colorFondo = "0xFFFFFF"; }
if (! srs) { srs = "EPSG:4326"; }
capaWms.wmsUrl = url;
capaWms.wmsCapas = capas;
capaWms.wmsEstilos = estilos;
capaWms.wmsFormato = formato;
capaWms.wmsVersion = version;
capaWms.wmsColorFondo = colorFondo;
capaWms.wmsSrs = srs;
// la dirección web del fichero que contiene la imagen
capaWms.getTileUrl = obtenerUrlTile;
// opacidad expresada en tanto por uno
capaWms.getOpacity = function() { return opacidad; }
// el fichero que contiene la imagen está en formato PNG?
capaWms.isPng = function() { return formato == "image/png"; }
return capaWms;
}
// tile: GPoint
// zoom: Number
function obtenerUrlTile(tile, zoom) {
var xySupIzq; // coord. x/y de la esquina superior izquierda
var geoSupIzq; // coord. geográfica de la esquina superior
// izquierda
var xyInfDer; // coord. x/y de la esquina inferior derecha
var geoInfDer; // coord. geográfica de la esquina inferior
// derecha
var urlTile;
// obtiene las coordenadas x/y de las esquinas superior
// izquierda e inferior derecha
xySupIzq = new GPoint(tile.x * 256, (tile.y + 1) * 256);
xyInfDer = new GPoint((tile.x + 1) * 256, tile.y * 256);
// obtiene las coordenadas geográficas de las esquinas superior
// izquierda e inferior derecha
geoSupIzq = G_NORMAL_MAP.getProjection().
fromPixelToLatLng(xySupIzq, zoom);
geoInfDer = G_NORMAL_MAP.getProjection().
fromPixelToLatLng(xyInfDer, zoom);
// genera la URL del "tile"
urlTile = this.wmsUrl;
urlTile += "&REQUEST=GetMap";
urlTile += "&SERVICE=WMS";
urlTile += "&VERSION=" + this.wmsVersion;
urlTile += "&LAYERS=" + this.wmsCapas;
urlTile += "&STYLES=" + this.wmsEstilos;
urlTile += "&FORMAT=" + this.wmsFormato;
urlTile += "&BGCOLOR=" + this.wmsColorFondo;
urlTile += "&TRANSPARENT=TRUE";
urlTile += "&SRS=" + this.wmsSrs;
urlTile += "&BBOX=" + geoSupIzq.x + "," + geoSupIzq.y + "," +
geoInfDer.x + "," + geoInfDer.y;
urlTile += "&WIDTH=256";
urlTile += "&HEIGHT=256";
urlTile += "&reaspect=false";
return urlTile;
}
</script>
</head>
<body onload="initialize()" onunload="GUnload()">
<div id="elemento_mapa" style="width: 750px; height: 450px">
</div>
</body>
</html>
El resultado será parecido al siguiente:
Ejemplo

Ejemplo 3: mapa WMS combinado con el mapa normal de Google Maps
En este ejemplo, hemos creado un mapa personalizado que combina el mapa normal de
Google Maps con un mapa geológico a escala 1:50000 procedente del servicio WMS del
ICC. Sólo mostramos la función initialize, porque el resto del código no cambia respecto
al ejemplo n.º 2.

function initialize() {
var mapa;
var capaGeo;
var mapaCombi;
if (GBrowserIsCompatible()) {
mapa = new GMap2(document.getElementById("elemento_mapa"));
mapa.setCenter(new GLatLng(41.5580, 1.5906), 7);
mapa.setUIToDefault();
// crea la capa WMS
capaGeo = crearCapaWms(7, 15, 0.4,
"http://shagrat.icc.es/lizardtech/iserv/ows?",
"mgc50m,");
// crea un mapa personalizado a partir de la capa WMS y del
// mapa normal de Google Maps
mapaCombi = new GMapType(
[G_NORMAL_MAP.getTileLayers()[0], capaGeo],
G_NORMAL_MAP.getProjection(),
"WMS");
// agrega el mapa personalizado al visor
mapa.addMapType(mapaCombi);
}
}

El resultado será parecido al siguiente:


 Ejemplo 4: dos mapas WMS procedentes de una única fuente combinadosEl ejemplo siguiente combina dos mapas procedentes del servicio WMS del ICC: el topográfico
1:25000 y el geológico 1:50000. Sólo mostramos la función initialize, porque el
resto del código no cambia respecto al ejemplo n.º 2.

function initialize() {
var mapa;
var capaTopo;
var capaGeo;
var mapaCombi;
if (GBrowserIsCompatible()) {
mapa = new GMap2(document.getElementById("elemento_mapa"));
mapa.setCenter(new GLatLng(41.5580, 1.5906), 7);
mapa.setUIToDefault();
// crea la capa WMS del mapa topográfico
capaTopo = crearCapaWms(7, 12, 1.0,
"http://shagrat.icc.es/lizardtech/iserv/ows?",
"mtc50m,");
// crea la capa WMS del mapa geológico
capaGeo = crearCapaWms(7, 15, 0.40,
"http://shagrat.icc.es/lizardtech/iserv/ows?",
"mgc50m,");
// crea un mapa personalizado a partir de las dos capas WMS
mapaCombi = new GmapType(
[capaTopo, capaGeo],
G_NORMAL_MAP.getProjection(), "WMS");
// agrega el mapa personalizado al visor
mapa.addMapType(mapaCombi);
}
}

 El resultado será parecido al siguiente:




Bibliografía
Oracle, "The Java(tm) Tutorials", http://download.oracle.com/javase/tutorial/. 
Oracle, "Java(tm) 2 Platform Standard Edition 5.0 API Specification", http:// download.oracle.com/javase/1.5.0/docs/api/.
Personalización SIG, Albert Gavarró Rodríguez , Universidad Oberta  de Catalunya, España 2011


martes, 11 de noviembre de 2014

Instalación y Configuración API de ESRI en servidor Jboss 7.1 final

Instalación de la API de ArcGIS para JavaScript Library en Windows
Las instrucciones siguientes se supone que va a instalar la biblioteca de API de ArcGIS JavaScript en la siguiente ubicación en un servidor Web (Jboss 7.1 final ) , "http: // <myserver> /arcgis_js_api/library/3.12/" donde <myserver> es el nombre de dominio de su web sitio. Después de copiar los archivos a su servidor Web, tendrá que modificar algunos archivos para incluir la dirección URL para el servidor y el directorio que usted está planeando instalar.
  1. Copia \ arcgis_js_api \ biblioteca y todo su contenido desde el DVD a su servidor Web. En este ejemplo, los archivos se copian en: C:\jboss-as-7.1.1.Final\welcome-content\arcgis_js_api\ biblioteca
Instale el Build Normal o compacto

Opciones de configuración para la acumulación normal de:
  1. Abrir en C:\jboss-as-7.1.1.Final\welcome-content\ arcgis_js_api \ library \ 3.12 \ 3.12 \ Init.js en un editor de texto y buscar el texto "[HOSTNAME_AND_PATH_TO_JSAPI] ' , y reemplace este texto con "<myserver> /arcgis_js_api/library/3.12/ 3,12 / ". 
  2. Abrir C:\jboss-as-7.1.1.Final\welcome-content \ arcgis_js_api \ library \ 3.12 \ 3.12 \ dojo \ dojo.js en un editor de texto y buscar el texto "[HOSTNAME_AND_PATH_TO_JSAPI] ' , y reemplace este texto con "<myserver> / arcgis_js_api / biblioteca / 3.12 / 3.12 / "
Opciones de configuración para construcción compacta:
  1. Abrir C:\jboss-as-7.1.1.Final\welcome-content \ arcgis_js_api \ library \ 3.12 \ 3.12compact \ Init.js en un editor de texto y buscar el texto "[HOSTNAME_AND_PATH_TO_JSAPI]" , y reemplazar cada instancia de este texto con "<myserver> / arcgis_js_api / biblioteca / 3.12 / 3.12compact / "
  2. Abrir C:\jboss-as-7.1.1.Final\welcome-content \ arcgis_js_api \ library \ 3.12 \ 3.12compact \ dojo.js en un editor de texto y buscar el texto "[HOSTNAME_AND_PATH_TO_JSAPI] ' , y reemplace este texto con "<myserver> /arcgis_js_api/library/3.12 /3.12compact/ "
Prueba de la Instalación
Ahora usted debería ser capaz de acceder a la biblioteca de ArcGIS JavaScript de su servidor Web utilizando el siguiente URL (s):
    http: // <myserver> /arcgis_js_api/library/3.12/3.12/init.js
    http: // <myserver> /arcgis_js_api/library/3.12/3.12compact/init.js
Pruebe su instalación. Usted puede utilizar el siguiente código de prueba para validar su biblioteca JSAPI instalar.

<! DOCTYPE HTML PUBLIC "- // W3C // DTD HTML 4.01 // EN" "http://www.w3.org/TR/html4/strict.dtd">
<Html>
  <Head>
    <Meta http-equiv = "Content-Type" content = "text / html; charset = utf-8" />
    <Title> Simple Map </ title>
    <Link rel = "stylesheet" type = "text / css" href = "http: // <myserver> /arcgis_js_api/library/3.12/3.12/dijit/themes/tundra/tundra.css" />
    <Link rel = "stylesheet" type = "text / css" href = "http: // <myserver> /arcgis_js_api/library/3.12/3.12/esri/css/esri.css" />
    <Script type = "text / javascript" src = "http: // <myserver> /arcgis_js_api/library/3.12/3.12/init.js"> </ script>
    <Script type = "text / javascript">
      dojo.require ("esri.map");
      función init () {
        var myMap = new esri.Map ("mapDiv");
        // En cuenta que si usted no tiene acceso a Internet, entonces usted tendrá que apuntar esta URL a su propio servicio de caché local accesible.
        myTiledMapServiceLayer var = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/NGS_Topo_US_2D/MapServer");
        myMap.addLayer (myTiledMapServiceLayer);
      }
      dojo.addOnLoad (init);
    </ Script>
  </ Head>
  <Body class = "tundra">
    <Div id = estilo "mapDiv" = "width: 900px; altura: 600px; border: 1px solid # 000;"> </ div>
  </ Body>
</ Html>