Merge 7fe53441a2 into 94fa0047db
This commit is contained in:
commit
333c97133f
113
Extractor/BaseParser.cpp
Normal file
113
Extractor/BaseParser.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, others 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
*/
|
||||
|
||||
#include "BaseParser.h"
|
||||
|
||||
BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) :
|
||||
externalMemory(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) {
|
||||
luaState = se.getLuaStateForThreadID(0);
|
||||
ReadUseRestrictionsSetting();
|
||||
ReadRestrictionExceptions();
|
||||
}
|
||||
|
||||
void BaseParser::ReadUseRestrictionsSetting() {
|
||||
if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
|
||||
ERR(lua_tostring( luaState,-1)<< " occured in scripting block");
|
||||
}
|
||||
if( lua_isboolean( luaState, -1) ) {
|
||||
use_turn_restrictions = lua_toboolean(luaState, -1);
|
||||
}
|
||||
if( use_turn_restrictions ) {
|
||||
INFO("Using turn restrictions" );
|
||||
} else {
|
||||
INFO("Ignoring turn restrictions" );
|
||||
}
|
||||
}
|
||||
|
||||
void BaseParser::ReadRestrictionExceptions() {
|
||||
if(lua_function_exists(luaState, "get_exceptions" )) {
|
||||
//get list of turn restriction exceptions
|
||||
try {
|
||||
luabind::call_function<void>(
|
||||
luaState,
|
||||
"get_exceptions",
|
||||
boost::ref(restriction_exceptions)
|
||||
);
|
||||
INFO("Found " << restriction_exceptions.size() << " exceptions to turn restriction");
|
||||
BOOST_FOREACH(std::string & str, restriction_exceptions) {
|
||||
INFO(" " << str);
|
||||
}
|
||||
} catch (const luabind::error &er) {
|
||||
lua_State* Ler=er.state();
|
||||
report_errors(Ler, -1);
|
||||
ERR(er.what());
|
||||
}
|
||||
} else {
|
||||
INFO("Found no exceptions to turn restrictions");
|
||||
}
|
||||
}
|
||||
|
||||
void BaseParser::report_errors(lua_State *L, const int status) const {
|
||||
if( 0!=status ) {
|
||||
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
|
||||
lua_pop(L, 1); // remove error message
|
||||
}
|
||||
}
|
||||
|
||||
inline void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
|
||||
try {
|
||||
luabind::call_function<int>( localLuaState, "node_function", boost::ref(n) );
|
||||
} catch (const luabind::error &er) {
|
||||
lua_State* Ler=er.state();
|
||||
report_errors(Ler, -1);
|
||||
ERR(er.what());
|
||||
}
|
||||
}
|
||||
|
||||
inline void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
|
||||
try {
|
||||
luabind::call_function<int>( localLuaState, "way_function", boost::ref(w), w.path.size() );
|
||||
} catch (const luabind::error &er) {
|
||||
lua_State* Ler=er.state();
|
||||
report_errors(Ler, -1);
|
||||
ERR(er.what());
|
||||
}
|
||||
}
|
||||
|
||||
inline bool BaseParser::ShouldIgnoreRestriction(const std::string& except_tag_string) const {
|
||||
//should this restriction be ignored? yes if there's an overlap between:
|
||||
//a) the list of modes in the except tag of the restriction (except_tag_string), ex: except=bus;bicycle
|
||||
//b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle]
|
||||
|
||||
if( "" == except_tag_string ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Be warned, this is quadratic work here, but we assume that
|
||||
//only a few exceptions are actually defined.
|
||||
std::vector<std::string> exceptions;
|
||||
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
|
||||
BOOST_FOREACH(std::string& str, exceptions) {
|
||||
if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -29,23 +29,30 @@ extern "C" {
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
template<class ExternalMemoryT, typename NodeT, typename RestrictionT, typename WayT>
|
||||
class BaseParser : boost::noncopyable {
|
||||
public:
|
||||
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||
virtual ~BaseParser() {}
|
||||
virtual bool Init() = 0;
|
||||
virtual void RegisterCallbacks(ExternalMemoryT * externalMemory) = 0;
|
||||
virtual void RegisterScriptingEnvironment(ScriptingEnvironment & _se) = 0;
|
||||
virtual bool ReadHeader() = 0;
|
||||
virtual bool Parse() = 0;
|
||||
|
||||
void report_errors(lua_State *L, int status) {
|
||||
if ( status!=0 ) {
|
||||
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
|
||||
lua_pop(L, 1); // remove error message
|
||||
}
|
||||
}
|
||||
inline virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread);
|
||||
inline virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread);
|
||||
virtual void report_errors(lua_State *L, const int status) const;
|
||||
|
||||
protected:
|
||||
virtual void ReadUseRestrictionsSetting();
|
||||
virtual void ReadRestrictionExceptions();
|
||||
inline virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const;
|
||||
|
||||
ExtractorCallbacks* externalMemory;
|
||||
ScriptingEnvironment& scriptingEnvironment;
|
||||
lua_State* luaState;
|
||||
std::vector<std::string> restriction_exceptions;
|
||||
bool use_turn_restrictions;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
#include "PBFParser.h"
|
||||
|
||||
PBFParser::PBFParser(const char * fileName) : externalMemory(NULL){
|
||||
PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser( ec, se ) {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
|
||||
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
|
||||
@ -37,38 +37,10 @@ PBFParser::PBFParser(const char * fileName) : externalMemory(NULL){
|
||||
#endif
|
||||
}
|
||||
|
||||
void PBFParser::RegisterCallbacks(ExtractorCallbacks * em) {
|
||||
externalMemory = em;
|
||||
}
|
||||
|
||||
void PBFParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
|
||||
scriptingEnvironment = _se;
|
||||
|
||||
if(lua_function_exists(scriptingEnvironment.getLuaStateForThreadID(0), "get_exceptions" )) {
|
||||
//get list of turn restriction exceptions
|
||||
try {
|
||||
luabind::call_function<void>(
|
||||
scriptingEnvironment.getLuaStateForThreadID(0),
|
||||
"get_exceptions",
|
||||
boost::ref(restriction_exceptions_vector)
|
||||
);
|
||||
INFO("Found " << restriction_exceptions_vector.size() << " exceptions to turn restriction");
|
||||
BOOST_FOREACH(std::string & str, restriction_exceptions_vector) {
|
||||
INFO("ignoring: " << str);
|
||||
}
|
||||
} catch (const luabind::error &er) {
|
||||
lua_State* Ler=er.state();
|
||||
report_errors(Ler, -1);
|
||||
ERR(er.what());
|
||||
}
|
||||
} else {
|
||||
INFO("Found no exceptions to turn restrictions");
|
||||
}
|
||||
}
|
||||
|
||||
PBFParser::~PBFParser() {
|
||||
if(input.is_open())
|
||||
if(input.is_open()) {
|
||||
input.close();
|
||||
}
|
||||
|
||||
// Clean up any leftover ThreadData objects in the queue
|
||||
_ThreadData* td;
|
||||
@ -82,7 +54,7 @@ PBFParser::~PBFParser() {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool PBFParser::Init() {
|
||||
inline bool PBFParser::ReadHeader() {
|
||||
_ThreadData initData;
|
||||
/** read Header */
|
||||
if(!readPBFBlobHeader(input, &initData)) {
|
||||
@ -98,11 +70,13 @@ inline bool PBFParser::Init() {
|
||||
for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
|
||||
const std::string& feature = initData.PBFHeaderBlock.required_features( i );
|
||||
bool supported = false;
|
||||
if ( "OsmSchema-V0.6" == feature )
|
||||
if ( "OsmSchema-V0.6" == feature ) {
|
||||
supported = true;
|
||||
else if ( "DenseNodes" == feature )
|
||||
}
|
||||
else if ( "DenseNodes" == feature ) {
|
||||
supported = true;
|
||||
|
||||
}
|
||||
|
||||
if ( !supported ) {
|
||||
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
|
||||
return false;
|
||||
@ -120,9 +94,9 @@ inline void PBFParser::ReadData() {
|
||||
_ThreadData *threadData = new _ThreadData();
|
||||
keepRunning = readNextBlock(input, threadData);
|
||||
|
||||
if (keepRunning)
|
||||
if (keepRunning) {
|
||||
threadDataQueue->push(threadData);
|
||||
else {
|
||||
} else {
|
||||
threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered
|
||||
delete threadData;
|
||||
}
|
||||
@ -133,7 +107,7 @@ inline void PBFParser::ParseData() {
|
||||
while (true) {
|
||||
_ThreadData *threadData;
|
||||
threadDataQueue->wait_and_pop(threadData);
|
||||
if (threadData == NULL) {
|
||||
if( NULL==threadData ) {
|
||||
INFO("Parse Data Thread Finished");
|
||||
threadDataQueue->push(NULL); // Signal end of data for other threads
|
||||
break;
|
||||
@ -145,14 +119,18 @@ inline void PBFParser::ParseData() {
|
||||
threadData->currentGroupID = i;
|
||||
loadGroup(threadData);
|
||||
|
||||
if(threadData->entityTypeIndicator == TypeNode)
|
||||
if(threadData->entityTypeIndicator == TypeNode) {
|
||||
parseNode(threadData);
|
||||
if(threadData->entityTypeIndicator == TypeWay)
|
||||
}
|
||||
if(threadData->entityTypeIndicator == TypeWay) {
|
||||
parseWay(threadData);
|
||||
if(threadData->entityTypeIndicator == TypeRelation)
|
||||
}
|
||||
if(threadData->entityTypeIndicator == TypeRelation) {
|
||||
parseRelation(threadData);
|
||||
if(threadData->entityTypeIndicator == TypeDenseNode)
|
||||
}
|
||||
if(threadData->entityTypeIndicator == TypeDenseNode) {
|
||||
parseDenseNode(threadData);
|
||||
}
|
||||
}
|
||||
|
||||
delete threadData;
|
||||
@ -193,7 +171,7 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
||||
n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
|
||||
while (denseTagIndex < dense.keys_vals_size()) {
|
||||
const int tagValue = dense.keys_vals( denseTagIndex );
|
||||
if(tagValue == 0) {
|
||||
if( 0==tagValue ) {
|
||||
++denseTagIndex;
|
||||
break;
|
||||
}
|
||||
@ -210,24 +188,9 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
||||
#pragma omp parallel for schedule ( guided )
|
||||
for(unsigned i = 0; i < endi_nodes; ++i) {
|
||||
ImportNode &n = nodesToParse[i];
|
||||
/** Pass the unpacked node to the LUA call back **/
|
||||
try {
|
||||
luabind::call_function<int>(
|
||||
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
|
||||
"node_function",
|
||||
boost::ref(n)
|
||||
);
|
||||
} catch (const luabind::error &er) {
|
||||
lua_State* Ler=er.state();
|
||||
report_errors(Ler, -1);
|
||||
ERR(er.what());
|
||||
}
|
||||
// catch (...) {
|
||||
// ERR("Unknown error occurred during PBF dense node parsing!");
|
||||
// }
|
||||
ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_FOREACH(ImportNode &n, nodesToParse) {
|
||||
if(!externalMemory->nodeFunction(n))
|
||||
std::cerr << "[PBFParser] dense node not parsed" << std::endl;
|
||||
@ -241,9 +204,12 @@ inline void PBFParser::parseNode(_ThreadData * ) {
|
||||
inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||
//TODO: leave early, if relation is not a restriction
|
||||
//TODO: reuse rawRestriction container
|
||||
if( !use_turn_restrictions ) {
|
||||
return;
|
||||
}
|
||||
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
||||
for(int i = 0; i < group.relations_size(); ++i ) {
|
||||
std::string exception_of_restriction_tag;
|
||||
std::string except_tag_string;
|
||||
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
|
||||
bool isRestriction = false;
|
||||
bool isOnlyRestriction = false;
|
||||
@ -251,34 +217,25 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
|
||||
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
|
||||
if ("type" == key) {
|
||||
if( "restriction" == val)
|
||||
if( "restriction" == val) {
|
||||
isRestriction = true;
|
||||
else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if ("restriction" == key) {
|
||||
if(val.find("only_") == 0)
|
||||
isOnlyRestriction = true;
|
||||
}
|
||||
if ("except" == key) {
|
||||
exception_of_restriction_tag = val;
|
||||
}
|
||||
}
|
||||
|
||||
//Check if restriction shall be ignored
|
||||
if(isRestriction && ("" != exception_of_restriction_tag) ) {
|
||||
//Be warned, this is quadratic work here, but we assume that
|
||||
//only a few exceptions are actually defined.
|
||||
std::vector<std::string> tokenized_exception_tags_of_restriction;
|
||||
boost::algorithm::split_regex(tokenized_exception_tags_of_restriction, exception_of_restriction_tag, boost::regex("[;][ ]*"));
|
||||
BOOST_FOREACH(std::string & str, tokenized_exception_tags_of_restriction) {
|
||||
if(restriction_exceptions_vector.end() != std::find(restriction_exceptions_vector.begin(), restriction_exceptions_vector.end(), str)) {
|
||||
isRestriction = false;
|
||||
break; //BOOST_FOREACH
|
||||
}
|
||||
}
|
||||
if ("restriction" == key) {
|
||||
if(val.find("only_") == 0) {
|
||||
isOnlyRestriction = true;
|
||||
}
|
||||
}
|
||||
if ("except" == key) {
|
||||
except_tag_string = val;
|
||||
}
|
||||
}
|
||||
|
||||
if( isRestriction && ShouldIgnoreRestriction(except_tag_string) ) {
|
||||
isRestriction = false;
|
||||
}
|
||||
|
||||
if(isRestriction) {
|
||||
int64_t lastRef = 0;
|
||||
@ -293,11 +250,13 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||
|
||||
switch(inputRelation.types(rolesIndex)) {
|
||||
case 0: //node
|
||||
if("from" == role || "to" == role) //Only via should be a node
|
||||
if("from" == role || "to" == role) { //Only via should be a node
|
||||
continue;
|
||||
}
|
||||
assert("via" == role);
|
||||
if(UINT_MAX != currentRestrictionContainer.viaNode)
|
||||
if(UINT_MAX != currentRestrictionContainer.viaNode) {
|
||||
currentRestrictionContainer.viaNode = UINT_MAX;
|
||||
}
|
||||
assert(UINT_MAX == currentRestrictionContainer.viaNode);
|
||||
currentRestrictionContainer.restriction.viaNode = lastRef;
|
||||
break;
|
||||
@ -325,8 +284,9 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!externalMemory->restrictionFunction(currentRestrictionContainer))
|
||||
if(!externalMemory->restrictionFunction(currentRestrictionContainer)) {
|
||||
std::cerr << "[PBFParser] relation not parsed" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -357,29 +317,12 @@ inline void PBFParser::parseWay(_ThreadData * threadData) {
|
||||
#pragma omp parallel for schedule ( guided )
|
||||
for(unsigned i = 0; i < endi_ways; ++i) {
|
||||
ExtractionWay & w = waysToParse[i];
|
||||
/** Pass the unpacked way to the LUA call back **/
|
||||
try {
|
||||
luabind::call_function<int>(
|
||||
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
|
||||
"way_function",
|
||||
boost::ref(w),
|
||||
w.path.size()
|
||||
);
|
||||
|
||||
} catch (const luabind::error &er) {
|
||||
lua_State* Ler=er.state();
|
||||
report_errors(Ler, -1);
|
||||
ERR(er.what());
|
||||
}
|
||||
// catch (...) {
|
||||
// ERR("Unknown error!");
|
||||
// }
|
||||
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
|
||||
}
|
||||
|
||||
BOOST_FOREACH(ExtractionWay & w, waysToParse) {
|
||||
if(!externalMemory->wayFunction(w)) {
|
||||
if(!externalMemory->wayFunction(w))
|
||||
std::cerr << "[PBFParser] way not parsed" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,9 +419,10 @@ inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) {
|
||||
}
|
||||
|
||||
inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) {
|
||||
if(stream.eof())
|
||||
if(stream.eof()) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
const int size = threadData->PBFBlobHeader.datasize();
|
||||
if ( size < 0 || size > MAX_BLOB_SIZE ) {
|
||||
std::cerr << "[error] invalid Blob size:" << size << std::endl;
|
||||
@ -506,8 +450,9 @@ inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData)
|
||||
return false;
|
||||
}
|
||||
} else if ( threadData->PBFBlob.has_lzma_data() ) {
|
||||
if ( !unpackLZMA(stream, threadData) )
|
||||
if ( !unpackLZMA(stream, threadData) ) {
|
||||
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
|
||||
}
|
||||
delete[] data;
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@ -37,11 +37,8 @@
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
|
||||
#include "BaseParser.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ExtractorStructs.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
class PBFParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, ExtractionWay> {
|
||||
class PBFParser : public BaseParser {
|
||||
|
||||
enum EntityType {
|
||||
TypeNode = 1,
|
||||
@ -65,13 +62,10 @@ class PBFParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionCo
|
||||
};
|
||||
|
||||
public:
|
||||
PBFParser(const char * fileName);
|
||||
PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||
virtual ~PBFParser();
|
||||
|
||||
void RegisterCallbacks(ExtractorCallbacks * em);
|
||||
void RegisterScriptingEnvironment(ScriptingEnvironment & _se);
|
||||
|
||||
inline bool Init();
|
||||
inline bool ReadHeader();
|
||||
inline bool Parse();
|
||||
|
||||
private:
|
||||
@ -100,14 +94,8 @@ private:
|
||||
unsigned blockCount;
|
||||
#endif
|
||||
|
||||
ExtractorCallbacks * externalMemory;
|
||||
/* the input stream to parse */
|
||||
std::fstream input;
|
||||
/* ThreadData Queue */
|
||||
std::fstream input; // the input stream to parse
|
||||
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
|
||||
ScriptingEnvironment scriptingEnvironment;
|
||||
|
||||
std::vector<std::string> restriction_exceptions_vector;
|
||||
};
|
||||
|
||||
#endif /* PBFPARSER_H_ */
|
||||
|
||||
@ -27,42 +27,12 @@
|
||||
#include "../DataStructures/InputReaderFactory.h"
|
||||
|
||||
|
||||
XMLParser::XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){
|
||||
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
|
||||
WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf");
|
||||
inputReader = inputReaderFactory(filename);
|
||||
}
|
||||
|
||||
XMLParser::~XMLParser() {}
|
||||
|
||||
void XMLParser::RegisterCallbacks(ExtractorCallbacks * em) {
|
||||
externalMemory = em;
|
||||
}
|
||||
|
||||
void XMLParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
|
||||
myLuaState = _se.getLuaStateForThreadID(0);
|
||||
if(lua_function_exists(myLuaState, "get_exceptions" )) {
|
||||
//get list of turn restriction exceptions
|
||||
try {
|
||||
luabind::call_function<void>(
|
||||
myLuaState,
|
||||
"get_exceptions",
|
||||
boost::ref(restriction_exceptions_vector)
|
||||
);
|
||||
INFO("Found " << restriction_exceptions_vector.size() << " exceptions to turn restriction");
|
||||
BOOST_FOREACH(std::string & str, restriction_exceptions_vector) {
|
||||
INFO(" " << str);
|
||||
}
|
||||
} catch (const luabind::error &er) {
|
||||
lua_State* Ler=er.state();
|
||||
report_errors(Ler, -1);
|
||||
ERR(er.what());
|
||||
}
|
||||
} else {
|
||||
INFO("Found no exceptions to turn restrictions");
|
||||
}
|
||||
}
|
||||
|
||||
bool XMLParser::Init() {
|
||||
bool XMLParser::ReadHeader() {
|
||||
return (xmlTextReaderRead( inputReader ) == 1);
|
||||
}
|
||||
bool XMLParser::Parse() {
|
||||
@ -70,58 +40,28 @@ bool XMLParser::Parse() {
|
||||
const int type = xmlTextReaderNodeType( inputReader );
|
||||
|
||||
//1 is Element
|
||||
if ( type != 1 )
|
||||
if ( type != 1 ) {
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
xmlChar* currentName = xmlTextReaderName( inputReader );
|
||||
if ( currentName == NULL )
|
||||
if ( currentName == NULL ) {
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
|
||||
ImportNode n = _ReadXMLNode( );
|
||||
/** Pass the unpacked node to the LUA call back **/
|
||||
try {
|
||||
luabind::call_function<int>(
|
||||
myLuaState,
|
||||
"node_function",
|
||||
boost::ref(n)
|
||||
);
|
||||
if(!externalMemory->nodeFunction(n))
|
||||
std::cerr << "[XMLParser] dense node not parsed" << std::endl;
|
||||
} catch (const luabind::error &er) {
|
||||
std::cerr << er.what() << std::endl;
|
||||
lua_State* Ler=er.state();
|
||||
report_errors(Ler, -1);
|
||||
} catch (std::exception & e) {
|
||||
ERR(e.what());
|
||||
} catch (...) {
|
||||
ERR("Unknown error occurred during XML node parsing!");
|
||||
}
|
||||
ImportNode n = _ReadXMLNode();
|
||||
ParseNodeInLua( n, luaState );
|
||||
|
||||
if(!externalMemory->nodeFunction(n))
|
||||
std::cerr << "[XMLParser] dense node not parsed" << std::endl;
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||
ExtractionWay way = _ReadXMLWay( );
|
||||
|
||||
/** Pass the unpacked way to the LUA call back **/
|
||||
try {
|
||||
luabind::call_function<int>(
|
||||
myLuaState,
|
||||
"way_function",
|
||||
boost::ref(way),
|
||||
way.path.size()
|
||||
);
|
||||
if(!externalMemory->wayFunction(way)) {
|
||||
std::cerr << "[PBFParser] way not parsed" << std::endl;
|
||||
}
|
||||
} catch (const luabind::error &er) {
|
||||
std::cerr << er.what() << std::endl;
|
||||
lua_State* Ler=er.state();
|
||||
report_errors(Ler, -1);
|
||||
} catch (std::exception & e) {
|
||||
ERR(e.what());
|
||||
} catch (...) {
|
||||
ERR("Unknown error occurred during XML way parsing!");
|
||||
}
|
||||
ParseWayInLua( way, luaState );
|
||||
if(!externalMemory->wayFunction(way))
|
||||
std::cerr << "[PBFParser] way not parsed" << std::endl;
|
||||
}
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||
_RawRestrictionContainer r = _ReadXMLRestriction();
|
||||
@ -137,19 +77,20 @@ bool XMLParser::Parse() {
|
||||
}
|
||||
|
||||
_RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
||||
_RawRestrictionContainer restriction;
|
||||
std::string exception_of_restriction_tag;
|
||||
_RawRestrictionContainer restriction;
|
||||
std::string except_tag_string;
|
||||
|
||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int childType = xmlTextReaderNodeType( inputReader );
|
||||
if ( childType != 1 && childType != 15 )
|
||||
if ( childType != 1 && childType != 15 ) {
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||
if ( childName == NULL )
|
||||
if ( childName == NULL ) {
|
||||
continue;
|
||||
|
||||
}
|
||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||
xmlFree( childName );
|
||||
break;
|
||||
@ -164,18 +105,21 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||
if ( k != NULL && value != NULL ) {
|
||||
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
|
||||
if(0 == std::string((const char *) value).find("only_"))
|
||||
if(0 == std::string((const char *) value).find("only_")) {
|
||||
restriction.restriction.flags.isOnly = true;
|
||||
}
|
||||
}
|
||||
if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
|
||||
exception_of_restriction_tag = (const char*) value;
|
||||
except_tag_string = (const char*) value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( k != NULL )
|
||||
if ( k != NULL ) {
|
||||
xmlFree( k );
|
||||
if ( value != NULL )
|
||||
}
|
||||
if ( value != NULL ) {
|
||||
xmlFree( value );
|
||||
}
|
||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
|
||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
||||
if ( ref != NULL ) {
|
||||
@ -192,32 +136,24 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
||||
restriction.restriction.viaNode = atoi((const char*) ref);
|
||||
}
|
||||
|
||||
if(NULL != type)
|
||||
if(NULL != type) {
|
||||
xmlFree( type );
|
||||
if(NULL != role)
|
||||
}
|
||||
if(NULL != role) {
|
||||
xmlFree( role );
|
||||
if(NULL != ref)
|
||||
}
|
||||
if(NULL != ref) {
|
||||
xmlFree( ref );
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlFree( childName );
|
||||
}
|
||||
}
|
||||
|
||||
//Check if restriction shall be ignored
|
||||
if( "" != exception_of_restriction_tag ) {
|
||||
//Be warned, this is quadratic work here, but we assume that
|
||||
//only a few exceptions are actually defined.
|
||||
std::vector<std::string> tokenized_exception_tags_of_restriction;
|
||||
boost::algorithm::split_regex(tokenized_exception_tags_of_restriction, exception_of_restriction_tag, boost::regex("[;][ ]*"));
|
||||
BOOST_FOREACH(std::string & str, tokenized_exception_tags_of_restriction) {
|
||||
if(restriction_exceptions_vector.end() != std::find(restriction_exceptions_vector.begin(), restriction_exceptions_vector.end(), str)) {
|
||||
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
|
||||
break; //BOOST_FOREACH
|
||||
}
|
||||
}
|
||||
if( ShouldIgnoreRestriction(except_tag_string) ) {
|
||||
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
|
||||
}
|
||||
|
||||
return restriction;
|
||||
}
|
||||
|
||||
@ -227,12 +163,14 @@ ExtractionWay XMLParser::_ReadXMLWay() {
|
||||
const int depth = xmlTextReaderDepth( inputReader );
|
||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int childType = xmlTextReaderNodeType( inputReader );
|
||||
if ( childType != 1 && childType != 15 )
|
||||
if ( childType != 1 && childType != 15 ) {
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||
if ( childName == NULL )
|
||||
if ( childName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
||||
@ -249,15 +187,16 @@ ExtractionWay XMLParser::_ReadXMLWay() {
|
||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||
// cout << "->k=" << k << ", v=" << value << endl;
|
||||
// cout << "->k=" << k << ", v=" << value << endl;
|
||||
if ( k != NULL && value != NULL ) {
|
||||
|
||||
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value));
|
||||
}
|
||||
if ( k != NULL )
|
||||
if ( k != NULL ) {
|
||||
xmlFree( k );
|
||||
if ( value != NULL )
|
||||
}
|
||||
if ( value != NULL ) {
|
||||
xmlFree( value );
|
||||
}
|
||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
|
||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
||||
if ( ref != NULL ) {
|
||||
@ -295,12 +234,14 @@ ImportNode XMLParser::_ReadXMLNode() {
|
||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int childType = xmlTextReaderNodeType( inputReader );
|
||||
// 1 = Element, 15 = EndElement
|
||||
if ( childType != 1 && childType != 15 )
|
||||
if ( childType != 1 && childType != 15 ) {
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||
if ( childName == NULL )
|
||||
if ( childName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
|
||||
xmlFree( childName );
|
||||
@ -317,10 +258,12 @@ ImportNode XMLParser::_ReadXMLNode() {
|
||||
if ( k != NULL && value != NULL ) {
|
||||
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
|
||||
}
|
||||
if ( k != NULL )
|
||||
if ( k != NULL ) {
|
||||
xmlFree( k );
|
||||
if ( value != NULL )
|
||||
}
|
||||
if ( value != NULL ) {
|
||||
xmlFree( value );
|
||||
}
|
||||
}
|
||||
|
||||
xmlFree( childName );
|
||||
|
||||
@ -25,28 +25,18 @@
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "BaseParser.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
class XMLParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, ExtractionWay> {
|
||||
class XMLParser : public BaseParser {
|
||||
public:
|
||||
XMLParser(const char * filename);
|
||||
virtual ~XMLParser();
|
||||
void RegisterCallbacks(ExtractorCallbacks * em);
|
||||
void RegisterScriptingEnvironment(ScriptingEnvironment & _se);
|
||||
bool Init();
|
||||
XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||
bool ReadHeader();
|
||||
bool Parse();
|
||||
|
||||
private:
|
||||
_RawRestrictionContainer _ReadXMLRestriction();
|
||||
ExtractionWay _ReadXMLWay();
|
||||
ImportNode _ReadXMLNode( );
|
||||
/* Input Reader */
|
||||
ImportNode _ReadXMLNode();
|
||||
xmlTextReaderPtr inputReader;
|
||||
ExtractorCallbacks * externalMemory;
|
||||
lua_State *myLuaState;
|
||||
|
||||
std::vector<std::string> restriction_exceptions_vector;
|
||||
};
|
||||
|
||||
#endif /* XMLPARSER_H_ */
|
||||
|
||||
@ -94,20 +94,20 @@ int main (int argc, char *argv[]) {
|
||||
|
||||
stringMap[""] = 0;
|
||||
extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap);
|
||||
BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, ExtractionWay> * parser;
|
||||
BaseParser* parser;
|
||||
if(isPBF) {
|
||||
parser = new PBFParser(argv[1]);
|
||||
parser = new PBFParser(argv[1], extractCallBacks, scriptingEnvironment);
|
||||
} else {
|
||||
parser = new XMLParser(argv[1]);
|
||||
parser = new XMLParser(argv[1], extractCallBacks, scriptingEnvironment);
|
||||
}
|
||||
parser->RegisterCallbacks(extractCallBacks);
|
||||
parser->RegisterScriptingEnvironment(scriptingEnvironment);
|
||||
|
||||
if(!parser->Init())
|
||||
|
||||
if(!parser->ReadHeader()) {
|
||||
ERR("Parser not initialized!");
|
||||
}
|
||||
INFO("Parsing in progress..");
|
||||
double time = get_timestamp();
|
||||
parser->Parse();
|
||||
INFO("parsing finished after " << get_timestamp() - time << " seconds");
|
||||
INFO("Parsing finished after " << get_timestamp() - time << " seconds");
|
||||
|
||||
externalMemory.PrepareData(outputFileName, restrictionsFileName, amountOfRAM);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
@routing @bicycle @restrictions
|
||||
Feature: Bike - Turn restrictions
|
||||
Handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction
|
||||
Ignore turn restrictions on bicycle, since you always become a temporary pedestrian.
|
||||
Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
|
||||
|
||||
Background:
|
||||
@ -26,7 +26,7 @@ Feature: Bike - Turn restrictions
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | w | |
|
||||
| s | w | sj,wj |
|
||||
| s | n | sj,nj |
|
||||
| s | e | sj,ej |
|
||||
|
||||
@ -52,7 +52,7 @@ Feature: Bike - Turn restrictions
|
||||
| from | to | route |
|
||||
| s | w | sj,wj |
|
||||
| s | n | sj,nj |
|
||||
| s | e | |
|
||||
| s | e | sj,ej |
|
||||
|
||||
@no_turning
|
||||
Scenario: Bike - No u-turn
|
||||
@ -74,7 +74,7 @@ Feature: Bike - Turn restrictions
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | w | |
|
||||
| s | w | sj,wj |
|
||||
| s | n | sj,nj |
|
||||
| s | e | sj,ej |
|
||||
|
||||
@ -98,7 +98,7 @@ Feature: Bike - Turn restrictions
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | w | |
|
||||
| s | w | sj,wj |
|
||||
| s | n | sj,nj |
|
||||
| s | e | sj,ej |
|
||||
|
||||
@ -123,8 +123,8 @@ Feature: Bike - Turn restrictions
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | w | sj,wj |
|
||||
| s | n | |
|
||||
| s | e | |
|
||||
| s | n | sj,nj |
|
||||
| s | e | sj,ej |
|
||||
|
||||
@only_turning
|
||||
Scenario: Bike - Only right turn
|
||||
@ -146,8 +146,8 @@ Feature: Bike - Turn restrictions
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | w | |
|
||||
| s | n | |
|
||||
| s | w | sj,wj |
|
||||
| s | n | sj,nj |
|
||||
| s | e | sj,ej |
|
||||
|
||||
@only_turning
|
||||
@ -170,9 +170,9 @@ Feature: Bike - Turn restrictions
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | w | |
|
||||
| s | w | sj,wj |
|
||||
| s | n | sj,nj |
|
||||
| s | e | |
|
||||
| s | e | sj,ej |
|
||||
|
||||
@no_turning
|
||||
Scenario: Bike - Handle any only_* restriction
|
||||
@ -194,9 +194,9 @@ Feature: Bike - Turn restrictions
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | w | |
|
||||
| s | w | sj,wj |
|
||||
| s | n | sj,nj |
|
||||
| s | e | |
|
||||
| s | e | sj,ej |
|
||||
|
||||
@except
|
||||
Scenario: Bike - Except tag and on no_ restrictions
|
||||
@ -224,8 +224,8 @@ Feature: Bike - Turn restrictions
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | a | sj,aj |
|
||||
| s | b | |
|
||||
| s | c | |
|
||||
| s | b | sj,bj |
|
||||
| s | c | sj,cj |
|
||||
| s | d | sj,dj |
|
||||
|
||||
@except
|
||||
@ -281,9 +281,9 @@ Feature: Bike - Turn restrictions
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | a | |
|
||||
| s | a | sj,ja |
|
||||
| s | b | sj,jb |
|
||||
| s | c | sj,jc |
|
||||
| s | d | sj,jd |
|
||||
| s | e | |
|
||||
| s | f | |
|
||||
| s | e | sj,je |
|
||||
| s | f | sj,jf |
|
||||
|
||||
@ -205,14 +205,15 @@ def write_timestamp
|
||||
end
|
||||
|
||||
def reprocess
|
||||
use_pbf = true
|
||||
Dir.chdir TEST_FOLDER do
|
||||
write_osm
|
||||
write_timestamp
|
||||
convert_osm_to_pbf
|
||||
convert_osm_to_pbf if use_pbf
|
||||
unless extracted?
|
||||
log_preprocess_info
|
||||
log "== Extracting #{@osm_file}.osm...", :preprocess
|
||||
unless system "../osrm-extract #{@osm_file}.osm.pbf 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua"
|
||||
unless system "../osrm-extract #{@osm_file}.osm#{'.pbf' if use_pbf} 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua"
|
||||
log "*** Exited with code #{$?.exitstatus}.", :preprocess
|
||||
raise ExtractError.new $?.exitstatus, "osrm-extract exited with code #{$?.exitstatus}."
|
||||
end
|
||||
|
||||
@ -64,6 +64,7 @@ man_made_speeds = {
|
||||
route_speeds = {
|
||||
["ferry"] = 5
|
||||
}
|
||||
|
||||
take_minimum_of_speeds = true
|
||||
obey_oneway = true
|
||||
obey_bollards = false
|
||||
@ -71,7 +72,7 @@ use_restrictions = true
|
||||
ignore_areas = true -- future feature
|
||||
traffic_signal_penalty = 5
|
||||
u_turn_penalty = 20
|
||||
|
||||
use_turn_restrictions = false
|
||||
-- End of globals
|
||||
|
||||
function get_exceptions(vector)
|
||||
|
||||
@ -41,7 +41,7 @@ use_restrictions = false
|
||||
ignore_areas = true -- future feature
|
||||
traffic_signal_penalty = 2
|
||||
u_turn_penalty = 2
|
||||
|
||||
use_turn_restrictions = false
|
||||
-- End of globals
|
||||
|
||||
function get_exceptions(vector)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user