Commit e18e342b authored by jben's avatar jben

Initial commit

parents
AUTOMAKE_OPTIONS = foreign
SUBDIRS = route height sql doc utils
#!/bin/sh
aclocal
autoconf
automake --copy --add-missing
rm -r autom4te.cache/
rm aclocal.m4
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.68])
AC_INIT([rv], [0.0.1], [jben@jben.info])
AM_INIT_AUTOMAKE([rv], [0.0])
AC_CONFIG_SRCDIR([])
#AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
AC_LANG_PUSH([C++])
# Checks for libraries.
AC_CHECK_LIB([pqxx], [main], [], [AC_MSG_ERROR(You need the pqxx library.)])
# Checks for header files.
AC_CHECK_HEADERS([pqxx/pqxx],[],[AC_MSG_ERROR(File needed)])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_C_INLINE
# Checks for library functions.
AC_CHECK_FUNCS([sqrt floor])
#AC_CONFIG_FILES([Makefile
# man/Makefile
# src/Makefile])
AC_OUTPUT([Makefile
height/Makefile
route/Makefile
sql/Makefile
doc/Makefile
utils/Makefile])
docdir = $(datadir)/@PACKAGE@/doc
dist_doc_DATA = *.md
Prérequis sur le serveurs
=========================
Postgres
--------
apt-get install \
postgis \
postgresql-9.1-postgis \
osmosis \
postgresql-contrib \
postgresql-plperl
rv
--
apt-get install \
build-essential \
autoconf \
automake \
libpqxx3-dev
git clone http://git.jblg.fr/rv.git
cd rv
sh autogen.sh
./configure --prefix=$HOME/local
make
make install
Import des données
==================
Création de la database
-----------------------
# en tps que postgres
createuser rv
# creation database
createdb rv
createlang plperl rv
createlang plpgsql rv # inutile pour postgres >= 9.1
Schéma de la base
psql -d rv -c 'CREATE EXTENSION hstore;'
psql -d rv \
-f /usr/share/postgresql/9.1/contrib/postgis-1.5/postgis.sql
psql -d rv \
-f /usr/share/postgresql/9.1/contrib/postgis-1.5/spatial_ref_sys.sql
psql -d rv \
-f /usr/share/doc/osmosis/examples/pgsnapshot_schema_0.6.sql
psql -d rv \
-f /usr/share/doc/osmosis/examples/pgsnapshot_schema_0.6_action.sql
Ajouts pour rv
psql -d rv -f rv/sql/00-schema.sql
cat rv/sql/10-fonctions-*.sql | psql -d rv
Import des données OSM
----------------------
Téléchargement :
mkdir data/
mkdir data/import
wget -P data/ \
http://download.openstreetmap.fr/extracts/europe/france.osm.pbf
osmosis \
--read-pbf file=data/framce.osm.pbf \
--write-pgsql-dump directory=data/import/
Import initial:
dir=$(pwd)/data/import
(
echo "COPY nodes FROM '$dir/nodes.txt';"
echo "COPY relation_members FROM '$dir/relation_members.txt';"
echo "COPY relations FROM '$dir/relations.txt';"
echo "COPY users FROM '$dir/users.txt';"
echo "COPY way_nodes FROM '$dir/way_nodes.txt';"
echo "COPY ways FROM '$dir/ways.txt';"
) \
| xargs -d '\n' -i -P 0 psql -d rv -c {}
Une petite analyse de ce qu'on a mis :
psql -d rv -c "VACUUM ANALYZE;"
On se casse :
cd ..
Import des données SRTM
-----------------------
Récuperer la liste des tiles srtm necessaires
psql -d rv \
-t -F ' ' -A \
-c 'SELECT DISTINCT floor(ST_X(geom)),floor(ST_Y(geom)) from nodes;' \
> data/list_needed_srtm
Telecharger les données srtm
mkdir data/srtmzip
rv/utils/dlsrtm data/list_needed_srtm data/srtmzip/
Dézippage
mkdir data/srtm
rv/utils/unzipsrtm data/srtmzip/ data/srtm/
Remplissage paralelle de la database
rv/utils/populate_height_table_parallel \
data/list_needed_srtm 12 \
rv/height/rv_populate_height_table dbname=rv data/srtm/
Une petite analyse de ce qu'on a mis :
psql -d rv -c "VACUUM ANALYZE;"
Remplissage initial des tables perso
------------------------------------
psql -d rv -f rv/sql/90-initial-import.sql
Une petite analyse de ce qu'on a mis :
psql -d rv -c "VACUUM ANALYZE;"
Ménage
------
Un petit coup de balai
rm -r data/
Versions du programme de routage
================================
Forme
-----
La forme est x.y.z .
* x est un entier naturel, la version majeure
* y est un entier naturel, la version majeure de la base de donnée associée
* z est un entier naturel, la révision
Version majeure
---------------
Un changement de version majeure implique un changement de la façon dont
le programme de routage s'utilise ou un changement de la façon dont le programme
de routage retourne ses résultats.
Un changement de ce numéro de version entraîne probablement un changement dans
les frontends.
Version majeure de la base de donnée associée
---------------------------------------------
Il s'agit de la version majeure de la base de donnée que le programme de routage
s'attend à trouver lors de ces requêtes. La base de donnée DOIT avoir même
version majeure.
Révisions
---------
Un changement de ce numéro implique aucune modification destructive dans
l'interface avec l'utilisateur, et aucun changement dans ce qui est attendu dans
la base de données.
Attention, si il est garanti qu'un frontend fonctionnant avec la version x.y.z
fonctionne avec la version x.y.(z+1), la réciproque pourra être fausse en cas
d'ajout de nouvelles possiblilités.
Version de la base de données
=============================
Forme
-----
La forme est a.b
* a est un entier naturel, la version majeur
* b est un entier naturel, la révision
Version majeure
---------------
Un changement dans ce numéro de version indique un changement dans le stockage
des données accessibles au moteur de routage, ou un changement dans les
fonctions utilisées par le moteur de routage.
Révision
--------
Un changement dans ce numéro de version indique que les changements ne
concernent que le stockage des données non utilisées par le moteur de routage,
ou des fonctions internes.
Condition suffisante sur les versions
=====================================
(Qui peut ne pas être necessaire, mais c'est à vos risques et périls)
Il suffit que y=a pour que le moteur de routage puisse travailler avec la base
de données.
utilsdir = $(datadir)/@PACKAGE@/bin
utils_PROGRAMS = populate_height_table
populate_height_table_SOURCES = populate_height_table.cc populate_height_table.h
populate_height_table_CPPFLAGS = $(LIBPQXX_CFLAGS)
populate_height_table_LDADD = $(LIBPQXX_LIBS)
#include "populate_height_table.h"
int main(int argc, char* argv[])
{
if(argc!=7)
{
fprintf(stderr,"Usage : %s \"database connection string\" srtm_dir/ lon_min lat_min lon_max lat_max\n",argv[0]);
return(1);
}
std::string s_db = argv[1];
std::string s_srtm_dir = argv[2];
int lon_min, lon_max, lat_min, lat_max;
sscanf(argv[3],"%i",&lon_min);
sscanf(argv[4],"%i",&lat_min);
sscanf(argv[5],"%i",&lon_max);
sscanf(argv[6],"%i",&lat_max);
fprintf(stderr,"Openning database\n");
pqxx::connection db(s_db);
fprintf(stderr,"Deleting points of non original points of grid\n");
{
pqxx::work txn(db);
txn.exec("DELETE FROM rv_height WHERE approx;");
txn.commit();
}
/*
fprintf(stderr,"Unset node heights computed with non orignal points of grid\n");
{
pqxx::work txn(db);
txn.exec("UPDATE nodes SET (height,height_version,height_with_only_originals)=(NULL,0,TRUE) WHERE NOT height_with_only_originals;");
txn.commit();
}
*/
for(int lon_iter=lon_min; lon_iter<lon_max; lon_iter++)
{
for(int lat_iter=lat_min; lat_iter<lat_max; lat_iter++)
{
fprintf(stderr,"Inserting grid points where (lon,lat) in [%i,%i[ x [%i,%i[\n",lon_iter,lon_iter+1,lat_iter,lat_iter+1);
std::string s_dfilename = s_srtm_dir;
{
char dN = (lat_iter>=0) ? 'N' : 'S' ;
int dNs = (lat_iter>=0) ? 1 : -1 ;
char dE = (lon_iter>=0) ? 'E' : 'W' ;
int dEs = (lon_iter>=0) ? 1 : -1 ;
char fname[1024];
snprintf(fname,1024, "/%c%02u%c%03u.hgt",dN,dNs*lat_iter,dE,dEs*lon_iter);
s_dfilename.append(fname);
}
fprintf(stderr," Opening %s\n",s_dfilename.c_str());
std::ifstream ifs(s_dfilename.c_str());
if(!ifs.is_open())
{
fprintf(stderr," Error openning file %s\n",s_dfilename.c_str());
fprintf(stderr," Skipping...\n");
continue;
}
pqxx::work txn(db);
for(int lat_iter_3=3600; lat_iter_3>=0; lat_iter_3-=3)
{
for(int lon_iter_3=0; lon_iter_3<=3600; lon_iter_3+=3)
{
if(ifs.eof())
{
fprintf(stderr,"Unexpected end of file, lat_iter_3 = %i ; lon_iter_3 = %i\n",lat_iter_3,lon_iter_3);
abort();
}
char c[2];
ifs.read(c,2);
short s;
s=(unsigned char)(c[0]);
s=s<<8;
s+=(unsigned char)(c[1]);
if(s!=-32768 && lon_iter_3!=3600 && lat_iter_3!=3600)
{
int lon_s=3600*lon_iter+lon_iter_3;
int lat_s=3600*lat_iter+lat_iter_3;
double lon = lon_s * 1.0/3600;
double lat = lat_s * 1.0/3600;
char req2[1024];
snprintf(req2,1024,"INSERT INTO rv_height (lon_s,lat_s,height,geom,approx) VALUES (%i,%i,%i,'SRID=4326;POINT(%.6f %.6f)'::geometry,FALSE);",lon_s,lat_s,s,lon,lat);
txn.exec(req2);
}
}
}
txn.commit();
}
}
fprintf(stderr,"\nDone!\n");
return(0);
}
#ifndef H_CREATE_HEIGHT_DB
#define H_CREATE_HEIGHT_DB 1
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <pqxx/pqxx>
#endif
# this lists the binaries to produce, the (non-PHONY, binary) targets in
# the previous manual Makefile
bin_PROGRAMS = rv_route
rv_route_SOURCES = database.cc main.cc model.cc node.cc node_parcouru.cc queue.h route.h database.h Makefile.am model.h node.h node_parcouru.h route.cc edge.h
rv_route_CPPFLAGS = $(LIBPQXX_CFLAGS)
rv_route_LDADD = $(LIBPQXX_LIBS)
This diff is collapsed.
#include "database.h"
#include<iostream>
node database::get_node(const unsigned long long & ull_id)
{
pqxx::work txn(db);
char z_req[1024];
snprintf(z_req,1024,"SELECT ST_X(geom),ST_Y(geom),height FROM rv_nodes WHERE id=%lld;",ull_id);
pqxx::result r=txn.exec(z_req);
if(r.size()==0)
{
fprintf(stderr,"\nMissing node %llu\n",ull_id);
abort();
}
double d_lon = r[0][0].as<double>();
double d_lat = r[0][1].as<double>();
double d_height = r[0][2].as<double>();
node n_result(ull_id,d_lon,d_lat,d_height);
return(n_result);
}
unsigned long long database::find_node(const double & d_lon, const double & d_lat)
{
unsigned long long ull_id_node=0;
double diam = 0.015;
do
{
pqxx::work txn(db);
char z_req[1024];
snprintf(z_req,1024,"SELECT id FROM rv_nodes WHERE geom && ST_Expand('SRID=4326;POINT(%.8f %.8f)'::geometry,%f) ORDER BY ST_Distance(geom,'POINT(%.8f %.8f)'::geography) LIMIT 1;",d_lon,d_lat,diam,d_lon,d_lat);
pqxx::result res = txn.exec(z_req);
if(res.size()>0)
ull_id_node = res[0][0].as<unsigned long long>();
else
diam*=2;
} while(ull_id_node==0);
fprintf(stderr,"%llu\n",ull_id_node);
return(ull_id_node);
}
edge database::get_edge(const unsigned long long & ull_from, const unsigned long long & ull_to)
{
pqxx::work txn(db);
char z_req[1024];
snprintf(z_req,1024,"SELECT way_id FROM rv_edges WHERE from_id=%lld AND to_id=%lld;",ull_from,ull_to);
pqxx::result r=txn.exec(z_req);
if(r.size()==0)
{
fprintf(stderr,"\nMissing edge (%llu,%llu)\n",ull_from,ull_to);
abort();
}
unsigned long long ull_id_way = r[0][0].as<unsigned long long>();
edge E_result(ull_from,ull_to,ull_id_way);
return(E_result);
}
std::list<unsigned long long> database::get_adjoining(const unsigned long long & ull_id)
{
pqxx::work txn(db);
char z_req[1024];
snprintf(z_req,1024,"SELECT to_id FROM rv_edges WHERE from_id=%lld;",ull_id);
std::list<unsigned long long> lull_adj;
pqxx::result r=txn.exec(z_req);
for(pqxx::result::iterator it=r.begin();it!=r.end();it++)
{
lull_adj.push_back(it[0].as<unsigned long long>());
}
return(lull_adj);
}
#ifndef H_ROUTAGE_DATABASE
#define H_ROUTAGE_DATABASE 1
#include <pqxx/pqxx>
#include <string>
#include <iomanip>
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
#include <list>
#include <math.h>
#include "node.h"
#include "edge.h"
#define PREC(N) std::setiosflags(std::ios::fixed) << std::setprecision(N) <<
class database
{
public:
pqxx::connection db;
database(const std::string & s_filename) : db(s_filename) {}
node get_node(const unsigned long long & ull_id);
edge get_edge(const unsigned long long & ull_from, const unsigned long long & ull_to);
std::list<unsigned long long> get_adjoining(const unsigned long long & ull_id);
unsigned long long find_node(const double & d_lon, const double & d_lat);
double get_height_s(const int & lon_s, const int & lat_s);
double get_height(const double & lon, const double & lat);
};
#endif
#ifndef H_EDGE
#define H_EDGE 1
class edge
{
public:
unsigned long long ull_from;
unsigned long long ull_to;
unsigned long long ull_id_way;
node n_from;
node n_to;
double d_dist;
double d_pente;
edge(const unsigned long long & ull_from_i, const unsigned long long & ull_to_i, const unsigned long long & ull_id_way_i) :
ull_from(ull_from_i),
ull_to(ull_to_i),
ull_id_way(ull_id_way_i),
d_dist(0),
d_pente(0),
n_from(0,0,0,0),
n_to(0,0,0,0)
{}
edge(const edge & E_orig) :
ull_from(E_orig.ull_from),
ull_to(E_orig.ull_to),
ull_id_way(E_orig.ull_id_way),
d_dist(E_orig.d_dist),
d_pente(E_orig.d_pente),
n_from(E_orig.n_from),
n_to(E_orig.n_to)
{}
};
#endif
#!/usr/bin/perl
use strict;
sub maxima2cc
{
my $chaine=$_[0];
my $nomvariable=$_[1];
my $indent=$_[2];
my $provprefix=$_[3];
my $old;
my $out="";
# number -> as double
do
{
$old=$chaine;
$chaine =~ s/([^A-Za-z_0-9\.]|^)([0-9]+)([^0-9\.]|$)/\1\2\.0\3/g;
} while(!($old eq $chaine));
# On recherche toutes les puissances pour les precalculer
my %pui=();
my $copy = $chaine;
while($copy =~ s/([A-Za-z_0-9\.]+\^[0-9\.]+)//)
{
$pui{$1}++;
}
my $compteur=0;
foreach my $expr (keys(%pui))
{
$expr=~m/(.*)\^(.*)/;
$out="$out${indent}double $provprefix$compteur = std::pow($1,$2); // $expr\n";
$expr =~ s/\^/\\\^/;
$chaine =~ s/$expr/$provprefix$compteur/g;
$compteur++;
}
# std::pow
my $chaineside;
$chaineside = qr/
(
(?>[A-Za-z_0-9\.]+)
|
\(
(?>[^()]*)
(
(?1)(?>[^()]*)
)*
\)
)
/x;
do
{
$old=$chaine;
$chaine =~ s/(?<a>$chaineside)\^(?<b>$chaineside)/pow($+{'a'},$+{'b'})/g;
} while(!($old eq $chaine));
$chaine =~ s/pow/std::pow/g;
# std::sqrt
$chaine =~ s/sqrt/std::sqrt/g;
# espacement
$chaine =~ s/([\+\-\*\/])/ \1 /g;
# fin
$out= "$out\n$indent$nomvariable=$chaine\n\n";
return $out;
}
# On écrit les equations
open(my $f,">calc_model.mc");
# Energie cinetique
print $f 'd_Ec:1/2*d_masse*(d_V1^2-d_V0^2)$';
print $f "\n";
# Energie depensé dans les frottement du vents (avec une progression
# affine de la vitesse entre V0 et V1
print $f 'd_V1r:d_V1+d_vent$';
print $f "\n";
print $f 'd_V0r:d_V0+d_vent$';
print $f "\n";
print $f 'd_Vr:x/d_d*(d_V1r-d_V0r)+d_V0r$';
print $f "\n";
print $f 'd_Ea:1/2*d_rho_air*d_SCx*factor(integrate(d_Vr^2,x,0,d_d))$';
print $f "\n";
# On calcule le temps en fonction des vitesses
print $f 't:2*d_d/(d_V0+d_V1)$';
print $f "\n";
# On écrit l'équation
print $f 'Equation:d_Ec+d_Ea+d_Ep+d_Er=t*d_P$';
print $f "\n";
# On la resoud et on récupere la racine
print $f 'r:subst(solve(Equation,d_V1)[3],d_V1)$';
print $f "\n";
# On ecrit les resultats
print $f 'stringout("calc_model_V1.out",r)$';
print $f 'stringout("calc_model_Ea.out",d_Ea)$';
print $f 'stringout("calc_model_Ec.out",d_Ec)$';
print $f "\n";
# On ferme le fichier
close($f);
system("maxima -b calc_model.mc");
# Lecture du resultat
open(my $g,"<calc_model_V1.out");
my $inV1="";
while(<$g>)
{
chomp;
$inV1="$inV1$_";
}
close($g);
open(my $g2,"<calc_model_Ea.out");
my $inEa="";
while(<$g2>)
{
chomp;
$inEa="$inEa$_";
}
close($g2);
open(my $g3,"<calc_model_Ec.out");
my $inEc="";
while(<$g3>)
{
chomp;