Added generator_tool option for set osm data type [xml or o5m]

This commit is contained in:
Sergey Yershov 2015-02-13 21:22:46 +03:00 committed by Alex Zolotarev
parent 351a5deb33
commit 3363aba81c
23 changed files with 1402 additions and 729 deletions

View file

@ -2,7 +2,8 @@
TEMPLATE = subdirs
SUBDIRS = freetype fribidi zlib bzip2 jansson tomcrypt protobuf osrm expat
SUBDIRS = freetype fribidi zlib bzip2 jansson tomcrypt protobuf osrm expat \
o5mreader
!iphone*:!tizen*:!android* {
SUBDIRS += gflags \

View file

@ -0,0 +1,516 @@
#include "o5mreader.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#define STR_PAIR_TABLE_SIZE 15000
#define STR_PAIR_STRING_SIZE 256
void o5mreader_setError(O5mreader *pReader,int code, const char* message);
void o5mreader_setNoError(O5mreader *pReader);
O5mreaderRet o5mreader_readUInt(O5mreader *pReader, uint64_t *ret) {
uint8_t b;
uint8_t i = 0;
*ret = 0LL;
do {
if ( fread(&b,1,1,pReader->f) == 0 ) {
o5mreader_setError(pReader,
O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE,
NULL
);
return O5MREADER_RET_ERR;
}
*ret |= (long long)(b & 0x7f) << (i++ * 7);
} while ( b & 0x80 );
o5mreader_setNoError(pReader);
return O5MREADER_RET_OK;
}
O5mreaderRet o5mreader_readInt(O5mreader *pReader, uint64_t *ret) {
if ( o5mreader_readUInt(pReader, ret) == O5MREADER_RET_ERR )
return O5MREADER_RET_ERR;
*ret = *ret & 1
? -(int64_t)(*ret >> 1) - 1
: (int64_t)(*ret >> 1);
return O5MREADER_RET_OK;
}
O5mreaderRet o5mreader_readStrPair(O5mreader *pReader, char **tagpair, int single) {
static char buffer[1024];
char* pBuf;
static uint64_t pointer = 0;
int length;
char byte;
uint64_t key;
int i;
if ( o5mreader_readUInt(pReader,&key) == O5MREADER_RET_ERR ) {
return O5MREADER_RET_ERR;
}
if ( key ) {
*tagpair = pReader->strPairTable[(pointer+15000-key)%15000];
return key;
}
else {
pBuf = buffer;
for ( i=0; i<(single?1:2); i++ ) {
do {
if ( fread(pBuf,1,1,pReader->f) == 0 ) {
o5mreader_setError(pReader,
O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE,
NULL
);
return O5MREADER_RET_ERR;
}
} while ( *(pBuf++) );
}
length = strlen(buffer) + (single ? 1 : strlen(buffer+strlen(buffer) +1) + 2);
if ( length <= 252 ) {
*tagpair = pReader->strPairTable[(pointer+15000)%15000];
memcpy(pReader->strPairTable[((pointer++)+15000)%15000],buffer,length);
}
else {
*tagpair = buffer;
}
}
return O5MREADER_RET_OK;
}
O5mreaderRet o5mreader_reset(O5mreader *pReader) {
pReader->nodeId = pReader->wayId = pReader->wayNodeId = pReader->relId = pReader->nodeRefId = pReader->wayRefId = pReader->relRefId = 0;
pReader->lon = pReader->lat = 0;
pReader->offset = 0;
pReader->canIterateTags = pReader->canIterateNds = pReader->canIterateRefs = 0;
return O5MREADER_RET_OK;
}
O5mreaderRet o5mreader_open(O5mreader **ppReader,FILE* f) {
uint8_t byte;
int i;
*ppReader = malloc(sizeof(O5mreader));
if ( !(*ppReader) ) {
return O5MREADER_RET_ERR;
}
(*ppReader)->errMsg = NULL;
(*ppReader)->f = f;
if ( fread(&byte,1,1,(*ppReader)->f) == 0 ) {
o5mreader_setError(*ppReader,
O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE,
NULL
);
return O5MREADER_RET_ERR;
}
if ( byte != O5MREADER_DS_RESET ) {
o5mreader_setError(*ppReader,
O5MREADER_ERR_CODE_FILE_HAS_WRONG_START,
NULL
);
return O5MREADER_RET_ERR;
}
o5mreader_reset(*ppReader);
(*ppReader)->strPairTable = malloc(STR_PAIR_TABLE_SIZE*sizeof(char*));
if ( (*ppReader)->strPairTable == 0 ) {
o5mreader_setError(*ppReader,
O5MREADER_ERR_CODE_MEMORY_ERROR,
NULL
);
return O5MREADER_RET_ERR;
}
for ( i = 0; i < STR_PAIR_TABLE_SIZE; ++i ) {
(*ppReader)->strPairTable[i] = malloc(sizeof(char)*STR_PAIR_STRING_SIZE);
if ( (*ppReader)->strPairTable[i] == 0 ) {
o5mreader_setError(*ppReader,
O5MREADER_ERR_CODE_MEMORY_ERROR,
NULL
);
return O5MREADER_RET_ERR;
}
}
o5mreader_setNoError(*ppReader);
return O5MREADER_RET_OK;
}
void o5mreader_close(O5mreader *pReader) {
int i;
if ( pReader ) {
if ( pReader->strPairTable ) {
for ( i = 0; i < STR_PAIR_TABLE_SIZE; ++i )
if ( pReader->strPairTable[i] )
free(pReader->strPairTable[i]);
free(pReader->strPairTable);
}
o5mreader_setNoError(pReader);
free(pReader);
}
}
const char* o5mreader_strerror(int errCode) {
switch ( errCode ) {
case O5MREADER_ERR_CODE_FILE_HAS_WRONG_START:
return "'0xFF' isn't first byte of file.";
case O5MREADER_ERR_CODE_MEMORY_ERROR:
return "Memory error.";
case O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE:
return "Unexpected end of file.";
case O5MREADER_ERR_CODE_CAN_NOT_ITERATE_TAGS_HERE:
return "Tags iteration is not allowed here.";
case O5MREADER_ERR_CODE_CAN_NOT_ITERATE_NDS_HERE:
return "Nodes iteration is not allowed here.";
case O5MREADER_ERR_CODE_CAN_NOT_ITERATE_REFS_HERE:
return "References iteration is not allowed here.";
default:
return "Unknown error code";
}
}
void o5mreader_setError(O5mreader *pReader,int code, const char* message) {
pReader->errCode = code;
if ( pReader->errMsg ) {
free(pReader->errMsg);
}
if ( message ) {
pReader->errMsg = malloc(strlen(message)+1);
strcpy(pReader->errMsg,message);
}
}
void o5mreader_setNoError(O5mreader *pReader) {
pReader->errCode = O5MREADER_ERR_CODE_OK;
if ( pReader->errMsg ) {
free(pReader->errMsg);
}
pReader->errMsg = NULL;
}
O5mreaderIterateRet o5mreader_iterateDataSet(O5mreader *pReader, O5mreaderDataset* ds) {
for (;;) {
if ( pReader->offset ) {
if ( o5mreader_skipTags(pReader) == O5MREADER_ITERATE_RET_ERR )
return O5MREADER_ITERATE_RET_ERR;
fseek(
pReader->f,
(pReader->current - ftell(pReader->f)) + pReader->offset,
SEEK_CUR
);
pReader->offset = 0;
}
if ( fread(&(ds->type),1,1,pReader->f) == 0 ) {
o5mreader_setError(pReader,
O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE,
NULL
);
return O5MREADER_ITERATE_RET_ERR;
}
if ( O5MREADER_DS_END == ds->type )
return O5MREADER_ITERATE_RET_DONE;
if ( O5MREADER_DS_RESET == ds->type ) {
o5mreader_reset(pReader);
}
else if ( 0xf0 == ds->type ) {}
else {
if ( o5mreader_readUInt(pReader,&pReader->offset) == O5MREADER_RET_ERR ) {
return O5MREADER_ITERATE_RET_ERR;
}
pReader->current = ftell(pReader->f);
switch ( ds->type ) {
case O5MREADER_DS_NODE:
return o5mreader_readNode(pReader, ds);
case O5MREADER_DS_WAY:
return o5mreader_readWay(pReader, ds);
case O5MREADER_DS_REL:
return o5mreader_readRel(pReader, ds);
/*
case O5MREADER_DS_BBOX:
case O5MREADER_DS_TSTAMP:
case O5MREADER_DS_HEADER:
case O5MREADER_DS_SYNC:
case O5MREADER_DS_JUMP:
default:
break;
*/
}
}
}
}
int o5mreader_thereAreNoMoreData(O5mreader *pReader) {
return (int)((pReader->current - ftell(pReader->f)) + pReader->offset) <= 0;
}
O5mreaderIterateRet o5mreader_readVersion(O5mreader *pReader, O5mreaderDataset* ds) {
uint64_t tmp;
if ( o5mreader_readUInt(pReader,&tmp) == O5MREADER_ITERATE_RET_ERR ) {
return O5MREADER_ITERATE_RET_ERR;
}
ds->version = tmp;
if ( tmp ) {
if ( o5mreader_readUInt(pReader,&tmp) == O5MREADER_ITERATE_RET_ERR ) {
return O5MREADER_ITERATE_RET_ERR;
}
if ( o5mreader_readInt(pReader,&tmp) == O5MREADER_ITERATE_RET_ERR ) {
return O5MREADER_ITERATE_RET_ERR;
}
if ( o5mreader_thereAreNoMoreData(pReader) )
return O5MREADER_ITERATE_RET_DONE;
if ( o5mreader_readStrPair(pReader,&pReader->tagPair,0) == O5MREADER_ITERATE_RET_ERR ) {
return O5MREADER_ITERATE_RET_ERR;
}
}
if ( o5mreader_thereAreNoMoreData(pReader) )
return O5MREADER_ITERATE_RET_DONE;
return O5MREADER_ITERATE_RET_NEXT;
}
O5mreaderIterateRet o5mreader_iterateTags(O5mreader *pReader, char** pKey, char** pVal) {
if ( pReader->canIterateRefs ) {
if ( o5mreader_skipRefs(pReader) == O5MREADER_ITERATE_RET_ERR )
return O5MREADER_ITERATE_RET_ERR;
}
if ( pReader->canIterateNds ) {
if ( o5mreader_skipNds(pReader) == O5MREADER_ITERATE_RET_ERR )
return O5MREADER_ITERATE_RET_ERR;
}
if ( !pReader->canIterateTags ) {
o5mreader_setError(pReader,
O5MREADER_ERR_CODE_CAN_NOT_ITERATE_TAGS_HERE,
NULL
);
return O5MREADER_ITERATE_RET_ERR;
}
if ( o5mreader_thereAreNoMoreData(pReader) ) {
pReader->canIterateTags = 0;
return O5MREADER_ITERATE_RET_DONE;
}
if ( o5mreader_readStrPair(pReader,&pReader->tagPair,0) == O5MREADER_RET_ERR ) {
return O5MREADER_ITERATE_RET_ERR;
}
if ( pKey )
*pKey = pReader->tagPair;
if ( pVal )
*pVal = pReader->tagPair + strlen(pReader->tagPair) + 1;
return O5MREADER_ITERATE_RET_NEXT;
}
O5mreaderIterateRet o5mreader_skipTags(O5mreader *pReader) {
int ret;
if ( pReader->canIterateTags ) {
while ( O5MREADER_ITERATE_RET_NEXT == (ret = o5mreader_iterateTags(pReader, NULL, NULL)) );
}
return ret;
}
O5mreaderIterateRet o5mreader_readNode(O5mreader *pReader, O5mreaderDataset* ds) {
uint64_t nodeId;
int64_t lon,lat;
if ( o5mreader_readInt(pReader,&nodeId) == O5MREADER_RET_ERR )
return O5MREADER_ITERATE_RET_ERR;
pReader->canIterateRefs = 0;
pReader->canIterateNds = 0;
pReader->canIterateTags = 1;
pReader->nodeId += nodeId;
ds->id = pReader->nodeId;
if ( o5mreader_readVersion(pReader, ds) == O5MREADER_ITERATE_RET_DONE ) {
ds->isEmpty = 1;
return O5MREADER_ITERATE_RET_NEXT;
}
else
ds->isEmpty = 0;
if ( o5mreader_thereAreNoMoreData(pReader) ) {
return O5MREADER_ITERATE_RET_NEXT;
}
if ( o5mreader_readInt(pReader,&lon) == O5MREADER_RET_ERR )
return O5MREADER_ITERATE_RET_ERR;
pReader->lon += (int32_t)lon;
if ( o5mreader_readInt(pReader,&lat) == O5MREADER_RET_ERR ) {
return O5MREADER_ITERATE_RET_ERR;
}
pReader->lat += (int32_t)lat;
ds->lon = pReader->lon;
ds->lat = pReader->lat;
return O5MREADER_ITERATE_RET_NEXT;
}
O5mreaderIterateRet o5mreader_iterateNds(O5mreader *pReader, uint64_t *nodeId) {
int64_t wayNodeId;
if ( !pReader->canIterateNds ) {
o5mreader_setError(pReader,
O5MREADER_ERR_CODE_CAN_NOT_ITERATE_NDS_HERE,
NULL
);
return O5MREADER_ITERATE_RET_ERR;
}
if ( ftell(pReader->f) >= pReader->offsetNd ) {
pReader->canIterateNds = 0;
pReader->canIterateTags = 1;
pReader->canIterateRefs = 0;
return O5MREADER_ITERATE_RET_DONE;
}
if ( o5mreader_readInt(pReader,&wayNodeId) == O5MREADER_RET_ERR )
return O5MREADER_ITERATE_RET_ERR;
pReader->wayNodeId += wayNodeId;
if ( nodeId )
*nodeId = pReader->wayNodeId;
return O5MREADER_ITERATE_RET_NEXT;
}
O5mreaderIterateRet o5mreader_skipNds(O5mreader *pReader) {
uint8_t ret;
while ( pReader->canIterateNds &&
O5MREADER_ITERATE_RET_NEXT == (ret = o5mreader_iterateNds(pReader, NULL)) );
return ret;
}
O5mreaderIterateRet o5mreader_readWay(O5mreader *pReader, O5mreaderDataset* ds) {
int64_t wayId;
if ( o5mreader_readInt(pReader,&wayId) == O5MREADER_RET_ERR)
return O5MREADER_ITERATE_RET_ERR;
pReader->wayId += wayId;
ds->id = pReader->wayId;
if ( o5mreader_readVersion(pReader, ds) == O5MREADER_ITERATE_RET_DONE ) {
ds->isEmpty = 1;
return O5MREADER_ITERATE_RET_NEXT;
}
else
ds->isEmpty = 0;
if ( o5mreader_readUInt(pReader,&pReader->offsetNd) == O5MREADER_RET_ERR ) {
return O5MREADER_ITERATE_RET_ERR;
}
pReader->offsetNd += ftell(pReader->f);
pReader->canIterateRefs = 0;
pReader->canIterateNds = 1;
pReader->canIterateTags = 0;
return O5MREADER_ITERATE_RET_NEXT;
}
O5mreaderIterateRet o5mreader_iterateRefs(O5mreader *pReader, uint64_t *refId, uint8_t *type, char** pRole) {
int64_t relRefId;
if ( !pReader->canIterateRefs ) {
o5mreader_setError(pReader,
O5MREADER_ERR_CODE_CAN_NOT_ITERATE_REFS_HERE,
NULL
);
return O5MREADER_ITERATE_RET_ERR;
}
if ( ftell(pReader->f) >= pReader->offsetRf ) {
pReader->canIterateNds = 0;
pReader->canIterateTags = 1;
pReader->canIterateRefs = 0;
return O5MREADER_ITERATE_RET_DONE;
}
if ( o5mreader_readInt(pReader, &relRefId) == O5MREADER_RET_ERR )
return O5MREADER_ITERATE_RET_ERR;
//fread(_,1,1,pReader->f);
if ( o5mreader_readStrPair(pReader, &pReader->tagPair,1) == O5MREADER_RET_ERR ) {
return O5MREADER_ITERATE_RET_ERR;
}
switch( pReader->tagPair[0] ) {
case '0':
if ( type )
*type = O5MREADER_DS_NODE;
pReader->nodeRefId += relRefId;
if ( refId )
*refId = pReader->nodeRefId;
break;
case '1':
if ( type )
*type = O5MREADER_DS_WAY;
pReader->wayRefId += relRefId;
if ( refId )
*refId = pReader->wayRefId;
break;
case '2':
if ( type )
*type = O5MREADER_DS_REL;
pReader->relRefId += relRefId;
if ( refId )
*refId = pReader->relRefId;
break;
}
if ( pRole ) {
*pRole = pReader->tagPair + 1;
}
return O5MREADER_ITERATE_RET_NEXT;
}
O5mreaderIterateRet o5mreader_skipRefs(O5mreader *pReader) {
uint8_t ret;
while ( pReader->canIterateRefs &&
O5MREADER_ITERATE_RET_NEXT == (ret = o5mreader_iterateRefs(pReader, NULL, NULL, NULL)) );
return ret;
}
O5mreaderIterateRet o5mreader_readRel(O5mreader *pReader, O5mreaderDataset* ds) {
int64_t relId;
if ( o5mreader_readInt(pReader,&relId) == O5MREADER_RET_ERR )
return O5MREADER_ITERATE_RET_ERR;
pReader->relId += relId;
ds->id = pReader->relId;
if ( o5mreader_readVersion(pReader,ds) == O5MREADER_ITERATE_RET_DONE ) {
ds->isEmpty = 1;
return O5MREADER_ITERATE_RET_NEXT;
}
else
ds->isEmpty = 0;
o5mreader_readUInt(pReader,&pReader->offsetRf);
pReader->offsetRf += ftell(pReader->f);
pReader->canIterateRefs = 1;
pReader->canIterateNds = 0;
pReader->canIterateTags = 0;
return O5MREADER_ITERATE_RET_NEXT;
}

View file

@ -0,0 +1,93 @@
#ifndef __O5MREADER__H__
#define __O5MREADER__H__
#include <stdint.h>
#include <stdio.h>
#define O5MREADER_RET_OK 1
#define O5MREADER_RET_ERR 0
#define O5MREADER_ITERATE_RET_DONE 0
#define O5MREADER_ITERATE_RET_ERR -1
#define O5MREADER_ITERATE_RET_NEXT 1
#define O5MREADER_DS_END 0xfe
#define O5MREADER_DS_NODE 0x10
#define O5MREADER_DS_WAY 0x11
#define O5MREADER_DS_REL 0x12
#define O5MREADER_DS_BBOX 0xdb
#define O5MREADER_DS_TSTAMP 0xdc
#define O5MREADER_DS_HEADER 0xe0
#define O5MREADER_DS_SYNC 0xee
#define O5MREADER_DS_JUMP 0xef
#define O5MREADER_DS_RESET 0xff
#define O5MREADER_ERR_CODE_OK 0
#define O5MREADER_ERR_CODE_FILE_HAS_WRONG_START 1
#define O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE 2
#define O5MREADER_ERR_CODE_MEMORY_ERROR 3
#define O5MREADER_ERR_CODE_CAN_NOT_ITERATE_TAGS_HERE 4
#define O5MREADER_ERR_CODE_CAN_NOT_ITERATE_NDS_HERE 5
#define O5MREADER_ERR_CODE_CAN_NOT_ITERATE_REFS_HERE 6
typedef int O5mreaderRet;
typedef int O5mreaderIterateRet;
typedef struct {
int errCode;
char* errMsg;
FILE *f;
uint64_t offset;
uint64_t offsetNd;
uint64_t offsetRf;
uint64_t current;
char* tagPair;
int64_t nodeId;
int64_t wayId;
int64_t wayNodeId;
int64_t relId;
int64_t nodeRefId;
int64_t wayRefId;
int64_t relRefId;
int32_t lon;
int32_t lat;
uint8_t canIterateTags;
uint8_t canIterateNds;
uint8_t canIterateRefs;
char** strPairTable;
} O5mreader;
typedef struct {
uint8_t type;
uint64_t id;
uint32_t version;
uint8_t isEmpty;
int32_t lon;
int32_t lat;
} O5mreaderDataset;
#if defined (__cplusplus)
extern "C" {
#endif
O5mreaderRet o5mreader_open(O5mreader **ppReader,FILE* f);
void o5mreader_close(O5mreader *pReader);
const char* o5mreader_strerror(int errCode);
O5mreaderIterateRet o5mreader_iterateDataSet(O5mreader *pReader, O5mreaderDataset* ds);
O5mreaderIterateRet o5mreader_iterateTags(O5mreader *pReader, char** pKey, char** pVal);
O5mreaderIterateRet o5mreader_iterateNds(O5mreader *pReader, uint64_t *nodeId);
O5mreaderIterateRet o5mreader_iterateRefs(O5mreader *pReader, uint64_t *refId, uint8_t *type, char** pRole);
#if defined (__cplusplus)
}
#endif
#endif //__O5MREADER__H__

View file

@ -0,0 +1,17 @@
#-------------------------------------------------
#
# Project created by QtCreator 2015-02-13T20:23:55
#
#-------------------------------------------------
ROOT_DIR = ../..
TARGET = o5mreader
TEMPLATE = lib
CONFIG += staticlib
include($$ROOT_DIR/common.pri)
SOURCES += o5mreader.c
HEADERS += o5mreader.h

View file

@ -8,6 +8,7 @@
#include "../base/assert.hpp"
#include "../base/bits.hpp"
#include "../std/cmath.hpp"
namespace {
vector<uint32_t> SerialFreqsToDistrTable(Reader & reader, uint64_t & decodeOffset, uint64_t cnt)

View file

@ -17,7 +17,7 @@ namespace stream
SinkReaderStream(TReader & reader) : m_reader(reader) {}
template <typename T>
typename enable_if<is_integral<T>, SinkReaderStream &>::type
typename enable_if<is_integral<T>::value, SinkReaderStream &>::type
operator >> (T & t)
{
t = ReadPrimitiveFromSource<T>(m_reader);
@ -53,7 +53,7 @@ namespace stream
SinkWriterStream(TWriter & writer) : m_writer(writer) {}
template <typename T>
typename enable_if<is_integral<T>, SinkWriterStream &>::type
typename enable_if<is_integral<T>::value, SinkWriterStream &>::type
operator << (T const & t)
{
WriteToSink(m_writer, t);

View file

@ -6,7 +6,7 @@
template <class TSink, typename T>
typename enable_if<is_integral<T>, void>::type WriteToSink(TSink & sink, T const & v)
typename enable_if<is_integral<T>::value, void>::type WriteToSink(TSink & sink, T const & v)
{
T const t = SwapIfBigEndian(v);
sink.Write(&t, sizeof(T));

View file

@ -1,107 +0,0 @@
#include "data_generator.hpp"
#include "data_cache_file.hpp"
#include "first_pass_parser.hpp"
#include "osm_decl.hpp"
#include "../base/std_serialization.hpp"
#include "../base/logging.hpp"
#include "../std/bind.hpp"
#include "point_storage.hpp"
namespace data
{
template <class TNodesHolder>
class FileHolder : public cache::BaseFileHolder<TNodesHolder, cache::DataFileWriter, FileWriter>
{
typedef cache::BaseFileHolder<TNodesHolder, cache::DataFileWriter, FileWriter> base_type;
typedef typename base_type::user_id_t user_id_t;
template <class TMap, class TVec>
void add_id2rel_vector(TMap & rMap, user_id_t relid, TVec const & v)
{
for (size_t i = 0; i < v.size(); ++i)
rMap.write(v[i].first, relid);
}
public:
FileHolder(TNodesHolder & nodes, string const & dir) : base_type(nodes, dir) {}
void AddNode(uint64_t id, double lat, double lng)
{
this->m_nodes.AddPoint(id, lat, lng);
}
void AddWay(user_id_t id, WayElement const & e)
{
this->m_ways.Write(id, e);
}
void AddRelation(user_id_t id, RelationElement const & e)
{
const string relationType = e.GetType();
if (relationType == "multipolygon" || relationType == "route" || relationType == "boundary")
{
this->m_relations.Write(id, e);
add_id2rel_vector(this->m_nodes2rel, id, e.nodes);
add_id2rel_vector(this->m_ways2rel, id, e.ways);
}
}
void SaveIndex()
{
this->m_ways.SaveOffsets();
this->m_relations.SaveOffsets();
this->m_nodes2rel.flush_to_file();
this->m_ways2rel.flush_to_file();
}
};
template <class TNodesHolder>
bool GenerateImpl(string const & dir, string const & osmFileName = string())
{
try
{
TNodesHolder nodes(dir + NODES_FILE);
typedef FileHolder<TNodesHolder> holder_t;
holder_t holder(nodes, dir);
FirstPassParser<holder_t> parser(holder);
if (osmFileName.empty())
ParseXMLFromStdIn(parser);
else
ParseXMLFromFile(parser, osmFileName);
LOG(LINFO, ("Added points count = ", nodes.GetCount()));
holder.SaveIndex();
}
catch (Writer::Exception const & e)
{
LOG(LERROR, ("Error with file ", e.what()));
return false;
}
return true;
}
bool GenerateToFile(string const & dir, string const & nodeStorage, string const & osmFileName)
{
if (nodeStorage == "raw")
return GenerateImpl<RawFileShortPointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileName);
else if (nodeStorage == "map")
return GenerateImpl<MapFileShortPointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileName);
else if (nodeStorage == "sqlite")
return GenerateImpl<SQLitePointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileName);
else if (nodeStorage == "mem")
return GenerateImpl<RawMemShortPointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileName);
else
CHECK(nodeStorage.empty(), ("Incorrect node_storage type:", nodeStorage));
return false;
}
}

View file

@ -1,8 +0,0 @@
#pragma once
#include "../std/string.hpp"
namespace data
{
bool GenerateToFile(string const & dir, string const & nodeStorage, string const & osmFileName);
}

View file

@ -1,18 +1,13 @@
#include "feature_generator.hpp"
#include "data_cache_file.hpp"
#include "osm_element.hpp"
#include "polygonizer.hpp"
#include "osm_decl.hpp"
#include "generate_info.hpp"
#include "coastlines_generator.hpp"
#include "world_map_generator.hpp"
#include "../defines.hpp"
#include "../indexer/data_header.hpp"
#include "../indexer/mercator.hpp"
#include "../indexer/cell_id.hpp"
#include "../indexer/classificator.hpp"
#include "../coding/varint.hpp"
@ -24,103 +19,11 @@
#include "../std/unordered_map.hpp"
#include "../std/target_os.hpp"
#include "point_storage.hpp"
namespace feature
{
template <class TNodesHolder>
class FileHolder : public cache::BaseFileHolder<TNodesHolder, cache::DataFileReader, FileReader>
{
typedef cache::DataFileReader reader_t;
typedef cache::BaseFileHolder<TNodesHolder, reader_t, FileReader> base_type;
typedef typename base_type::offset_map_t offset_map_t;
typedef typename base_type::user_id_t user_id_t;
template <class TElement, class ToDo> struct process_base
{
protected:
reader_t & m_reader;
ToDo & m_toDo;
public:
process_base(reader_t & reader, ToDo & toDo) : m_reader(reader), m_toDo(toDo) {}
bool operator() (uint64_t id)
{
TElement e;
if (m_reader.Read(id, e))
return m_toDo(id, e);
return false;
}
};
template <class ToDo> struct process_relation : public process_base<RelationElement, ToDo>
{
typedef process_base<RelationElement, ToDo> base_type;
public:
process_relation(reader_t & reader, ToDo & toDo) : base_type(reader, toDo) {}
};
template <class ToDo> struct process_relation_cached : public process_relation<ToDo>
{
typedef process_relation<ToDo> base_type;
public:
process_relation_cached(reader_t & rels, ToDo & toDo)
: base_type(rels, toDo) {}
bool operator() (uint64_t id)
{
return this->m_toDo(id, this->m_reader);
}
};
public:
FileHolder(TNodesHolder & holder, string const & dir) : base_type(holder, dir) {}
bool GetNode(uint64_t id, double & lat, double & lng)
{
return this->m_nodes.GetPoint(id, lat, lng);
}
bool GetWay(user_id_t id, WayElement & e)
{
return this->m_ways.Read(id, e);
}
template <class ToDo> void ForEachRelationByWay(user_id_t id, ToDo & toDo)
{
process_relation<ToDo> processor(this->m_relations, toDo);
this->m_ways2rel.for_each_ret(id, processor);
}
template <class ToDo> void ForEachRelationByNodeCached(user_id_t id, ToDo & toDo)
{
process_relation_cached<ToDo> processor(this->m_relations, toDo);
this->m_nodes2rel.for_each_ret(id, processor);
}
template <class ToDo> void ForEachRelationByWayCached(user_id_t id, ToDo & toDo)
{
process_relation_cached<ToDo> processor(this->m_relations, toDo);
this->m_ways2rel.for_each_ret(id, processor);
}
void LoadIndex()
{
this->m_ways.LoadOffsets();
this->m_relations.LoadOffsets();
this->m_nodes2rel.read_to_memory();
this->m_ways2rel.read_to_memory();
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// FeaturesCollector implementation
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace feature {
FeaturesCollector::FeaturesCollector(string const & fName)
: m_datFile(fName)
@ -213,232 +116,5 @@ void FeaturesCollector::operator() (FeatureBuilder1 const & fb)
(void)WriteFeatureBase(bytes, fb);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Generate functions implementations.
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace
{
class MainFeaturesEmitter
{
typedef WorldMapGenerator<FeaturesCollector> WorldGenerator;
typedef CountryMapGenerator<Polygonizer<FeaturesCollector> > CountriesGenerator;
unique_ptr<CountriesGenerator> m_countries;
unique_ptr<WorldGenerator> m_world;
unique_ptr<CoastlineFeaturesGenerator> m_coasts;
unique_ptr<FeaturesCollector> m_coastsHolder;
string m_srcCoastsFile;
template <class T1, class T2> class CombinedEmitter
{
T1 * m_p1;
T2 * m_p2;
public:
CombinedEmitter(T1 * p1, T2 * p2) : m_p1(p1), m_p2(p2) {}
void operator() (FeatureBuilder1 const & fb, uint64_t)
{
if (m_p1) (*m_p1)(fb);
if (m_p2) (*m_p2)(fb);
}
};
enum TypeIndex
{
NATURAL_COASTLINE,
NATURAL_LAND,
PLACE_ISLAND,
PLACE_ISLET,
TYPES_COUNT
};
uint32_t m_types[TYPES_COUNT];
inline uint32_t Type(TypeIndex i) const { return m_types[i]; }
public:
MainFeaturesEmitter(GenerateInfo const & info)
{
Classificator const & c = classif();
char const * arr[][2] = {
{ "natural", "coastline" },
{ "natural", "land" },
{ "place", "island" },
{ "place", "islet" }
};
STATIC_ASSERT(ARRAY_SIZE(arr) == TYPES_COUNT);
for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
m_types[i] = c.GetTypeByPath(vector<string>(arr[i], arr[i] + 2));
m_srcCoastsFile = info.m_tmpDir + WORLD_COASTS_FILE_NAME + info.m_datFileSuffix;
CHECK(!info.m_makeCoasts || !info.m_createWorld,
("We can't do make_coasts and generate_world at the same time"));
if (!info.m_makeCoasts)
{
m_countries.reset(new CountriesGenerator(info));
if (info.m_emitCoasts)
{
m_coastsHolder.reset(new FeaturesCollector(
info.m_datFilePrefix + WORLD_COASTS_FILE_NAME + info.m_datFileSuffix));
}
}
else
{
// 4-10 - level range for cells
// 20000 - max points count per feature
m_coasts.reset(new CoastlineFeaturesGenerator(Type(NATURAL_COASTLINE), 4, 10, 20000));
m_coastsHolder.reset(new FeaturesCollector(m_srcCoastsFile));
}
if (info.m_createWorld)
m_world.reset(new WorldGenerator(info));
}
void operator() (FeatureBuilder1 fb)
{
uint32_t const coastType = Type(NATURAL_COASTLINE);
bool const hasCoast = fb.HasType(coastType);
if (m_coasts)
{
if (hasCoast)
{
CHECK ( fb.GetGeomType() != feature::GEOM_POINT, () );
// leave only coastline type
fb.SetType(coastType);
(*m_coasts)(fb);
}
}
else
{
if (hasCoast)
{
fb.PopExactType(Type(NATURAL_LAND));
fb.PopExactType(coastType);
}
else if ((fb.HasType(Type(PLACE_ISLAND)) || fb.HasType(Type(PLACE_ISLET))) &&
fb.GetGeomType() == feature::GEOM_AREA)
{
fb.AddType(Type(NATURAL_LAND));
}
if (fb.RemoveInvalidTypes())
{
if (m_world)
(*m_world)(fb);
if (m_countries)
(*m_countries)(fb);
}
}
}
/// @return false if coasts are not merged and FLAG_fail_on_coasts is set
bool Finish()
{
if (m_world)
m_world->DoMerge();
if (m_coasts)
{
// Check and stop if some coasts were not merged
if (!m_coasts->Finish())
return false;
size_t const count = m_coasts->GetCellsCount();
LOG(LINFO, ("Generating coastline polygons", count));
for (size_t i = 0; i < count; ++i)
{
vector<FeatureBuilder1> vecFb;
m_coasts->GetFeatures(i, vecFb);
for (size_t j = 0; j < vecFb.size(); ++j)
(*m_coastsHolder)(vecFb[j]);
}
}
else if (m_coastsHolder)
{
CombinedEmitter<FeaturesCollector, CountriesGenerator>
emitter(m_coastsHolder.get(), m_countries.get());
feature::ForEachFromDatRawFormat(m_srcCoastsFile, emitter);
}
return true;
}
inline void GetNames(vector<string> & names) const
{
if (m_countries)
names = m_countries->Parent().Names();
else
names.clear();
}
};
}
template <class NodesHolderT>
bool GenerateImpl(GenerateInfo & info, string const & osmFileName = string())
{
try
{
NodesHolderT nodes(info.m_tmpDir + NODES_FILE);
typedef FileHolder<NodesHolderT> HolderT;
HolderT holder(nodes, info.m_tmpDir);
holder.LoadIndex();
MainFeaturesEmitter bucketer(info);
SecondPassParser<MainFeaturesEmitter, HolderT> parser(
bucketer, holder,
info.m_makeCoasts ? classif().GetCoastType() : 0,
info.m_addressFile);
if (osmFileName.empty())
ParseXMLFromStdIn(parser);
else
ParseXMLFromFile(parser, osmFileName);
parser.Finish();
// Stop if coasts are not merged and FLAG_fail_on_coasts is set
if (!bucketer.Finish())
return false;
bucketer.GetNames(info.m_bucketNames);
}
catch (Reader::Exception const & e)
{
LOG(LERROR, ("Error with file ", e.what()));
return false;
}
return true;
}
bool GenerateFeatures(GenerateInfo & info, string const & nodeStorage, string const & osmFileName)
{
if (nodeStorage == "raw")
return GenerateImpl<RawFileShortPointStorage<BasePointStorage::MODE_READ>>(info, osmFileName);
else if (nodeStorage == "map")
return GenerateImpl<MapFileShortPointStorage<BasePointStorage::MODE_READ>>(info, osmFileName);
else if (nodeStorage == "sqlite")
return GenerateImpl<SQLitePointStorage<BasePointStorage::MODE_READ>>(info, osmFileName);
else if (nodeStorage == "mem")
return GenerateImpl<RawMemShortPointStorage<BasePointStorage::MODE_READ>>(info, osmFileName);
else
CHECK(nodeStorage.empty(), ("Incorrect node_storage type:", nodeStorage));
return false;
}
}

View file

@ -12,10 +12,6 @@ class FeatureBuilder1;
namespace feature
{
struct GenerateInfo;
bool GenerateFeatures(GenerateInfo & info, string const & nodeStorage, string const & osmFileName);
// Writes features to dat file.
class FeaturesCollector
{

View file

@ -16,7 +16,7 @@ QT *= core
SOURCES += \
feature_merger.cpp \
xml_element.cpp \
data_generator.cpp \
osm_source.cpp \
feature_generator.cpp \
feature_sorter.cpp \
update_generator.cpp \

View file

@ -1,4 +1,3 @@
#include "../data_generator.hpp"
#include "../feature_generator.hpp"
#include "../feature_sorter.hpp"
#include "../update_generator.hpp"
@ -10,6 +9,7 @@
#include "../generate_info.hpp"
#include "../check_model.hpp"
#include "../routing_generator.hpp"
#include "../osm_source.hpp"
#include "../../indexer/drawing_rules.hpp"
#include "../../indexer/classificator_loader.hpp"
@ -35,7 +35,7 @@ DEFINE_bool(generate_update, false,
DEFINE_bool(generate_classif, false, "Generate classificator.");
DEFINE_bool(preprocess_xml, false, "1st pass - create nodes/ways/relations data");
DEFINE_bool(preprocess, false, "1st pass - create nodes/ways/relations data");
DEFINE_bool(make_coasts, false, "create intermediate file with coasts data");
DEFINE_bool(emit_coasts, false, "push coasts features from intermediate file to out files/countries");
@ -44,7 +44,7 @@ DEFINE_bool(generate_geometry, false, "3rd pass - split and simplify geometry an
DEFINE_bool(generate_index, false, "4rd pass - generate index");
DEFINE_bool(generate_search_index, false, "5th pass - generate search index");
DEFINE_bool(calc_statistics, false, "Calculate feature statistics for specified mwm bucket files");
DEFINE_string(node_storage, "raw", "Type of storage for intermediate points representation. Available: raw, map, sqlite, mem");
DEFINE_string(node_storage, "map", "Type of storage for intermediate points representation. Available: raw, map, mem");
DEFINE_string(data_path, "", "Working directory, 'path_to_exe/../../data' if empty.");
DEFINE_string(output, "", "File name for process (without 'mwm' ext).");
DEFINE_string(intermediate_data_path, "", "Path to stored nodes, ways, relations.");
@ -65,6 +65,7 @@ DEFINE_string(address_file_name, "", "Output file name for storing full addresse
DEFINE_string(export_poly_path, "", "Output dir for osm .poly files created from .borders (countires are read from polygons.lst)");
DEFINE_string(osrm_file_name, "", "Input osrm file to generate routing info");
DEFINE_string(osm_file_name, "", "Input osm area file");
DEFINE_string(osm_file_type, "xml", "Input osm area file type [xml, o5m]");
DEFINE_string(user_resource_path, "", "User defined resource path for classificator.txt and etc.");
@ -101,10 +102,10 @@ int main(int argc, char ** argv)
FLAGS_data_path.empty() ? pl.WritableDir() : AddSlashIfNeeded(FLAGS_data_path);
// Generating intermediate files
if (FLAGS_preprocess_xml)
if (FLAGS_preprocess)
{
LOG(LINFO, ("Generating intermediate data ...."));
if (!data::GenerateToFile(FLAGS_intermediate_data_path, FLAGS_node_storage, FLAGS_osm_file_name))
if (!GenerateIntermediateData(FLAGS_intermediate_data_path, FLAGS_node_storage, FLAGS_osm_file_type, FLAGS_osm_file_name))
return -1;
}
@ -148,7 +149,7 @@ int main(int argc, char ** argv)
if (!FLAGS_address_file_name.empty())
genInfo.m_addressFile = path + FLAGS_address_file_name;
if (!feature::GenerateFeatures(genInfo, FLAGS_node_storage, FLAGS_osm_file_name))
if (!GenerateFeatures(genInfo, FLAGS_node_storage, FLAGS_osm_file_type, FLAGS_osm_file_name))
return -1;
// without --spit_by_polygons, we have empty name country as result - assign it

View file

@ -2,7 +2,7 @@
ROOT_DIR = ../..
DEPENDENCIES = generator routing storage indexer platform geometry coding base \
osrm gflags expat sgitess jansson protobuf tomcrypt
osrm gflags expat sgitess jansson protobuf tomcrypt o5mreader
include($$ROOT_DIR/common.pri)
@ -18,8 +18,6 @@ QT *= core
win32: LIBS *= -lShell32
macx-*: LIBS *= "-framework Foundation"
LIBS *= -lsqlite3
SOURCES += \
generator_tool.cpp \

View file

@ -382,6 +382,7 @@ class SecondPassParser : public BaseOSMParser
}
//@}
public:
/// The main entry point for parsing process.
virtual void EmitElement(XMLElement * p)
{

647
generator/osm_source.cpp Normal file
View file

@ -0,0 +1,647 @@
#include "osm_source.hpp"
#include "osm_decl.hpp"
#include "data_cache_file.hpp"
#include "coastlines_generator.hpp"
#include "world_map_generator.hpp"
#include "feature_generator.hpp"
#include "polygonizer.hpp"
#include "point_storage.hpp"
#include "xml_element.hpp"
#include "first_pass_parser.hpp"
#include "osm_element.hpp"
#include "../defines.hpp"
#include "../indexer/mercator.hpp"
#include "../indexer/classificator.hpp"
#include "../coding/parse_xml.hpp"
#include "../3party/o5mreader/o5mreader.h"
#define DECODE_O5M_COORD(coord) (static_cast<double>(coord) / 1E+7)
namespace
{
class SourceReader
{
string const &m_filename;
FILE * m_file;
public:
SourceReader(string const & filename) : m_filename(filename)
{
if (m_filename.empty())
{
LOG(LINFO, ("Read OSM data from stdin..."));
m_file = freopen(NULL, "rb", stdin);
}
else
{
LOG(LINFO, ("Read OSM data from", filename));
m_file = fopen(filename.c_str(), "rb");
}
}
~SourceReader()
{
if (!m_filename.empty())
fclose(m_file);
}
inline FILE * Handle() { return m_file; }
uint64_t Read(char * buffer, uint64_t bufferSize)
{
return fread(buffer, sizeof(char), bufferSize, m_file);
}
};
}
namespace feature
{
template <class TNodesHolder>
class FileHolder : public cache::BaseFileHolder<TNodesHolder, cache::DataFileReader, FileReader>
{
typedef cache::DataFileReader reader_t;
typedef cache::BaseFileHolder<TNodesHolder, reader_t, FileReader> base_type;
typedef typename base_type::offset_map_t offset_map_t;
typedef typename base_type::user_id_t user_id_t;
template <class TElement, class ToDo> struct process_base
{
protected:
reader_t & m_reader;
ToDo & m_toDo;
public:
process_base(reader_t & reader, ToDo & toDo) : m_reader(reader), m_toDo(toDo) {}
bool operator() (uint64_t id)
{
TElement e;
if (m_reader.Read(id, e))
return m_toDo(id, e);
return false;
}
};
template <class ToDo> struct process_relation : public process_base<RelationElement, ToDo>
{
typedef process_base<RelationElement, ToDo> base_type;
public:
process_relation(reader_t & reader, ToDo & toDo) : base_type(reader, toDo) {}
};
template <class ToDo> struct process_relation_cached : public process_relation<ToDo>
{
typedef process_relation<ToDo> base_type;
public:
process_relation_cached(reader_t & rels, ToDo & toDo)
: base_type(rels, toDo) {}
bool operator() (uint64_t id)
{
return this->m_toDo(id, this->m_reader);
}
};
public:
FileHolder(TNodesHolder & holder, string const & dir) : base_type(holder, dir) {}
bool GetNode(uint64_t id, double & lat, double & lng)
{
return this->m_nodes.GetPoint(id, lat, lng);
}
bool GetWay(user_id_t id, WayElement & e)
{
return this->m_ways.Read(id, e);
}
template <class ToDo> void ForEachRelationByWay(user_id_t id, ToDo & toDo)
{
process_relation<ToDo> processor(this->m_relations, toDo);
this->m_ways2rel.for_each_ret(id, processor);
}
template <class ToDo> void ForEachRelationByNodeCached(user_id_t id, ToDo & toDo)
{
process_relation_cached<ToDo> processor(this->m_relations, toDo);
this->m_nodes2rel.for_each_ret(id, processor);
}
template <class ToDo> void ForEachRelationByWayCached(user_id_t id, ToDo & toDo)
{
process_relation_cached<ToDo> processor(this->m_relations, toDo);
this->m_ways2rel.for_each_ret(id, processor);
}
void LoadIndex()
{
this->m_ways.LoadOffsets();
this->m_relations.LoadOffsets();
this->m_nodes2rel.read_to_memory();
this->m_ways2rel.read_to_memory();
}
};
} // namespace feature
namespace data
{
template <class TNodesHolder>
class FileHolder : public cache::BaseFileHolder<TNodesHolder, cache::DataFileWriter, FileWriter>
{
typedef cache::BaseFileHolder<TNodesHolder, cache::DataFileWriter, FileWriter> base_type;
typedef typename base_type::user_id_t user_id_t;
template <class TMap, class TVec>
void add_id2rel_vector(TMap & rMap, user_id_t relid, TVec const & v)
{
for (size_t i = 0; i < v.size(); ++i)
rMap.write(v[i].first, relid);
}
public:
FileHolder(TNodesHolder & nodes, string const & dir) : base_type(nodes, dir) {}
void AddNode(uint64_t id, double lat, double lng)
{
this->m_nodes.AddPoint(id, lat, lng);
}
void AddWay(user_id_t id, WayElement const & e)
{
this->m_ways.Write(id, e);
}
void AddRelation(user_id_t id, RelationElement const & e)
{
const string relationType = e.GetType();
if (relationType == "multipolygon" || relationType == "route" || relationType == "boundary")
{
this->m_relations.Write(id, e);
add_id2rel_vector(this->m_nodes2rel, id, e.nodes);
add_id2rel_vector(this->m_ways2rel, id, e.ways);
}
}
void SaveIndex()
{
this->m_ways.SaveOffsets();
this->m_relations.SaveOffsets();
this->m_nodes2rel.flush_to_file();
this->m_ways2rel.flush_to_file();
}
};
} // namespace data
namespace
{
class MainFeaturesEmitter
{
typedef WorldMapGenerator<feature::FeaturesCollector> WorldGenerator;
typedef CountryMapGenerator<feature::Polygonizer<feature::FeaturesCollector> > CountriesGenerator;
unique_ptr<CountriesGenerator> m_countries;
unique_ptr<WorldGenerator> m_world;
unique_ptr<CoastlineFeaturesGenerator> m_coasts;
unique_ptr<feature::FeaturesCollector> m_coastsHolder;
string m_srcCoastsFile;
template <class T1, class T2> class CombinedEmitter
{
T1 * m_p1;
T2 * m_p2;
public:
CombinedEmitter(T1 * p1, T2 * p2) : m_p1(p1), m_p2(p2) {}
void operator() (FeatureBuilder1 const & fb, uint64_t)
{
if (m_p1) (*m_p1)(fb);
if (m_p2) (*m_p2)(fb);
}
};
enum TypeIndex
{
NATURAL_COASTLINE,
NATURAL_LAND,
PLACE_ISLAND,
PLACE_ISLET,
TYPES_COUNT
};
uint32_t m_types[TYPES_COUNT];
inline uint32_t Type(TypeIndex i) const { return m_types[i]; }
public:
MainFeaturesEmitter(feature::GenerateInfo const & info)
{
Classificator const & c = classif();
char const * arr[][2] = {
{ "natural", "coastline" },
{ "natural", "land" },
{ "place", "island" },
{ "place", "islet" }
};
STATIC_ASSERT(ARRAY_SIZE(arr) == TYPES_COUNT);
for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
m_types[i] = c.GetTypeByPath(vector<string>(arr[i], arr[i] + 2));
m_srcCoastsFile = info.m_tmpDir + WORLD_COASTS_FILE_NAME + info.m_datFileSuffix;
CHECK(!info.m_makeCoasts || !info.m_createWorld,
("We can't do make_coasts and generate_world at the same time"));
if (!info.m_makeCoasts)
{
m_countries.reset(new CountriesGenerator(info));
if (info.m_emitCoasts)
{
m_coastsHolder.reset(new feature::FeaturesCollector(
info.m_datFilePrefix + WORLD_COASTS_FILE_NAME + info.m_datFileSuffix));
}
}
else
{
// 4-10 - level range for cells
// 20000 - max points count per feature
m_coasts.reset(new CoastlineFeaturesGenerator(Type(NATURAL_COASTLINE), 4, 10, 20000));
m_coastsHolder.reset(new feature::FeaturesCollector(m_srcCoastsFile));
}
if (info.m_createWorld)
m_world.reset(new WorldGenerator(info));
}
void operator() (FeatureBuilder1 fb)
{
uint32_t const coastType = Type(NATURAL_COASTLINE);
bool const hasCoast = fb.HasType(coastType);
if (m_coasts)
{
if (hasCoast)
{
CHECK ( fb.GetGeomType() != feature::GEOM_POINT, () );
// leave only coastline type
fb.SetType(coastType);
(*m_coasts)(fb);
}
}
else
{
if (hasCoast)
{
fb.PopExactType(Type(NATURAL_LAND));
fb.PopExactType(coastType);
}
else if ((fb.HasType(Type(PLACE_ISLAND)) || fb.HasType(Type(PLACE_ISLET))) &&
fb.GetGeomType() == feature::GEOM_AREA)
{
fb.AddType(Type(NATURAL_LAND));
}
if (fb.RemoveInvalidTypes())
{
if (m_world)
(*m_world)(fb);
if (m_countries)
(*m_countries)(fb);
}
}
}
/// @return false if coasts are not merged and FLAG_fail_on_coasts is set
bool Finish()
{
if (m_world)
m_world->DoMerge();
if (m_coasts)
{
// Check and stop if some coasts were not merged
if (!m_coasts->Finish())
return false;
size_t const count = m_coasts->GetCellsCount();
LOG(LINFO, ("Generating coastline polygons", count));
for (size_t i = 0; i < count; ++i)
{
vector<FeatureBuilder1> vecFb;
m_coasts->GetFeatures(i, vecFb);
for (size_t j = 0; j < vecFb.size(); ++j)
(*m_coastsHolder)(vecFb[j]);
}
}
else if (m_coastsHolder)
{
CombinedEmitter<feature::FeaturesCollector, CountriesGenerator>
emitter(m_coastsHolder.get(), m_countries.get());
feature::ForEachFromDatRawFormat(m_srcCoastsFile, emitter);
}
return true;
}
inline void GetNames(vector<string> & names) const
{
if (m_countries)
names = m_countries->Parent().Names();
else
names.clear();
}
};
} // namespace anonymous
template <typename HolderT>
void BuildIntermediateDataFromO5M(SourceReader & stream, HolderT & holder)
{
O5mreader * reader;
O5mreaderRet rc;
if ((rc = o5mreader_open(&reader, stream.Handle())) != O5MREADER_RET_OK)
{
LOG(LCRITICAL, ("O5M Open error:", o5mreader_strerror(rc)));
exit(1);
}
O5mreaderDataset ds;
O5mreaderIterateRet ret;
while ((ret = o5mreader_iterateDataSet(reader, &ds)) == O5MREADER_ITERATE_RET_NEXT)
{
O5mreaderIterateRet ret2;
switch (ds.type)
{
case O5MREADER_DS_NODE:
{
// Could do something with ds.id, ds.lon, ds.lat here, lon and lat are ints in 1E+7 * degree units
// convert to mercator
double const lat = MercatorBounds::LatToY(DECODE_O5M_COORD(ds.lat));
double const lng = MercatorBounds::LonToX(DECODE_O5M_COORD(ds.lon));
holder.AddNode(ds.id, lat, lng);
} break;
case O5MREADER_DS_WAY:
{
// store way
WayElement way(ds.id);
uint64_t nodeId = 0;
while ((ret2 = o5mreader_iterateNds(reader, &nodeId)) == O5MREADER_ITERATE_RET_NEXT)
way.nodes.push_back(nodeId);
if (way.IsValid())
holder.AddWay(ds.id, way);
} break;
case O5MREADER_DS_REL:
{
// store relation
RelationElement relation;
uint64_t refId = 0;
uint8_t type = 0;
char * role = nullptr;
while ((ret2 = o5mreader_iterateRefs(reader, &refId, &type, &role)) == O5MREADER_ITERATE_RET_NEXT)
{
// Could do something with refId (way or node or rel id depends on type), type and role
if (type == O5MREADER_DS_NODE)
relation.nodes.emplace_back(make_pair(refId, string(role)));
else if (type == O5MREADER_DS_WAY)
relation.ways.emplace_back(make_pair(refId, string(role)));
// we just ignore type == "relation"
}
char * key = nullptr;
char * val = nullptr;
while ((ret2 = o5mreader_iterateTags(reader, &key, &val)) == O5MREADER_ITERATE_RET_NEXT)
relation.tags.emplace(make_pair(string(key), string(val)));
if (relation.IsValid())
holder.AddRelation(ds.id, relation);
} break;
}
}
}
void BuildFeaturesFromO5M(SourceReader & stream, BaseOSMParser & parser)
{
O5mreader * reader;
O5mreaderRet rc;
if ((rc = o5mreader_open(&reader, stream.Handle())) != O5MREADER_RET_OK)
{
LOG(LCRITICAL, ("O5M Open error:", o5mreader_strerror(rc)));
exit(1);
}
O5mreaderDataset ds;
O5mreaderIterateRet ret;
while ((ret = o5mreader_iterateDataSet(reader, &ds)) == O5MREADER_ITERATE_RET_NEXT)
{
XMLElement p;
p.id = ds.id;
O5mreaderIterateRet ret2;
char * key = nullptr;
char * val = nullptr;
switch (ds.type)
{
case O5MREADER_DS_NODE:
{
p.tagKey = XMLElement::ET_NODE;
p.lat = DECODE_O5M_COORD(ds.lat);
p.lng = DECODE_O5M_COORD(ds.lon);
} break;
case O5MREADER_DS_WAY:
{
p.tagKey = XMLElement::ET_WAY;
uint64_t nodeId = 0;
while ((ret2 = o5mreader_iterateNds(reader, &nodeId)) == O5MREADER_ITERATE_RET_NEXT)
p.AddND(nodeId);
} break;
case O5MREADER_DS_REL:
{
p.tagKey = XMLElement::ET_RELATION;
uint64_t refId = 0;
uint8_t type = 0;
char * role = nullptr;
while ((ret2 = o5mreader_iterateRefs(reader, &refId, &type, &role)) == O5MREADER_ITERATE_RET_NEXT)
{
string strType;
switch (type)
{
case O5MREADER_DS_NODE:
strType = "node";
break;
case O5MREADER_DS_WAY:
strType = "way";
break;
case O5MREADER_DS_REL:
strType = "relation";
break;
default:
break;
}
p.AddMEMBER(refId, strType, role);
}
} break;
}
while ((ret2 = o5mreader_iterateTags(reader, &key, &val)) == O5MREADER_ITERATE_RET_NEXT)
p.AddKV(key, val);
parser.EmitElement(&p);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Generate functions implementations.
///////////////////////////////////////////////////////////////////////////////////////////////////
template <class NodesHolderT>
bool GenerateFeaturesImpl(feature::GenerateInfo & info, string const &osmFileType, string const & osmFileName = string())
{
try
{
NodesHolderT nodes(info.m_tmpDir + NODES_FILE);
typedef feature::FileHolder<NodesHolderT> HolderT;
HolderT holder(nodes, info.m_tmpDir);
holder.LoadIndex();
MainFeaturesEmitter bucketer(info);
SecondPassParser<MainFeaturesEmitter, HolderT> parser(
bucketer, holder,
info.m_makeCoasts ? classif().GetCoastType() : 0,
info.m_addressFile);
SourceReader reader(osmFileName);
if (osmFileType == "xml")
{
ParseXMLSequence(reader, parser);
}
else if (osmFileType == "o5m")
{
BuildFeaturesFromO5M(reader, parser);
}
else
{
LOG(LERROR, ("Unknown source type:", osmFileType));
return false;
}
parser.Finish();
// Stop if coasts are not merged and FLAG_fail_on_coasts is set
if (!bucketer.Finish())
return false;
bucketer.GetNames(info.m_bucketNames);
}
catch (Reader::Exception const & e)
{
LOG(LERROR, ("Error with file ", e.what()));
return false;
}
return true;
}
template <class TNodesHolder>
bool GenerateIntermediateDataImpl(string const & dir, string const &osmFileType, string const & osmFileName = string())
{
try
{
TNodesHolder nodes(dir + NODES_FILE);
typedef data::FileHolder<TNodesHolder> HolderT;
HolderT holder(nodes, dir);
SourceReader reader(osmFileName);
LOG(LINFO, ("Data sorce format:", osmFileType));
if (osmFileType == "xml")
{
FirstPassParser<HolderT> parser(holder);
ParseXMLSequence(reader, parser);
}
else if (osmFileType == "o5m")
{
BuildIntermediateDataFromO5M(reader, holder);
}
else
{
LOG(LERROR, ("Unknown source type:", osmFileType));
return false;
}
LOG(LINFO, ("Added points count = ", nodes.GetCount()));
holder.SaveIndex();
}
catch (Writer::Exception const & e)
{
LOG(LERROR, ("Error with file ", e.what()));
return false;
}
return true;
}
bool GenerateFeatures(feature::GenerateInfo & info, string const & nodeStorage, string const &osmFileType, string const & osmFileName)
{
if (nodeStorage == "raw")
return GenerateFeaturesImpl<RawFileShortPointStorage<BasePointStorage::MODE_READ>>(info, osmFileType, osmFileName);
else if (nodeStorage == "map")
return GenerateFeaturesImpl<MapFileShortPointStorage<BasePointStorage::MODE_READ>>(info, osmFileType, osmFileName);
else if (nodeStorage == "mem")
return GenerateFeaturesImpl<RawMemShortPointStorage<BasePointStorage::MODE_READ>>(info, osmFileType, osmFileName);
else
CHECK(nodeStorage.empty(), ("Incorrect node_storage type:", nodeStorage));
return false;
}
bool GenerateIntermediateData(string const & dir, string const & nodeStorage, string const &osmFileType, string const & osmFileName)
{
if (nodeStorage == "raw")
return GenerateIntermediateDataImpl<RawFileShortPointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileType, osmFileName);
else if (nodeStorage == "map")
return GenerateIntermediateDataImpl<MapFileShortPointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileType, osmFileName);
else if (nodeStorage == "mem")
return GenerateIntermediateDataImpl<RawMemShortPointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileType, osmFileName);
else
CHECK(nodeStorage.empty(), ("Incorrect node_storage type:", nodeStorage));
return false;
}

11
generator/osm_source.hpp Normal file
View file

@ -0,0 +1,11 @@
#pragma once
#include "generate_info.hpp"
#include "../std/string.hpp"
bool GenerateFeatures(feature::GenerateInfo & info, string const & nodeStorage, string const &osmFileType, string const & osmFileName);
bool GenerateIntermediateData(string const & dir, string const & nodeStorage, string const &osmFileType, string const & osmFileName);

View file

@ -1,8 +1,9 @@
#pragma once
#include "../coding/mmap_reader.hpp"
#include <sqlite3.h>
#include "../std/iostream.hpp"
#include "../std/type_traits.hpp"
/// Used to store all world nodes inside temporary index file.
/// To find node by id, just calculate offset inside index file:
@ -12,14 +13,14 @@ struct LatLon
double lat;
double lon;
};
STATIC_ASSERT(sizeof(LatLon) == 16);
static_assert(sizeof(LatLon) == 16, "Invalid structure size");
struct ShortLatLon
{
int32_t lat;
int32_t lon;
};
STATIC_ASSERT(sizeof(ShortLatLon) == 8);
static_assert(sizeof(ShortLatLon) == 8, "Invalid structure size");
struct LatLonPos
{
@ -27,7 +28,7 @@ struct LatLonPos
double lat;
double lon;
};
STATIC_ASSERT(sizeof(LatLonPos) == 24);
static_assert(sizeof(LatLonPos) == 24, "Invalid structure size");
struct ShortLatLonPos
{
@ -35,7 +36,7 @@ struct ShortLatLonPos
int32_t lat;
int32_t lon;
};
STATIC_ASSERT(sizeof(ShortLatLonPos) == 16);
static_assert(sizeof(ShortLatLonPos) == 16, "Invalid structure size");
class BasePointStorage
@ -53,7 +54,7 @@ protected:
public:
enum EStorageMode {MODE_READ = false, MODE_WRITE = true};
BasePointStorage(string const & name, size_t factor)
BasePointStorage(string const & name, size_t factor = 1000)
{
m_progress.Begin(name, factor);
}
@ -61,155 +62,22 @@ public:
uint64_t GetCount() const { return m_progress.GetCount(); }
};
template < BasePointStorage::EStorageMode ModeT >
class SQLitePointStorage : public BasePointStorage
{
sqlite3 *m_db;
sqlite3_stmt *m_prepared_statement;
public:
SQLitePointStorage(string const & name) : BasePointStorage(name, 1000)
{
if( sqlite3_open((name+".sqlite").c_str(), &m_db) != SQLITE_OK ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(m_db));
sqlite3_close(m_db);
exit(1);
}
InitStorage(EnableIf<ModeT>());
}
~SQLitePointStorage()
{
DoneStorage(EnableIf<ModeT>());
sqlite3_finalize(m_prepared_statement);
sqlite3_close(m_db);
}
void InitStorage(EnableIf<MODE_WRITE>)
{
string create_table("drop table if exists points; drop index if exists points_idx; create table points(id integer PRIMARY KEY, ll blob) WITHOUT ROWID;");
if( sqlite3_exec(m_db, create_table.c_str(), NULL, NULL, NULL ) != SQLITE_OK ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(m_db));
sqlite3_close(m_db);
exit(1);
}
char* errorMessage;
sqlite3_exec(m_db, "PRAGMA synchronous=OFF", NULL, NULL, &errorMessage);
sqlite3_exec(m_db, "PRAGMA count_changes=OFF", NULL, NULL, &errorMessage);
sqlite3_exec(m_db, "PRAGMA journal_mode=MEMORY", NULL, NULL, &errorMessage);
sqlite3_exec(m_db, "PRAGMA temp_store=MEMORY", NULL, NULL, &errorMessage);
string insert("insert into points(id, ll) values(?,?);");
if( sqlite3_prepare_v2(m_db, insert.c_str(), -1, &m_prepared_statement, NULL) != SQLITE_OK ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(m_db));
sqlite3_close(m_db);
exit(1);
}
if( sqlite3_exec(m_db, "BEGIN TRANSACTION", NULL, NULL, NULL ) != SQLITE_OK ){
fprintf(stderr, "Can't start transaction: %s\n", sqlite3_errmsg(m_db));
sqlite3_close(m_db);
exit(1);
}
}
void InitStorage(EnableIf<MODE_READ>)
{
string select("select ll from points where id=?;");
if( sqlite3_prepare_v2(m_db, select.c_str(), -1, &m_prepared_statement, NULL) != SQLITE_OK ){
fprintf(stderr, "failed sqlite3_prepare_v2: %s\n", sqlite3_errmsg(m_db));
sqlite3_close(m_db);
exit(1);
}
}
void DoneStorage(EnableIf<MODE_WRITE>)
{
if( sqlite3_exec(m_db, "COMMIT TRANSACTION", NULL, NULL, NULL ) != SQLITE_OK ){
fprintf(stderr, "Can't end transaction: %s\n", sqlite3_errmsg(m_db));
sqlite3_close(m_db);
exit(1);
}
if( sqlite3_exec(m_db, "create unique index points_idx on points(id);", NULL, NULL, NULL ) != SQLITE_OK ){
fprintf(stderr, "Can't end transaction: %s\n", sqlite3_errmsg(m_db));
sqlite3_close(m_db);
exit(1);
}
}
void DoneStorage(EnableIf<MODE_READ>) {}
void AddPoint(uint64_t id, double lat, double lng)
{
LatLon ll = {lat, lng};
if (sqlite3_bind_int64(m_prepared_statement, 1, id) != SQLITE_OK) {
cerr << "bind1 failed: " << sqlite3_errmsg(m_db) << endl;
exit(1);
}
if (sqlite3_bind_blob(m_prepared_statement, 2, &ll, sizeof(ll), SQLITE_STATIC) != SQLITE_OK) {
cerr << "bind2 failed: " << sqlite3_errmsg(m_db) << endl;
exit(1);
}
if (sqlite3_step(m_prepared_statement) != SQLITE_DONE) {
cerr << "execution failed: " << sqlite3_errmsg(m_db) << endl;
exit(1);
}
sqlite3_reset(m_prepared_statement);
m_progress.Inc();
}
bool GetPoint(uint64_t id, double & lat, double & lng) const
{
bool found = true;
if (sqlite3_bind_int64(m_prepared_statement, 1, id) != SQLITE_OK) {
cerr << "bind1 failed: " << sqlite3_errmsg(m_db) << endl;
exit(1);
}
int rc = sqlite3_step(m_prepared_statement);
if (rc == SQLITE_DONE)
{
found = false;
}
else if (rc == SQLITE_ROW)
{
const void * data;
data = sqlite3_column_blob (m_prepared_statement, 0);
LatLon const &ll = *((LatLon const *)data);
lat = ll.lat;
lng = ll.lon;
}
else
{
cerr << "execution failed: " << sqlite3_errmsg(m_db) << endl;
exit(1);
}
sqlite3_reset(m_prepared_statement);
return found;
}
};
template < BasePointStorage::EStorageMode ModeT >
class RawFilePointStorage : public BasePointStorage
{
#ifdef OMIM_OS_WINDOWS
typedef FileReader FileReaderT;
#else
typedef MmapReader FileReaderT;
#endif
typename std::conditional<ModeT, FileWriter, FileReaderT>::type m_file;
typename conditional<ModeT, FileWriter, FileReaderT>::type m_file;
public:
RawFilePointStorage(string const & name) : BasePointStorage(name, 1000), m_file(name) {}
RawFilePointStorage(string const & name) : BasePointStorage(name), m_file(name) {}
template <bool T = (ModeT == BasePointStorage::MODE_WRITE)>
typename std::enable_if<T, void>::type AddPoint(uint64_t id, double lat, double lng)
typename enable_if<T, void>::type AddPoint(uint64_t id, double lat, double lng)
{
LatLon ll;
ll.lat = lat;
@ -221,16 +89,10 @@ public:
}
template <bool T = (ModeT == BasePointStorage::MODE_READ)>
typename std::enable_if<T, bool>::type GetPoint(uint64_t id, double & lat, double & lng) const
typename enable_if<T, bool>::type GetPoint(uint64_t id, double & lat, double & lng) const
{
// I think, it's not good idea to write this ugly code.
// memcpy isn't to slow for that.
//#ifdef OMIM_OS_WINDOWS
LatLon ll;
m_file.Read(id * sizeof(ll), &ll, sizeof(ll));
//#else
// LatLon const & ll = *reinterpret_cast<LatLon const *>(m_file.Data() + id * sizeof(ll));
//#endif
// assume that valid coordinate is not (0, 0)
if (ll.lat != 0.0 || ll.lon != 0.0)
@ -251,25 +113,24 @@ public:
template < BasePointStorage::EStorageMode ModeT >
class RawFileShortPointStorage : public BasePointStorage
{
#ifdef OMIM_OS_WINDOWS
typedef FileReader FileReaderT;
#else
typedef MmapReader FileReaderT;
#endif
typename std::conditional<ModeT, FileWriter, FileReaderT>::type m_file;
typename conditional<ModeT, FileWriter, FileReaderT>::type m_file;
double const m_precision = 10000000;
constexpr static double const kValueOrder = 1E+7;
public:
RawFileShortPointStorage(string const & name) : BasePointStorage(name, 1000), m_file(name) {}
RawFileShortPointStorage(string const & name) : BasePointStorage(name), m_file(name) {}
template <bool T = (ModeT == BasePointStorage::MODE_WRITE)>
typename std::enable_if<T, void>::type AddPoint(uint64_t id, double lat, double lng)
typename enable_if<T, void>::type AddPoint(uint64_t id, double lat, double lng)
{
int64_t const lat64 = lat * m_precision;
int64_t const lng64 = lng * m_precision;
int64_t const lat64 = lat * kValueOrder;
int64_t const lng64 = lng * kValueOrder;
ShortLatLon ll;
ll.lat = static_cast<int32_t>(lat64);
@ -284,22 +145,16 @@ public:
}
template <bool T = (ModeT == BasePointStorage::MODE_READ)>
typename std::enable_if<T, bool>::type GetPoint(uint64_t id, double & lat, double & lng) const
typename enable_if<T, bool>::type GetPoint(uint64_t id, double & lat, double & lng) const
{
// I think, it's not good idea to write this ugly code.
// memcpy isn't to slow for that.
//#ifdef OMIM_OS_WINDOWS
ShortLatLon ll;
m_file.Read(id * sizeof(ll), &ll, sizeof(ll));
//#else
// LatLon const & ll = *reinterpret_cast<LatLon const *>(m_file.Data() + id * sizeof(ll));
//#endif
// assume that valid coordinate is not (0, 0)
if (ll.lat != 0.0 || ll.lon != 0.0)
{
lat = static_cast<double>(ll.lat) / m_precision;
lng = static_cast<double>(ll.lon) / m_precision;
lat = static_cast<double>(ll.lat) / kValueOrder;
lng = static_cast<double>(ll.lon) / kValueOrder;
return true;
}
else
@ -314,15 +169,17 @@ public:
template < BasePointStorage::EStorageMode ModeT >
class RawMemShortPointStorage : public BasePointStorage
{
typename std::conditional<ModeT, FileWriter, FileReader>::type m_file;
typename conditional<ModeT, FileWriter, FileReader>::type m_file;
double const m_precision = 10000000;
constexpr static double const kValueOrder = 1E+7;
vector<ShortLatLon> m_data;
typedef ShortLatLon LonLatT;
vector<LonLatT> m_data;
public:
RawMemShortPointStorage(string const & name)
: BasePointStorage(name, 1000)
: BasePointStorage(name)
, m_file(name)
, m_data((size_t)0xFFFFFFFF)
{
@ -338,21 +195,21 @@ public:
void InitStorage(EnableIf<MODE_READ>)
{
m_file.Read(0, m_data.data(), m_data.size());
m_file.Read(0, m_data.data(), m_data.size() * sizeof(LonLatT));
}
void DoneStorage(EnableIf<MODE_WRITE>)
{
m_file.Write(m_data.data(), m_data.size());
m_file.Write(m_data.data(), m_data.size() * sizeof(LonLatT));
}
void DoneStorage(EnableIf<MODE_READ>) {}
template <bool T = (ModeT == BasePointStorage::MODE_WRITE)>
typename std::enable_if<T, void>::type AddPoint(uint64_t id, double lat, double lng)
typename enable_if<T, void>::type AddPoint(uint64_t id, double lat, double lng)
{
int64_t const lat64 = lat * m_precision;
int64_t const lng64 = lng * m_precision;
int64_t const lat64 = lat * kValueOrder;
int64_t const lng64 = lng * kValueOrder;
ShortLatLon & ll = m_data[id];
ll.lat = static_cast<int32_t>(lat64);
@ -364,14 +221,14 @@ public:
}
template <bool T = (ModeT == BasePointStorage::MODE_READ)>
typename std::enable_if<T, bool>::type GetPoint(uint64_t id, double & lat, double & lng) const
typename enable_if<T, bool>::type GetPoint(uint64_t id, double & lat, double & lng) const
{
ShortLatLon const & ll = m_data[id];
// assume that valid coordinate is not (0, 0)
if (ll.lat != 0.0 || ll.lon != 0.0)
{
lat = static_cast<double>(ll.lat) / m_precision;
lng = static_cast<double>(ll.lon) / m_precision;
lat = static_cast<double>(ll.lat) / kValueOrder;
lng = static_cast<double>(ll.lon) / kValueOrder;
return true;
}
else
@ -382,13 +239,10 @@ public:
}
};
template < BasePointStorage::EStorageMode ModeT >
class MapFilePointStorage : public BasePointStorage
{
typename std::conditional<ModeT, FileWriter, FileReader>::type m_file;
typename conditional<ModeT, FileWriter, FileReader>::type m_file;
typedef unordered_map<uint64_t, pair<double, double> > ContainerT;
ContainerT m_map;
@ -412,7 +266,7 @@ public:
LatLonPos ll;
m_file.Read(pos, &ll, sizeof(ll));
(void)m_map.insert(make_pair(ll.pos, make_pair(ll.lat, ll.lon)));
m_map.emplace(make_pair(ll.pos, make_pair(ll.lat, ll.lon)));
pos += sizeof(ll);
}
@ -434,27 +288,22 @@ public:
bool GetPoint(uint64_t id, double & lat, double & lng) const
{
auto i = m_map.find(id);
if (i != m_map.end())
{
lat = i->second.first;
lng = i->second.second;
return true;
}
return false;
if (i == m_map.end())
return false;
lat = i->second.first;
lng = i->second.second;
return true;
}
};
template < BasePointStorage::EStorageMode ModeT >
class MapFileShortPointStorage : public BasePointStorage
{
typename std::conditional<ModeT, FileWriter, FileReader>::type m_file;
typename conditional<ModeT, FileWriter, FileReader>::type m_file;
typedef unordered_map<uint64_t, pair<int32_t, int32_t> > ContainerT;
ContainerT m_map;
double const m_precision = 10000000;
constexpr static double const kValueOrder = 1E+7;
public:
MapFileShortPointStorage(string const & name) : BasePointStorage(name, 10000), m_file(name+".short")
@ -476,7 +325,7 @@ public:
ShortLatLonPos ll;
m_file.Read(pos, &ll, sizeof(ll));
(void)m_map.insert(make_pair(ll.pos, make_pair(ll.lat, ll.lon)));
m_map.emplace(make_pair(ll.pos, make_pair(ll.lat, ll.lon)));
pos += sizeof(ll);
}
@ -487,10 +336,8 @@ public:
void AddPoint(uint64_t id, double lat, double lng)
{
int64_t const lat64 = lat * m_precision;
int64_t const lng64 = lng * m_precision;
int64_t const lat64 = lat * kValueOrder;
int64_t const lng64 = lng * kValueOrder;
ShortLatLonPos ll;
ll.pos = id;
@ -506,13 +353,11 @@ public:
bool GetPoint(uint64_t id, double & lat, double & lng) const
{
auto i = m_map.find(id);
if (i != m_map.end())
{
lat = static_cast<double>(i->second.first) / m_precision;
lng = static_cast<double>(i->second.second) / m_precision;
return true;
}
return false;
if (i == m_map.end())
return false;
lat = static_cast<double>(i->second.first) / kValueOrder;
lng = static_cast<double>(i->second.second) / kValueOrder;
return true;
}
};

View file

@ -18,6 +18,29 @@ void XMLElement::AddKV(string const & k, string const & v)
e.parent = this;
}
void XMLElement::AddND(uint64_t ref)
{
childs.push_back(XMLElement());
XMLElement & e = childs.back();
e.tagKey = ET_ND;
e.ref = ref;
e.parent = this;
}
void XMLElement::AddMEMBER(uint64_t ref, string const & type, string const & role)
{
childs.push_back(XMLElement());
XMLElement & e = childs.back();
e.tagKey = ET_MEMBER;
e.ref = ref;
e.type = type;
e.role = role;
e.parent = this;
}
void BaseOSMParser::AddAttr(string const & key, string const & value)
{
if (m_current)
@ -101,46 +124,3 @@ void BaseOSMParser::Pop(string const &)
(*m_current) = XMLElement();
}
}
namespace
{
struct StdinReader
{
uint64_t Read(char * buffer, uint64_t bufferSize)
{
return fread(buffer, sizeof(char), bufferSize, stdin);
}
};
struct FileReader
{
FILE * m_file;
FileReader(string const & filename)
{
m_file = fopen(filename.c_str(), "rb");
}
~FileReader()
{
fclose(m_file);
}
uint64_t Read(char * buffer, uint64_t bufferSize)
{
return fread(buffer, sizeof(char), bufferSize, m_file);
}
};
}
void ParseXMLFromStdIn(BaseOSMParser & parser)
{
StdinReader reader;
(void)ParseXMLSequence(reader, parser);
}
void ParseXMLFromFile(BaseOSMParser & parser, string const & osmFileName)
{
FileReader reader(osmFileName);
(void)ParseXMLSequence(reader, parser);
}

View file

@ -34,6 +34,9 @@ struct XMLElement
vector<XMLElement> childs;
void AddKV(string const & k, string const & v);
void AddND(uint64_t ref);
void AddMEMBER(uint64_t ref, string const & type, string const & role);
};
class BaseOSMParser
@ -53,10 +56,8 @@ public:
void Pop(string const &);
void CharData(string const &) {}
virtual void EmitElement(XMLElement * p) = 0;
protected:
bool MatchTag(string const & tagName, XMLElement::ETag & tagKey);
virtual void EmitElement(XMLElement * p) = 0;
};
void ParseXMLFromStdIn(BaseOSMParser & parser);
void ParseXMLFromFile(BaseOSMParser & parser, string const & osmFileName);

View file

@ -14,18 +14,18 @@
#endif
#endif
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <type_traits>
using boost::enable_if;
using std::enable_if;
using std::conditional;
using boost::is_same;
using boost::make_signed;
using boost::make_unsigned;
using boost::is_signed;
using boost::is_unsigned;
using boost::is_floating_point;
using boost::is_integral;
using std::is_same;
using std::make_signed;
using std::make_unsigned;
using std::is_signed;
using std::is_unsigned;
using std::is_floating_point;
using std::is_integral;
#ifdef DEBUG_NEW
#define new DEBUG_NEW

View file

@ -108,11 +108,11 @@ function merge_coasts() {
log "TIMEMARK" "Filter coastlines done"
# Preprocess coastlines to separate intermediate directory
log "TIMEMARK" "Generate coastlines intermediate"
$CONVERT_TOOL $COASTS_FILE | $GENERATOR_TOOL -intermediate_data_path=$INTCOASTSDIR -node_storage=map -preprocess_xml
$GENERATOR_TOOL -intermediate_data_path=$INTCOASTSDIR -node_storage=map -preprocess --osm_file_type=o5m --osm_file_name=$COASTS_FILE
log "TIMEMARK" "Generate coastlines intermediate done"
# Generate temporary coastlines file in the coasts intermediate dir
log "TIMEMARK" "Generate coastlines"
$CONVERT_TOOL $COASTS_FILE | $GENERATOR_TOOL -intermediate_data_path=$INTCOASTSDIR -node_storage=map -make_coasts -fail_on_coasts=$FAIL_ON_COASTS
$GENERATOR_TOOL -intermediate_data_path=$INTCOASTSDIR -node_storage=map -make_coasts -fail_on_coasts=$FAIL_ON_COASTS --osm_file_type=o5m --osm_file_name=$COASTS_FILE
log "TIMEMARK" "Generate coastlines done"
}
@ -163,20 +163,20 @@ fi
# make a working copy of generated coastlines file
cp $INTCOASTSDIR/WorldCoasts.mwm.tmp $INTDIR/WorldCoasts.mwm.tmp
NODE_STORAGE=raw
NODE_STORAGE=mem
if [[ $1 == "--generate" || $1 == "--full" ]]; then
log "TIMEMARK" "Generate intermediate data"
# 1st pass, run in parallel - preprocess whole planet to speed up generation if all coastlines are correct
$CONVERT_TOOL $PLANET_FILE | $GENERATOR_TOOL -intermediate_data_path=$INTDIR -node_storage=$NODE_STORAGE -preprocess_xml
$GENERATOR_TOOL -intermediate_data_path=$INTDIR -node_storage=$NODE_STORAGE -preprocess --osm_file_type=o5m --osm_file_name=$PLANET_FILE
log "TIMEMARK" "Generate intermediate data done"
fi
if [[ $1 == "--generate" || $1 == "--continue" || $1 == "--full" ]]; then
# 2nd pass - paralleled in the code
log "TIMEMARK" "Generate features"
$CONVERT_TOOL $PLANET_FILE | $GENERATOR_TOOL -intermediate_data_path=$INTDIR \
-node_storage=$NODE_STORAGE -split_by_polygons \
$GENERATOR_TOOL -intermediate_data_path=$INTDIR \
--osm_file_type=o5m --osm_file_name=$PLANET_FILE -node_storage=$NODE_STORAGE -split_by_polygons \
-generate_features -generate_world \
-data_path=$DATA_PATH -emit_coasts
log "TIMEMARK" "Generate features done"

View file

@ -21,4 +21,8 @@ mkdir $OUT_DIR || true
$GENERATOR_TOOL -export_poly_path $POLY_FILES_PATH
ls $POLY_FILES_PATH | parallel -t -v "$OSMCONVERT_TOOL $PLANET_FILE --hash-memory=2000 -B=$POLY_FILES_PATH/{} --complex-ways --out-pbf -o=$OUT_DIR/{.}.pbf"
EXT=.poly
NUM_INSTANCES=8
COUNTRY_LIST=${COUNTRY_LIST-$(ls -1 $POLY_FILES_PATH/*$EXT | xargs -d "\n" basename -s $EXT)}
echo "$COUNTRY_LIST" | xargs -d "\n" -P $NUM_INSTANCES -I % $OSMCONVERT_TOOL $PLANET_FILE --hash-memory=2000 -B=$POLY_FILES_PATH/%.poly --complex-ways --out-pbf -o=$OUT_DIR/%.pbf &>~/split_planet_osmconvert.log