osmpbfreader.h

osmpbfreder. h 라 이브 러 리 를 수정 하여 metanfo 를 추가 하 였 습 니 다.
osmpbfreader. h 헤더 파일:
/*
Copyright (c) 2012, Canal TP
All rights reserved.
*/
#pragma once
#include 
#include 
#include 
#include  // pbf blobs     zlib  
#include  //               
#include  //    network-byte-order     

#include 
#include 
#include 

//     blob      
#include 
//     OSM      
#include 
//  byte      blob header   
const int max_blob_header_size = 64 * 1024; // 64 kB
//  byte          blob   
const int max_uncompressed_blob_size = 32 * 1024 * 1024; // 32 MB
//   double int        /     
const int lonlat_resolution = 1000 * 1000 * 1000; 

namespace CanalTP {
//      ,msg   ,warn  ,fatal  (    err)
//   :         std::cout   msg()   
//  : msg()<msg & operator<debug & operator<warn & operator<fatal & operator< Tags;
//        tags   
template
Tags get_tags(T object, const OSMPBF::PrimitiveBlock &primblock){
    Tags result;
    for(int i = 0; i < object.keys_size(); ++i){
        uint64_t key = object.keys(i);
        uint64_t val = object.vals(i);
        std::string key_string = primblock.stringtable().s(key);
        std::string val_string = primblock.stringtable().s(val);
        result[key_string] = val_string;
    }
    return result;
}
// Info     (node/way/relation)  info 
struct Info {
    int32_t version = 0;
    int64_t timestamp = 0;
    int64_t changeset = 0;
    int32_t uid = 0;
//  uint32_t user_sid;
    std::string user_name; //  user_sid stringtable  
    bool visible = true;

};

//        info   (   densenode)
Info get_Info(OSMPBF::Info INFO, const OSMPBF::PrimitiveBlock &primblock) {
    Info info;
    info.version = INFO.version();
    info.timestamp = INFO.timestamp();
    info.changeset = INFO.changeset();
    info.uid = INFO.uid();
    info.user_name = primblock.stringtable().s(INFO.user_sid());
//  info.user_sid = INFO.user_sid();
    info.visible = INFO.visible();
    return info;
}

// Relation        
struct Reference {
    OSMPBF::Relation::MemberType member_type; //        
    uint64_t member_id; //       ID
    std::string role; //       role

    Reference() {}
    Reference(OSMPBF::Relation::MemberType member_type, uint64_t member_id, std::string role) :
        member_type(member_type), member_id(member_id), role(role)
    {}
};
//    relation        ,     
typedef std::vector References;

// Main function
template
void read_osm_pbf(const std::string & filename, Visitor & visitor);

template
struct Parser {
private:
    Visitor & visitor;
    std::ifstream file;
    char* buffer;
    char* unpack_buffer;
    bool finished;
public:
    //     
    Parser(const std::string & filename, Visitor & visitor)
        : visitor(visitor), file(filename.c_str(), std::ios::binary ), finished(false)
    {   //     、     
        if(!file.is_open())
            fatal() << "Unable to open the file " << filename;
        buffer = new char[max_uncompressed_blob_size];
        unpack_buffer = new char[max_uncompressed_blob_size];
        msg() << "Reading the file" << filename;
    }
    //     
    ~Parser(){  //        
        delete[] buffer;
        delete[] unpack_buffer;
        google::protobuf::ShutdownProtobufLibrary();
    }
    //      
    void parse(){
        while(!this->file.eof() && !finished) {
            OSMPBF::BlobHeader header = this->read_header();
            if(!this->finished){
                int32_t sz = this->read_blob(header);
                if(header.type() == "OSMData") {
                    this->parse_primitiveblock(sz);
                }
                else if(header.type() == "OSMHeader"){
                    // -----   ,  OSMHeader     -----
                }
                else {
                    warn() << "  unknown blob type: " << header.type();
                }
            }
        }
    }
    // 1.     (BlobHeader)
    OSMPBF::BlobHeader read_header(){
        int32_t sz;
        OSMPBF::BlobHeader result;

        // read the first 4 bytes of the file, this is the size of the blob-header
        if( !file.read((char*)&sz, 4) ){
            msg() << "We finished reading the file";
            this->finished = true;
            return result;
        }

        sz = ntohl(sz);// convert the size from network byte-order to host byte-order

        if(sz > max_blob_header_size)
            fatal() << "blob-header-size is bigger then allowed " << sz << " > " << max_blob_header_size;

        this->file.read(this->buffer, sz);
        if(!this->file.good())
            fatal() << "unable to read blob-header from file";

        // parse the blob-header from the read-buffer
        if(!result.ParseFromArray(this->buffer, sz))
            fatal() << "unable to parse blob header";
        return result;
    }
    // 2.   Blob (   OSMHeader   OSMData,       OSMData)
    int32_t read_blob(const OSMPBF::BlobHeader & header){
        OSMPBF::Blob blob;
        // size of the following blob
        int32_t sz = header.datasize();

        if(sz > max_uncompressed_blob_size)
            fatal() << "blob-size is bigger then allowed";

        if(!this->file.read(buffer, sz))
            fatal() << "unable to read blob from file";
        if(!blob.ParseFromArray(this->buffer, sz))
            fatal() << "unable to parse blob";

        // if the blob has uncompressed data
        if(blob.has_raw()) {
            // size of the blob-data
            sz = blob.raw().size();

            // check that raw_size is set correctly
            if(sz != blob.raw_size())
                warn() << "  reports wrong raw_size: " << blob.raw_size() << " bytes";

            memcpy(unpack_buffer, buffer, sz);
            return sz;
        }


        if(blob.has_zlib_data()) {
            sz = blob.zlib_data().size();

            z_stream z;
            z.next_in   = (unsigned char*) blob.zlib_data().c_str();
            z.avail_in  = sz;
            z.next_out  = (unsigned char*) unpack_buffer;
            z.avail_out = blob.raw_size();
            z.zalloc    = Z_NULL;
            z.zfree     = Z_NULL;
            z.opaque    = Z_NULL;

            if(inflateInit(&z) != Z_OK) {
                fatal() << "failed to init zlib stream";
            }
            if(inflate(&z, Z_FINISH) != Z_STREAM_END) {
                fatal() << "failed to inflate zlib stream";
            }
            if(inflateEnd(&z) != Z_OK) {
                fatal() << "failed to deinit zlib stream";
            }
            return z.total_out;
        }

        if(blob.has_lzma_data()) {
            fatal() << "lzma-decompression is not supported";
        }
        return 0;
    }

    void parse_primitiveblock(int32_t sz) {
        OSMPBF::PrimitiveBlock primblock;
        if(!primblock.ParseFromArray(this->unpack_buffer, sz))
            fatal() << "unable to parse primitive block";

        for(int i = 0, l = primblock.primitivegroup_size(); i < l; i++) {
            OSMPBF::PrimitiveGroup pg = primblock.primitivegroup(i);

            // Simple Nodes
            for(int i = 0; i < pg.nodes_size(); ++i) {
                OSMPBF::Node n = pg.nodes(i);

                double lon = 0.000000001 * (primblock.lon_offset() + (primblock.granularity() * n.lon())) ;
                double lat = 0.000000001 * (primblock.lat_offset() + (primblock.granularity() * n.lat())) ;

                visitor.node_callback(n.id(), lon, lat, get_tags(n, primblock),get_Info(n.info(),primblock));
            }

            // Dense Nodes
            if(pg.has_dense()) {
                OSMPBF::DenseNodes dn = pg.dense();
                uint64_t id = 0;
                double lon = 0;
                double lat = 0;

                int current_kv = 0;

                Info dninfo; // densenode info;
                uint32_t user_sid;

                for(int i = 0; i < dn.id_size(); ++i) {  //  id_size  densenode
                    id += dn.id(i); // id、 lon、 lat         
                    lon +=  0.000000001 * (primblock.lon_offset() + (primblock.granularity() * dn.lon(i)));
                    lat +=  0.000000001 * (primblock.lat_offset() + (primblock.granularity() * dn.lat(i)));

                    Tags tags; //            keys_vals    ( 0  ),
                               //    densenode keys_vals     ,    0    
                    while (current_kv < dn.keys_vals_size() && dn.keys_vals(current_kv) != 0){ // 0    ,            densenode
                        uint64_t key = dn.keys_vals(current_kv);
                        uint64_t val = dn.keys_vals(current_kv + 1);
                        std::string key_string = primblock.stringtable().s(key);
                        std::string val_string = primblock.stringtable().s(val);
                        current_kv += 2;
                        tags[key_string] = val_string;
                    }
                    ++current_kv; //    0  ,      densenode   keys_vals 
                    // DenseInfo    
                    dninfo.version = dn.denseinfo().version(i); // not delta coded
                    dninfo.timestamp += dn.denseinfo().timestamp(i);
                    dninfo.changeset +=dn.denseinfo().changeset(i);
                    dninfo.uid +=dn.denseinfo().uid(i);

                    user_sid += dn.denseinfo().user_sid(i);
                    dninfo.user_name = primblock.stringtable().s(user_sid);

                    // dninfo.visible = dn.denseinfo().visible(); // question remains ?????
                    // End DenseInfo    

                    visitor.node_callback(id, lon, lat, tags, dninfo);  //   
                }
            }
            // Ways
            for(int i = 0; i < pg.ways_size(); ++i) {
                OSMPBF::Way w = pg.ways(i);

                uint64_t ref = 0;
                std::vector refs;
                for(int j = 0; j < w.refs_size(); ++j){
                    ref += w.refs(j);
                    refs.push_back(ref);
                }
                uint64_t id = w.id();

                visitor.way_callback(id, get_tags(w, primblock), refs, get_Info(w.info(),primblock));
            }

            // Relations
            for(int i=0; i < pg.relations_size(); ++i){
                OSMPBF::Relation rel = pg.relations(i);
                uint64_t id = 0;
                References refs;

                for(int l = 0; l < rel.memids_size(); ++l){
                    id += rel.memids(l);
                    refs.push_back(Reference(rel.types(l), id, primblock.stringtable().s(rel.roles_sid(l))));
                }

                visitor.relation_callback(rel.id(), get_tags(rel, primblock), refs, get_Info(rel.info(),primblock));    
            }
        }
    }
};

template
void read_osm_pbf(const std::string & filename, Visitor & visitor){
    Parser p(filename, visitor);
    p.parse();
}

}

debug 형식 으로 인쇄 된 프로그램 ShowAll. cc:
/*
To build this file :
g++ -O2 -o counter example_counter.cc -losmpbf -lprotobuf

To run it:
./counter path_to_your_data.osm.pbf
*/

#include "osmpbfreader .h"
#include 
#include  //for iterator
#include 
using namespace CanalTP;

// We need to define a visitor with three methods that will be called while the file is read
struct Counter {
    // Three integers count how many times each object type occurs
    uint64_t n_ID;
    uint64_t w_ID;
    uint64_t r_ID; //objects' ID
    
    void printNode(uint64_t node_id, double lon, double lat, const Tags & tags);

    // Counter() : nodes(0), ways(0), relations(0) {}

    // This method is called every time a Node is read
    void node_callback(uint64_t node_id, double lon, double lat, const Tags & tags,const Info & Ninfo){
        std::cout<first <second < &refs, const Info & Winfo){
/*
        std::cout<first <second <first <second <

좋은 웹페이지 즐겨찾기