PRE-REQUIS
Choix d'un parser(léger) XML en C++: TinyXML
J'ai recherché sur le Web des importateurs de données x3d vers postgis. Je n'ai rien trouvé pour le moment. La première chose que j'ai faite a donc été de trouver un parser c++ assez léger. Je me suis tournée pour celà vers TinyXML dont le site est http://tinyxml.sourceforge.net. Son installation n'a rien de compliquer
make
Installer la version de PostGIS modifié
A l'heure de la rédaction de ce billet, aucun patch officiel pour le moment dans le SVN de PostGIS n'a encore été envisagé pour la fonctionnalité
AsX3D()
. Pour l'installer, on peut se servir de mon repository disponible Ã
http://www.davidgis.fr/download/postgis-svn-20070405.tar.gz
Pour se faire, j'ai dû modifier légèrement le patch de Olivier et de David de la ligne 148 à 152 du fichier
lwgeom/lwgeom_x3d.c
/* -1 value are ignored (could be a way to code postgis-users@postgis.refractions.net>
various faces dimension in Postgres array) */
//if (value != -1)
//{
j++;
sprintf(buf,"%i,",value);
add_str_simple(buf_face, buf);
//}
Le programme
En examinant le tutorial proposé sur le même site, je suis donc parti d'un programme déjà proposé par l'auteur. Je l'ai agrémenté à ma sauce pour pouvoir le rendre compatible avec mes objectifs. J'avoue j'ai passé une bonne partie de la nuit à le faire - je n'avais pas fait de C++ depuis au moins 5 ans -. Le programme est à http://www.davidgis.fr/download/x3dtopgsql.cpp. Pour le compiler, il faut le mettre dans les sources de tinyxml, et faire
g++ -c -Wall -Wno-format -g -DDEBUG -DTIXML_USE_STL x3dtopgsql.cpp -o x3dtopgsql.o
g++ -o x3dtopgsql -g tinyxml.o tinyxmlparser.o x3dtopgsql.o tinyxmlerror.o tinystr.o
Et pour l'utiliser par exemple:
x3dtopgsql [fichier.x3d] [table]
où
[fichier.x3d]
est le nom du fichier .x3d que l'on souhaite importer;
[table]
est le nom de la table qui sera associée et crée dans la base.
Bon là , il m'a fallut deux machines, une sous Windows et une sous GNU/Linux. Pour commencer, je me suis amuser avec Google Sketchup à créer une petite maison que j'ai ensuite exporter en fichier .kmz. Je l'ai ensuite dézippé sous GNU/Linux. J'ai ensuite remis le fichier doc.kml sous Windows. KML2X3D me l'a exporté proprement.
L'importation dans PostGIS s'est faite en faisant
cd /mnt/sources/tinyxxml
./x3dtopgsql doc.x3d maison | psql -U postgres testgis
aura pour effet de me générer les instructions SQL suivantes
SELECT DropGeometryTable('maison');
BEGIN TRANSACTION;
CREATE TABLE maison (id SERIAL PRIMARY KEY,vertices integer[]);
SELECT AddGeometryColumn('maison','the_geom',-1,'MULTIPOINT',3);
INSERT INTO maison(id,vertices,the_geom) values
(0,array[[0,1,2,3,4,-1,...,...-1,24,25,14,15,23,-1,25,24,20,19,-]],GeomFromEWKT('SRID=-1;MULTIPOINT((...)'));
INSERT INTO maison(id,vertices,the_geom) values
(1,array[[0,1,-1,2,3,-1,...,...,1,86,87,-1,88,89,-1,90,91,-1,92,93,-]],GeomFromEWKT('SRID=-1;MULTIPOINT(...)'));
END TRANSACTION;
En recrachant rapidement les lignes obtenues par AsX3D():
SELECT AsX3D(the_geom,vertices) from maison limit 1;
<IndexedFaceSet coordIndex='0,1,2,3,4,-1,...,-1,25,24,20,19,-1'>
<Coordinate point='5.924419 0 -3.077384,5.879113 0 -17.345828,...,16.230912 8.780875 -17.868433'/>
</IndexedFaceSet>
dans un fichier x3d, - faudra que je pense à automatiser tout ça -, avec freewrl on obtient par exemple les belles screenshots suivantes

Ma petite maison vu de face.

Ma petite maison vu d'en haut.
Le contenu de mon fichier x3d sera par exemple
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D version="3.0" profile="Immersive" xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="http://www.web3d.org/specifications/x3d-3.0.xsd">
<Scene>
<Background groundColor="0.057 0.221 0.4" skyColor="0.057 0.221 0.4" />
<Shape>
<Appearance >
<Material DEF='test' diffuseColor='1.000000 1.000000 1.000000' transparency='-0.000000'/>
</Appearance>
<IndexedFaceSet coordIndex='0,1,2,3,4,-1,5,6,7,8,9,-1,1,0,6,5,-1,2,1,5,9,-1,4,3,8,7,-1,0,4,7,6,-1,2,10,11,3,-1,12,9,8,13,-1,10,2,9,12,14,-1,13,15,14,12,-1,3,11,15,13,8,-1,3,2,9,8,-1,16,11,10,17,18,-1,11,10,14,15,-1,17,10,14,19,-1,18,17,19,20,-1,7,21,6,-1,22,5,6,21,-1,9,22,21,7,8,-1,22,9,5,-1,15,23,20,19,14,-1,11,16,23,15,-1,16,18,20,23,-1,20,24,23,-1,25,19,14,-1,24,25,14,15,23,-1,25,24,20,19,-1'>
<Coordinate point='5.924419 0 -3.077384,5.879113 0 -17.345828,8.63502 0 -17.354579,8.651169 0 -12.268231,8.680321 0 -3.086135,5.879113 5.6515 -17.345828,5.924419 5.6515 -3.077384,8.680321 5.6515 -3.086135,8.651169 5.6515 -12.268231,8.63502 5.6515 -17.354579,14.858036 0 -17.374334,14.87418 0 -12.287986,14.858036 5.6515 -17.374334,14.87418 5.6515 -12.287986,14.858036 5.63245 -17.374334,14.87418 5.63245 -12.287986,14.905019 0 -2.57249,18.299745 0 -17.385257,18.346721 0 -2.583413,18.299745 5.63245 -17.385257,18.346721 5.63245 -2.583413,7.37257 8.73204 -3.081982,7.32769 8.73204 -17.217077,14.905019 5.63245 -2.57249,16.279447 8.780875 -2.576852,16.230912 8.780875 -17.868433'/>
</IndexedFaceSet>
</Shape>
<Viewpoint DEF='doc Front' position='12.112917 4.390437 16.128923' jump='true' centerOfRotation='12.112917 4.390437 -10.220461' description='doc Front View' />
<Viewpoint DEF='doc Left' position='41.290635 4.390437 -10.220461' jump='true' centerOfRotation='12.112917 4.390437 -10.220461' description='doc Left View' orientation='0 1 0 1.571'/>
<Viewpoint DEF='doc Top' position='12.112917 31.724789 -10.220461' jump='true' centerOfRotation='12.112917 4.390437 -10.220461' description='doc Top View' orientation='-1 0 0 1.571'/>
<Viewpoint DEF='doc Back' position='12.112917 4.390437 -36.569845' jump='true' centerOfRotation='12.112917 4.390437 -10.220461' description='doc Back View' orientation='0 1 0 3.142'/>
<Viewpoint DEF='doc Right' position='-17.064802 4.390437 -10.220461' jump='true' centerOfRotation='12.112917 4.390437 -10.220461' description='doc Right View' orientation='0 -1 0 1.571'/>
<Viewpoint DEF='doc Bottom' position='12.112917 -22.943915 -10.220461' jump='true' centerOfRotation='12.112917 4.390437 -10.220461' description='doc Bottom View' orientation='1 0 0 1.571'/>
<NavigationInfo DEF='ExamineNavInfo' type='"EXAMINE","LOOKAT"' />
</Scene>
</X3D>