Пример #1
0
            /**
             * Add a node to the block using DenseNodes.
             *
             * @param node The node to add.
             */
            void write_dense_node(const shared_ptr<Osmium::OSM::Node const>& node) {
                // add a DenseNodes-Section to the PrimitiveGroup
                OSMPBF::DenseNodes* dense = pbf_nodes->mutable_dense();

                // copy the id, delta encoded
                dense->add_id(m_delta_id.update(node->id()));

                // copy the longitude, delta encoded
                dense->add_lon(m_delta_lon.update(lonlat2int(node->get_lon())));

                // copy the latitude, delta encoded
                dense->add_lat(m_delta_lat.update(lonlat2int(node->get_lat())));

                // in the densenodes structure keys and vals are encoded in an intermixed
                // array, individual nodes are seperated by a value of 0 (0 in the StringTable
                // is always unused)
                // so for three nodes the keys_vals array may look like this: 3 5 2 1 0 0 8 5
                // the first node has two tags (3=>5 and 2=>1), the second node has does not
                // have any tags and the third node has a single tag (8=>5)
                Osmium::OSM::TagList::const_iterator end = node->tags().end();
                for (Osmium::OSM::TagList::const_iterator it = node->tags().begin(); it != end; ++it) {
                    dense->add_keys_vals(string_table.record_string(it->key()));
                    dense->add_keys_vals(string_table.record_string(it->value()));
                }
                dense->add_keys_vals(0);

                if (should_add_metadata()) {
                    // add a DenseInfo-Section to the PrimitiveGroup
                    OSMPBF::DenseInfo* denseinfo = dense->mutable_denseinfo();

                    denseinfo->add_version(node->version());

                    if (m_add_visible) {
                        denseinfo->add_visible(node->visible());
                    }

                    // copy the timestamp, delta encoded
                    denseinfo->add_timestamp(m_delta_timestamp.update(timestamp2int(node->timestamp())));

                    // copy the changeset, delta encoded
                    denseinfo->add_changeset(m_delta_changeset.update(node->changeset()));

                    // copy the user id, delta encoded
                    denseinfo->add_uid(m_delta_uid.update(node->uid()));

                    // record the user-name to the interim stringtable and copy the
                    // interim string-id to the pbf-object
                    denseinfo->add_user_sid(string_table.record_string(node->user()));
                }
            }
Пример #2
0
void OsmPbfWriterPrivate::writeBlock(bool forceWrite)
{
    if ( (forceWrite && (nodesList.count() + waysList.count() + relationsList.count() > 0) ) ||
         (nodesList.count() + waysList.count() + relationsList.count() >= entitiesPerBlockLimit) ) {
        OSMPBF::PrimitiveBlock currentFileBlockParsed;
        int32_t granularityCoordinate = 100, granularityDate = 1000;
        int64_t offsetLat = 0, offsetLon = 0;

        //FIXME: keep order of addition
        //Extract all strings to hash for future reference
        //FIXME extract granularities and offset
        QHash<QString, int32_t> stringTableHash;
        for (QList<OsmStructures::Node>::const_iterator iNode = nodesList.constBegin(); iNode != nodesList.constEnd() ; ++iNode)
            addEntityStringsToTable(&stringTableHash, *iNode);
        for (QList<OsmStructures::Way>::const_iterator iWay = waysList.constBegin(); iWay != waysList.constEnd() ; ++iWay)
            addEntityStringsToTable(&stringTableHash, *iWay);
        for (QList<OsmStructures::Relation>::const_iterator iRelation = relationsList.constBegin(); iRelation != relationsList.constEnd() ; ++iRelation) {
            addEntityStringsToTable(&stringTableHash, *iRelation);
            for (QSet<OsmStructures::RelationMember>::const_iterator iRelationMember = iRelation->members.constBegin(); iRelationMember != iRelation->members.constEnd() ; ++iRelationMember) {
                addStringToTable(&stringTableHash, iRelationMember->role);
            }
        }

        //Create list of strings from hash (sorted by value)
        int32_t stringsCount = stringTableHash.count() + 1;
        QScopedArrayPointer<QString> stringTableList(new QString[stringsCount]);
        stringTableList[0] = QString("");

        for (QHash<QString, int32_t>::const_iterator iString = stringTableHash.constBegin() ; iString != stringTableHash.constEnd() ; ++iString) {
            stringTableList[iString.value()] = iString.key();
        }

        //Write list of string to block stringtable
        for (int iIndex = 0 ; iIndex < stringsCount ; iIndex++) {
            currentFileBlockParsed.mutable_stringtable()->add_s(stringTableList[iIndex].toUtf8().data(), stringTableList[iIndex].toUtf8().length());
        }
        stringTableList.reset();

        //Write granularities and offsets
        if (granularityCoordinate != 100)
            currentFileBlockParsed.set_granularity(granularityCoordinate);
        if (granularityDate != 1000)
            currentFileBlockParsed.set_date_granularity(granularityDate);
        if (offsetLat != 0)
            currentFileBlockParsed.set_lat_offset(offsetLat);
        if (offsetLon != 0)
            currentFileBlockParsed.set_lon_offset(offsetLon);

        //Write nodes
        if (nodesList.count() > 0) {
            OSMPBF::PrimitiveGroup* nodesGroup = currentFileBlockParsed.add_primitivegroup();
            int64_t denseId = 0, denseLat = 0, denseLon = 0;
            int64_t denseTimestamp = 0, denseChangeset = 0, denseUid = 0, denseUser = 0;
            for (QList<OsmStructures::Node>::const_iterator iNode = nodesList.constBegin(); iNode != nodesList.constEnd() ; ++iNode) {
                if ( ( (iNode->getLatNanoDegree() - offsetLat) % granularityCoordinate ) ||
                     (iNode->getLonNanoDegree() - offsetLon) % granularityCoordinate )
                    qFatal("Loosing precision");
                int64_t lat_int = (iNode->getLatNanoDegree() - offsetLat) / granularityCoordinate;
                int64_t lon_int = (iNode->getLonNanoDegree() - offsetLon) / granularityCoordinate;
                if (useDenseNodes) {
                    OSMPBF::DenseNodes* pbfDense = nodesGroup->mutable_dense();
                    pbfDense->add_id(iNode->id - denseId);
                    pbfDense->add_lat(lat_int - denseLat);
                    pbfDense->add_lon(lon_int - denseLon);
                    denseId = iNode->id;
                    denseLat = lat_int;
                    denseLon = lon_int;

                    pbfDense->mutable_denseinfo()->add_version(iNode->version);
                    if (iNode->timestamp.toMSecsSinceEpoch() % granularityDate)
                        qFatal("Loosing precision");
                    int64_t timestamp_value = iNode->timestamp.toMSecsSinceEpoch() / granularityDate;
                    int32_t user_sid = stringTableHash.value(iNode->user);
                    pbfDense->mutable_denseinfo()->add_timestamp(timestamp_value - denseTimestamp);
                    pbfDense->mutable_denseinfo()->add_changeset(iNode->changeset - denseChangeset);
                    pbfDense->mutable_denseinfo()->add_uid(iNode->uid - denseUid);
                    pbfDense->mutable_denseinfo()->add_user_sid(user_sid - denseUser);
                    denseTimestamp = timestamp_value;
                    denseChangeset = iNode->changeset;
                    denseUid = iNode->uid;
                    denseUser = user_sid;

                    for (QHash<QString, QString>::const_iterator iTagString = iNode->tags.constBegin() ; iTagString != iNode->tags.constEnd() ; ++iTagString) {
                        pbfDense->add_keys_vals(stringTableHash.value(iTagString.key()));
                        pbfDense->add_keys_vals(stringTableHash.value(iTagString.value()));
                    }
                    pbfDense->add_keys_vals(0);
                } else {
                    OSMPBF::Node* pbfNode = nodesGroup->add_nodes();
                    pbfNode->set_id(iNode->id);

                    pbfNode->set_lon(lat_int);
                    pbfNode->set_lat(lon_int);

                    packEntityInfo(pbfNode->mutable_info(), *iNode, granularityDate, stringTableHash);
                    for (QHash<QString, QString>::const_iterator iTagString = iNode->tags.constBegin() ; iTagString != iNode->tags.constEnd() ; ++iTagString) {
                        pbfNode->add_keys(stringTableHash.value(iTagString.key()));
                        pbfNode->add_vals(stringTableHash.value(iTagString.value()));
                    }
                }
            }
        }
        //write ways
        if (waysList.count() > 0) {
            OSMPBF::PrimitiveGroup* waysGroup = currentFileBlockParsed.add_primitivegroup();
            for (QList<OsmStructures::Way>::const_iterator iWay = waysList.constBegin(); iWay != waysList.constEnd() ; ++iWay) {
                OSMPBF::Way* pbfWay = waysGroup->add_ways();
                pbfWay->set_id(iWay->id);
                int64_t currentNodeId = 0;
                for (QList<int64_t>::const_iterator iNodeId = iWay->nodes.constBegin() ; iNodeId != iWay->nodes.constEnd() ; ++iNodeId) {
                    pbfWay->add_refs(*iNodeId - currentNodeId);
                    currentNodeId = *iNodeId;
                }

                packEntityInfo(pbfWay->mutable_info(), *iWay, granularityDate, stringTableHash);
                for (QHash<QString, QString>::const_iterator iTagString = iWay->tags.constBegin() ; iTagString != iWay->tags.constEnd() ; ++iTagString) {
                    pbfWay->add_keys(stringTableHash.value(iTagString.key()));
                    pbfWay->add_vals(stringTableHash.value(iTagString.value()));
                }
            }
        }
        //write relations
        if (relationsList.count() > 0) {
            OSMPBF::PrimitiveGroup* relationsGroup = currentFileBlockParsed.add_primitivegroup();
            for (QList<OsmStructures::Relation>::const_iterator iRelation = relationsList.constBegin(); iRelation != relationsList.constEnd() ; ++iRelation) {
                OSMPBF::Relation *pbfRelation = relationsGroup->add_relations();
                pbfRelation->set_id(iRelation->id);

                int64_t currentMemberId = 0;
                for (QSet<OsmStructures::RelationMember>::const_iterator iRelationMember = iRelation->members.constBegin(); iRelationMember != iRelation->members.constEnd() ; ++iRelationMember) {
                    pbfRelation->add_roles_sid(stringTableHash.value(iRelationMember->role));
                    pbfRelation->add_memids(iRelationMember->memberRef.id - currentMemberId);
                    currentMemberId = iRelationMember->memberRef.id;
                    OSMPBF::Relation_MemberType currentType;
                    switch (iRelationMember->memberRef.type) {
                    case OsmStructures::EnumOsmNode:     currentType = OSMPBF::Relation_MemberType_NODE;     break;
                    case OsmStructures::EnumOsmWay:      currentType = OSMPBF::Relation_MemberType_WAY;      break;
                    case OsmStructures::EnumOsmRelation: currentType = OSMPBF::Relation_MemberType_RELATION; break;
                    default:
                        throw std::exception();
                        break;
                    }
                    pbfRelation->add_types(currentType);
                }

                packEntityInfo(pbfRelation->mutable_info(), *iRelation, granularityDate, stringTableHash);
                for (QHash<QString, QString>::const_iterator iTagString = iRelation->tags.constBegin() ; iTagString != iRelation->tags.constEnd() ; ++iTagString) {
                    pbfRelation->add_keys(stringTableHash.value(iTagString.key()));
                    pbfRelation->add_vals(stringTableHash.value(iTagString.value()));
                }
            }
        }

        QByteArray currentFileBlockPacked = packPbfMessageToArray(currentFileBlockParsed);
        writeFileblock("OSMData", currentFileBlockPacked);

        nodesList.clear();
        waysList.clear();
        relationsList.clear();
    }
}