curso geoexplorer - caam/GeoExplorer GitHub Wiki

GeoExplorer + gxp

##Crear código en github

  • Entrar en http://github.com y crear una cuenta en 'Signup and Pricing'. Pinchar sobre 'Create a free account'. Es gratuito para software libre (y nuestro código es necesariamente GPL ya que incluye librerías GPL)
  • Introducir un login (Username) único, un correo electrónico y una contraseña. Pinchar en 'Create an account'
  • Ir a http://github.com/opengeo/GeoExplorer. Pinchar sobre 'Fork'
  • Repetir el proceso en http://github.com/opengeo/gxp

##Descargar el código

  • Instalar los programa git, ant y openjdk-7-jdk:

    sudo apt-get install git ant openjdk-6-jdk

  • Descargar el código con:

    git clone git://github.com//GeoExplorer.git

Nota: Los puertos están cortados en la CARM, pero he pedido que se abran desde 147.84.40.0/22

  • Modificar GeoExplorer para que tire de /gxp (en lugar de opengeo/gxp):

  • Eliminamos el módulo gxp (de opengeo)

    git config -f .gitmodules --remove-section submodule.app/static/externals/gxp
    git rm --cached app/static/externals/gxp
    rm -rf app/static/externals/gxp

Nota: Si se ha hecho git init hay que borrarlo también de .git/config con git config -f .git/config --remove-section submodule.app/static/externals/gxp

Nota: A fecha 9/12 hay un error en el código de opengeo... Se puede subsanar si eliminamos el módulo ringo-fork:

git config -f .gitmodules --remove-section submodule.externals/ringojs-fork  
git config -f .git/config --remove-section submodule.externals/ringojs-fork  
git rm --cached externals/ringojs-fork  
rm -rf externals/ringojs-fork

y en build.xml cambiamos ringojs-fork por ringojs

  • Añadimos el nuevo módulo gxp (de login):

    git submodule add -b HEAD git://github.com/lo>gin/gxp.git app/static/externals/gxp

  • Confirmamos cambios:

    git commit git push --repo=https://github.com/<login>gxp.git

  • Ejecución desde tomcat:

  • Compilar

    cd GeoExplorer ant war

  • Publicar en Tomcat:

    sudo cp build/geoexplorer.war /var/lib/tomcat7/webapps

  • Ver el resultado en http://localhost:8080/geoexplorer

  • Ejecución 'standalone' (sin tomcat, para depurar) utilizando el puerto 8081 (ya que el 8080 está pillado por tomcat) y redirigiendo las peticiones de geoserver al geoserver de tomcat). Se ve desde http://localhost:8081:

    cd GeoExplorer ant -Dapp.port=8081 -Dapp.proxy.geoserver=http://localhost:8080/geoserver/ debug

  • Comprobar que se crea el fichero geoexplorer.db. Se puede mover de sitio en /var/lib/tomcat7/webapps/geoexplorer/WEB-INF/web.xml añadiendo el parámetro GEOEXPLORER_DATA. Por ejemplo, añadir:

    <init-param> <param-name>GEOEXPLORER_DATA</param-name> <param-value>/var/geoexplorer</param-value> </init-param> ... crear /var/geoexplorer con permisos RW al usuario tomcat7: sudo mkdir /var/geoexplorer sudo chown tomcat7 /var/geoexplorer sudo /etc/init.d/tomcat7 restart.

Lanzar la aplicación, grabar un mapa y probar:

sudo apt-get install sqlite3
cd /var/geoexplorer
sqlite3 geoexplorer.db
sqlite> .tables (vemos que existe la tabla "maps")
sqlite> .schema maps (vemos que contiene las columnas id y config)
sqlite> select count(*) from maps;
sqlite> select * from maps;

Ficheros/carpetas interesantes

  • GeoExplorer/buildjs.cfg: indica qué ficheros incluir para construir el war de producción.
  • app/templates/composer.html: HTML principal. Incluye a base.html. Realmente es una plantilla que el tomcat completa y envía al navegador.
  • app/root: código ejecutable en servidor. Realmente es javascript interpretado en servidor con un motor denominado RINGO:
  • proxy.js: El proxy
  • login.js: Validación (va contra geoserver)
  • maps.js: Acceso al almacén de mapas
  • index.js -> llama a composer
  • composer.js -> Genera javascript del visor principal
  • viewer.js -> Genera javascript de un visor reducido
  • app/static/externals: librerías javascript:
  • ExtJS 3.4
  • GeoExt
  • gxp
  • OpenLayers
  • PrintPreview (generación de PDFs)
  • proj4js (para reproyectar a otro sistemas de referencia)
  • app/static/theme: css's
  • app/static/script/app/GeoExplorer.js: Código JS para constructor GeoExplorer (hereda de gxp.Viewer).
  • app/static/script/app/GeoExplorer/composer.js: Código JS constructor GeoExplorer.Composer (hereda de GeoExplorer)

Poner I/F en español

Añadir en buildjs.cfg en root=:

`app/static/externals`

y en el include=:

`gxp/src/script/locale/es.js`

Cambiar sistema de proyección, orígenes y capas iniciales

  • Editar GeoExplorer/app/templates/composer.html

  • Quitar en sources todo, salvo local y ol

  • Añadir los siguiente orígenes (sources):

    cartomur: { url: "http://cartomur.imida.es/SgdWms/SgdWms_cartomur.dll/WMS?", title: "CARTOMUR" }, catastro: { url: "http://www1.sedecatastro.gob.es/Cartografia/WMS/ServidorWMS.aspx?", title: "catastro" }, mapabase: { url: "http://iderm.imida.es/arcgis/services/TOPOGRAFICOS/Topografico_UTM_ETRS89/MapServer/WMSServer", title: "MAPABASE" }, topograficos: { url: "http://iderm.imida.es/arcgis/services/TOPOGRAFICOS/MTR/MapServer/WMSServer", title: "TOPOGRAFICOS" },

En mapa, especificar:

`map: {
    projection: "EPSG:25830",
    units: "m",
    maxResolution: 305.748113140558,
    maxExtent: [518423,4118918,740113,4318973],
    numZoomLevels: 12,
    layers: [
      {
        title: "Orto 2009",
        name: "Ortofoto_2009",
        source: "cartomur",
        group: "background"
      }, { 
        source: "ol",
        group: "background",
        type: "OpenLayers.Layer.ArcGIS93Rest",
        args: [
          "Natmur 2008",
          "http://iderm.imida.es/ArcGIS/rest/services/Raster/Natmur2008_UTM_ETRS89/MapServer/export", 
          {layers: "show:0", format: 'jpeg'}, 
          {singleTile: false, visibility: false, noLegend: true}
        ]
      }, {
        source: "ol",
        group: "background",
        type: "OpenLayers.Layer.ArcGIS93Rest",
        args: [
          "Mapa Topográfico",
          "http://iderm.imida.es/ArcGIS/rest/services/TOPOGRAFICOS/MTR/MapServer/export",
          {layers: "show:0", format: 'jpeg'}, 
          {singleTile: false, visibility: true, noLegend: true}
        ]
      }, {
        source: "ol",
        group: "background",
        fixed: true,
        type: "OpenLayers.Layer",
          args: [
            "None", {visibility: false}
          ]
        }
      ],
    center: [0, 0],
    zoom: 1
  }
`

Para que funcionen las capas ArcGIS (Orto del 2008 y MTR) es preciso añadir en buildjs.cfg en la zona include=:

`OpenLayers/Layer/ArcGIS93Rest.js`

Añadir la posición del ratón bajo la escala

En composer.html añadir al final:

`app.on("ready", function () {
  app.mapPanel.map.addControl(new OpenLayers.Control.MousePosition(
    {numDigits: 0, suffix: ' m ETRS89', prefix: ' x, y: ', separator: ' m, '}
  )); 
});
`

Para que no se confundan los números con el mapa de fondo, se puede poner el fondo en blanco utilizando CSS en composer.html (justo antes del comienzo del script que indica el comienzo del código principal):

` <style>
  .olControlMousePosition {
     background: #FFFFFF;
  }    </style>
`

Además hay que añadir en buildjs.cfg en include=:

` OpenLayers/Control/MousePosition.js`

Recibir como argumento posición X, Y, Zoom inicial

En composer.html añadir al final:

`app.on("ready", function () {
  var myX= urlParams["x"],
      myY= urlParams["y"],
      myZ= urlParams["z"];
  if (myX && myY && myZ) {
    app.mapPanel.map.panTo(new OpenLayers.LonLat(myX,myY));
    app.mapPanel.map.zoomTo(myZ);
  }
});`

urlParams se declara al principio del archivo; justo después de script:

`var getParams = document.URL.split("?"),
  urlParams=Ext.urlDecode(getParams[getParams.length - 1]);`

Ahora podemos invocar por ejemplo: http://localhost:8081/composer?x=657273&y=4213524&z=6 para ver Molina de Segura.

Nota: Es interesante para ver el parseo de los argumentos inspeccionar con Firebug: document.URL, document.URL.split("?"), document.URL.split("?")[1], Ext.urlDecode(document.URL.split("?")[1]), Ext.urlDecode(document.URL.split("?")[1]).x

Añadir buscador

El buscador por atributos (utilizando WFS) está presente en geoeditor (http://suite.opengeo.org/geoeditor/). Sin embargo, el código de geoeditor es más antiguo que geoexplorer, con lo que para no perder funcionalidad, lo más interesante es integrar la funcionalidad de geoeditor en geoexplorer.

El código de geoeditor lo podemos bajar por subversion (svn):

`sudo apt-get install subversion
svn checkout http://svn.opengeo.org/tike/editor/trunk/ geoeditor`

Tomamos el fichero geoeditor/src/script/app/GeoExplorer.js y vamos añadiendo trozos a GeoExplorer/app/static/script/app:

Nota: Con vi podemos editar dos ficheros simultaneamente editando el primero de ellos (vi geoeditor/src/script/app/GeoExplorer.js), partiendo la ventana en dos (Control+w y s), cambiamos a la zona de abajo (Control+w y Control+w) y cargamos el segundo fichero (:e GeoExplorer/app/static/script/app/GeoExplorer.js).

  • Copiamos el método createFeatureLayer y lo añadimos. Añadimos al final de este método la línea:

    this.mapPanel.map.addLayer(this.featureLayer);

  • En la función loadConfig, cambiamos la línea mapUrl por:

    var mapUrl = window.location.hash.substr(1).split("?")[0];

    • En la función initPortal, añadir tras declarar westPanel:

      this.createFeatureLayer();

    • Poner id a westPanel:

      id: 'westPanel',

    • Debajo de la declaración de this.mapPanelContainer, añadir todo el resto del fichero desde var queryPanel = new gxp.QueryPanel({ hasta var southPanel = new Ext.Panel(.....

    • Proteger la declaración de queryPanel por: if (this.initialConfig.featureTypes) { }

    • Cambiar this.portalItems = ... por:

      if (southPanel) { this.portalItems = [{ region: "center", layout: "border", tbar: this.toolbar, items: [ this.mapPanelContainer, westPanel, southPanel ] }]; } else { this.portalItems = [{ region: "center", layout: "border", tbar: this.toolbar, items: [ this.mapPanelContainer, westPanel ] }]; }

    • Para que al seleccionar un resultado, la capa vectorial creada esté la primera: Añadir al final de la función query: function(panel, store) ...

      this.mapPanel.map.raiseLayer(this.featureLayer,999);

    • Añadir la función getSearchResultsTitle

    • Cambiar las referencias a this.map por this.mapPanel.map (4 cambios)

    • Cambiar var button = toolbar.find("iconCls"...) por

      var button = Ext.getCmp('westPanel').items.items[0].toolbars[0].find("iconCls","gxp-icon-addlayers")[0];

En composer.html hay que recibir el "FeatureLayer" desde la URL para lo que hay que añadir como último argumento del objeto map (GeoExplorer.Composer):

`featureTypes: urlParams["f"] && Ext.util.JSON.decode(urlParams["f"])`

Proteger en composer.html todo el código entre:

`Ext.onReady(function() {
  Ext.QuickTips.init()
  ...
});`

En buildjs.cfg hay que añadir:

`widgets/QueryPanel.js
widgets/grid/FeatureGrid.js
widgets/grid/CapabilitiesGrid.js

GeoExt/widgets/grid/FeatureSelectionModel.js`

Ahora para pasar el "FeatureLayer" hay que invocar:

`http://localhost:8081/composer?f=[%20{%20%22title%22:%20%22molina%22,%20%22name%22:%20%22molina%22,%20%22namespace%22:%20%22http://caamext.carm.es/curso%22,%20%22url%22:%20%22/geoserver/wfs%22,%20%22schema%22:%20%22/geoserver/wfs%3Fversion%3D1.1.0%26request%3DDescribeFeatureType%26typeName%3Dcurso:molina%22}]`

Nota: Si hay problemas que no se ven claros en la ventana de console de Firebug se puede cambiar las librerías (ext-all.js en base.html o GeoExt.js y gxp.js en composer.html) a su versión debug (por ejemplo ext-all-debug.js).

Módulo de impresión en geoserver

Se explica en http://docs.geoserver.org/stable/en/user/community/printing/

  • Descargar en http://gridlock.opengeo.org/geoserver/2.1.x/community-latest/ el fichero geoserver-2.1-SNAPSHOT-printing-plugin.zip:

    wget http://gridlock.opengeo.org/geoserver/2.1.x/community-latest/geoserver-2.1-SNAPSHOT-printing-plugin.zip

    • Descomprimir:

      unzip geoserver-2.1-SNAPSHOT-printing-plugin.zip

    • Copiar los jar's a /var/lib/tomcat7/webapps/geoserver/WEB-INF/lib:

      sudo cp *.jar /var/lib/tomcat7/webapps/geoserver/WEB-INF/lib

    • Reiniciar geoserver (tomcat):

      sudo /etc/init.d/tomcat7 restart

Búsqueda por proximidad (buffer)

Añadir a app/static/externals/gxp/src/script/widgets/QueryPanel.js:

  • Los atributos justo debajo de spatialQuery:false

    bufferQuery: false, queryByBufferText: "Query by buffer",

  • En this.addEvents, dentro de initComponent: añadir debajo de this.mapExtentField=...

    this.bufferFieldX = new Ext.form.TextField({ fieldLabel: "X", readOnly: false, anchor: "100%", value: 0 }); this.bufferFieldY = new Ext.form.TextField({ fieldLabel: "Y", readOnly: false, anchor: "100%", value: 0 }); this.bufferFieldR = new Ext.form.TextField({ fieldLabel: "R", readOnly: false, anchor: "100%", value: 0 });

    • Añadir debajo del objeto de xtype fieldset de título this.queryByLocationText el siguiente:

      { xtype: "fieldset", title: this.queryByBufferText, checkboxToggle: true, collapsed: !this.bufferQuery, anchor: "95%", items: [this.bufferFieldX, this.bufferFieldY, this.bufferFieldR], listeners: { collapse: function() { this.bufferQuery = false; }, expand: function() { this.bufferQuery = true; }, scope: this } },

    • En la función getFilter añadir:

      var bufferFilter = this.bufferQuery && new OpenLayers.Filter.Spatial({ type: OpenLayers.Filter.Spatial.DWITHIN, value: new OpenLayers.Geometry.Point( this.bufferFieldX.getValue(), this.bufferFieldY.getValue()), distance: this.bufferFieldR.getValue(), distanceUnits: 'm' });

    • Y al final de la función modificar filter = attributeFilter||spatialFilter por:

      filter = attributeFilter || spatialFilter || bufferFilter;

Ejercicio para control

Hacer búsqueda del polígono 8, parcela 1 de Molina. Enviar pantallazo a [email protected]

Más información:

⚠️ **GitHub.com Fallback** ⚠️