Le blog de Jean David TECHER, un Réunionnais à Saint-Priest/Lyon

Aller au contenu | Aller au menu | Aller à la recherche


< 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 >

samedi 12 mai 2007

QGIS 0.8.0 : test de l'exportateur de projet vers mapfile pour MapServer

Récemment, je me suis aperçu que par rapport à mon premier billet sur l'installation de QGIS 0.8.0, l'option d'exportation de QGIS ne marchait pas! Par «exportation de QGIS », j'entends

fichier de projet de QGIS en .qgs --[Exportation]--> fichier .map pour MapServer

En effet dans le sous-répertoire tools/mapserver_export/, la compilation ne passait pas.

Or celui-ci a besoin des headers de Python 2.4 (chez moi) pour être compilé. La solution a donc été

apt-get install python2.4-dev
puis comme cette option de Qgis nécessite python, c'est surtout l'option --with-python qu'il faut passer à configure pour l'activer
 ./configure --with-qtdir=/usr --with-wfs --with-python --with-geos=/usr/local/bin/geos-config --with-projdir=/usr/local \
--with-gdal=/opt/gdal-1.4.0/bin/gdal-config --with-postgresql=/usr/local/pgsql/bin
Et ensuite comme d'habitude
make
make install

Pour tester ensuite l'option, je me suis ensuite connecté au server WMS de GEOSIGNAL que j'ai chargé dans QGIS. Conformément à la directive de licence en cours sur le site de cette société, je rappelle ici l'URL de la licence du cadre d'utilisation. Je me suis amusé à zoomersur ma propre ville à savoir Castelnau-Le-Lez. En utilisant l'exportateur, j'ai eu

vendredi 11 mai 2007

Errors with PostGIS and POLYGON

Here I will try to show two examples of error with PostGIS and POLYGON.

1. Self-Intersection
The follwing POLYGON is not valid.
testgis=# SELECT IsValid('POLYGON((402 253,401 434,675 435,675 314,487 314,559 314,559 201,404 253,402 253))'::geometry);
INFO:  Self-intersection
INFO:  Self-intersection
 isvalid
---------
 f
He intersects hilmself. Have a look on the following picture!
2. Ring Self-Intersection
Suppose that you have a the following POLYGON
POLYGON ((380 340, 40 340, 40 20, 380 20, 380 340),(120 300, 300 280, 320 200, 
160 140, 200 80, 320 120, 320 200, 360 60, 120 40, 120 300))
Let's try Summary() function.
testgis=# SELECT summary('POLYGON ((380 340, 40 340, 40 20, 380 20, 380 340),
(120 300, 300 280, 320 200, 160 140, 200 80, 320 120, 320 200, 360 60, 120 40, 120 300))'::geometry);
         summary
-------------------------

 Polygon[B] with 2 rings
    ring 0 has 5 points
    ring 1 has 10 points

(1 ligne)
With
  • ring 0 = [380 340, 40 340, 40 20, 380 20, 380 340] --> My POLYGON
  • ring 1 = [120 300, 300 280, 320 200, 160 140, 200 80, 320 120, 320 200, 360 60, 120 40, 120 300] --> the hole of my polygon
If I try IsValid() function with PostGIS, I get
testgis=# SELECT IsValid('POLYGON ((380 340, 40 340, 40 20, 380 20, 380 340),
(120 300, 300 280, 320 200, 160 140, 200 80, 320 120, 320 200, 360 60, 120 40, 120 300))'::geometry);

INFO:  Ring Self-intersection
INFO:  Ring Self-intersection
 isvalid
---------
 f
(1 ligne)
That's not correct according to OGC Specification. A Polygon with a hole (ring 1) that self-intersects (i.e. POINT (320 200) )! Remember that it is just a case! This example has been taken from Geos SVN repository at ./tests/xmltester/TestValid.xml

mardi 8 mai 2007

Libpqxx 2.6.9 - une belle interface de programmation en C++ pour PostgreSQL - 1ère partie

RESUME

C'est sûrement l'interface de programmation en C++ de PostgreSQL, la plus innovante. Elle constitue par rapport aux habituelles, l'une de la nouvelle génération. Son intérêt réside surtout avec son adéquation avec la bibliothèque STL (Standard Template Library). Comme le souligne son auteur, elle a été pensée «STL-compatible» . Le site de développement est http://thaiopensource.org/development/libpqxx/.

Autre point à signaler, libpqxx est basée sur le mode transactionnel de PostgreSQL. Elle sort donc du cadre purement basique de la programmation «Requêtes - Réponses» pour l'interfaçage client-serveur. La richesse de ses fonctionnalités est vraiment impressionnante, déroutante parfois au premier abord. Elle permet un code lisible, bien stylé, appréciable.

INSTALLATION SOUS UBUNTU DAPPER

En pré-requis, il faut avoir un serveur PostgreSQL sous la main. Libpqxx est basée sur libpq. Sous Windows, j'ai pu la compilé avec MinGW/Msys sans souci. Je livre ici mes notes pour une compilation sous Ubuntu Dapper (ou Debian). Je ne l'ai pas testé sous Visual C++.

Son installation se fait en faisant
wget http://thaiopensource.org/download/software/libpqxx/libpqxx-2.6.9.tar.gz
tar xvzf libpqxx-2.6.9.tar.gz
cd libpqxx-2.6.9
Chez moi PostgreSQL est installé à /opt/pgsql/, je dois effectuer une modification du fichier libpqxx.pc.in avant de continuer. Je fais celà surtout pour pouvoir compiler mes programmes par la suite. On ouvre donc le fichier et on effectue le remplacement suivant
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@

Name: libpqxx
Description: a C++ API to the PostgreSQL database management system.
Version: @VERSION@
Libs: -L${libdir} -L@with_postgres_lib@ -lpq -lpqxx
Cflags: -I${includedir} -I@with_postgres_include@

On peut maintenant compiler.
export PATH=/opt/pgsql/bin/:$PATH
./configure 
make
make install
En essayant d'utiliser pqxx-config, j'ai eu l'erreur suivante
#pqxx-config --libs
pqxx-config is deprecated; please use "/usr/bin/pkg-config --libs libpqxx"

En fait c'est surtout sur la commande pkg-config --libs libpqxx ou pkg-config --cflags libpqxx qu'il faut se baser. Par exemple, pour l'une des deux j'obtiens
# pkg-config --libs libpqxx
-L/usr/local/lib -L/opt/pgsql/lib -lpq -lpqxx
TEST DE REGRESSION
Toujours dans les sources, il faut se rendre dans le sous-répertoire test les sources et faire
cd test
chmod 777 -R .
su postgres
make check
UN PREMIER PROGRAMME
Pour la compilation de mon programme, je vais me doter du Makefile suivant
PKGCONFIG=/usr/bin/pkg-config
CXXFLAGS = -g -Wall $(shell $(PKGCONFIG) --cflags libpqxx)
LDLIBS   = $(shell $(PKGCONFIG) --libs libpqxx)

exes = test1

all:	$(exes)

test1: test1.cc

clean:
	rm -f $(exes)
Si l'utilisation d'un Makefile peut s'avérer déroutant, on pourra essayer
g++ -g -Wall -I/usr/local/include -I/opt/pgsql/include      test1.cc  -L/usr/local/lib -L/opt/pgsql/lib -lpq -lpqxx   -o test1
Mon programme test1.cc sera le suivant, juste un petit programme de connexion
/* test1.cc */

#include <stdlib.h>	// Nécessaire pour exit(), EXIT_SUCCESS, et EXIT_FAILURE
#include <iostream> 	// requis pour cerr
#include <pqxx/pqxx>	// définitions pour libpqxx

using namespace pqxx;
using namespace std;

int main( int argc, const char * argv[] )
{

  try 
  {
    connection    myConnection( argc > 1 ? argv[1] : "" );

    myConnection.activate();
    if (myConnection.is_open())
    {
       string host = to_string( myConnection.server_version() );
       host.replace(1,1,"."); host.replace(3,1,".");
       cout<<" INFORMATIONS:"<<endl;
        cout<<" Paramètres de connexion host="<<myConnection.hostname();
       cout<<" dbname="<<myConnection.dbname()<<" user="<<myConnection.username()<<endl;
       cout<<" Serveur - Version "<<host<<endl;
    }
  }	
  catch( runtime_error & e )
  {
    cerr << "Echec à la connexion avec erreur := " << e.what();
    exit( EXIT_FAILURE );
  }
  catch( exception & e )
  {
    cerr << e.what();
    exit( EXIT_FAILURE );
  }
  catch( ... )
  {
    cerr << "Erreur/exception inconnue !" << endl;
    exit( EXIT_FAILURE );
  }

  exit( EXIT_SUCCESS );

}


Ensuite on tape
make
Pour une utilisation standard, je vais passer à test1 les paramètres de connexion
./test1 "host=localhost dbname=testgis user=postgres password=empr888"
qui me renverra
 INFORMATIONS:
 Paramètres de connexion host=localhost dbname=testgis user=postgres
 Serveur - Version 8.2.3
On peut aussi utiliser des variables d'environnement de PostgreSQL, par exemple
# PGHOST=localhost PGUSER=postgres ./test1 "dbname=testgis password=empr888"
 INFORMATIONS:
 Paramètres de connexion host=localhost dbname=testgis user=postgres
 Serveur - Version 8.2.3
Bien sûr, en cas d'échec de connexion, j'aurais par exemple sur un hôte distant
# PGHOST=192.168.0.5 PGUSER=postgres ./test1 "dbname=testgis password=empr888"
Echec à la connexion avec erreur := FATAL:  authentification par mot de passe échouée pour l'utilisateur  «postgres»

Test du module de PgRouting de Ka-Map avec les données NavTeq

Suite à mon précédent billet, je me suis amusé à tester les données NavTeq de ADCI avec le module PgRoutin de KaMap. Un exemple de démo avec les données de Orkney est visible à kappa.gonfi.org/dev/gonfi-ka-map/htdocs/index_routing.html

J'ai réussi à obtenir par exemple la screenshot suivante pour mes propres données

Une démo est disponible chez moi à http://www.davidgis.fr/ka-map/index_routing.html

Pour commencer il faut suivre les indications de http://ka-map.ominiverdi.org/wiki/index.php/KaRouting. Malheureusement il s'avère que les indications fournies sont incomplètes . Reprenons ici les détails de l'installation

On s'assure par exemple d'avoir le jeu de tests de PgRouting provenant de http://www.postlbs.org/postlbs-cms/en/download à savoir «pgRouting Sample Application». Chez moi, j'ai décompressé le répertoire dans mon "/var/www/". J'ai ensuite copié tout ce qui était associé à streets.shp dans /var/www/routingj/data/

cp streets.* /var/www/routingj/data/

J'ai ensuite crée la mapfile suivante /var/www/routingj/maps/kamap-streets.map dont le contenu est

MAP
  IMAGETYPE   PNG
  EXTENT      -77.1166763305664 38.7924194335938 -76.909538269043 38.9952430725098
  #SIZE        500 489.585635359116
  SIZE 200 195.834254143646
  IMAGECOLOR  255 255 255
  SHAPEPATH   "../data"

  FONTSET     "../fonts/fonts.list"
  
REFERENCE
   IMAGE "/var/www/keymap-streets.png"
  EXTENT -77.1166763305664 38.7924194335938 -76.909538269043 38.9952430725098
  STATUS ON
  COLOR -1 -1 -1
  OUTLINECOLOR 255 0 0
  SIZE 200 164
END

  WEB
    IMAGEPATH "/var/www/tmp/"
    IMAGEURL  "/tmp/"
  END
		
  PROJECTION
   "init=epsg:4326" # JGD2000
  END

  UNITS DD

  SYMBOL
    NAME "hatch"
    TYPE hatch
  END
  
  LAYER 
    NAME "roads"
    DATA streets
    STATUS DEFAULT
    TYPE LINE

    CLASS
      COLOR 155 155 155
    END

  END 

END 

Bien sûr pour calculer l'extent et les dimensions adéquates de l'image pour width=500, je me suis servi des requêtes suivantes

routing=# select extent(the_geom) from streets_edges;
                                  extent
---------------------------------------------------------------------------
 BOX(-77.1166763305664 38.7924194335938,-76.909538269043 38.9952430725098)
(1 ligne)
et de
routing=# SELECT
               500*(abs(Ymax(foo.extent)-Ymin(foo.extent))/abs(Xmax(foo.extent)-Xmin(foo.extent)))
               AS hauteur
         FROM (SELECT Extent(the_geom) FROM streets_edges) AS foo;
     hauteur
------------------
 489.585635359116
(1 ligne)
Générer la keymap pour la légende
Pour connaître les dimensions pour width=200
routing=# SELECT
               200*(abs(Ymax(foo.extent)-Ymin(foo.extent))/abs(Xmax(foo.extent)-Xmin(foo.extent)))
               AS hauteur
         FROM (SELECT Extent(the_geom) FROM streets_edges) AS foo;
     hauteur
------------------
 195.834254143646
(1 ligne)
Le script php suivant a amplement suffit pour générer la keymap /var/www/keymap-streets.png
<html>
<body>
<?php
    $sw_MapFile = "/var/www/routingj/maps/kamap-streets.map";
    
    $map = ms_newMapObj( $sw_MapFile );
    
    $image = $map->draw();
//$image_url = $image->saveWebImage(MS_PNG,1,1,0);
$image->saveImage("/var/www/keymap-streets.png");
echo "<IMG   
BORDER=0 
SRC='".$image_url."'
width='".$map->width."' height='".$map->height."'/>
<BR>"; 
?>
</body>
</html>
Configuration de PgRouting avec Kamap

On peut télécharger la CVS disponible à http://ka-map.ominiverdi.org/CVSimg/ka-map-cvs-image.tar.gz

cd /var/www/
wget http://ka-map.ominiverdi.org/CVSimg/ka-map-cvs-image.tar.gz
tar xvzf ka-map-cvs-image.tar.gz
Ce qui donnera le répertoire ka-map.

Comme précisé dans le wiki

i
cd ka-map
cp include/config.routing.dist.php include/config.php
Par rapport au contenu proposé voici le mien avec les différences notables en gras

 // $aszGMap = array (
 //        'title' => 'GMap 75',
 //        'path' => '/var/www/gmap/htdocs/gmap75.map',
 //        'scales' => array( 40000000, 25000000, 12000000, 7500000, 3000000, 1000000 ),
 //        'format' =>'PNG'
 //        /* Sample authorized_users entry. See auth.php for more details:
 //         * ,'authorized_users' => array('popplace' => array('user1', 'user2'),
 //         *                              'park'     => array('user1')
 //         */
 //);

 $aszKaRoute = array (
         'title' => 'Routing',
         'path' => '/var/www/routingj/maps/kamap-streets.map',
         'scales' => array(100000,50000,10000 ),
         'format' =>'PNG'
         /* Sample authorized_users entry. See auth.php for more details:
          * ,'authorized_users' => array('popplace' => array('user1', 'user2'),
          *                              'park'     => array('user1')
          */
 );
 $aszMapFiles = array( 'routeMap'=>$aszKaRoute);


/******************************************************************************
 * figure out which map file to use and set up the necessary variables for
 * the rest of the code to use.  This does need to be done on every page load
 * unfortunately.
 *
 * szMap should be set to the default map file to use but can change if
 * this script is called with map=.
 */
$szMap = 'routeMap';

/******************************************************************************
 * Configure kaRouting settings
 * the array set the second mapfile you need to call and let kaRouting.php 
 * override and the postgres connection string
 */
$kaRoute = Array(
			'routeMap' => '/var/www/routingj/maps/mapfile.map',//the second mapfile -should be changed with an SLD file
			'pgConn' => 'dbname=routing host=localhost port=5432 user=postgres password=empr888',
			'myGraphTable' => 'streets_edges',
			'costColumn' => 'length',
			'reverseCostColumn' => 'reverse_cost',
			'directed' => 'false',//check pgRouting docs for this value
			'has_reverse_cost' => 'true',//check pgRouting docs for this value
			'buffer' => '0.01'//should be related to your map unit
		);

La pour la suite, il faut créer la mapfile /var/www/routingj/maps/mapfile.map dont le contenu sera - conformément au wiki -

MAP
  IMAGETYPE   png
  EXTENT      139.602 35.413 139.678 35.489
  SIZE        550 450 

   IMAGECOLOR  255 255 255
  SHAPEPATH   "data" #there are no shapes ;-)

   FONTSET      "../fonts/fonts.list"
  WEB
    IMAGEPATH "../tmp/"
    IMAGEURL  "/routingj/tmp/" 
  END 

  PROJECTION
   "init=epsg:4612" # JGD2000. the kanagawa one
  END 

  UNITS DD 

  SYMBOL
    NAME "hatch"
    TYPE hatch
  END 

LAYER
      NAME "path"
      CONNECTION "user=postgres password=empr888 dbname=routing host=localhost port=5432"
      CONNECTIONTYPE postgis
      STATUS OFF 
      TYPE LINE 

      CLASS
        NAME "path"
        STYLE
          COLOR 155 0 0
          WIDTH 2
       END
      END
 END


END
Rappel: Création de la table streets_edges

Par la suite, on s'assurera pour la création de la table streets_egdes de suivre les indications de http://www.davidgis.fr/documentation/win32/html/apa.html aux sections «A.8.1. Importation d'un jeu de données NavTeq» et «A.8.2. Noeuds du réseau et direction pour le routage».

Recommencdations supplémentaires du wiki

Pour être conforme au wiki, il faut ensuite modifier son fichier de configuration d'Apache

Alias /ka-map/ "/var/www/ka-map/htdocs/"

       Options Indexes
       AllowOverride None
       Order allow,deny
       Allow from all

Et ensuite de créer la table suivante dont le contenu sera
CREATE TABLE kroute (
    gid serial NOT NULL,
    sessionid text,
    the_geom geometry NOT NULL,
    date timestamp without time zone,
    CONSTRAINT enforce_dims_the_geom CHECK ((ndims(the_geom) = 2)),
    CONSTRAINT enforce_geotype_the_geom CHECK (((geometrytype(the_geom) = 'MULTILINESTRING'::text) OR (the_geom IS NULL))),
    CONSTRAINT enforce_srid_the_geom CHECK ((srid(the_geom) = -1))
);
Pour lancer l'application, il suffira de pointer vers http://localhost/ka-map/index_routing.html