Commit 8025f5af authored by Jean-Benoist Leger's avatar Jean-Benoist Leger

Creating route from pbf

parent 26d70e0f
......@@ -5,10 +5,12 @@ CXXFLAGS=-O2 -std=c++11
LDFLAGS=-O2 -fwhole-program -flto
LDLIBS_LMDB=-llmdb
LDLIBS_PQXX=-lpqxx
LDLIBS_OSMPBF=-L/home/rv/osmpbf/osmpbf -losmpbf -lprotobuf -lz
INCLUDE_OSMPBF=-I/home/rv/osmpbf -I/home/rv/osmpbf/osmpbf/include
.PHONY: clean
all: elevation_create_database elevation_query_database route_create_databases route_query_nodes_database route_query_lookup_database route
all: elevation_create_database elevation_query_database route_create_databases route_query_nodes_database route_query_lookup_database route route_create_databases_from_pbf
elevation_create_database: elevation.o elevation_create_database.o
$(CC) $(LDFLAGS) -o $@ $+ $(LDLIBS_LMDB)
......@@ -28,6 +30,9 @@ route_query_lookup_database: route_query_lookup_database.o lookup.o functions.o
route: route.o route_db.o lookup.o functions.o nodes_db.o lookup_db.o conv_functions.o get_route.o
$(CC) $(LDFLAGS) -o $@ $+ $(LDLIBS_LMDB)
route_create_databases_from_pbf: route_create_databases_from_pbf.o lookup_db.o nodes_db.o elevation.o parse_way.o conv_functions.o
$(CC) $(LDFLAGS) -o $@ $+ $(LDLIBS_LMDB) $(LDLIBS_OSMPBF)
elevation.o: elevation.cc elevation.h conf.h
$(CC) $(CXXFLAGS) -c $< -o $@
......@@ -70,5 +75,8 @@ get_route.o: get_route.cc get_route.h
route.o: route.cc
$(CC) $(CXXFLAGS) -c $< -o $@
route_create_databases_from_pbf.o: route_create_databases_from_pbf.cc
$(CC) $(CXXFLAGS) $(INCLUDE_OSMPBF) -c $< -o $@
clean:
rm -f *.o
#include "parse_way.h"
// For parsing
std::string no_str = "no";
std::string false_str = "false";
std::string motorway_str = "motorway";
std::string trunk_str = "trunk";
std::string construction_str = "construction";
std::string steps_str = "steps";
std::string foot_str = "foot";
std::string pedestrian_str = "pedestrian";
std::string track_str = "track";
std::string m1_str = "-1";
std::string p1_str = "1";
std::string yes_str = "yes";
std::string true_str = "true";
std::string roundabout_str = "roundabout";
std::string opposite_str = "opposite";
void parse_way(
bool& we_use_it,
way_kind_t& way_kind,
int& oneway,
std::string& tag_highway,
std::string& tag_cycleway,
std::string& tag_bicycle,
std::string& tag_oneway,
std::string& tag_junction)
{
we_use_it = false;
// if the tag cycleway is present and different of no and false
// we take the way in kind RV_WK_CYCLEWAY
if(tag_cycleway.size()>=2 && tag_cycleway.substr(0,2) != no_str)
{
if(tag_cycleway.size()>=5)
{
if(tag_cycleway.substr(0,5) != false_str)
{
way_kind = RV_WK_CYCLEWAY;
we_use_it = true;
}
}
else
{
way_kind = RV_WK_CYCLEWAY;
we_use_it = true;
}
}
// else if the tag bicycle is present and different of no and false
// we take the way in kind RV_WK_OTHERS
if(!we_use_it)
{
if(tag_bicycle.size()>=2 && tag_bicycle.substr(0,2) != no_str)
{
if(tag_bicycle.size()>=5)
{
if(tag_bicycle.substr(0,5) != false_str)
{
way_kind = RV_WK_OTHERS;
we_use_it = true;
}
}
else
{
way_kind = RV_WK_OTHERS;
we_use_it = true;
}
}
}
// else if the tag highway is present and begin by foot or pedestrian
// we take the way in kind RV_WK_FOOTWAY
if(!we_use_it)
{
if(tag_highway.size()>=10 && tag_highway.substr(0,10) == pedestrian_str)
{
way_kind = RV_WK_FOOTWAY;
we_use_it = true;
}
if(tag_highway.size()>=4 && tag_highway.substr(0,4) == foot_str)
{
way_kind = RV_WK_FOOTWAY;
we_use_it = true;
}
}
// else if the tag highway is present and different of motorway /
// trunk / construction / steps / track we take in in kind
// RV_WK_OTHERS
if(!we_use_it)
{
if(tag_highway.size()>0)
{
we_use_it = true;
if(tag_highway.size()>=8 && tag_highway.substr(0,8) == motorway_str)
we_use_it=false;
if(tag_highway.size()>=5 && tag_highway.substr(0,5) == trunk_str)
we_use_it=false;
if(tag_highway.size()>=12 && tag_highway.substr(0,12) == construction_str)
we_use_it=false;
if(tag_highway.size()>=5 && tag_highway.substr(0,5) == steps_str)
we_use_it=false;
if(tag_highway.size()>=5 && tag_highway.substr(0,5) == track_str)
we_use_it=false;
// and we check for the exception
if(tag_bicycle.size()>=2 && tag_bicycle.substr(0,2) == no_str)
we_use_it=false;
if(tag_bicycle.size()>=5 && tag_bicycle.substr(0,5) == false_str)
we_use_it=false;
if(we_use_it)
way_kind = RV_WK_OTHERS;
}
}
if(we_use_it)
{
oneway=0;
if(tag_oneway.size()>=2 && tag_oneway.substr(0,2) == m1_str)
oneway=-1;
if(tag_oneway.size()>=1 && tag_oneway.substr(0,1) == p1_str)
oneway=1;
if(tag_oneway.size()>=3 && tag_oneway.substr(0,3) == yes_str)
oneway=1;
if(tag_oneway.size()>=4 && tag_oneway.substr(0,4) == true_str)
oneway=1;
if(tag_junction.size()>=10 && tag_junction.substr(0,10) == roundabout_str)
oneway=1;
if(tag_cycleway.size()>=8 && tag_cycleway.substr(0,8) == opposite_str)
oneway=0;
}
}
#ifndef H_PARSE_WAY
#define H_PARSE_WAY
#include "conf.h"
#include "types.h"
void parse_way(
bool& we_use_it,
way_kind_t& way_kind,
int& oneway,
std::string& tag_highway,
std::string& tag_cycleway,
std::string& tag_bicycle,
std::string& tag_oneway,
std::string& tag_junction);
#endif
/*
This file is part of the osmpbf library.
Copyright(c) 2014 Daniel Bahrdt.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see
<http://www.gnu.org/licenses/>.
*/
#include "parse_way.h"
#include <iostream>
#include <osmpbf/osmfile.h>
#include <osmpbf/inode.h>
#include <osmpbf/iway.h>
#include <osmpbf/irelation.h>
#include <osmpbf/filter.h>
#include <osmpbf/primitiveblockinputadaptor.h>
#include <algorithm>
#include "conv_functions.h"
#include "elevation.h"
#include "types.h"
#include "nodes_db.h"
#include "lookup_db.h"
#include <sys/stat.h>
#include <sys/types.h>
struct simple_way_t
{
ccid_t ccid;
std::vector<nid_t> nids;
int oneway;
way_kind_t way_kind;
};
struct simple_node_t
{
ccid_t ccid;
double lon;
double lat;
elevation_value elevation;
};
void parseBlock_ways(
osmpbf::PrimitiveBlockInputAdaptor & pbi,
std::unordered_map<wid_t, simple_way_t> & ways,
std::unordered_map<nid_t, std::vector<wid_t>> & node_ways)
{
if (pbi.waysSize())
{
for (osmpbf::IWayStream way = pbi.getWayStream(); !way.isNull(); way.next())
{
std::string tag_highway, tag_cycleway, tag_bicycle, tag_oneway, tag_junction;
for(uint32_t i = 0, s = way.tagsSize(); i < s; ++i)
{
if( way.key(i) == "highway" )
tag_highway = way.value(i);
if( way.key(i) == "cycleway" )
tag_cycleway = way.value(i);
if( way.key(i) == "bicycle" )
tag_bicycle = way.value(i);
if( way.key(i) == "oneway" )
tag_oneway = way.value(i);
if( way.key(i) == "junction" )
tag_junction = way.value(i);
}
bool we_use_it;
way_kind_t way_kind;
int oneway;
parse_way(
we_use_it,
way_kind,
oneway,
tag_highway,
tag_cycleway,
tag_bicycle,
tag_oneway,
tag_junction);
if(we_use_it)
{
simple_way_t simple_way;
simple_way.ccid = way.id();
simple_way.oneway = oneway;
simple_way.way_kind = way_kind;
for(osmpbf::IWay::RefIterator refIt(way.refBegin()), refEnd(way.refEnd()); refIt != refEnd; ++refIt)
{
node_ways[*refIt].push_back(way.id());
simple_way.nids.push_back(*refIt);
}
ways[way.id()] = simple_way;
}
}
}
}
void parseBlock_nodes(
osmpbf::PrimitiveBlockInputAdaptor & pbi,
std::unordered_map<nid_t, simple_node_t> & nodes,
std::unordered_map<nid_t, std::vector<wid_t>> & node_ways)
{
if (pbi.nodesSize())
{
for (osmpbf::INodeStream node = pbi.getNodeStream(); !node.isNull(); node.next())
{
// is the node exist in our database
if(node_ways.count(node.id())>0)
{
simple_node_t simple_node;
simple_node.lon = node.lond();
simple_node.lat = node.latd();
nodes[node.id()] = simple_node;
}
}
}
}
int main(int argc, char ** argv)
{
if (argc < 2) {
std::cout << "Need in file" << std::endl;
}
std::unordered_map<nid_t, simple_node_t> nodes;
std::unordered_map<wid_t, simple_way_t> ways;
std::unordered_map<nid_t, std::vector<wid_t>> node_ways;
fprintf(stderr,"Parsing ways from pbf and creating ways map\n");
// scope
{
std::string inputFileName(argv[1]);
osmpbf::OSMFileIn inFile(inputFileName, false);
if (!inFile.open())
{
std::cout << "Failed to open " << inputFileName << std::endl;
return -1;
}
osmpbf::PrimitiveBlockInputAdaptor pbi;
while (inFile.parseNextBlock(pbi))
{
if (pbi.isNull())
continue;
parseBlock_ways(pbi, ways, node_ways);
}
}
fprintf(stderr,"Parsing nodes from pbf and creating nodes map\n");
// scope
{
std::string inputFileName(argv[1]);
osmpbf::OSMFileIn inFile(inputFileName, false);
if (!inFile.open())
{
std::cout << "Failed to open " << inputFileName << std::endl;
return -1;
}
osmpbf::PrimitiveBlockInputAdaptor pbi;
while (inFile.parseNextBlock(pbi))
{
if (pbi.isNull())
continue;
parseBlock_nodes(pbi, nodes, node_ways);
}
}
fprintf(stderr,"Computing connected components\n");
// now we construct way_way adjacency
{
std::unordered_map<wid_t,std::vector<wid_t>> way_ways;
for(auto ways_it = ways.begin();
ways_it != ways.end();
ways_it++)
{
// ways_it->first wid
std::vector<wid_t> & neighbors = way_ways[ways_it->first];
// ways_it->second.nids nodes
for(auto nit = ways_it->second.nids.begin();
nit != ways_it->second.nids.end();
nit ++)
{
// we get ways
std::vector<wid_t> & node_neighbors = node_ways[*nit];
for(auto node_neighbors_it = node_neighbors.begin();
node_neighbors_it != node_neighbors.end();
node_neighbors_it++)
{
if(*node_neighbors_it != ways_it->first)
neighbors.push_back(*node_neighbors_it);
}
}
std::sort(neighbors.begin(),neighbors.end());
auto last = std::unique(neighbors.begin(),neighbors.end());
neighbors.erase(last,neighbors.end());
}
unsigned int iter = 0;
while(1)
{
unsigned int modified=0;
iter++;
for(auto ways_it = ways.begin();
ways_it != ways.end();
ways_it++)
{
ccid_t & ccid = ways_it->second.ccid;
ccid_t new_ccid = ccid;
std::vector<wid_t> & neighbors = way_ways[ways_it->first];
for(unsigned int t=0;t<neighbors.size();t++)
{
ccid_t & neigh_ccid = ways[neighbors[t]].ccid;
if(neigh_ccid < new_ccid)
new_ccid = neigh_ccid;
}
if(new_ccid < ccid)
{
ccid = new_ccid;
modified++;
}
}
RV_BLANKLINE;
fprintf(stderr,"\r-> Pass %u done: Modified %u ",iter,modified);
if(modified==0)
break;
}
}
/* for(auto ways_it = ways.begin();
ways_it != ways.end();
ways_it++)
{
fprintf(stdout,"%lu -> %lu\n",ways_it->first,ways_it->second.ccid);
}
*/
char zreq[RV_ZCHAR_LENGTH];
char zfilename[RV_ZCHAR_LENGTH];
// elevation_db (read-only)
elevation elevation_db(argv[2]);
// cleaning (without checking status, lmdb will check after and fail if this
// is not goot)
snprintf(zfilename,RV_ZCHAR_LENGTH,"%s/%s/data.mdb",argv[3],RV_NODES_DB_RELATIVE_PATH);
remove(zfilename);
snprintf(zfilename,RV_ZCHAR_LENGTH,"%s/%s/lock.mdb",argv[3],RV_NODES_DB_RELATIVE_PATH);
remove(zfilename);
snprintf(zfilename,RV_ZCHAR_LENGTH,"%s/%s/data.mdb",argv[3],RV_LOOKUP_DB_RELATIVE_PATH);
remove(zfilename);
snprintf(zfilename,RV_ZCHAR_LENGTH,"%s/%s/lock.mdb",argv[3],RV_LOOKUP_DB_RELATIVE_PATH);
remove(zfilename);
mkdir(argv[3],0755);
snprintf(zfilename,RV_ZCHAR_LENGTH,"%s/%s",argv[3],RV_NODES_DB_RELATIVE_PATH);
mkdir(zfilename,0755);
snprintf(zfilename,RV_ZCHAR_LENGTH,"%s/%s",argv[3],RV_LOOKUP_DB_RELATIVE_PATH);
mkdir(zfilename,0755);
unsigned int total_number_of_nodes = std::distance(nodes.begin(),nodes.end());
RV_BLANKLINE;
fprintf(stderr,"Computing elevation on nodes\n");
for(auto nodes_it = nodes.begin();
nodes_it != nodes.end();
nodes_it++)
{
nodes_it->second.elevation = elevation_db.get_elevation(
nodes_it->second.lon,
nodes_it->second.lat);
}
{
fprintf(stderr,"Exporting nodes on nodes db\n");
// nodes_db (write)
snprintf(zfilename,RV_ZCHAR_LENGTH,"%s/%s",argv[3],RV_NODES_DB_RELATIVE_PATH);
nodes_db_t nodes_db(zfilename,true);
unsigned int count_nodes = 0;
for(auto nodes_it = nodes.begin();
nodes_it != nodes.end();
nodes_it++)
{
// first we must found neighbors
std::vector<wid_t> & ways_of_nodes = node_ways[nodes_it->first];
std::list<std::pair<nid_t,way_kind_t>> neighbors_from;
std::list<nid_t> neighbors_to;
for(auto way_it = ways_of_nodes.begin();
way_it != ways_of_nodes.end();
way_it++)
{
simple_way_t & way = ways[*way_it];
nodes_it->second.ccid = way.ccid;
for(unsigned int i = 0; i<way.nids.size(); i++)
{
if(way.nids[i] == nodes_it->first)
{
if(i>0)
{
if(way.oneway>=0)
{
// i-1 from
neighbors_from.push_back( std::pair<nid_t,way_kind_t>(way.nids[i-1],way.way_kind) );
}
if(way.oneway<=0)
{
// i-1 to
neighbors_to.push_back( way.nids[i-1] );
}
}
if(i<way.nids.size()-1)
{
if(way.oneway>=0)
{
// i+1 to
neighbors_to.push_back( way.nids[i+1] );
}
if(way.oneway<=0)
{
// i+1 from
neighbors_from.push_back( std::pair<nid_t,way_kind_t>(way.nids[i+1],way.way_kind) );
}
}
}
}
}
std::list<neighbor_t> neighbors;
for(std::list< std::pair<nid_t,way_kind_t> >::iterator neighbors_from_it = neighbors_from.begin();
neighbors_from_it!=neighbors_from.end();
neighbors_from_it++)
{
nid_t nid_from = (*neighbors_from_it).first;
way_kind_t way_kind = (*neighbors_from_it).second;
for(std::list< nid_t >::iterator neighbors_to_it = neighbors_to.begin();
neighbors_to_it!=neighbors_to.end();
neighbors_to_it++)
{
nid_t nid_to = *neighbors_to_it;
if(nid_from!=nid_to)
{
neighbor_t neighbor;
neighbor.from = nid_from;
neighbor.to = nid_to;
neighbor.way_kind = way_kind;
neighbors.push_back(neighbor);
}
}
}
if(neighbors.size()==0)
{
// No-exit way, last node
for(std::list< std::pair<nid_t,way_kind_t> >::iterator neighbors_from_it = neighbors_from.begin();
neighbors_from_it!=neighbors_from.end();
neighbors_from_it++)
{
nid_t nid_from = (*neighbors_from_it).first;
way_kind_t way_kind = (*neighbors_from_it).second;
neighbor_t neighbor;
neighbor.from = nid_from;
neighbor.to = 0;
neighbor.way_kind = way_kind;
neighbors.push_back(neighbor);
}
for(std::list< nid_t >::iterator neighbors_to_it = neighbors_to.begin();
neighbors_to_it!=neighbors_to.end();
neighbors_to_it++)
{
nid_t nid_to = *neighbors_to_it;
neighbor_t neighbor;
neighbor.from = 0;
neighbor.to = nid_to;
neighbor.way_kind = RV_WK_OTHERS;
neighbors.push_back(neighbor);
}
}
nid_t nid = nodes_it->first;