Merge pull request #1159 from Project-OSRM/feature/libosmium
parallelizing profile calls and porting lib osmium to Windows
This commit is contained in:
commit
9a0581ea7f
10
.travis.yml
10
.travis.yml
@ -7,15 +7,17 @@ install:
|
||||
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||
- sudo apt-get update >/dev/null
|
||||
- sudo apt-get -q install protobuf-compiler libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev
|
||||
- sudo apt-get -q install protobuf-compiler libprotoc-dev libprotobuf7 libprotobuf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev
|
||||
- sudo apt-get -q install g++-4.8
|
||||
- sudo apt-get install libboost1.54-all-dev
|
||||
#luabind
|
||||
# luabind
|
||||
- curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
|
||||
#osmosis
|
||||
# osmosis
|
||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
||||
#cmake
|
||||
# cmake
|
||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/5fad9bee5c7f09fd7fc9/raw/ | sudo bash
|
||||
# osmpbf library
|
||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/13b1b4fe38a57ead850e/raw/install_osmpbf.sh | sudo bash
|
||||
before_script:
|
||||
- rvm use 1.9.3
|
||||
- gem install bundler
|
||||
|
@ -99,7 +99,7 @@ class TarjanSCC
|
||||
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
|
||||
using RestrictionMap = std::unordered_map<RestrictionSource, unsigned>;
|
||||
|
||||
std::vector<NodeInfo> m_coordinate_list;
|
||||
std::vector<QueryNode> m_coordinate_list;
|
||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||
std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
|
||||
std::unordered_set<NodeID> barrier_node_list;
|
||||
@ -113,14 +113,14 @@ class TarjanSCC
|
||||
std::vector<NodeID> &bn,
|
||||
std::vector<NodeID> &tl,
|
||||
std::vector<TurnRestriction> &irs,
|
||||
std::vector<NodeInfo> &nI)
|
||||
std::vector<QueryNode> &nI)
|
||||
: m_coordinate_list(nI), m_restriction_counter(irs.size())
|
||||
{
|
||||
TIMER_START(SCC_LOAD);
|
||||
for (const TurnRestriction &restriction : irs)
|
||||
{
|
||||
std::pair<NodeID, NodeID> restriction_source = {restriction.fromNode,
|
||||
restriction.viaNode};
|
||||
std::pair<NodeID, NodeID> restriction_source = {restriction.from.node,
|
||||
restriction.via.node};
|
||||
unsigned index = 0;
|
||||
const auto restriction_iterator = m_restriction_map.find(restriction_source);
|
||||
if (restriction_iterator == m_restriction_map.end())
|
||||
@ -137,7 +137,7 @@ class TarjanSCC
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (restriction.flags.isOnly)
|
||||
else if (restriction.flags.is_only)
|
||||
{
|
||||
// We are going to insert an is_only_*-restriction. There can be only one.
|
||||
m_restriction_bucket_list.at(index).clear();
|
||||
@ -145,7 +145,7 @@ class TarjanSCC
|
||||
}
|
||||
|
||||
m_restriction_bucket_list.at(index)
|
||||
.emplace_back(restriction.toNode, restriction.flags.isOnly);
|
||||
.emplace_back(restriction.to.node, restriction.flags.is_only);
|
||||
}
|
||||
|
||||
barrier_node_list.insert(bn.begin(), bn.end());
|
||||
|
@ -24,13 +24,13 @@ FixedPointCoordinateListPtr LoadCoordinates(const boost::filesystem::path &nodes
|
||||
{
|
||||
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
|
||||
|
||||
NodeInfo current_node;
|
||||
QueryNode current_node;
|
||||
unsigned number_of_coordinates = 0;
|
||||
nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
|
||||
auto coords = std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates);
|
||||
for (unsigned i = 0; i < number_of_coordinates; ++i)
|
||||
{
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode));
|
||||
coords->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
|
||||
BOOST_ASSERT((std::abs(coords->at(i).lat) >> 30) == 0);
|
||||
BOOST_ASSERT((std::abs(coords->at(i).lon) >> 30) == 0);
|
||||
|
@ -31,6 +31,7 @@ OPTION(WITH_TOOLS "Build OSRM tools" OFF)
|
||||
OPTION(BUILD_TOOLS "Build OSRM tools" OFF)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Include/)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ThirdParty/)
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp FingerPrint.cpp.alwaysbuild
|
||||
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||
@ -51,7 +52,7 @@ configure_file(
|
||||
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
|
||||
)
|
||||
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||
file(GLOB ImporterGlob DataStructures/Import*.cpp)
|
||||
file(GLOB ImporterGlob DataStructures/ImportEdge.cpp DataStructures/ExternalMemoryNode.cpp)
|
||||
add_library(IMPORT OBJECT ${ImporterGlob})
|
||||
add_library(LOGGER OBJECT Util/simple_logger.cpp)
|
||||
add_library(PHANTOMNODE OBJECT DataStructures/phantom_node.cpp)
|
||||
@ -155,6 +156,9 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
|
||||
add_definitions(-D_USE_MATH_DEFINES) # define M_PI
|
||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||
add_definitions(-DXML_STATIC)
|
||||
find_library(ws2_32_LIBRARY_PATH ws2_32)
|
||||
target_link_libraries(osrm-extract wsock32 ws2_32)
|
||||
endif()
|
||||
|
||||
# Activate C++11
|
||||
@ -238,9 +242,9 @@ else()
|
||||
endif()
|
||||
include_directories(${LUA_INCLUDE_DIR})
|
||||
|
||||
find_package(LibXml2 REQUIRED)
|
||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
|
||||
find_package(EXPAT REQUIRED)
|
||||
include_directories(${EXPAT_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${EXPAT_LIBRARIES})
|
||||
|
||||
find_package( STXXL REQUIRED )
|
||||
include_directories(${STXXL_INCLUDE_DIR})
|
||||
|
@ -45,7 +45,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
std::unique_ptr<RestrictionMap> restriction_map,
|
||||
std::vector<NodeID> &barrier_node_list,
|
||||
std::vector<NodeID> &traffic_light_node_list,
|
||||
std::vector<NodeInfo> &node_info_list,
|
||||
std::vector<QueryNode> &node_info_list,
|
||||
SpeedProfileProperties &speed_profile)
|
||||
: speed_profile(speed_profile),
|
||||
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
|
||||
|
@ -63,7 +63,7 @@ class EdgeBasedGraphFactory
|
||||
std::unique_ptr<RestrictionMap> restricion_map,
|
||||
std::vector<NodeID> &barrier_node_list,
|
||||
std::vector<NodeID> &traffic_light_node_list,
|
||||
std::vector<NodeInfo> &m_node_info_list,
|
||||
std::vector<QueryNode> &node_info_list,
|
||||
SpeedProfileProperties &speed_profile);
|
||||
|
||||
void Run(const std::string &original_edge_data_filename,
|
||||
@ -97,7 +97,7 @@ class EdgeBasedGraphFactory
|
||||
|
||||
unsigned m_number_of_edge_based_nodes;
|
||||
|
||||
std::vector<NodeInfo> m_node_info_list;
|
||||
std::vector<QueryNode> m_node_info_list;
|
||||
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||
|
||||
|
@ -561,7 +561,7 @@ void Prepare::WriteNodeMapping()
|
||||
if (size_of_mapping > 0)
|
||||
{
|
||||
node_stream.write((char *)&(internal_to_external_node_map[0]),
|
||||
size_of_mapping * sizeof(NodeInfo));
|
||||
size_of_mapping * sizeof(QueryNode));
|
||||
}
|
||||
node_stream.close();
|
||||
internal_to_external_node_map.clear();
|
||||
|
@ -42,7 +42,7 @@ class Prepare
|
||||
void BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list);
|
||||
|
||||
private:
|
||||
std::vector<NodeInfo> internal_to_external_node_map;
|
||||
std::vector<QueryNode> internal_to_external_node_map;
|
||||
std::vector<TurnRestriction> restriction_list;
|
||||
std::vector<NodeID> barrier_node_list;
|
||||
std::vector<NodeID> traffic_light_list;
|
||||
|
@ -25,19 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "ImportNode.h"
|
||||
#include "ExternalMemoryNode.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
ExternalMemoryNode::ExternalMemoryNode(
|
||||
int lat, int lon, unsigned int node_id, bool bollard, bool traffic_light)
|
||||
: NodeInfo(lat, lon, node_id), bollard(bollard), trafficLight(traffic_light)
|
||||
int lat, int lon, unsigned int node_id, bool barrier, bool traffic_lights)
|
||||
: QueryNode(lat, lon, node_id), barrier(barrier), traffic_lights(traffic_lights)
|
||||
{
|
||||
}
|
||||
|
||||
ExternalMemoryNode::ExternalMemoryNode() : bollard(false), trafficLight(false)
|
||||
{
|
||||
}
|
||||
ExternalMemoryNode::ExternalMemoryNode() : barrier(false), traffic_lights(false) {}
|
||||
|
||||
ExternalMemoryNode ExternalMemoryNode::min_value()
|
||||
{
|
||||
@ -53,12 +51,18 @@ ExternalMemoryNode ExternalMemoryNode::max_value()
|
||||
false);
|
||||
}
|
||||
|
||||
void ImportNode::Clear()
|
||||
bool ExternalMemoryNodeSTXXLCompare::operator()(const ExternalMemoryNode &left,
|
||||
const ExternalMemoryNode &right) const
|
||||
{
|
||||
keyVals.Clear();
|
||||
lat = 0;
|
||||
lon = 0;
|
||||
node_id = 0;
|
||||
bollard = false;
|
||||
trafficLight = false;
|
||||
return left.node_id < right.node_id;
|
||||
}
|
||||
|
||||
ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::max_value()
|
||||
{
|
||||
return ExternalMemoryNode::max_value();
|
||||
}
|
||||
|
||||
ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::min_value()
|
||||
{
|
||||
return ExternalMemoryNode::min_value();
|
||||
}
|
@ -25,17 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef IMPORTNODE_H_
|
||||
#define IMPORTNODE_H_
|
||||
#ifndef EXTERNAL_MEMORY_NODE_H__
|
||||
#define EXTERNAL_MEMORY_NODE_H__
|
||||
|
||||
#include "QueryNode.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct ExternalMemoryNode : NodeInfo
|
||||
struct ExternalMemoryNode : QueryNode
|
||||
{
|
||||
ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light);
|
||||
ExternalMemoryNode(int lat, int lon, NodeID id, bool barrier, bool traffic_light);
|
||||
|
||||
ExternalMemoryNode();
|
||||
|
||||
@ -43,15 +42,16 @@ struct ExternalMemoryNode : NodeInfo
|
||||
|
||||
static ExternalMemoryNode max_value();
|
||||
|
||||
bool bollard;
|
||||
bool trafficLight;
|
||||
bool barrier;
|
||||
bool traffic_lights;
|
||||
};
|
||||
|
||||
struct ImportNode : public ExternalMemoryNode
|
||||
struct ExternalMemoryNodeSTXXLCompare
|
||||
{
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
|
||||
inline void Clear();
|
||||
using value_type = ExternalMemoryNode;
|
||||
bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const;
|
||||
value_type max_value();
|
||||
value_type min_value();
|
||||
};
|
||||
|
||||
#endif /* IMPORTNODE_H_ */
|
||||
#endif /* EXTERNAL_MEMORY_NODE_H__ */
|
@ -25,30 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef XMLPARSER_H_
|
||||
#define XMLPARSER_H_
|
||||
#ifndef NODE_ID_H__
|
||||
#define NODE_ID_H__
|
||||
|
||||
#include "BaseParser.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
class ExtractorCallbacks;
|
||||
|
||||
class XMLParser : public BaseParser
|
||||
struct Cmp
|
||||
{
|
||||
public:
|
||||
XMLParser(const char *filename,
|
||||
ExtractorCallbacks *extractor_callbacks,
|
||||
ScriptingEnvironment &scripting_environment);
|
||||
bool ReadHeader();
|
||||
bool Parse();
|
||||
|
||||
private:
|
||||
InputRestrictionContainer ReadXMLRestriction();
|
||||
ExtractionWay ReadXMLWay();
|
||||
ImportNode ReadXMLNode();
|
||||
xmlTextReaderPtr inputReader;
|
||||
using value_type = NodeID;
|
||||
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
|
||||
value_type max_value() { return 0xffffffff; }
|
||||
value_type min_value() { return 0x0; }
|
||||
};
|
||||
|
||||
#endif /* XMLPARSER_H_ */
|
||||
#endif // NODE_ID_H__
|
@ -36,13 +36,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct NodeInfo
|
||||
struct QueryNode
|
||||
{
|
||||
using key_type = NodeID; // type of NodeID
|
||||
using value_type = int; // type of lat,lons
|
||||
|
||||
explicit NodeInfo(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
|
||||
NodeInfo()
|
||||
explicit QueryNode(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
|
||||
QueryNode()
|
||||
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
|
||||
node_id(std::numeric_limits<unsigned>::max())
|
||||
{
|
||||
@ -52,18 +52,18 @@ struct NodeInfo
|
||||
int lon;
|
||||
NodeID node_id;
|
||||
|
||||
static NodeInfo min_value()
|
||||
static QueryNode min_value()
|
||||
{
|
||||
return NodeInfo(static_cast<int>(-90 * COORDINATE_PRECISION),
|
||||
static_cast<int>(-180 * COORDINATE_PRECISION),
|
||||
std::numeric_limits<NodeID>::min());
|
||||
return QueryNode(static_cast<int>(-90 * COORDINATE_PRECISION),
|
||||
static_cast<int>(-180 * COORDINATE_PRECISION),
|
||||
std::numeric_limits<NodeID>::min());
|
||||
}
|
||||
|
||||
static NodeInfo max_value()
|
||||
static QueryNode max_value()
|
||||
{
|
||||
return NodeInfo(static_cast<int>(90 * COORDINATE_PRECISION),
|
||||
static_cast<int>(180 * COORDINATE_PRECISION),
|
||||
std::numeric_limits<NodeID>::max());
|
||||
return QueryNode(static_cast<int>(90 * COORDINATE_PRECISION),
|
||||
static_cast<int>(180 * COORDINATE_PRECISION),
|
||||
std::numeric_limits<NodeID>::max());
|
||||
}
|
||||
|
||||
value_type operator[](const std::size_t n) const
|
||||
|
@ -34,19 +34,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
struct TurnRestriction
|
||||
{
|
||||
NodeID viaNode;
|
||||
NodeID fromNode;
|
||||
NodeID toNode;
|
||||
union WayOrNode
|
||||
{
|
||||
NodeID node;
|
||||
EdgeID way;
|
||||
};
|
||||
WayOrNode via;
|
||||
WayOrNode from;
|
||||
WayOrNode to;
|
||||
|
||||
struct Bits
|
||||
{ // mostly unused
|
||||
Bits()
|
||||
: isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false),
|
||||
: is_only(false), uses_via_way(false), unused2(false), unused3(false), unused4(false),
|
||||
unused5(false), unused6(false), unused7(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool isOnly : 1;
|
||||
bool unused1 : 1;
|
||||
bool is_only : 1;
|
||||
bool uses_via_way : 1;
|
||||
bool unused2 : 1;
|
||||
bool unused3 : 1;
|
||||
bool unused4 : 1;
|
||||
@ -55,57 +61,57 @@ struct TurnRestriction
|
||||
bool unused7 : 1;
|
||||
} flags;
|
||||
|
||||
explicit TurnRestriction(NodeID viaNode)
|
||||
: viaNode(viaNode), fromNode(std::numeric_limits<unsigned>::max()),
|
||||
toNode(std::numeric_limits<unsigned>::max())
|
||||
explicit TurnRestriction(NodeID node)
|
||||
{
|
||||
via.node = node;
|
||||
from.node = SPECIAL_NODEID;
|
||||
to.node = SPECIAL_NODEID;
|
||||
}
|
||||
|
||||
explicit TurnRestriction(const bool isOnly = false)
|
||||
: viaNode(std::numeric_limits<unsigned>::max()),
|
||||
fromNode(std::numeric_limits<unsigned>::max()),
|
||||
toNode(std::numeric_limits<unsigned>::max())
|
||||
explicit TurnRestriction(const bool is_only = false)
|
||||
{
|
||||
flags.isOnly = isOnly;
|
||||
via.node = SPECIAL_NODEID;
|
||||
from.node = SPECIAL_NODEID;
|
||||
to.node = SPECIAL_NODEID;
|
||||
flags.is_only = is_only;
|
||||
}
|
||||
};
|
||||
|
||||
struct InputRestrictionContainer
|
||||
{
|
||||
EdgeID fromWay;
|
||||
EdgeID toWay;
|
||||
unsigned viaNode;
|
||||
// EdgeID fromWay;
|
||||
// EdgeID toWay;
|
||||
// NodeID via_node;
|
||||
TurnRestriction restriction;
|
||||
|
||||
InputRestrictionContainer(EdgeID fromWay, EdgeID toWay, NodeID vn, unsigned vw)
|
||||
: fromWay(fromWay), toWay(toWay), viaNode(vw)
|
||||
InputRestrictionContainer(EdgeID fromWay, EdgeID toWay, EdgeID vw)
|
||||
{
|
||||
restriction.viaNode = vn;
|
||||
restriction.from.way = fromWay;
|
||||
restriction.to.way = toWay;
|
||||
restriction.via.way = vw;
|
||||
}
|
||||
explicit InputRestrictionContainer(bool isOnly = false)
|
||||
: fromWay(std::numeric_limits<unsigned>::max()),
|
||||
toWay(std::numeric_limits<unsigned>::max()), viaNode(std::numeric_limits<unsigned>::max())
|
||||
explicit InputRestrictionContainer(bool is_only = false)
|
||||
{
|
||||
restriction.flags.isOnly = isOnly;
|
||||
restriction.from.way = SPECIAL_EDGEID;
|
||||
restriction.to.way = SPECIAL_EDGEID;
|
||||
restriction.via.node = SPECIAL_NODEID;
|
||||
restriction.flags.is_only = is_only;
|
||||
}
|
||||
|
||||
static InputRestrictionContainer min_value() { return InputRestrictionContainer(0, 0, 0, 0); }
|
||||
static InputRestrictionContainer min_value() { return InputRestrictionContainer(0, 0, 0); }
|
||||
static InputRestrictionContainer max_value()
|
||||
{
|
||||
return InputRestrictionContainer(std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max());
|
||||
return InputRestrictionContainer(SPECIAL_EDGEID, SPECIAL_EDGEID, SPECIAL_EDGEID);
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpRestrictionContainerByFrom
|
||||
{
|
||||
using value_type = InputRestrictionContainer;
|
||||
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
||||
const
|
||||
typedef InputRestrictionContainer value_type;
|
||||
inline bool operator()(const InputRestrictionContainer &a,
|
||||
const InputRestrictionContainer &b) const
|
||||
{
|
||||
return a.fromWay < b.fromWay;
|
||||
return a.restriction.from.way < b.restriction.from.way;
|
||||
}
|
||||
inline value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
||||
inline value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
||||
@ -113,11 +119,11 @@ struct CmpRestrictionContainerByFrom
|
||||
|
||||
struct CmpRestrictionContainerByTo
|
||||
{
|
||||
using value_type = InputRestrictionContainer;
|
||||
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
||||
const
|
||||
typedef InputRestrictionContainer value_type;
|
||||
inline bool operator()(const InputRestrictionContainer &a,
|
||||
const InputRestrictionContainer &b) const
|
||||
{
|
||||
return a.toWay < b.toWay;
|
||||
return a.restriction.to.way < b.restriction.to.way;
|
||||
}
|
||||
value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
||||
value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
||||
|
@ -41,10 +41,10 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
|
||||
// a pair of starting edge and a list of all end nodes
|
||||
for (auto &restriction : restriction_list)
|
||||
{
|
||||
m_restriction_start_nodes.insert(restriction.fromNode);
|
||||
m_no_turn_via_node_set.insert(restriction.viaNode);
|
||||
m_restriction_start_nodes.insert(restriction.from.node);
|
||||
m_no_turn_via_node_set.insert(restriction.via.node);
|
||||
|
||||
RestrictionSource restriction_source = {restriction.fromNode, restriction.viaNode};
|
||||
RestrictionSource restriction_source = {restriction.from.node, restriction.via.node};
|
||||
|
||||
unsigned index;
|
||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||
@ -62,7 +62,7 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (restriction.flags.isOnly)
|
||||
else if (restriction.flags.is_only)
|
||||
{
|
||||
// We are going to insert an is_only_*-restriction. There can be only one.
|
||||
m_count -= m_restriction_bucket_list.at(index).size();
|
||||
@ -71,7 +71,7 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
|
||||
}
|
||||
++m_count;
|
||||
m_restriction_bucket_list.at(index)
|
||||
.emplace_back(restriction.toNode, restriction.flags.isOnly);
|
||||
.emplace_back(restriction.to.node, restriction.flags.is_only);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "SharedMemoryFactory.h"
|
||||
#include "SharedMemoryVectorWrapper.h"
|
||||
|
||||
#include "../ThirdParty/variant/variant.hpp"
|
||||
#include "../Util/floating_point.hpp"
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
@ -54,6 +53,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <variant/variant.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
@ -71,6 +72,190 @@ template <class EdgeDataT,
|
||||
class StaticRTree
|
||||
{
|
||||
public:
|
||||
struct RectangleInt2D
|
||||
{
|
||||
RectangleInt2D() : min_lon(INT_MAX), max_lon(INT_MIN), min_lat(INT_MAX), max_lat(INT_MIN) {}
|
||||
|
||||
int32_t min_lon, max_lon;
|
||||
int32_t min_lat, max_lat;
|
||||
|
||||
inline void InitializeMBRectangle(const std::array<EdgeDataT, LEAF_NODE_SIZE> &objects,
|
||||
const uint32_t element_count,
|
||||
const std::vector<QueryNode> &coordinate_list)
|
||||
{
|
||||
for (uint32_t i = 0; i < element_count; ++i)
|
||||
{
|
||||
min_lon = std::min(min_lon,
|
||||
std::min(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
max_lon = std::max(max_lon,
|
||||
std::max(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
|
||||
min_lat = std::min(min_lat,
|
||||
std::min(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
max_lat = std::max(max_lat,
|
||||
std::max(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
}
|
||||
BOOST_ASSERT(min_lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(min_lon != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(max_lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(max_lon != std::numeric_limits<int>::min());
|
||||
}
|
||||
|
||||
inline void MergeBoundingBoxes(const RectangleInt2D &other)
|
||||
{
|
||||
min_lon = std::min(min_lon, other.min_lon);
|
||||
max_lon = std::max(max_lon, other.max_lon);
|
||||
min_lat = std::min(min_lat, other.min_lat);
|
||||
max_lat = std::max(max_lat, other.max_lat);
|
||||
BOOST_ASSERT(min_lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(min_lon != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(max_lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(max_lon != std::numeric_limits<int>::min());
|
||||
}
|
||||
|
||||
inline FixedPointCoordinate Centroid() const
|
||||
{
|
||||
FixedPointCoordinate centroid;
|
||||
// The coordinates of the midpoints are given by:
|
||||
// x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||
centroid.lon = (min_lon + max_lon) / 2;
|
||||
centroid.lat = (min_lat + max_lat) / 2;
|
||||
return centroid;
|
||||
}
|
||||
|
||||
inline bool Intersects(const RectangleInt2D &other) const
|
||||
{
|
||||
FixedPointCoordinate upper_left(other.max_lat, other.min_lon);
|
||||
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
|
||||
FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
|
||||
FixedPointCoordinate lower_left(other.min_lat, other.min_lon);
|
||||
|
||||
return (Contains(upper_left) || Contains(upper_right) || Contains(lower_right) ||
|
||||
Contains(lower_left));
|
||||
}
|
||||
|
||||
inline float GetMinDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
const bool is_contained = Contains(location);
|
||||
if (is_contained)
|
||||
{
|
||||
return 0.;
|
||||
}
|
||||
|
||||
enum Direction
|
||||
{
|
||||
INVALID = 0,
|
||||
NORTH = 1,
|
||||
SOUTH = 2,
|
||||
EAST = 4,
|
||||
NORTH_EAST = 5,
|
||||
SOUTH_EAST = 6,
|
||||
WEST = 8,
|
||||
NORTH_WEST = 9,
|
||||
SOUTH_WEST = 10
|
||||
};
|
||||
|
||||
Direction d = INVALID;
|
||||
if (location.lat > max_lat)
|
||||
d = (Direction) (d | NORTH);
|
||||
else if (location.lat < min_lat)
|
||||
d = (Direction) (d | SOUTH);
|
||||
if (location.lon > max_lon)
|
||||
d = (Direction) (d | EAST);
|
||||
else if (location.lon < min_lon)
|
||||
d = (Direction) (d | WEST);
|
||||
|
||||
BOOST_ASSERT(d != INVALID);
|
||||
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
switch (d)
|
||||
{
|
||||
case NORTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon));
|
||||
break;
|
||||
case SOUTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon));
|
||||
break;
|
||||
case WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon));
|
||||
break;
|
||||
case EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon));
|
||||
break;
|
||||
case NORTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon));
|
||||
break;
|
||||
case NORTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon));
|
||||
break;
|
||||
case SOUTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon));
|
||||
break;
|
||||
case SOUTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(min_dist != std::numeric_limits<float>::max());
|
||||
|
||||
return min_dist;
|
||||
}
|
||||
|
||||
inline float GetMinMaxDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
float min_max_dist = std::numeric_limits<float>::max();
|
||||
// Get minmax distance to each of the four sides
|
||||
const FixedPointCoordinate upper_left(max_lat, min_lon);
|
||||
const FixedPointCoordinate upper_right(max_lat, max_lon);
|
||||
const FixedPointCoordinate lower_right(min_lat, max_lon);
|
||||
const FixedPointCoordinate lower_left(min_lat, min_lon);
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left)));
|
||||
return min_max_dist;
|
||||
}
|
||||
|
||||
inline bool Contains(const FixedPointCoordinate &location) const
|
||||
{
|
||||
const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat);
|
||||
const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon);
|
||||
return lats_contained && lons_contained;
|
||||
}
|
||||
|
||||
inline friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect)
|
||||
{
|
||||
out << rect.min_lat / COORDINATE_PRECISION << "," << rect.min_lon / COORDINATE_PRECISION
|
||||
<< " " << rect.max_lat / COORDINATE_PRECISION << ","
|
||||
<< rect.max_lon / COORDINATE_PRECISION;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
using RectangleT = RectangleInt2D;
|
||||
|
||||
struct TreeNode
|
||||
@ -158,7 +343,7 @@ class StaticRTree
|
||||
explicit StaticRTree(std::vector<EdgeDataT> &input_data_vector,
|
||||
const std::string tree_node_filename,
|
||||
const std::string leaf_node_filename,
|
||||
const std::vector<NodeInfo> &coordinate_list)
|
||||
const std::vector<QueryNode> &coordinate_list)
|
||||
: m_element_count(input_data_vector.size()), m_leaf_node_filename(leaf_node_filename)
|
||||
{
|
||||
SimpleLogger().Write() << "constructing r-tree of " << m_element_count
|
||||
@ -1020,7 +1205,7 @@ class StaticRTree
|
||||
inline void InitializeMBRectangle(RectangleT& rectangle,
|
||||
const std::array<EdgeDataT, LEAF_NODE_SIZE> &objects,
|
||||
const uint32_t element_count,
|
||||
const std::vector<NodeInfo> &coordinate_list)
|
||||
const std::vector<QueryNode> &coordinate_list)
|
||||
{
|
||||
for (uint32_t i = 0; i < element_count; ++i)
|
||||
{
|
||||
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "BaseParser.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
|
||||
ScriptingEnvironment &scripting_environment)
|
||||
: extractor_callbacks(extractor_callbacks),
|
||||
lua_state(scripting_environment.getLuaState()),
|
||||
scripting_environment(scripting_environment), use_turn_restrictions(true)
|
||||
{
|
||||
ReadUseRestrictionsSetting();
|
||||
ReadRestrictionExceptions();
|
||||
}
|
||||
|
||||
void BaseParser::ReadUseRestrictionsSetting()
|
||||
{
|
||||
if (0 != luaL_dostring(lua_state, "return use_turn_restrictions\n"))
|
||||
{
|
||||
use_turn_restrictions = false;
|
||||
}
|
||||
else if (lua_isboolean(lua_state, -1))
|
||||
{
|
||||
use_turn_restrictions = lua_toboolean(lua_state, -1);
|
||||
}
|
||||
|
||||
if (use_turn_restrictions)
|
||||
{
|
||||
SimpleLogger().Write() << "Using turn restrictions";
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleLogger().Write() << "Ignoring turn restrictions";
|
||||
}
|
||||
}
|
||||
|
||||
void BaseParser::ReadRestrictionExceptions()
|
||||
{
|
||||
if (lua_function_exists(lua_state, "get_exceptions"))
|
||||
{
|
||||
// get list of turn restriction exceptions
|
||||
luabind::call_function<void>(
|
||||
lua_state, "get_exceptions", boost::ref(restriction_exceptions));
|
||||
const unsigned exception_count = restriction_exceptions.size();
|
||||
SimpleLogger().Write() << "Found " << exception_count
|
||||
<< " exceptions to turn restrictions:";
|
||||
for (const std::string &str : restriction_exceptions)
|
||||
{
|
||||
SimpleLogger().Write() << " " << str;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
|
||||
}
|
||||
}
|
||||
|
||||
void BaseParser::report_errors(lua_State *lua_state, const int status) const
|
||||
{
|
||||
if (0 != status)
|
||||
{
|
||||
std::cerr << "-- " << lua_tostring(lua_state, -1) << std::endl;
|
||||
lua_pop(lua_state, 1); // remove error message
|
||||
}
|
||||
}
|
||||
|
||||
void BaseParser::ParseNodeInLua(ImportNode &node, lua_State *local_lua_state)
|
||||
{
|
||||
luabind::call_function<void>(local_lua_state, "node_function", boost::ref(node));
|
||||
}
|
||||
|
||||
void BaseParser::ParseWayInLua(ExtractionWay &way, lua_State *local_lua_state)
|
||||
{
|
||||
luabind::call_function<void>(local_lua_state, "way_function", boost::ref(way));
|
||||
}
|
||||
|
||||
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), eg: except=bus;bicycle
|
||||
// b) the lua profile defines a hierachy of modes,
|
||||
// eg: [access, vehicle, bicycle]
|
||||
|
||||
if (except_tag_string.empty())
|
||||
{
|
||||
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("[;][ ]*"));
|
||||
for (std::string ¤t_string : exceptions)
|
||||
{
|
||||
const auto string_iterator =
|
||||
std::find(restriction_exceptions.begin(), restriction_exceptions.end(), current_string);
|
||||
if (restriction_exceptions.end() != string_iterator)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
@ -27,10 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionWay.h"
|
||||
|
||||
#include "../DataStructures/NodeID.h"
|
||||
#include "../DataStructures/RangeTable.h"
|
||||
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/TimingUtil.h"
|
||||
#include "../DataStructures/RangeTable.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
@ -82,19 +85,24 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
|
||||
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
||||
TIMER_START(sorting_nodes);
|
||||
stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
|
||||
stxxl::sort(all_nodes_list.begin(),
|
||||
all_nodes_list.end(),
|
||||
ExternalMemoryNodeSTXXLCompare(),
|
||||
stxxl_memory);
|
||||
TIMER_STOP(sorting_nodes);
|
||||
std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
|
||||
|
||||
|
||||
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
||||
TIMER_START(sort_ways);
|
||||
stxxl::sort(
|
||||
way_start_end_id_list.begin(), way_start_end_id_list.end(), CmpWayByID(), stxxl_memory);
|
||||
stxxl::sort(way_start_end_id_list.begin(),
|
||||
way_start_end_id_list.end(),
|
||||
FirstAndLastSegmentOfWayStxxlCompare(),
|
||||
stxxl_memory);
|
||||
TIMER_STOP(sort_ways);
|
||||
std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
|
||||
|
||||
std::cout << "[extractor] Sorting restrictions. by from... " << std::flush;
|
||||
std::cout << "[extractor] Sorting " << restrictions_list.size() << " restrictions. by from... " << std::flush;
|
||||
TIMER_START(sort_restrictions);
|
||||
stxxl::sort(restrictions_list.begin(),
|
||||
restrictions_list.end(),
|
||||
@ -111,39 +119,39 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||
restrictions_iterator != restrictions_list.end())
|
||||
{
|
||||
if (way_start_and_end_iterator->wayID < restrictions_iterator->fromWay)
|
||||
if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.from.way)
|
||||
{
|
||||
++way_start_and_end_iterator;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (way_start_and_end_iterator->wayID > restrictions_iterator->fromWay)
|
||||
if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.from.way)
|
||||
{
|
||||
++restrictions_iterator;
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
|
||||
const NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||
BOOST_ASSERT(way_start_and_end_iterator->way_id == restrictions_iterator->restriction.from.way);
|
||||
const NodeID via_node_id = restrictions_iterator->restriction.via.node;
|
||||
|
||||
if (way_start_and_end_iterator->firstStart == via_node_id)
|
||||
if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.fromNode =
|
||||
way_start_and_end_iterator->firstTarget;
|
||||
restrictions_iterator->restriction.from.node =
|
||||
way_start_and_end_iterator->first_segment_source_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->firstTarget == via_node_id)
|
||||
else if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.fromNode =
|
||||
way_start_and_end_iterator->firstStart;
|
||||
restrictions_iterator->restriction.from.node =
|
||||
way_start_and_end_iterator->first_segment_source_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->lastStart == via_node_id)
|
||||
else if (way_start_and_end_iterator->last_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.fromNode =
|
||||
way_start_and_end_iterator->lastTarget;
|
||||
restrictions_iterator->restriction.from.node =
|
||||
way_start_and_end_iterator->last_segment_target_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->lastTarget == via_node_id)
|
||||
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
|
||||
restrictions_iterator->restriction.from.node = way_start_and_end_iterator->last_segment_source_id;
|
||||
}
|
||||
++restrictions_iterator;
|
||||
}
|
||||
@ -168,36 +176,36 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||
restrictions_iterator != restrictions_list.end())
|
||||
{
|
||||
if (way_start_and_end_iterator->wayID < restrictions_iterator->toWay)
|
||||
if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way)
|
||||
{
|
||||
++way_start_and_end_iterator;
|
||||
continue;
|
||||
}
|
||||
if (way_start_and_end_iterator->wayID > restrictions_iterator->toWay)
|
||||
if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way)
|
||||
{
|
||||
++restrictions_iterator;
|
||||
continue;
|
||||
}
|
||||
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||
if (way_start_and_end_iterator->lastStart == via_node_id)
|
||||
NodeID via_node_id = restrictions_iterator->restriction.via.node;
|
||||
if (way_start_and_end_iterator->last_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
|
||||
restrictions_iterator->restriction.to.node = way_start_and_end_iterator->last_segment_target_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->lastTarget == via_node_id)
|
||||
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
|
||||
restrictions_iterator->restriction.to.node = way_start_and_end_iterator->last_segment_source_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->firstStart == via_node_id)
|
||||
else if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
|
||||
restrictions_iterator->restriction.to.node = way_start_and_end_iterator->first_segment_source_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->firstTarget == via_node_id)
|
||||
else if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
|
||||
restrictions_iterator->restriction.to.node = way_start_and_end_iterator->first_segment_source_id;
|
||||
}
|
||||
|
||||
if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.fromNode &&
|
||||
std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.toNode)
|
||||
if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.from.node &&
|
||||
std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.to.node)
|
||||
{
|
||||
++number_of_useable_restrictions;
|
||||
}
|
||||
@ -215,8 +223,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
|
||||
for(const auto & restriction_container : restrictions_list)
|
||||
{
|
||||
if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
|
||||
std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
|
||||
if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.from.node &&
|
||||
std::numeric_limits<unsigned>::max() != restriction_container.restriction.to.node)
|
||||
{
|
||||
restrictions_out_stream.write((char *)&(restriction_container.restriction),
|
||||
sizeof(TurnRestriction));
|
||||
|
@ -29,7 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define EXTRACTIONCONTAINERS_H_
|
||||
|
||||
#include "InternalExtractorEdge.h"
|
||||
#include "ExtractorStructs.h"
|
||||
#include "FirstAndLastSegmentOfWay.h"
|
||||
#include "../DataStructures/ExternalMemoryNode.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/FingerPrint.h"
|
||||
|
||||
@ -48,7 +49,7 @@ class ExtractionContainers
|
||||
using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
|
||||
using STXXLStringVector = stxxl::vector<std::string>;
|
||||
using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
|
||||
using STXXLWayIDStartEndVector = stxxl::vector<WayIDStartAndEndEdge>;
|
||||
using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;
|
||||
|
||||
STXXLNodeIDVector used_node_id_list;
|
||||
STXXLNodeVector all_nodes_list;
|
||||
|
@ -41,7 +41,7 @@ namespace qi = boost::spirit::qi;
|
||||
|
||||
// TODO: Move into LUA
|
||||
|
||||
inline bool durationIsValid(const std::string &s)
|
||||
bool durationIsValid(const std::string &s)
|
||||
{
|
||||
boost::regex e(
|
||||
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
|
||||
@ -53,7 +53,7 @@ inline bool durationIsValid(const std::string &s)
|
||||
return matched;
|
||||
}
|
||||
|
||||
inline unsigned parseDuration(const std::string &s)
|
||||
unsigned parseDuration(const std::string &s)
|
||||
{
|
||||
unsigned hours = 0;
|
||||
unsigned minutes = 0;
|
||||
|
@ -25,33 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MACHINE_INFO_H
|
||||
#define MACHINE_INFO_H
|
||||
#ifndef EXTRACTION_NODE_H
|
||||
#define EXTRACTION_NODE_H
|
||||
|
||||
enum Endianness
|
||||
{ LittleEndian = 1,
|
||||
BigEndian = 2 };
|
||||
|
||||
// Function is optimized to a single 'mov eax,1' on GCC, clang and icc using -O3
|
||||
Endianness GetMachineEndianness()
|
||||
struct ExtractionNode
|
||||
{
|
||||
int i(1);
|
||||
char *p = (char *)&i;
|
||||
if (1 == p[0])
|
||||
ExtractionNode() : traffic_lights(false), barrier(false) { }
|
||||
void clear()
|
||||
{
|
||||
return LittleEndian;
|
||||
traffic_lights = barrier = false;
|
||||
}
|
||||
return BigEndian;
|
||||
}
|
||||
|
||||
// Reverses Network Byte Order into something usable, compiles down to a bswap-mov combination
|
||||
unsigned SwapEndian(unsigned x)
|
||||
{
|
||||
if (GetMachineEndianness() == LittleEndian)
|
||||
{
|
||||
return ((x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24));
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
#endif // MACHINE_INFO_H
|
||||
bool traffic_lights;
|
||||
bool barrier;
|
||||
};
|
||||
#endif // EXTRACTION_NODE_H
|
@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTION_WAY_H
|
||||
#define EXTRACTION_WAY_H
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/TravelMode.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
@ -37,21 +36,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
struct ExtractionWay
|
||||
{
|
||||
ExtractionWay() { Clear(); }
|
||||
ExtractionWay() { clear(); }
|
||||
|
||||
inline void Clear()
|
||||
void clear()
|
||||
{
|
||||
id = SPECIAL_NODEID;
|
||||
nameID = INVALID_NAMEID;
|
||||
path.clear();
|
||||
keyVals.Clear();
|
||||
forward_speed = -1;
|
||||
backward_speed = -1;
|
||||
duration = -1;
|
||||
access = true;
|
||||
roundabout = false;
|
||||
isAccessRestricted = false;
|
||||
ignoreInGrid = false;
|
||||
is_access_restricted = false;
|
||||
ignore_in_grid = false;
|
||||
name.clear();
|
||||
forward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||
backward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||
}
|
||||
@ -61,11 +56,11 @@ struct ExtractionWay
|
||||
oneway,
|
||||
bidirectional,
|
||||
opposite };
|
||||
|
||||
|
||||
// These accessor methods exists to support the depreciated "way.direction" access
|
||||
// in LUA. Since the direction attribute was removed from ExtractionWay, the
|
||||
// in LUA. Since the direction attribute was removed from ExtractionWay, the
|
||||
// accessors translate to/from the mode attributes.
|
||||
inline void set_direction(const Directions m)
|
||||
void set_direction(const Directions m)
|
||||
{
|
||||
if (Directions::oneway == m)
|
||||
{
|
||||
@ -84,7 +79,7 @@ struct ExtractionWay
|
||||
}
|
||||
}
|
||||
|
||||
inline const Directions get_direction() const
|
||||
const Directions get_direction() const
|
||||
{
|
||||
if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode && TRAVEL_MODE_INACCESSIBLE != backward_travel_mode)
|
||||
{
|
||||
@ -106,23 +101,18 @@ struct ExtractionWay
|
||||
|
||||
// These accessors exists because it's not possible to take the address of a bitfield,
|
||||
// and LUA therefore cannot read/write the mode attributes directly.
|
||||
inline void set_forward_mode(const TravelMode m) { forward_travel_mode = m; }
|
||||
inline const TravelMode get_forward_mode() const { return forward_travel_mode; }
|
||||
inline void set_backward_mode(const TravelMode m) { backward_travel_mode = m; }
|
||||
inline const TravelMode get_backward_mode() const { return backward_travel_mode; }
|
||||
void set_forward_mode(const TravelMode m) { forward_travel_mode = m; }
|
||||
const TravelMode get_forward_mode() const { return forward_travel_mode; }
|
||||
void set_backward_mode(const TravelMode m) { backward_travel_mode = m; }
|
||||
const TravelMode get_backward_mode() const { return backward_travel_mode; }
|
||||
|
||||
unsigned id;
|
||||
unsigned nameID;
|
||||
double forward_speed;
|
||||
double backward_speed;
|
||||
double duration;
|
||||
std::string name;
|
||||
bool access;
|
||||
bool roundabout;
|
||||
bool isAccessRestricted;
|
||||
bool ignoreInGrid;
|
||||
std::vector<NodeID> path;
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
bool is_access_restricted;
|
||||
bool ignore_in_grid;
|
||||
TravelMode forward_travel_mode : 4;
|
||||
TravelMode backward_travel_mode : 4;
|
||||
};
|
||||
|
@ -27,253 +27,222 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "Extractor.h"
|
||||
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ExtractionContainers.h"
|
||||
#include "PBFParser.h"
|
||||
#include "ExtractionNode.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ExtractorOptions.h"
|
||||
#include "RestrictionParser.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
#include "XMLParser.h"
|
||||
|
||||
#include "../Util/GitDescription.h"
|
||||
#include "../Util/IniFileUtil.h"
|
||||
#include "../DataStructures/ConcurrentQueue.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/TimingUtil.h"
|
||||
#include "../Util/make_unique.hpp"
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <luabind/luabind.hpp>
|
||||
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
#include <variant/optional.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
Extractor::Extractor() : requested_num_threads(0), file_has_pbf_format(false)
|
||||
{
|
||||
}
|
||||
|
||||
Extractor::~Extractor() {}
|
||||
|
||||
bool Extractor::ParseArguments(int argc, char *argv[])
|
||||
{
|
||||
// declare a group of options that will be allowed only on command line
|
||||
boost::program_options::options_description generic_options("Options");
|
||||
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
|
||||
"config,c",
|
||||
boost::program_options::value<boost::filesystem::path>(&config_file_path)
|
||||
->default_value("extractor.ini"),
|
||||
"Path to a configuration file.");
|
||||
|
||||
// declare a group of options that will be allowed both on command line and in config file
|
||||
boost::program_options::options_description config_options("Configuration");
|
||||
config_options.add_options()("profile,p",
|
||||
boost::program_options::value<boost::filesystem::path>(
|
||||
&profile_path)->default_value("profile.lua"),
|
||||
"Path to LUA routing profile")(
|
||||
"threads,t",
|
||||
boost::program_options::value<unsigned int>(&requested_num_threads)
|
||||
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||
"Number of threads to use");
|
||||
|
||||
// hidden options, will be allowed both on command line and in config file, but will not be
|
||||
// shown to the user
|
||||
boost::program_options::options_description hidden_options("Hidden options");
|
||||
hidden_options.add_options()(
|
||||
"input,i",
|
||||
boost::program_options::value<boost::filesystem::path>(&input_path),
|
||||
"Input file in .osm, .osm.bz2 or .osm.pbf format");
|
||||
|
||||
// positional option
|
||||
boost::program_options::positional_options_description positional_options;
|
||||
positional_options.add("input", 1);
|
||||
|
||||
// combine above options for parsing
|
||||
boost::program_options::options_description cmdline_options;
|
||||
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description config_file_options;
|
||||
config_file_options.add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description visible_options(
|
||||
boost::filesystem::basename(argv[0]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
|
||||
visible_options.add(generic_options).add(config_options);
|
||||
|
||||
// parse command line options
|
||||
boost::program_options::variables_map option_variables;
|
||||
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
|
||||
.options(cmdline_options)
|
||||
.positional(positional_options)
|
||||
.run(),
|
||||
option_variables);
|
||||
|
||||
if (option_variables.count("version"))
|
||||
{
|
||||
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (option_variables.count("help"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::program_options::notify(option_variables);
|
||||
|
||||
// parse config file
|
||||
if (boost::filesystem::is_regular_file(config_file_path))
|
||||
{
|
||||
SimpleLogger().Write() << "Reading options from: " << config_file_path.string();
|
||||
std::string ini_file_contents = ReadIniFileAndLowerContents(config_file_path);
|
||||
std::stringstream config_stream(ini_file_contents);
|
||||
boost::program_options::store(parse_config_file(config_stream, config_file_options),
|
||||
option_variables);
|
||||
boost::program_options::notify(option_variables);
|
||||
}
|
||||
|
||||
if (!option_variables.count("input"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Extractor::GenerateOutputFilesNames()
|
||||
{
|
||||
output_file_name = input_path.string();
|
||||
restriction_file_name = input_path.string();
|
||||
std::string::size_type pos = output_file_name.find(".osm.bz2");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
pos = output_file_name.find(".osm.pbf");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
file_has_pbf_format = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = output_file_name.find(".osm.xml");
|
||||
}
|
||||
}
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
pos = output_file_name.find(".pbf");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
file_has_pbf_format = true;
|
||||
}
|
||||
}
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
pos = output_file_name.find(".osm");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
output_file_name.append(".osrm");
|
||||
restriction_file_name.append(".osrm.restrictions");
|
||||
}
|
||||
else
|
||||
{
|
||||
output_file_name.replace(pos, 5, ".osrm");
|
||||
restriction_file_name.replace(pos, 5, ".osrm.restrictions");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
output_file_name.replace(pos, 8, ".osrm");
|
||||
restriction_file_name.replace(pos, 8, ".osrm.restrictions");
|
||||
}
|
||||
}
|
||||
#include <vector>
|
||||
|
||||
int Extractor::Run(int argc, char *argv[])
|
||||
{
|
||||
ExtractorConfig extractor_config;
|
||||
|
||||
try
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
|
||||
TIMER_START(extracting);
|
||||
|
||||
if (!ParseArguments(argc, argv))
|
||||
if (!ExtractorOptions::ParseArguments(argc, argv, extractor_config))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ExtractorOptions::GenerateOutputFilesNames(extractor_config);
|
||||
|
||||
if (1 > requested_num_threads)
|
||||
if (1 > extractor_config.requested_num_threads)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(input_path))
|
||||
if (!boost::filesystem::is_regular_file(extractor_config.input_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Input file " << input_path.string()
|
||||
<< " not found!";
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "Input file " << extractor_config.input_path.string() << " not found!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(profile_path))
|
||||
if (!boost::filesystem::is_regular_file(extractor_config.profile_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string()
|
||||
SimpleLogger().Write(logWARNING) << "Profile " << extractor_config.profile_path.string()
|
||||
<< " not found!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
|
||||
const auto number_of_threads = std::min(recommended_num_threads, extractor_config.requested_num_threads);
|
||||
tbb::task_scheduler_init init(number_of_threads);
|
||||
|
||||
SimpleLogger().Write() << "Input file: " << input_path.filename().string();
|
||||
SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
|
||||
SimpleLogger().Write() << "Threads: " << requested_num_threads;
|
||||
if (recommended_num_threads != requested_num_threads)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
|
||||
<< recommended_num_threads
|
||||
<< "! This setting may have performance side-effects.";
|
||||
}
|
||||
SimpleLogger().Write() << "Input file: " << extractor_config.input_path.filename().string();
|
||||
SimpleLogger().Write() << "Profile: " << extractor_config.profile_path.filename().string();
|
||||
SimpleLogger().Write() << "Threads: " << number_of_threads;
|
||||
|
||||
tbb::task_scheduler_init init(requested_num_threads);
|
||||
|
||||
/*** Setup Scripting Environment ***/
|
||||
ScriptingEnvironment scripting_environment(profile_path.string().c_str());
|
||||
|
||||
GenerateOutputFilesNames();
|
||||
// setup scripting environment
|
||||
ScriptingEnvironment scripting_environment(extractor_config.profile_path.string().c_str());
|
||||
|
||||
std::unordered_map<std::string, NodeID> string_map;
|
||||
ExtractionContainers extraction_containers;
|
||||
|
||||
string_map[""] = 0;
|
||||
auto extractor_callbacks = new ExtractorCallbacks(extraction_containers, string_map);
|
||||
BaseParser *parser;
|
||||
if (file_has_pbf_format)
|
||||
{
|
||||
parser = new PBFParser(input_path.string().c_str(),
|
||||
extractor_callbacks,
|
||||
scripting_environment,
|
||||
requested_num_threads);
|
||||
}
|
||||
else
|
||||
{
|
||||
parser = new XMLParser(input_path.string().c_str(),
|
||||
extractor_callbacks,
|
||||
scripting_environment);
|
||||
}
|
||||
|
||||
if (!parser->ReadHeader())
|
||||
{
|
||||
throw OSRMException("Parser not initialized!");
|
||||
}
|
||||
ExtractionContainers extraction_containers;
|
||||
auto extractor_callbacks =
|
||||
osrm::make_unique<ExtractorCallbacks>(extraction_containers, string_map);
|
||||
|
||||
osmium::io::File input_file(extractor_config.input_path.string());
|
||||
osmium::io::Reader reader(input_file);
|
||||
osmium::io::Header header = reader.header();
|
||||
|
||||
unsigned number_of_nodes = 0;
|
||||
unsigned number_of_ways = 0;
|
||||
unsigned number_of_relations = 0;
|
||||
unsigned number_of_others = 0;
|
||||
|
||||
SimpleLogger().Write() << "Parsing in progress..";
|
||||
TIMER_START(parsing);
|
||||
|
||||
parser->Parse();
|
||||
delete parser;
|
||||
delete extractor_callbacks;
|
||||
std::string generator = header.get("generator");
|
||||
if (generator.empty())
|
||||
{
|
||||
generator = "unknown tool";
|
||||
}
|
||||
SimpleLogger().Write() << "input file generated by " << generator;
|
||||
|
||||
// write .timestamp data file
|
||||
std::string timestamp = header.get("osmosis_replication_timestamp");
|
||||
if (timestamp.empty())
|
||||
{
|
||||
timestamp = "n/a";
|
||||
}
|
||||
SimpleLogger().Write() << "timestamp: " << timestamp;
|
||||
|
||||
boost::filesystem::ofstream timestamp_out(extractor_config.timestamp_file_name);
|
||||
timestamp_out.write(timestamp.c_str(), timestamp.length());
|
||||
timestamp_out.close();
|
||||
|
||||
// initialize vectors holding parsed objects
|
||||
tbb::concurrent_vector<std::pair<std::size_t, ExtractionNode>> resulting_nodes;
|
||||
tbb::concurrent_vector<std::pair<std::size_t, ExtractionWay>> resulting_ways;
|
||||
tbb::concurrent_vector<mapbox::util::optional<InputRestrictionContainer>>
|
||||
resulting_restrictions;
|
||||
|
||||
// setup restriction parser
|
||||
RestrictionParser restriction_parser(scripting_environment.getLuaState());
|
||||
|
||||
while (osmium::memory::Buffer buffer = reader.read())
|
||||
{
|
||||
// create a vector of iterators into the buffer
|
||||
std::vector<osmium::memory::Buffer::iterator> osm_elements;
|
||||
osmium::memory::Buffer::iterator iter = std::begin(buffer);
|
||||
while (iter != std::end(buffer))
|
||||
{
|
||||
osm_elements.push_back(iter);
|
||||
iter = std::next(iter);
|
||||
}
|
||||
|
||||
// clear resulting vectors
|
||||
resulting_nodes.clear();
|
||||
resulting_ways.clear();
|
||||
resulting_restrictions.clear();
|
||||
|
||||
// parse OSM entities in parallel, store in resulting vectors
|
||||
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, osm_elements.size()),
|
||||
[&](const tbb::blocked_range<std::size_t> &range)
|
||||
{
|
||||
for (auto x = range.begin(); x != range.end(); ++x)
|
||||
{
|
||||
auto entity = osm_elements[x];
|
||||
|
||||
ExtractionNode result_node;
|
||||
ExtractionWay result_way;
|
||||
|
||||
switch (entity->type())
|
||||
{
|
||||
case osmium::item_type::node:
|
||||
++number_of_nodes;
|
||||
result_node.clear();
|
||||
luabind::call_function<void>(
|
||||
scripting_environment.getLuaState(),
|
||||
"node_function",
|
||||
boost::cref(static_cast<osmium::Node &>(*entity)),
|
||||
boost::ref(result_node));
|
||||
resulting_nodes.push_back(std::make_pair(x, result_node));
|
||||
break;
|
||||
case osmium::item_type::way:
|
||||
++number_of_ways;
|
||||
result_way.clear();
|
||||
luabind::call_function<void>(
|
||||
scripting_environment.getLuaState(),
|
||||
"way_function",
|
||||
boost::cref(static_cast<osmium::Way &>(*entity)),
|
||||
boost::ref(result_way));
|
||||
resulting_ways.push_back(std::make_pair(x, result_way));
|
||||
break;
|
||||
case osmium::item_type::relation:
|
||||
++number_of_relations;
|
||||
resulting_restrictions.push_back(
|
||||
restriction_parser.TryParse(scripting_environment.getLuaState(),
|
||||
static_cast<osmium::Relation &>(*entity)));
|
||||
break;
|
||||
default:
|
||||
++number_of_others;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// put parsed objects thru extractor callbacks
|
||||
for (const auto &result : resulting_nodes)
|
||||
{
|
||||
extractor_callbacks->ProcessNode(
|
||||
static_cast<osmium::Node &>(*(osm_elements[result.first])), result.second);
|
||||
}
|
||||
for (const auto &result : resulting_ways)
|
||||
{
|
||||
extractor_callbacks->ProcessWay(
|
||||
static_cast<osmium::Way &>(*(osm_elements[result.first])), result.second);
|
||||
}
|
||||
for (const auto &result : resulting_restrictions)
|
||||
{
|
||||
extractor_callbacks->ProcessRestriction(result);
|
||||
}
|
||||
}
|
||||
TIMER_STOP(parsing);
|
||||
SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds";
|
||||
SimpleLogger().Write() << "Raw input contains " << number_of_nodes << " nodes, "
|
||||
<< number_of_ways << " ways, and " << number_of_relations
|
||||
<< " relations, and " << number_of_others << " unknown entities";
|
||||
|
||||
extractor_callbacks.reset();
|
||||
|
||||
if (extraction_containers.all_edges_list.empty())
|
||||
{
|
||||
@ -281,17 +250,13 @@ int Extractor::Run(int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
extraction_containers.PrepareData(output_file_name, restriction_file_name);
|
||||
|
||||
extraction_containers.PrepareData(extractor_config.output_file_name,
|
||||
extractor_config.restriction_file_name);
|
||||
TIMER_STOP(extracting);
|
||||
SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting) << "s";
|
||||
SimpleLogger().Write() << "To prepare the data for routing, run: "
|
||||
<< "./osrm-prepare " << output_file_name << std::endl;
|
||||
}
|
||||
catch (boost::program_options::too_many_positional_options_error &)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
|
||||
return 1;
|
||||
<< "./osrm-prepare " << extractor_config.output_file_name
|
||||
<< std::endl;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
|
@ -1,36 +1,13 @@
|
||||
#ifndef EXTRACTOR_H_
|
||||
#define EXTRACTOR_H_
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
class ExtractorCallbacks;
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
/** \brief Class of 'extract' utility. */
|
||||
class Extractor
|
||||
struct Extractor
|
||||
{
|
||||
protected:
|
||||
unsigned requested_num_threads;
|
||||
boost::filesystem::path config_file_path;
|
||||
boost::filesystem::path input_path;
|
||||
boost::filesystem::path profile_path;
|
||||
|
||||
std::string output_file_name;
|
||||
std::string restriction_file_name;
|
||||
bool file_has_pbf_format;
|
||||
|
||||
/** \brief Parses "extractor's" command line arguments */
|
||||
bool ParseArguments(int argc, char *argv[]);
|
||||
|
||||
/** \brief Parses config file, if present in options */
|
||||
void GenerateOutputFilesNames();
|
||||
|
||||
public:
|
||||
explicit Extractor();
|
||||
Extractor(const Extractor &) = delete;
|
||||
virtual ~Extractor();
|
||||
|
||||
int Run(int argc, char *argv[]);
|
||||
};
|
||||
#endif /* EXTRACTOR_H_ */
|
||||
|
@ -27,10 +27,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionNode.h"
|
||||
#include "ExtractionWay.h"
|
||||
|
||||
#include "../DataStructures/ExternalMemoryNode.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../Util/container.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
@ -46,137 +48,176 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containe
|
||||
}
|
||||
|
||||
/** warning: caller needs to take care of synchronization! */
|
||||
void ExtractorCallbacks::ProcessNode(const ExternalMemoryNode &n)
|
||||
void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node,
|
||||
const ExtractionNode &result_node)
|
||||
{
|
||||
if (n.lat <= 85 * COORDINATE_PRECISION && n.lat >= -85 * COORDINATE_PRECISION)
|
||||
external_memory.all_nodes_list.push_back({
|
||||
static_cast<int>(input_node.location().lat() * COORDINATE_PRECISION),
|
||||
static_cast<int>(input_node.location().lon() * COORDINATE_PRECISION),
|
||||
static_cast<NodeID>(input_node.id()),
|
||||
result_node.barrier,
|
||||
result_node.traffic_lights
|
||||
});
|
||||
}
|
||||
|
||||
void ExtractorCallbacks::ProcessRestriction(
|
||||
const mapbox::util::optional<InputRestrictionContainer> &restriction)
|
||||
{
|
||||
if (restriction)
|
||||
{
|
||||
external_memory.all_nodes_list.push_back(n);
|
||||
external_memory.restrictions_list.push_back(restriction.get());
|
||||
// SimpleLogger().Write() << "from: " << restriction.get().restriction.from.node <<
|
||||
// ",via: " << restriction.get().restriction.via.node <<
|
||||
// ", to: " << restriction.get().restriction.to.node <<
|
||||
// ", only: " << (restriction.get().restriction.flags.is_only ? "y" : "n");
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &restriction)
|
||||
{
|
||||
external_memory.restrictions_list.push_back(restriction);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** warning: caller needs to take care of synchronization! */
|
||||
void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
||||
void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const ExtractionWay &parsed_way)
|
||||
{
|
||||
if (((0 >= parsed_way.forward_speed) ||
|
||||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) &&
|
||||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) &&
|
||||
((0 >= parsed_way.backward_speed) ||
|
||||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) &&
|
||||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) &&
|
||||
(0 >= parsed_way.duration))
|
||||
{ // Only true if the way is specified by the speed profile
|
||||
return;
|
||||
}
|
||||
|
||||
if (parsed_way.path.size() <= 1)
|
||||
if (input_way.nodes().size() <= 1)
|
||||
{ // safe-guard against broken data
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::numeric_limits<unsigned>::max() == parsed_way.id)
|
||||
if (std::numeric_limits<decltype(input_way.id())>::max() == input_way.id())
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
|
||||
<< " of size " << parsed_way.path.size();
|
||||
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << input_way.id()
|
||||
<< " of size " << input_way.nodes().size();
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 < parsed_way.duration)
|
||||
{
|
||||
// TODO: iterate all way segments and set duration corresponding to the length of each
|
||||
// segment
|
||||
parsed_way.forward_speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
||||
parsed_way.backward_speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
||||
const_cast<ExtractionWay&>(parsed_way).forward_speed = parsed_way.duration / (input_way.nodes().size() - 1);
|
||||
const_cast<ExtractionWay&>(parsed_way).backward_speed = parsed_way.duration / (input_way.nodes().size() - 1);
|
||||
}
|
||||
|
||||
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.forward_speed))
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
|
||||
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << input_way.id();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the unique identifier for the street name
|
||||
const auto &string_map_iterator = string_map.find(parsed_way.name);
|
||||
unsigned name_id = external_memory.name_list.size();
|
||||
if (string_map.end() == string_map_iterator)
|
||||
{
|
||||
parsed_way.nameID = external_memory.name_list.size();
|
||||
external_memory.name_list.push_back(parsed_way.name);
|
||||
string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||
string_map.insert(std::make_pair(parsed_way.name, name_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
parsed_way.nameID = string_map_iterator->second;
|
||||
name_id = string_map_iterator->second;
|
||||
}
|
||||
|
||||
if (TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)
|
||||
{
|
||||
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
||||
parsed_way.forward_travel_mode = parsed_way.backward_travel_mode;
|
||||
parsed_way.backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||
}
|
||||
const bool split_edge = (parsed_way.forward_speed > 0) &&
|
||||
(TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) &&
|
||||
(parsed_way.backward_speed > 0) &&
|
||||
(TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) &&
|
||||
((parsed_way.forward_speed != parsed_way.backward_speed) ||
|
||||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode));
|
||||
|
||||
const bool split_edge =
|
||||
(parsed_way.forward_speed>0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) &&
|
||||
(parsed_way.backward_speed>0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) &&
|
||||
((parsed_way.forward_speed != parsed_way.backward_speed) ||
|
||||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode));
|
||||
|
||||
BOOST_ASSERT(parsed_way.forward_travel_mode>0);
|
||||
for (unsigned n = 0; n < (parsed_way.path.size() - 1); ++n)
|
||||
auto pair_wise_segment_split = [&](const osmium::NodeRef &first_node,
|
||||
const osmium::NodeRef &last_node)
|
||||
{
|
||||
// SimpleLogger().Write() << "adding edge (" << first_node.ref() << "," <<
|
||||
// last_node.ref() << "), fwd speed: " << parsed_way.forward_speed;
|
||||
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||
parsed_way.path[n],
|
||||
parsed_way.path[n + 1],
|
||||
((split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode) ? ExtractionWay::oneway
|
||||
: ExtractionWay::bidirectional),
|
||||
first_node.ref(),
|
||||
last_node.ref(),
|
||||
((split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)
|
||||
? ExtractionWay::oneway
|
||||
: ExtractionWay::bidirectional),
|
||||
parsed_way.forward_speed,
|
||||
parsed_way.nameID,
|
||||
name_id,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
parsed_way.ignore_in_grid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
parsed_way.is_access_restricted,
|
||||
parsed_way.forward_travel_mode,
|
||||
split_edge));
|
||||
external_memory.used_node_id_list.push_back(parsed_way.path[n]);
|
||||
external_memory.used_node_id_list.push_back(first_node.ref());
|
||||
};
|
||||
|
||||
const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode;
|
||||
if (is_opposite_way)
|
||||
{
|
||||
const_cast<ExtractionWay&>(parsed_way).forward_travel_mode = parsed_way.backward_travel_mode;
|
||||
const_cast<ExtractionWay&>(parsed_way).backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||
osrm::for_each_pair(
|
||||
input_way.nodes().crbegin(), input_way.nodes().crend(), pair_wise_segment_split);
|
||||
external_memory.used_node_id_list.push_back(input_way.nodes().front().ref());
|
||||
}
|
||||
else
|
||||
{
|
||||
osrm::for_each_pair(
|
||||
input_way.nodes().cbegin(), input_way.nodes().cend(), pair_wise_segment_split);
|
||||
external_memory.used_node_id_list.push_back(input_way.nodes().back().ref());
|
||||
}
|
||||
external_memory.used_node_id_list.push_back(parsed_way.path.back());
|
||||
|
||||
// The following information is needed to identify start and end segments of restrictions
|
||||
external_memory.way_start_end_id_list.push_back(
|
||||
WayIDStartAndEndEdge(parsed_way.id,
|
||||
parsed_way.path[0],
|
||||
parsed_way.path[1],
|
||||
parsed_way.path[parsed_way.path.size() - 2],
|
||||
parsed_way.path.back()));
|
||||
{(EdgeID)input_way.id(),
|
||||
(NodeID)input_way.nodes()[0].ref(),
|
||||
(NodeID)input_way.nodes()[1].ref(),
|
||||
(NodeID)input_way.nodes()[input_way.nodes().size() - 2].ref(),
|
||||
(NodeID)input_way.nodes().back().ref()});
|
||||
|
||||
if (split_edge)
|
||||
{ // Only true if the way should be split
|
||||
BOOST_ASSERT(parsed_way.backward_travel_mode>0);
|
||||
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
||||
|
||||
for (std::vector<NodeID>::size_type n = 0; n < parsed_way.path.size() - 1; ++n)
|
||||
auto pair_wise_segment_split_2 = [&](const osmium::NodeRef &first_node,
|
||||
const osmium::NodeRef &last_node)
|
||||
{
|
||||
// SimpleLogger().Write() << "adding edge (" << last_node.ref() << "," <<
|
||||
// first_node.ref() << "), bwd speed: " << parsed_way.backward_speed;
|
||||
external_memory.all_edges_list.push_back(
|
||||
InternalExtractorEdge(parsed_way.path[n],
|
||||
parsed_way.path[n + 1],
|
||||
InternalExtractorEdge(last_node.ref(),
|
||||
first_node.ref(),
|
||||
ExtractionWay::oneway,
|
||||
parsed_way.backward_speed,
|
||||
parsed_way.nameID,
|
||||
name_id,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
parsed_way.ignore_in_grid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
parsed_way.is_access_restricted,
|
||||
parsed_way.backward_travel_mode,
|
||||
split_edge));
|
||||
};
|
||||
|
||||
if (is_opposite_way)
|
||||
{
|
||||
// SimpleLogger().Write() << "opposite2";
|
||||
osrm::for_each_pair(input_way.nodes().crbegin(),
|
||||
input_way.nodes().crend(),
|
||||
pair_wise_segment_split_2);
|
||||
external_memory.used_node_id_list.push_back(input_way.nodes().front().ref());
|
||||
}
|
||||
else
|
||||
{
|
||||
osrm::for_each_pair(input_way.nodes().cbegin(),
|
||||
input_way.nodes().cend(),
|
||||
pair_wise_segment_split_2);
|
||||
external_memory.used_node_id_list.push_back(input_way.nodes().back().ref());
|
||||
}
|
||||
|
||||
external_memory.way_start_end_id_list.push_back(
|
||||
WayIDStartAndEndEdge(parsed_way.id,
|
||||
parsed_way.path[0],
|
||||
parsed_way.path[1],
|
||||
parsed_way.path[parsed_way.path.size() - 2],
|
||||
parsed_way.path.back()));
|
||||
{(EdgeID)input_way.id(),
|
||||
(NodeID)input_way.nodes()[1].ref(),
|
||||
(NodeID)input_way.nodes()[0].ref(),
|
||||
(NodeID)input_way.nodes().back().ref(),
|
||||
(NodeID)input_way.nodes()[input_way.nodes().size() - 2].ref()});
|
||||
}
|
||||
}
|
||||
|
@ -28,15 +28,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTOR_CALLBACKS_H
|
||||
#define EXTRACTOR_CALLBACKS_H
|
||||
|
||||
#include "ExtractionWay.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <osmium/osm.hpp>
|
||||
|
||||
#include <variant/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
struct ExternalMemoryNode;
|
||||
class ExtractionContainers;
|
||||
struct ExtractionWay;
|
||||
struct InputRestrictionContainer;
|
||||
struct ExtractionNode;
|
||||
|
||||
class ExtractorCallbacks
|
||||
{
|
||||
@ -51,13 +56,13 @@ class ExtractorCallbacks
|
||||
std::unordered_map<std::string, NodeID> &string_map);
|
||||
|
||||
// warning: caller needs to take care of synchronization!
|
||||
void ProcessNode(const ExternalMemoryNode &node);
|
||||
void ProcessNode(const osmium::Node ¤t_node, const ExtractionNode &result_node);
|
||||
|
||||
// warning: caller needs to take care of synchronization!
|
||||
bool ProcessRestriction(const InputRestrictionContainer &restriction);
|
||||
void ProcessRestriction(const mapbox::util::optional<InputRestrictionContainer> &restriction);
|
||||
|
||||
// warning: caller needs to take care of synchronization!
|
||||
void ProcessWay(ExtractionWay &way);
|
||||
void ProcessWay(const osmium::Way ¤t_way, const ExtractionWay &result_way);
|
||||
};
|
||||
|
||||
#endif /* EXTRACTOR_CALLBACKS_H */
|
||||
|
167
Extractor/ExtractorOptions.cpp
Normal file
167
Extractor/ExtractorOptions.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "ExtractorOptions.h"
|
||||
|
||||
#include "../Util/GitDescription.h"
|
||||
#include "../Util/IniFileUtil.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
bool ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config)
|
||||
{
|
||||
// declare a group of options that will be allowed only on command line
|
||||
boost::program_options::options_description generic_options("Options");
|
||||
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
|
||||
"config,c",
|
||||
boost::program_options::value<boost::filesystem::path>(&extractor_config.config_file_path)
|
||||
->default_value("extractor.ini"),
|
||||
"Path to a configuration file.");
|
||||
|
||||
// declare a group of options that will be allowed both on command line and in config file
|
||||
boost::program_options::options_description config_options("Configuration");
|
||||
config_options.add_options()("profile,p",
|
||||
boost::program_options::value<boost::filesystem::path>(
|
||||
&extractor_config.profile_path)->default_value("profile.lua"),
|
||||
"Path to LUA routing profile")(
|
||||
"threads,t",
|
||||
boost::program_options::value<unsigned int>(&extractor_config.requested_num_threads)
|
||||
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||
"Number of threads to use");
|
||||
|
||||
// hidden options, will be allowed both on command line and in config file, but will not be
|
||||
// shown to the user
|
||||
boost::program_options::options_description hidden_options("Hidden options");
|
||||
hidden_options.add_options()(
|
||||
"input,i",
|
||||
boost::program_options::value<boost::filesystem::path>(&extractor_config.input_path),
|
||||
"Input file in .osm, .osm.bz2 or .osm.pbf format");
|
||||
|
||||
// positional option
|
||||
boost::program_options::positional_options_description positional_options;
|
||||
positional_options.add("input", 1);
|
||||
|
||||
// combine above options for parsing
|
||||
boost::program_options::options_description cmdline_options;
|
||||
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description config_file_options;
|
||||
config_file_options.add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description visible_options(
|
||||
boost::filesystem::basename(argv[0]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
|
||||
visible_options.add(generic_options).add(config_options);
|
||||
|
||||
// parse command line options
|
||||
boost::program_options::variables_map option_variables;
|
||||
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
|
||||
.options(cmdline_options)
|
||||
.positional(positional_options)
|
||||
.run(),
|
||||
option_variables);
|
||||
|
||||
if (option_variables.count("version"))
|
||||
{
|
||||
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (option_variables.count("help"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::program_options::notify(option_variables);
|
||||
|
||||
// parse config file
|
||||
if (boost::filesystem::is_regular_file(extractor_config.config_file_path))
|
||||
{
|
||||
SimpleLogger().Write() << "Reading options from: "
|
||||
<< extractor_config.config_file_path.string();
|
||||
std::string ini_file_contents =
|
||||
ReadIniFileAndLowerContents(extractor_config.config_file_path);
|
||||
std::stringstream config_stream(ini_file_contents);
|
||||
boost::program_options::store(parse_config_file(config_stream, config_file_options),
|
||||
option_variables);
|
||||
boost::program_options::notify(option_variables);
|
||||
}
|
||||
|
||||
if (!option_variables.count("input"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_config)
|
||||
{
|
||||
boost::filesystem::path &input_path = extractor_config.input_path;
|
||||
extractor_config.output_file_name = input_path.string();
|
||||
extractor_config.restriction_file_name = input_path.string();
|
||||
extractor_config.timestamp_file_name = input_path.string();
|
||||
std::string::size_type pos = extractor_config.output_file_name.find(".osm.bz2");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
pos = extractor_config.output_file_name.find(".osm.pbf");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
pos = extractor_config.output_file_name.find(".osm.xml");
|
||||
}
|
||||
}
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
pos = extractor_config.output_file_name.find(".pbf");
|
||||
}
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
pos = extractor_config.output_file_name.find(".osm");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
extractor_config.output_file_name.append(".osrm");
|
||||
extractor_config.restriction_file_name.append(".osrm.restrictions");
|
||||
extractor_config.timestamp_file_name.append(".osrm.timestamp");
|
||||
}
|
||||
else
|
||||
{
|
||||
extractor_config.output_file_name.replace(pos, 5, ".osrm");
|
||||
extractor_config.restriction_file_name.replace(pos, 5, ".osrm.restrictions");
|
||||
extractor_config.timestamp_file_name.replace(pos, 5, ".osrm.timestamp");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
extractor_config.output_file_name.replace(pos, 8, ".osrm");
|
||||
extractor_config.restriction_file_name.replace(pos, 8, ".osrm.restrictions");
|
||||
extractor_config.timestamp_file_name.replace(pos, 8, ".osrm.timestamp");
|
||||
}
|
||||
}
|
@ -25,54 +25,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HASH_TABLE_H
|
||||
#define HASH_TABLE_H
|
||||
#ifndef EXTRACTOR_OPTIONS_H__
|
||||
#define EXTRACTOR_OPTIONS_H__
|
||||
|
||||
#include <vector>
|
||||
#include "Extractor.h"
|
||||
|
||||
template <typename Key, typename Value>
|
||||
class HashTable
|
||||
struct ExtractorConfig
|
||||
{
|
||||
private:
|
||||
using KeyValPair = std::pair<Key, Value>;
|
||||
std::vector<KeyValPair> table;
|
||||
ExtractorConfig() noexcept : requested_num_threads(0) {}
|
||||
unsigned requested_num_threads;
|
||||
boost::filesystem::path config_file_path;
|
||||
boost::filesystem::path input_path;
|
||||
boost::filesystem::path profile_path;
|
||||
|
||||
public:
|
||||
HashTable() {}
|
||||
|
||||
inline void Add(Key const &key, Value const &value)
|
||||
{
|
||||
table.emplace_back(std::move(key), std::move(value));
|
||||
}
|
||||
|
||||
inline void Clear()
|
||||
{
|
||||
table.clear();
|
||||
}
|
||||
|
||||
inline const Value Find(Key const &key) const
|
||||
{
|
||||
for (const auto &key_val_pair : table)
|
||||
{
|
||||
if (key_val_pair.first == key)
|
||||
{
|
||||
return key_val_pair.second;
|
||||
}
|
||||
}
|
||||
return Value();
|
||||
}
|
||||
|
||||
inline const bool Holds(Key const &key) const
|
||||
{
|
||||
for (const auto &key_val_pair : table)
|
||||
{
|
||||
if (key_val_pair.first == key)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
std::string output_file_name;
|
||||
std::string restriction_file_name;
|
||||
std::string timestamp_file_name;
|
||||
};
|
||||
|
||||
#endif /* HASH_TABLE_H */
|
||||
struct ExtractorOptions
|
||||
{
|
||||
static bool ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config);
|
||||
|
||||
static void GenerateOutputFilesNames(ExtractorConfig &extractor_config);
|
||||
};
|
||||
|
||||
#endif // EXTRACTOR_OPTIONS_H__
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef EXTRACTORSTRUCTS_H_
|
||||
#define EXTRACTORSTRUCTS_H_
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
struct ExtractorRelation
|
||||
{
|
||||
ExtractorRelation() : type(unknown) {}
|
||||
enum
|
||||
{ unknown = 0,
|
||||
ferry,
|
||||
turnRestriction } type;
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
};
|
||||
|
||||
struct WayIDStartAndEndEdge
|
||||
{
|
||||
unsigned wayID;
|
||||
NodeID firstStart;
|
||||
NodeID firstTarget;
|
||||
NodeID lastStart;
|
||||
NodeID lastTarget;
|
||||
WayIDStartAndEndEdge()
|
||||
: wayID(std::numeric_limits<unsigned>::max()), firstStart(std::numeric_limits<unsigned>::max()), firstTarget(std::numeric_limits<unsigned>::max()), lastStart(std::numeric_limits<unsigned>::max()),
|
||||
lastTarget(std::numeric_limits<unsigned>::max())
|
||||
{
|
||||
}
|
||||
|
||||
explicit WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt)
|
||||
: wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt)
|
||||
{
|
||||
}
|
||||
|
||||
static WayIDStartAndEndEdge min_value()
|
||||
{
|
||||
return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(),
|
||||
(std::numeric_limits<unsigned>::min)(),
|
||||
(std::numeric_limits<unsigned>::min)(),
|
||||
(std::numeric_limits<unsigned>::min)(),
|
||||
(std::numeric_limits<unsigned>::min)());
|
||||
}
|
||||
static WayIDStartAndEndEdge max_value()
|
||||
{
|
||||
return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(),
|
||||
(std::numeric_limits<unsigned>::max)(),
|
||||
(std::numeric_limits<unsigned>::max)(),
|
||||
(std::numeric_limits<unsigned>::max)(),
|
||||
(std::numeric_limits<unsigned>::max)());
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpWayByID
|
||||
{
|
||||
using value_type = WayIDStartAndEndEdge;
|
||||
bool operator()(const WayIDStartAndEndEdge &a, const WayIDStartAndEndEdge &b) const
|
||||
{
|
||||
return a.wayID < b.wayID;
|
||||
}
|
||||
value_type max_value() { return WayIDStartAndEndEdge::max_value(); }
|
||||
value_type min_value() { return WayIDStartAndEndEdge::min_value(); }
|
||||
};
|
||||
|
||||
struct Cmp
|
||||
{
|
||||
using value_type = NodeID;
|
||||
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
|
||||
value_type max_value() { return 0xffffffff; }
|
||||
value_type min_value() { return 0x0; }
|
||||
};
|
||||
|
||||
struct CmpNodeByID
|
||||
{
|
||||
using value_type = ExternalMemoryNode;
|
||||
bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const
|
||||
{
|
||||
return left.node_id < right.node_id;
|
||||
}
|
||||
value_type max_value() { return ExternalMemoryNode::max_value(); }
|
||||
value_type min_value() { return ExternalMemoryNode::min_value(); }
|
||||
};
|
||||
|
||||
#endif /* EXTRACTORSTRUCTS_H_ */
|
88
Extractor/FirstAndLastSegmentOfWay.h
Normal file
88
Extractor/FirstAndLastSegmentOfWay.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef EXTRACTORSTRUCTS_H_
|
||||
#define EXTRACTORSTRUCTS_H_
|
||||
|
||||
#include "../DataStructures/ExternalMemoryNode.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
struct FirstAndLastSegmentOfWay
|
||||
{
|
||||
EdgeID way_id;
|
||||
NodeID first_segment_source_id;
|
||||
NodeID first_segment_target_id;
|
||||
NodeID last_segment_source_id;
|
||||
NodeID last_segment_target_id;
|
||||
FirstAndLastSegmentOfWay()
|
||||
: way_id(std::numeric_limits<EdgeID>::max()),
|
||||
first_segment_source_id(std::numeric_limits<NodeID>::max()),
|
||||
first_segment_target_id(std::numeric_limits<NodeID>::max()),
|
||||
last_segment_source_id(std::numeric_limits<NodeID>::max()),
|
||||
last_segment_target_id(std::numeric_limits<NodeID>::max())
|
||||
{
|
||||
}
|
||||
|
||||
FirstAndLastSegmentOfWay(EdgeID w, NodeID fs, NodeID ft, NodeID ls, NodeID lt)
|
||||
: way_id(w), first_segment_source_id(fs), first_segment_target_id(ft),
|
||||
last_segment_source_id(ls), last_segment_target_id(lt)
|
||||
{
|
||||
}
|
||||
|
||||
static FirstAndLastSegmentOfWay min_value()
|
||||
{
|
||||
return {std::numeric_limits<EdgeID>::min(),
|
||||
std::numeric_limits<NodeID>::min(),
|
||||
std::numeric_limits<NodeID>::min(),
|
||||
std::numeric_limits<NodeID>::min(),
|
||||
std::numeric_limits<NodeID>::min()};
|
||||
}
|
||||
static FirstAndLastSegmentOfWay max_value()
|
||||
{
|
||||
return {std::numeric_limits<EdgeID>::max(),
|
||||
std::numeric_limits<NodeID>::max(),
|
||||
std::numeric_limits<NodeID>::max(),
|
||||
std::numeric_limits<NodeID>::max(),
|
||||
std::numeric_limits<NodeID>::max()};
|
||||
}
|
||||
};
|
||||
|
||||
struct FirstAndLastSegmentOfWayStxxlCompare
|
||||
{
|
||||
using value_type = FirstAndLastSegmentOfWay;
|
||||
bool operator()(const FirstAndLastSegmentOfWay &a, const FirstAndLastSegmentOfWay &b) const
|
||||
{
|
||||
return a.way_id < b.way_id;
|
||||
}
|
||||
value_type max_value() { return FirstAndLastSegmentOfWay::max_value(); }
|
||||
value_type min_value() { return FirstAndLastSegmentOfWay::min_value(); }
|
||||
};
|
||||
|
||||
#endif /* EXTRACTORSTRUCTS_H_ */
|
@ -1,665 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "PBFParser.h"
|
||||
|
||||
#include "ExtractionWay.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/MachineInfo.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <thread>
|
||||
|
||||
PBFParser::PBFParser(const char *fileName,
|
||||
ExtractorCallbacks *extractor_callbacks,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
unsigned num_threads)
|
||||
: BaseParser(extractor_callbacks, scripting_environment)
|
||||
{
|
||||
if (0 == num_threads)
|
||||
{
|
||||
num_parser_threads = tbb::task_scheduler_init::default_num_threads();
|
||||
}
|
||||
else
|
||||
{
|
||||
num_parser_threads = num_threads;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
// Max 2500 items in queue, hardcoded.
|
||||
thread_data_queue = std::make_shared<ConcurrentQueue<ParserThreadData *>>(2500);
|
||||
input.open(fileName, std::ios::in | std::ios::binary);
|
||||
|
||||
if (!input)
|
||||
{
|
||||
throw OSRMException("pbf file not found.");
|
||||
}
|
||||
|
||||
block_count = 0;
|
||||
group_count = 0;
|
||||
}
|
||||
|
||||
PBFParser::~PBFParser()
|
||||
{
|
||||
if (input.is_open())
|
||||
{
|
||||
input.close();
|
||||
}
|
||||
|
||||
// Clean up any leftover ThreadData objects in the queue
|
||||
ParserThreadData *thread_data;
|
||||
while (thread_data_queue->try_pop(thread_data))
|
||||
{
|
||||
delete thread_data;
|
||||
}
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
SimpleLogger().Write(logDEBUG) << "parsed " << block_count << " blocks from pbf with "
|
||||
<< group_count << " groups";
|
||||
}
|
||||
|
||||
inline bool PBFParser::ReadHeader()
|
||||
{
|
||||
ParserThreadData init_data;
|
||||
/** read Header */
|
||||
if (!readPBFBlobHeader(input, &init_data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (readBlob(input, &init_data))
|
||||
{
|
||||
if (!init_data.PBFHeaderBlock.ParseFromArray(&(init_data.charBuffer[0]),
|
||||
static_cast<int>(init_data.charBuffer.size())))
|
||||
{
|
||||
std::cerr << "[error] Header not parseable!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto feature_size = init_data.PBFHeaderBlock.required_features_size();
|
||||
for (int i = 0; i < feature_size; ++i)
|
||||
{
|
||||
const std::string &feature = init_data.PBFHeaderBlock.required_features(i);
|
||||
bool supported = false;
|
||||
if ("OsmSchema-V0.6" == feature)
|
||||
{
|
||||
supported = true;
|
||||
}
|
||||
else if ("DenseNodes" == feature)
|
||||
{
|
||||
supported = true;
|
||||
}
|
||||
|
||||
if (!supported)
|
||||
{
|
||||
std::cerr << "[error] required feature not supported: " << feature.data()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "[error] blob not loaded!" << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void PBFParser::ReadData()
|
||||
{
|
||||
bool keep_running = true;
|
||||
do
|
||||
{
|
||||
ParserThreadData *thread_data = new ParserThreadData();
|
||||
keep_running = readNextBlock(input, thread_data);
|
||||
|
||||
if (keep_running)
|
||||
{
|
||||
thread_data_queue->push(thread_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No more data to read, parse stops when nullptr encountered
|
||||
thread_data_queue->push(nullptr);
|
||||
delete thread_data;
|
||||
}
|
||||
} while (keep_running);
|
||||
}
|
||||
|
||||
inline void PBFParser::ParseData()
|
||||
{
|
||||
tbb::task_scheduler_init init(num_parser_threads);
|
||||
|
||||
while (true)
|
||||
{
|
||||
ParserThreadData *thread_data;
|
||||
thread_data_queue->wait_and_pop(thread_data);
|
||||
if (nullptr == thread_data)
|
||||
{
|
||||
thread_data_queue->push(nullptr); // Signal end of data for other threads
|
||||
break;
|
||||
}
|
||||
|
||||
loadBlock(thread_data);
|
||||
|
||||
int group_size = thread_data->PBFprimitiveBlock.primitivegroup_size();
|
||||
for (int i = 0; i < group_size; ++i)
|
||||
{
|
||||
thread_data->currentGroupID = i;
|
||||
loadGroup(thread_data);
|
||||
|
||||
if (thread_data->entityTypeIndicator == TypeNode)
|
||||
{
|
||||
parseNode(thread_data);
|
||||
}
|
||||
if (thread_data->entityTypeIndicator == TypeWay)
|
||||
{
|
||||
parseWay(thread_data);
|
||||
}
|
||||
if (thread_data->entityTypeIndicator == TypeRelation)
|
||||
{
|
||||
parseRelation(thread_data);
|
||||
}
|
||||
if (thread_data->entityTypeIndicator == TypeDenseNode)
|
||||
{
|
||||
parseDenseNode(thread_data);
|
||||
}
|
||||
}
|
||||
|
||||
delete thread_data;
|
||||
thread_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool PBFParser::Parse()
|
||||
{
|
||||
// Start the read and parse threads
|
||||
std::thread read_thread(std::bind(&PBFParser::ReadData, this));
|
||||
|
||||
// Open several parse threads that are synchronized before call to
|
||||
std::thread parse_thread(std::bind(&PBFParser::ParseData, this));
|
||||
|
||||
// Wait for the threads to finish
|
||||
read_thread.join();
|
||||
parse_thread.join();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void PBFParser::parseDenseNode(ParserThreadData *thread_data)
|
||||
{
|
||||
const OSMPBF::DenseNodes &dense =
|
||||
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).dense();
|
||||
int denseTagIndex = 0;
|
||||
int64_t m_lastDenseID = 0;
|
||||
int64_t m_lastDenseLatitude = 0;
|
||||
int64_t m_lastDenseLongitude = 0;
|
||||
|
||||
const int number_of_nodes = dense.id_size();
|
||||
std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
|
||||
for (int i = 0; i < number_of_nodes; ++i)
|
||||
{
|
||||
m_lastDenseID += dense.id(i);
|
||||
m_lastDenseLatitude += dense.lat(i);
|
||||
m_lastDenseLongitude += dense.lon(i);
|
||||
extracted_nodes_vector[i].node_id = static_cast<NodeID>(m_lastDenseID);
|
||||
extracted_nodes_vector[i].lat = static_cast<int>(
|
||||
COORDINATE_PRECISION *
|
||||
((double)m_lastDenseLatitude * thread_data->PBFprimitiveBlock.granularity() +
|
||||
thread_data->PBFprimitiveBlock.lat_offset()) /
|
||||
NANO);
|
||||
extracted_nodes_vector[i].lon = static_cast<int>(
|
||||
COORDINATE_PRECISION *
|
||||
((double)m_lastDenseLongitude * thread_data->PBFprimitiveBlock.granularity() +
|
||||
thread_data->PBFprimitiveBlock.lon_offset()) /
|
||||
NANO);
|
||||
while (denseTagIndex < dense.keys_vals_size())
|
||||
{
|
||||
const int tagValue = dense.keys_vals(denseTagIndex);
|
||||
if (0 == tagValue)
|
||||
{
|
||||
++denseTagIndex;
|
||||
break;
|
||||
}
|
||||
const int keyValue = dense.keys_vals(denseTagIndex + 1);
|
||||
const std::string &key = thread_data->PBFprimitiveBlock.stringtable().s(tagValue);
|
||||
const std::string &value = thread_data->PBFprimitiveBlock.stringtable().s(keyValue);
|
||||
extracted_nodes_vector[i].keyVals.Add(std::move(key), std::move(value));
|
||||
denseTagIndex += 2;
|
||||
}
|
||||
}
|
||||
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, extracted_nodes_vector.size()),
|
||||
[this, &extracted_nodes_vector](const tbb::blocked_range<size_t> &range)
|
||||
{
|
||||
lua_State *lua_state = this->scripting_environment.getLuaState();
|
||||
for (size_t i = range.begin(); i != range.end(); ++i)
|
||||
{
|
||||
ImportNode &import_node = extracted_nodes_vector[i];
|
||||
ParseNodeInLua(import_node, lua_state);
|
||||
}
|
||||
});
|
||||
|
||||
for (const ImportNode &import_node : extracted_nodes_vector)
|
||||
{
|
||||
extractor_callbacks->ProcessNode(import_node);
|
||||
}
|
||||
}
|
||||
|
||||
inline void PBFParser::parseNode(ParserThreadData *)
|
||||
{
|
||||
throw OSRMException("Parsing of simple nodes not supported. PBF should use dense nodes");
|
||||
}
|
||||
|
||||
inline void PBFParser::parseRelation(ParserThreadData *thread_data)
|
||||
{
|
||||
// TODO: leave early, if relation is not a restriction
|
||||
// TODO: reuse rawRestriction container
|
||||
if (!use_turn_restrictions)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const OSMPBF::PrimitiveGroup &group =
|
||||
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID);
|
||||
|
||||
for (int i = 0, relation_size = group.relations_size(); i < relation_size; ++i)
|
||||
{
|
||||
std::string except_tag_string;
|
||||
const OSMPBF::Relation &inputRelation =
|
||||
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).relations(i);
|
||||
bool is_restriction = false;
|
||||
bool is_only_restriction = false;
|
||||
for (int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k)
|
||||
{
|
||||
const std::string &key =
|
||||
thread_data->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
|
||||
const std::string &val =
|
||||
thread_data->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
|
||||
if ("type" == key)
|
||||
{
|
||||
if ("restriction" == val)
|
||||
{
|
||||
is_restriction = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (("restriction" == key) && (val.find("only_") == 0))
|
||||
{
|
||||
is_only_restriction = true;
|
||||
}
|
||||
if ("except" == key)
|
||||
{
|
||||
except_tag_string = val;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_restriction && ShouldIgnoreRestriction(except_tag_string))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_restriction)
|
||||
{
|
||||
int64_t last_ref = 0;
|
||||
InputRestrictionContainer current_restriction_container(is_only_restriction);
|
||||
for (int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
|
||||
rolesIndex < last_role;
|
||||
++rolesIndex)
|
||||
{
|
||||
const std::string &role = thread_data->PBFprimitiveBlock.stringtable().s(
|
||||
inputRelation.roles_sid(rolesIndex));
|
||||
last_ref += inputRelation.memids(rolesIndex);
|
||||
|
||||
if (!("from" == role || "to" == role || "via" == role))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (inputRelation.types(rolesIndex))
|
||||
{
|
||||
case 0: // node
|
||||
if ("from" == role || "to" == role)
|
||||
{ // Only via should be a node
|
||||
continue;
|
||||
}
|
||||
BOOST_ASSERT("via" == role);
|
||||
if (std::numeric_limits<unsigned>::max() !=
|
||||
current_restriction_container.viaNode)
|
||||
{
|
||||
current_restriction_container.viaNode =
|
||||
std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() ==
|
||||
current_restriction_container.viaNode);
|
||||
current_restriction_container.restriction.viaNode =
|
||||
static_cast<NodeID>(last_ref);
|
||||
break;
|
||||
case 1: // way
|
||||
BOOST_ASSERT("from" == role || "to" == role || "via" == role);
|
||||
if ("from" == role)
|
||||
{
|
||||
current_restriction_container.fromWay = static_cast<EdgeID>(last_ref);
|
||||
}
|
||||
if ("to" == role)
|
||||
{
|
||||
current_restriction_container.toWay = static_cast<EdgeID>(last_ref);
|
||||
}
|
||||
if ("via" == role)
|
||||
{
|
||||
BOOST_ASSERT(current_restriction_container.restriction.toNode ==
|
||||
std::numeric_limits<unsigned>::max());
|
||||
current_restriction_container.viaNode = static_cast<NodeID>(last_ref);
|
||||
}
|
||||
break;
|
||||
case 2: // relation, not used. relations relating to relations are evil.
|
||||
continue;
|
||||
BOOST_ASSERT(false);
|
||||
break;
|
||||
|
||||
default: // should not happen
|
||||
BOOST_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!extractor_callbacks->ProcessRestriction(current_restriction_container))
|
||||
{
|
||||
std::cerr << "[PBFParser] relation not parsed" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void PBFParser::parseWay(ParserThreadData *thread_data)
|
||||
{
|
||||
const int number_of_ways =
|
||||
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways_size();
|
||||
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
|
||||
for (int i = 0; i < number_of_ways; ++i)
|
||||
{
|
||||
const OSMPBF::Way &input_way =
|
||||
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways(i);
|
||||
parsed_way_vector[i].id = static_cast<EdgeID>(input_way.id());
|
||||
unsigned node_id_in_path = 0;
|
||||
const auto number_of_referenced_nodes = input_way.refs_size();
|
||||
for (auto j = 0; j < number_of_referenced_nodes; ++j)
|
||||
{
|
||||
node_id_in_path += static_cast<NodeID>(input_way.refs(j));
|
||||
parsed_way_vector[i].path.push_back(node_id_in_path);
|
||||
}
|
||||
BOOST_ASSERT(input_way.keys_size() == input_way.vals_size());
|
||||
const auto number_of_keys = input_way.keys_size();
|
||||
for (auto j = 0; j < number_of_keys; ++j)
|
||||
{
|
||||
const std::string &key =
|
||||
thread_data->PBFprimitiveBlock.stringtable().s(input_way.keys(j));
|
||||
const std::string &val =
|
||||
thread_data->PBFprimitiveBlock.stringtable().s(input_way.vals(j));
|
||||
parsed_way_vector[i].keyVals.Add(std::move(key), std::move(val));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: investigate if schedule guided will be handled by tbb automatically
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, parsed_way_vector.size()),
|
||||
[this, &parsed_way_vector](const tbb::blocked_range<size_t> &range)
|
||||
{
|
||||
lua_State *lua_state = this->scripting_environment.getLuaState();
|
||||
for (size_t i = range.begin(); i != range.end(); i++)
|
||||
{
|
||||
ExtractionWay &extraction_way = parsed_way_vector[i];
|
||||
if (2 <= extraction_way.path.size())
|
||||
{
|
||||
ParseWayInLua(extraction_way, lua_state);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (ExtractionWay &extraction_way : parsed_way_vector)
|
||||
{
|
||||
if (2 <= extraction_way.path.size())
|
||||
{
|
||||
extractor_callbacks->ProcessWay(extraction_way);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void PBFParser::loadGroup(ParserThreadData *thread_data)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
++group_count;
|
||||
#endif
|
||||
|
||||
const OSMPBF::PrimitiveGroup &group =
|
||||
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID);
|
||||
thread_data->entityTypeIndicator = TypeDummy;
|
||||
if (0 != group.nodes_size())
|
||||
{
|
||||
thread_data->entityTypeIndicator = TypeNode;
|
||||
}
|
||||
if (0 != group.ways_size())
|
||||
{
|
||||
thread_data->entityTypeIndicator = TypeWay;
|
||||
}
|
||||
if (0 != group.relations_size())
|
||||
{
|
||||
thread_data->entityTypeIndicator = TypeRelation;
|
||||
}
|
||||
if (group.has_dense())
|
||||
{
|
||||
thread_data->entityTypeIndicator = TypeDenseNode;
|
||||
BOOST_ASSERT(0 != group.dense().id_size());
|
||||
}
|
||||
BOOST_ASSERT(thread_data->entityTypeIndicator != TypeDummy);
|
||||
}
|
||||
|
||||
inline void PBFParser::loadBlock(ParserThreadData *thread_data)
|
||||
{
|
||||
++block_count;
|
||||
thread_data->currentGroupID = 0;
|
||||
thread_data->currentEntityID = 0;
|
||||
}
|
||||
|
||||
inline bool PBFParser::readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data)
|
||||
{
|
||||
int size(0);
|
||||
stream.read((char *)&size, sizeof(int));
|
||||
size = SwapEndian(size);
|
||||
if (stream.eof())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (size > MAX_BLOB_HEADER_SIZE || size < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
char *data = new char[size];
|
||||
stream.read(data, size * sizeof(data[0]));
|
||||
|
||||
bool dataSuccessfullyParsed = (thread_data->PBFBlobHeader).ParseFromArray(data, size);
|
||||
delete[] data;
|
||||
return dataSuccessfullyParsed;
|
||||
}
|
||||
|
||||
inline bool PBFParser::unpackZLIB(ParserThreadData *thread_data)
|
||||
{
|
||||
auto raw_size = thread_data->PBFBlob.raw_size();
|
||||
char *unpacked_data_array = new char[raw_size];
|
||||
z_stream compressed_data_stream;
|
||||
compressed_data_stream.next_in = (unsigned char *)thread_data->PBFBlob.zlib_data().data();
|
||||
compressed_data_stream.avail_in = thread_data->PBFBlob.zlib_data().size();
|
||||
compressed_data_stream.next_out = (unsigned char *)unpacked_data_array;
|
||||
compressed_data_stream.avail_out = raw_size;
|
||||
compressed_data_stream.zalloc = Z_NULL;
|
||||
compressed_data_stream.zfree = Z_NULL;
|
||||
compressed_data_stream.opaque = Z_NULL;
|
||||
int return_code = inflateInit(&compressed_data_stream);
|
||||
if (return_code != Z_OK)
|
||||
{
|
||||
std::cerr << "[error] failed to init zlib stream" << std::endl;
|
||||
delete[] unpacked_data_array;
|
||||
return false;
|
||||
}
|
||||
|
||||
return_code = inflate(&compressed_data_stream, Z_FINISH);
|
||||
if (return_code != Z_STREAM_END)
|
||||
{
|
||||
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
|
||||
std::cerr << "[error] Error type: " << return_code << std::endl;
|
||||
delete[] unpacked_data_array;
|
||||
return false;
|
||||
}
|
||||
|
||||
return_code = inflateEnd(&compressed_data_stream);
|
||||
if (return_code != Z_OK)
|
||||
{
|
||||
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
|
||||
delete[] unpacked_data_array;
|
||||
return false;
|
||||
}
|
||||
|
||||
thread_data->charBuffer.clear();
|
||||
thread_data->charBuffer.resize(raw_size);
|
||||
std::copy(unpacked_data_array, unpacked_data_array + raw_size, thread_data->charBuffer.begin());
|
||||
delete[] unpacked_data_array;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool PBFParser::unpackLZMA(ParserThreadData *) { return false; }
|
||||
|
||||
inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_data)
|
||||
{
|
||||
if (stream.eof())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const int size = thread_data->PBFBlobHeader.datasize();
|
||||
if (size < 0 || size > MAX_BLOB_SIZE)
|
||||
{
|
||||
std::cerr << "[error] invalid Blob size:" << size << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
char *data = new char[size];
|
||||
stream.read(data, sizeof(data[0]) * size);
|
||||
|
||||
if (!thread_data->PBFBlob.ParseFromArray(data, size))
|
||||
{
|
||||
std::cerr << "[error] failed to parse blob" << std::endl;
|
||||
delete[] data;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (thread_data->PBFBlob.has_raw())
|
||||
{
|
||||
const std::string &data = thread_data->PBFBlob.raw();
|
||||
thread_data->charBuffer.clear();
|
||||
thread_data->charBuffer.resize(data.size());
|
||||
std::copy(data.begin(), data.end(), thread_data->charBuffer.begin());
|
||||
}
|
||||
else if (thread_data->PBFBlob.has_zlib_data())
|
||||
{
|
||||
if (!unpackZLIB(thread_data))
|
||||
{
|
||||
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
|
||||
delete[] data;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (thread_data->PBFBlob.has_lzma_data())
|
||||
{
|
||||
if (!unpackLZMA(thread_data))
|
||||
{
|
||||
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
|
||||
}
|
||||
delete[] data;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "[error] Blob contains no data" << std::endl;
|
||||
delete[] data;
|
||||
return false;
|
||||
}
|
||||
delete[] data;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PBFParser::readNextBlock(std::fstream &stream, ParserThreadData *thread_data)
|
||||
{
|
||||
if (stream.eof())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!readPBFBlobHeader(stream, thread_data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (thread_data->PBFBlobHeader.type() != "OSMData")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!readBlob(stream, thread_data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!thread_data->PBFprimitiveBlock.ParseFromArray(&(thread_data->charBuffer[0]),
|
||||
thread_data->charBuffer.size()))
|
||||
{
|
||||
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PBFPARSER_H_
|
||||
#define PBFPARSER_H_
|
||||
|
||||
#include "BaseParser.h"
|
||||
#include "../DataStructures/ConcurrentQueue.h"
|
||||
|
||||
#include <osmpbf/fileformat.pb.h>
|
||||
#include <osmpbf/osmformat.pb.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
class PBFParser : public BaseParser
|
||||
{
|
||||
|
||||
enum EntityType
|
||||
{ TypeDummy = 0,
|
||||
TypeNode = 1,
|
||||
TypeWay = 2,
|
||||
TypeRelation = 4,
|
||||
TypeDenseNode = 8 };
|
||||
|
||||
struct ParserThreadData
|
||||
{
|
||||
int currentGroupID;
|
||||
int currentEntityID;
|
||||
EntityType entityTypeIndicator;
|
||||
|
||||
OSMPBF::BlobHeader PBFBlobHeader;
|
||||
OSMPBF::Blob PBFBlob;
|
||||
|
||||
OSMPBF::HeaderBlock PBFHeaderBlock;
|
||||
OSMPBF::PrimitiveBlock PBFprimitiveBlock;
|
||||
|
||||
std::vector<char> charBuffer;
|
||||
};
|
||||
|
||||
public:
|
||||
PBFParser(const char *file_name,
|
||||
ExtractorCallbacks *extractor_callbacks,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
unsigned num_parser_threads = 0);
|
||||
virtual ~PBFParser();
|
||||
|
||||
inline bool ReadHeader();
|
||||
inline bool Parse();
|
||||
|
||||
private:
|
||||
inline void ReadData();
|
||||
inline void ParseData();
|
||||
inline void parseDenseNode(ParserThreadData *thread_data);
|
||||
inline void parseNode(ParserThreadData *thread_data);
|
||||
inline void parseRelation(ParserThreadData *thread_data);
|
||||
inline void parseWay(ParserThreadData *thread_data);
|
||||
|
||||
inline void loadGroup(ParserThreadData *thread_data);
|
||||
inline void loadBlock(ParserThreadData *thread_data);
|
||||
inline bool readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data);
|
||||
inline bool unpackZLIB(ParserThreadData *thread_data);
|
||||
inline bool unpackLZMA(ParserThreadData *thread_data);
|
||||
inline bool readBlob(std::fstream &stream, ParserThreadData *thread_data);
|
||||
inline bool readNextBlock(std::fstream &stream, ParserThreadData *thread_data);
|
||||
|
||||
static const int NANO = 1000 * 1000 * 1000;
|
||||
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
||||
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
|
||||
|
||||
unsigned group_count;
|
||||
unsigned block_count;
|
||||
|
||||
std::fstream input; // the input stream to parse
|
||||
std::shared_ptr<ConcurrentQueue<ParserThreadData *>> thread_data_queue;
|
||||
unsigned num_parser_threads;
|
||||
};
|
||||
|
||||
#endif /* PBFPARSER_H_ */
|
246
Extractor/RestrictionParser.cpp
Normal file
246
Extractor/RestrictionParser.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "RestrictionParser.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
#include "../DataStructures/ExternalMemoryNode.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
int lua_error_callback(lua_State *L)
|
||||
{
|
||||
luabind::object error_msg(luabind::from_stack(L, -1));
|
||||
std::ostringstream error_stream;
|
||||
error_stream << error_msg;
|
||||
throw OSRMException("ERROR occured in profile script:\n" + error_stream.str());
|
||||
}
|
||||
}
|
||||
|
||||
RestrictionParser::RestrictionParser(lua_State *lua_state)
|
||||
: /*lua_state(scripting_environment.getLuaState()),*/ use_turn_restrictions(true)
|
||||
{
|
||||
ReadUseRestrictionsSetting(lua_state);
|
||||
|
||||
if (use_turn_restrictions)
|
||||
{
|
||||
ReadRestrictionExceptions(lua_state);
|
||||
}
|
||||
}
|
||||
|
||||
void RestrictionParser::ReadUseRestrictionsSetting(lua_State *lua_state)
|
||||
{
|
||||
if (0 == luaL_dostring(lua_state, "return use_turn_restrictions\n"))
|
||||
{
|
||||
if (lua_isboolean(lua_state, -1))
|
||||
{
|
||||
use_turn_restrictions = lua_toboolean(lua_state, -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (use_turn_restrictions)
|
||||
{
|
||||
SimpleLogger().Write() << "Using turn restrictions";
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleLogger().Write() << "Ignoring turn restrictions";
|
||||
}
|
||||
}
|
||||
|
||||
void RestrictionParser::ReadRestrictionExceptions(lua_State *lua_state)
|
||||
{
|
||||
if (lua_function_exists(lua_state, "get_exceptions"))
|
||||
{
|
||||
luabind::set_pcall_callback(&lua_error_callback);
|
||||
// get list of turn restriction exceptions
|
||||
luabind::call_function<void>(
|
||||
lua_state, "get_exceptions", boost::ref(restriction_exceptions));
|
||||
const unsigned exception_count = restriction_exceptions.size();
|
||||
SimpleLogger().Write() << "Found " << exception_count
|
||||
<< " exceptions to turn restrictions:";
|
||||
for (const std::string &str : restriction_exceptions)
|
||||
{
|
||||
SimpleLogger().Write() << " " << str;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
|
||||
}
|
||||
}
|
||||
|
||||
mapbox::util::optional<InputRestrictionContainer> RestrictionParser::TryParse(lua_State *lua_state, osmium::Relation &relation) const
|
||||
{
|
||||
// return if turn restrictions should be ignored
|
||||
if (!use_turn_restrictions)
|
||||
{
|
||||
return mapbox::util::optional<InputRestrictionContainer>();
|
||||
}
|
||||
|
||||
osmium::tags::KeyPrefixFilter filter(false);
|
||||
filter.add(true, "restriction");
|
||||
|
||||
const osmium::TagList &tag_list = relation.tags();
|
||||
|
||||
osmium::tags::KeyPrefixFilter::iterator fi_begin(filter, tag_list.begin(), tag_list.end());
|
||||
osmium::tags::KeyPrefixFilter::iterator fi_end(filter, tag_list.end(), tag_list.end());
|
||||
|
||||
// if it's a restriction, continue;
|
||||
if (std::distance(fi_begin, fi_end) == 0)
|
||||
{
|
||||
return mapbox::util::optional<InputRestrictionContainer>();
|
||||
}
|
||||
|
||||
// check if the restriction should be ignored
|
||||
const char *except = relation.get_value_by_key("except");
|
||||
if (except != nullptr)
|
||||
{
|
||||
if (ShouldIgnoreRestriction(except))
|
||||
{
|
||||
return mapbox::util::optional<InputRestrictionContainer>();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_only_restriction = false;
|
||||
|
||||
for (auto iter = fi_begin; iter != fi_end; ++iter)
|
||||
{
|
||||
if (std::string("restriction") == iter->key() ||
|
||||
std::string("restriction::hgv") == iter->key())
|
||||
{
|
||||
const std::string restriction_value(iter->value());
|
||||
|
||||
if (restriction_value.find("only_") == 0)
|
||||
{
|
||||
is_only_restriction = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InputRestrictionContainer restriction_container(is_only_restriction);
|
||||
|
||||
for (const auto &member : relation.members())
|
||||
{
|
||||
const char *role = member.role();
|
||||
if (strcmp("from", role) != 0 && strcmp("to", role) != 0 && strcmp("via", role) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (member.type())
|
||||
{
|
||||
case osmium::item_type::node:
|
||||
// Make sure nodes appear only in the role if a via node
|
||||
if (0 == strcmp("from", role) || 0 == strcmp("to", role))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
BOOST_ASSERT(0 == strcmp("via", role));
|
||||
// set the via node id
|
||||
// SimpleLogger().Write() << "via: " << member.ref();
|
||||
|
||||
restriction_container.restriction.via.node = member.ref();
|
||||
break;
|
||||
|
||||
case osmium::item_type::way:
|
||||
BOOST_ASSERT(0 == strcmp("from", role) || 0 == strcmp("to", role) ||
|
||||
0 == strcmp("via", role));
|
||||
if (0 == strcmp("from", role))
|
||||
{
|
||||
// SimpleLogger().Write() << "from: " << member.ref();
|
||||
restriction_container.restriction.from.way = member.ref();
|
||||
}
|
||||
else if (0 == strcmp("to", role))
|
||||
{
|
||||
// SimpleLogger().Write() << "to: " << member.ref();
|
||||
restriction_container.restriction.to.way = member.ref();
|
||||
}
|
||||
else if (0 == strcmp("via", role))
|
||||
{
|
||||
// not yet suppported
|
||||
// restriction_container.restriction.via.way = member.ref();
|
||||
}
|
||||
break;
|
||||
case osmium::item_type::relation:
|
||||
// not yet supported, but who knows what the future holds...
|
||||
continue;
|
||||
BOOST_ASSERT(false);
|
||||
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
// SimpleLogger().Write() << (restriction_container.restriction.flags.is_only ? "only" : "no")
|
||||
// << "-restriction "
|
||||
// << "<" << restriction_container.restriction.from.node << "->"
|
||||
// << restriction_container.restriction.via.node << "->" << restriction_container.restriction.to.node
|
||||
// << ">";
|
||||
|
||||
return mapbox::util::optional<InputRestrictionContainer>(restriction_container);
|
||||
}
|
||||
|
||||
bool RestrictionParser::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), eg: except=bus;bicycle
|
||||
// b) the lua profile defines a hierachy of modes,
|
||||
// eg: [access, vehicle, bicycle]
|
||||
|
||||
if (except_tag_string.empty())
|
||||
{
|
||||
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("[;][ ]*"));
|
||||
for (std::string ¤t_string : exceptions)
|
||||
{
|
||||
const auto string_iterator =
|
||||
std::find(restriction_exceptions.begin(), restriction_exceptions.end(), current_string);
|
||||
if (restriction_exceptions.end() != string_iterator)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
@ -25,43 +25,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BASEPARSER_H_
|
||||
#define BASEPARSER_H_
|
||||
#ifndef RESTRICTION_PARSER_H_
|
||||
#define RESTRICTION_PARSER_H_
|
||||
|
||||
#include "../DataStructures/Restriction.h"
|
||||
|
||||
#include <osmium/osm.hpp>
|
||||
#include <osmium/tags/regex_filter.hpp>
|
||||
|
||||
#include <variant/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct lua_State;
|
||||
class ExtractorCallbacks;
|
||||
class ScriptingEnvironment;
|
||||
struct ExtractionWay;
|
||||
struct ImportNode;
|
||||
|
||||
class BaseParser
|
||||
class RestrictionParser
|
||||
{
|
||||
public:
|
||||
BaseParser() = delete;
|
||||
BaseParser(const BaseParser &) = delete;
|
||||
BaseParser(ExtractorCallbacks *extractor_callbacks,
|
||||
ScriptingEnvironment &scripting_environment);
|
||||
virtual ~BaseParser() {}
|
||||
virtual bool ReadHeader() = 0;
|
||||
virtual bool Parse() = 0;
|
||||
// RestrictionParser(ScriptingEnvironment &scripting_environment);
|
||||
RestrictionParser(lua_State *lua_state);
|
||||
mapbox::util::optional<InputRestrictionContainer> TryParse(lua_State *lua_state, osmium::Relation& relation) const;
|
||||
|
||||
virtual void ParseNodeInLua(ImportNode &node, lua_State *lua_state);
|
||||
virtual void ParseWayInLua(ExtractionWay &way, lua_State *lua_state);
|
||||
virtual void report_errors(lua_State *lua_state, const int status) const;
|
||||
private:
|
||||
void ReadUseRestrictionsSetting(lua_State *lua_state);
|
||||
void ReadRestrictionExceptions(lua_State *lua_state);
|
||||
bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
|
||||
|
||||
protected:
|
||||
virtual void ReadUseRestrictionsSetting();
|
||||
virtual void ReadRestrictionExceptions();
|
||||
virtual bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
|
||||
|
||||
ExtractorCallbacks *extractor_callbacks;
|
||||
lua_State *lua_state;
|
||||
ScriptingEnvironment &scripting_environment;
|
||||
// lua_State *lua_state;
|
||||
std::vector<std::string> restriction_exceptions;
|
||||
bool use_turn_restrictions;
|
||||
};
|
||||
|
||||
#endif /* BASEPARSER_H_ */
|
||||
#endif /* RESTRICTION_PARSER_H_ */
|
@ -28,16 +28,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
#include "ExtractionHelperFunctions.h"
|
||||
#include "ExtractionNode.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../DataStructures/ExternalMemoryNode.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <luabind/tag_function.hpp>
|
||||
|
||||
#include <osmium/osm.hpp>
|
||||
|
||||
#include <sstream>
|
||||
namespace {
|
||||
// wrapper method as luabind doesn't automatically overload funcs w/ default parameters
|
||||
template<class T>
|
||||
auto get_value_by_key(T const& object, const char *key) -> decltype(object.get_value_by_key(key))
|
||||
{
|
||||
return object.get_value_by_key(key, "");
|
||||
}
|
||||
|
||||
int lua_error_callback(lua_State *L) // This is so I can use my own function as an
|
||||
// exception handler, pcall_log()
|
||||
{
|
||||
luabind::object error_msg(luabind::from_stack(L, -1));
|
||||
std::ostringstream error_stream;
|
||||
error_stream << error_msg;
|
||||
throw OSRMException("ERROR occured in profile script:\n" + error_stream.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ScriptingEnvironment::ScriptingEnvironment() {}
|
||||
ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
|
||||
: file_name(file_name)
|
||||
{
|
||||
@ -46,6 +68,8 @@ ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
|
||||
|
||||
void ScriptingEnvironment::initLuaState(lua_State* lua_state)
|
||||
{
|
||||
typedef double (osmium::Location::* location_member_ptr_type)() const;
|
||||
|
||||
luabind::open(lua_state);
|
||||
// open utility libraries string library;
|
||||
luaL_openlibs(lua_state);
|
||||
@ -58,33 +82,31 @@ void ScriptingEnvironment::initLuaState(lua_State* lua_state)
|
||||
luabind::def("durationIsValid", durationIsValid),
|
||||
luabind::def("parseDuration", parseDuration),
|
||||
|
||||
luabind::class_<HashTable<std::string, std::string>>("keyVals")
|
||||
.def("Add", &HashTable<std::string, std::string>::Add)
|
||||
.def("Find", &HashTable<std::string, std::string>::Find)
|
||||
.def("Holds", &HashTable<std::string, std::string>::Holds),
|
||||
luabind::class_<std::vector<std::string>>("vector")
|
||||
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(&std::vector<std::string>::push_back)),
|
||||
|
||||
luabind::class_<ImportNode>("Node")
|
||||
// .def(luabind::constructor<>())
|
||||
.def_readwrite("lat", &ImportNode::lat)
|
||||
.def_readwrite("lon", &ImportNode::lon)
|
||||
.def_readonly("id", &ImportNode::node_id)
|
||||
.def_readwrite("bollard", &ImportNode::bollard)
|
||||
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
||||
.def_readwrite("tags", &ImportNode::keyVals),
|
||||
luabind::class_<osmium::Location>("Location")
|
||||
.def<location_member_ptr_type>("lat", &osmium::Location::lat)
|
||||
.def<location_member_ptr_type>("lon", &osmium::Location::lon),
|
||||
|
||||
luabind::class_<ExtractionWay>("Way")
|
||||
luabind::class_<osmium::Node>("Node")
|
||||
// .def<node_member_ptr_type>("tags", &osmium::Node::tags)
|
||||
.def("get_value_by_key", &osmium::Node::get_value_by_key)
|
||||
.def("get_value_by_key", &get_value_by_key<osmium::Node>),
|
||||
|
||||
luabind::class_<ExtractionNode>("ResultNode")
|
||||
.def_readwrite("traffic_lights", &ExtractionNode::traffic_lights)
|
||||
.def_readwrite("barrier", &ExtractionNode::barrier),
|
||||
|
||||
luabind::class_<ExtractionWay>("ResultWay")
|
||||
// .def(luabind::constructor<>())
|
||||
.def_readonly("id", &ExtractionWay::id)
|
||||
.def_readwrite("name", &ExtractionWay::name)
|
||||
.def_readwrite("forward_speed", &ExtractionWay::forward_speed)
|
||||
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
||||
.def_readwrite("duration", &ExtractionWay::duration)
|
||||
.def_readwrite("access", &ExtractionWay::access)
|
||||
.def_readwrite("name", &ExtractionWay::name)
|
||||
.def_readwrite("roundabout", &ExtractionWay::roundabout)
|
||||
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
|
||||
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
|
||||
.def_readwrite("tags", &ExtractionWay::keyVals)
|
||||
.property("direction", &ExtractionWay::get_direction, &ExtractionWay::set_direction)
|
||||
.def_readwrite("is_access_restricted", &ExtractionWay::is_access_restricted)
|
||||
.def_readwrite("ignore_in_index", &ExtractionWay::ignore_in_grid)
|
||||
.def_readwrite("duration", &ExtractionWay::duration)
|
||||
.property("forward_mode", &ExtractionWay::get_forward_mode, &ExtractionWay::set_forward_mode)
|
||||
.property("backward_mode", &ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode)
|
||||
.enum_("constants")[
|
||||
@ -93,8 +115,9 @@ void ScriptingEnvironment::initLuaState(lua_State* lua_state)
|
||||
luabind::value("bidirectional", 2),
|
||||
luabind::value("opposite", 3)
|
||||
],
|
||||
luabind::class_<std::vector<std::string>>("vector")
|
||||
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(&std::vector<std::string>::push_back))
|
||||
luabind::class_<osmium::Way>("Way")
|
||||
.def("get_value_by_key", &osmium::Way::get_value_by_key)
|
||||
.def("get_value_by_key", &get_value_by_key<osmium::Way>)
|
||||
];
|
||||
|
||||
if (0 != luaL_dofile(lua_state, file_name.c_str()))
|
||||
@ -116,6 +139,7 @@ lua_State *ScriptingEnvironment::getLuaState()
|
||||
ref = state;
|
||||
initLuaState(ref.get());
|
||||
}
|
||||
luabind::set_pcall_callback(&lua_error_callback);
|
||||
|
||||
return ref.get();
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ struct lua_State;
|
||||
class ScriptingEnvironment
|
||||
{
|
||||
public:
|
||||
ScriptingEnvironment();
|
||||
ScriptingEnvironment() = delete;
|
||||
explicit ScriptingEnvironment(const char *file_name);
|
||||
|
||||
lua_State *getLuaState();
|
||||
|
@ -1,354 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "XMLParser.h"
|
||||
|
||||
#include "ExtractionWay.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../DataStructures/InputReaderFactory.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/cast.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
XMLParser::XMLParser(const char *filename,
|
||||
ExtractorCallbacks *extractor_callbacks,
|
||||
ScriptingEnvironment &scripting_environment)
|
||||
: BaseParser(extractor_callbacks, scripting_environment)
|
||||
{
|
||||
inputReader = inputReaderFactory(filename);
|
||||
}
|
||||
|
||||
bool XMLParser::ReadHeader() { return xmlTextReaderRead(inputReader) == 1; }
|
||||
bool XMLParser::Parse()
|
||||
{
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int type = xmlTextReaderNodeType(inputReader);
|
||||
|
||||
// 1 is Element
|
||||
if (type != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
xmlChar *currentName = xmlTextReaderName(inputReader);
|
||||
if (currentName == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
|
||||
{
|
||||
ImportNode current_node = ReadXMLNode();
|
||||
ParseNodeInLua(current_node, lua_state);
|
||||
extractor_callbacks->ProcessNode(current_node);
|
||||
}
|
||||
|
||||
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
|
||||
{
|
||||
ExtractionWay way = ReadXMLWay();
|
||||
ParseWayInLua(way, lua_state);
|
||||
extractor_callbacks->ProcessWay(way);
|
||||
}
|
||||
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
|
||||
{
|
||||
InputRestrictionContainer current_restriction = ReadXMLRestriction();
|
||||
if ((UINT_MAX != current_restriction.fromWay) &&
|
||||
!extractor_callbacks->ProcessRestriction(current_restriction))
|
||||
{
|
||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||
}
|
||||
}
|
||||
xmlFree(currentName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
||||
{
|
||||
|
||||
InputRestrictionContainer restriction;
|
||||
|
||||
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||
{
|
||||
return restriction;
|
||||
}
|
||||
|
||||
std::string except_tag_string;
|
||||
const int depth = xmlTextReaderDepth(inputReader);
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int child_type = xmlTextReaderNodeType(inputReader);
|
||||
if (child_type != 1 && child_type != 15)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||
if (child_name == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (depth == child_depth && child_type == 15 &&
|
||||
xmlStrEqual(child_name, (const xmlChar *)"relation") == 1)
|
||||
{
|
||||
xmlFree(child_name);
|
||||
break;
|
||||
}
|
||||
if (child_type != 1)
|
||||
{
|
||||
xmlFree(child_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||
{
|
||||
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||
if (key != nullptr && value != nullptr)
|
||||
{
|
||||
if (xmlStrEqual(key, (const xmlChar *)"restriction") &&
|
||||
StringStartsWith((const char *)value, "only_"))
|
||||
{
|
||||
restriction.restriction.flags.isOnly = true;
|
||||
}
|
||||
if (xmlStrEqual(key, (const xmlChar *)"except"))
|
||||
{
|
||||
except_tag_string = (const char *)value;
|
||||
}
|
||||
}
|
||||
|
||||
if (key != nullptr)
|
||||
{
|
||||
xmlFree(key);
|
||||
}
|
||||
if (value != nullptr)
|
||||
{
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
else if (xmlStrEqual(child_name, (const xmlChar *)"member") == 1)
|
||||
{
|
||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||
if (ref != nullptr)
|
||||
{
|
||||
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
|
||||
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
|
||||
|
||||
if (xmlStrEqual(role, (const xmlChar *)"to") &&
|
||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||
{
|
||||
restriction.toWay = cast::string_to_uint((const char *)ref);
|
||||
}
|
||||
if (xmlStrEqual(role, (const xmlChar *)"from") &&
|
||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||
{
|
||||
restriction.fromWay = cast::string_to_uint((const char *)ref);
|
||||
}
|
||||
if (xmlStrEqual(role, (const xmlChar *)"via") &&
|
||||
xmlStrEqual(type, (const xmlChar *)"node"))
|
||||
{
|
||||
restriction.restriction.viaNode = cast::string_to_uint((const char *)ref);
|
||||
}
|
||||
|
||||
if (nullptr != type)
|
||||
{
|
||||
xmlFree(type);
|
||||
}
|
||||
if (nullptr != role)
|
||||
{
|
||||
xmlFree(role);
|
||||
}
|
||||
if (nullptr != ref)
|
||||
{
|
||||
xmlFree(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlFree(child_name);
|
||||
}
|
||||
|
||||
if (ShouldIgnoreRestriction(except_tag_string))
|
||||
{
|
||||
restriction.fromWay = UINT_MAX; // workaround to ignore the restriction
|
||||
}
|
||||
return restriction;
|
||||
}
|
||||
|
||||
ExtractionWay XMLParser::ReadXMLWay()
|
||||
{
|
||||
ExtractionWay way;
|
||||
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||
{
|
||||
return way;
|
||||
}
|
||||
const int depth = xmlTextReaderDepth(inputReader);
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int child_type = xmlTextReaderNodeType(inputReader);
|
||||
if (child_type != 1 && child_type != 15)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||
if (child_name == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (depth == child_depth && child_type == 15 &&
|
||||
xmlStrEqual(child_name, (const xmlChar *)"way") == 1)
|
||||
{
|
||||
xmlChar *way_id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||
way.id = cast::string_to_uint((char *)way_id);
|
||||
xmlFree(way_id);
|
||||
xmlFree(child_name);
|
||||
break;
|
||||
}
|
||||
if (child_type != 1)
|
||||
{
|
||||
xmlFree(child_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||
{
|
||||
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||
|
||||
if (key != nullptr && value != nullptr)
|
||||
{
|
||||
way.keyVals.Add(std::string((char *)key), std::string((char *)value));
|
||||
}
|
||||
if (key != nullptr)
|
||||
{
|
||||
xmlFree(key);
|
||||
}
|
||||
if (value != nullptr)
|
||||
{
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
else if (xmlStrEqual(child_name, (const xmlChar *)"nd") == 1)
|
||||
{
|
||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||
if (ref != nullptr)
|
||||
{
|
||||
way.path.push_back(cast::string_to_uint((const char *)ref));
|
||||
xmlFree(ref);
|
||||
}
|
||||
}
|
||||
xmlFree(child_name);
|
||||
}
|
||||
return way;
|
||||
}
|
||||
|
||||
ImportNode XMLParser::ReadXMLNode()
|
||||
{
|
||||
ImportNode node;
|
||||
|
||||
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
|
||||
if (attribute != nullptr)
|
||||
{
|
||||
node.lat = static_cast<int>(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute));
|
||||
xmlFree(attribute);
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
|
||||
if (attribute != nullptr)
|
||||
{
|
||||
node.lon = static_cast<int>(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute));
|
||||
xmlFree(attribute);
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||
if (attribute != nullptr)
|
||||
{
|
||||
node.node_id = cast::string_to_uint((const char *)attribute);
|
||||
xmlFree(attribute);
|
||||
}
|
||||
|
||||
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
const int depth = xmlTextReaderDepth(inputReader);
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int child_type = xmlTextReaderNodeType(inputReader);
|
||||
// 1 = Element, 15 = EndElement
|
||||
if (child_type != 1 && child_type != 15)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||
if (child_name == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (depth == child_depth && child_type == 15 &&
|
||||
xmlStrEqual(child_name, (const xmlChar *)"node") == 1)
|
||||
{
|
||||
xmlFree(child_name);
|
||||
break;
|
||||
}
|
||||
if (child_type != 1)
|
||||
{
|
||||
xmlFree(child_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||
{
|
||||
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||
if (key != nullptr && value != nullptr)
|
||||
{
|
||||
node.keyVals.Add(std::string((char *)(key)), std::string((char *)(value)));
|
||||
}
|
||||
if (key != nullptr)
|
||||
{
|
||||
xmlFree(key);
|
||||
}
|
||||
if (value != nullptr)
|
||||
{
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
|
||||
xmlFree(child_name);
|
||||
}
|
||||
return node;
|
||||
}
|
@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
// Exposes all data access interfaces to the algorithms via base class ptr
|
||||
|
||||
#include "../../DataStructures/EdgeBasedNode.h"
|
||||
#include "../../DataStructures/ImportNode.h"
|
||||
#include "../../DataStructures/ExternalMemoryNode.h"
|
||||
#include "../../DataStructures/phantom_node.hpp"
|
||||
#include "../../DataStructures/Range.h"
|
||||
#include "../../DataStructures/TurnInstructions.h"
|
||||
|
@ -126,14 +126,14 @@ template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<Edge
|
||||
{
|
||||
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
|
||||
|
||||
NodeInfo current_node;
|
||||
QueryNode current_node;
|
||||
unsigned number_of_coordinates = 0;
|
||||
nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
|
||||
m_coordinate_list =
|
||||
std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates);
|
||||
for (unsigned i = 0; i < number_of_coordinates; ++i)
|
||||
{
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode));
|
||||
m_coordinate_list->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
|
||||
BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lat) >> 30) == 0);
|
||||
BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lon) >> 30) == 0);
|
||||
|
@ -36,6 +36,6 @@ enum CompressionType
|
||||
gzipRFC1952,
|
||||
deflateRFC1951 };
|
||||
|
||||
} // namespace http
|
||||
}
|
||||
|
||||
#endif // COMPRESSION_TYPE_H
|
||||
|
783
ThirdParty/osmium/area/assembler.hpp
vendored
Normal file
783
ThirdParty/osmium/area/assembler.hpp
vendored
Normal file
@ -0,0 +1,783 @@
|
||||
#ifndef OSMIUM_AREA_ASSEMBLER_HPP
|
||||
#define OSMIUM_AREA_ASSEMBLER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/area.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/tags/filter.hpp>
|
||||
|
||||
#include <osmium/area/detail/proto_ring.hpp>
|
||||
#include <osmium/area/detail/node_ref_segment.hpp>
|
||||
#include <osmium/area/detail/segment_list.hpp>
|
||||
#include <osmium/area/problem_reporter.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
using osmium::area::detail::ProtoRing;
|
||||
|
||||
struct AssemblerConfig {
|
||||
|
||||
osmium::area::ProblemReporter* problem_reporter;
|
||||
|
||||
// Enables debug output to stderr
|
||||
bool debug;
|
||||
|
||||
explicit AssemblerConfig(osmium::area::ProblemReporter* pr = nullptr, bool d=false) :
|
||||
problem_reporter(pr),
|
||||
debug(d) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable debug output to stderr. This is for Osmium
|
||||
* developers only.
|
||||
*/
|
||||
void enable_debug_output(bool d=true) {
|
||||
debug = d;
|
||||
}
|
||||
|
||||
}; // struct AssemblerConfig
|
||||
|
||||
/**
|
||||
* Assembles area objects from multipolygon relations and their
|
||||
* members. This is called by the MultipolygonCollector object
|
||||
* after all members have been collected.
|
||||
*/
|
||||
class Assembler {
|
||||
|
||||
const AssemblerConfig m_config;
|
||||
|
||||
// The way segments
|
||||
osmium::area::detail::SegmentList m_segment_list;
|
||||
|
||||
// The rings we are building from the way segments
|
||||
std::list<ProtoRing> m_rings;
|
||||
|
||||
std::vector<ProtoRing*> m_outer_rings;
|
||||
std::vector<ProtoRing*> m_inner_rings;
|
||||
|
||||
int m_inner_outer_mismatches { 0 };
|
||||
|
||||
bool debug() const {
|
||||
return m_config.debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given NodeRefs have the same location.
|
||||
* Uses the actual location for the test, not the id. If both
|
||||
* have the same location, but not the same id, a problem
|
||||
* point will be added to the list of problem points.
|
||||
*/
|
||||
bool has_same_location(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) {
|
||||
if (nr1.location() != nr2.location()) {
|
||||
return false;
|
||||
}
|
||||
if (nr1.ref() != nr2.ref()) {
|
||||
if (m_config.problem_reporter) {
|
||||
m_config.problem_reporter->report_duplicate_node(nr1.ref(), nr2.ref(), nr1.location());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const {
|
||||
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
||||
for (const osmium::Tag& tag : way.tags()) {
|
||||
tl_builder.add_tag(tag.key(), tag.value());
|
||||
}
|
||||
}
|
||||
|
||||
void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set<const osmium::Way*>& ways) const {
|
||||
std::map<std::string, size_t> counter;
|
||||
for (const osmium::Way* way : ways) {
|
||||
for (const auto& tag : way->tags()) {
|
||||
std::string kv {tag.key()};
|
||||
kv.append(1, '\0');
|
||||
kv.append(tag.value());
|
||||
++counter[kv];
|
||||
}
|
||||
}
|
||||
|
||||
size_t num_ways = ways.size();
|
||||
for (const auto& t_c : counter) {
|
||||
if (debug()) {
|
||||
std::cerr << " tag " << t_c.first << " is used " << t_c.second << " times in " << num_ways << " ways\n";
|
||||
}
|
||||
if (t_c.second == num_ways) {
|
||||
size_t len = std::strlen(t_c.first.c_str());
|
||||
tl_builder.add_tag(t_c.first.c_str(), t_c.first.c_str() + len + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MPFilter : public osmium::tags::KeyFilter {
|
||||
|
||||
MPFilter() : osmium::tags::KeyFilter(true) {
|
||||
add(false, "type");
|
||||
add(false, "created_by");
|
||||
add(false, "source");
|
||||
add(false, "note");
|
||||
add(false, "test:id");
|
||||
add(false, "test:section");
|
||||
}
|
||||
|
||||
}; // struct MPFilter
|
||||
|
||||
static MPFilter& filter() {
|
||||
static MPFilter filter;
|
||||
return filter;
|
||||
}
|
||||
|
||||
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Relation& relation) const {
|
||||
auto count = std::count_if(relation.tags().begin(), relation.tags().end(), filter());
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " found " << count << " tags on relation (without ignored ones)\n";
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
if (debug()) {
|
||||
std::cerr << " use tags from relation\n";
|
||||
}
|
||||
|
||||
// write out all tags except type=*
|
||||
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
||||
for (const osmium::Tag& tag : relation.tags()) {
|
||||
if (strcmp(tag.key(), "type")) {
|
||||
tl_builder.add_tag(tag.key(), tag.value());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (debug()) {
|
||||
std::cerr << " use tags from outer ways\n";
|
||||
}
|
||||
std::set<const osmium::Way*> ways;
|
||||
for (const auto& ring : m_outer_rings) {
|
||||
ring->get_ways(ways);
|
||||
}
|
||||
if (ways.size() == 1) {
|
||||
if (debug()) {
|
||||
std::cerr << " only one outer way\n";
|
||||
}
|
||||
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
||||
for (const osmium::Tag& tag : (*ways.begin())->tags()) {
|
||||
tl_builder.add_tag(tag.key(), tag.value());
|
||||
}
|
||||
} else {
|
||||
if (debug()) {
|
||||
std::cerr << " multiple outer ways, get common tags\n";
|
||||
}
|
||||
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
||||
add_common_tags(tl_builder, ways);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through all the rings and find rings that are not closed.
|
||||
* Problems are reported through the problem reporter.
|
||||
*
|
||||
* @returns true if any rings were not closed, false otherwise
|
||||
*/
|
||||
bool check_for_open_rings() {
|
||||
bool open_rings = false;
|
||||
|
||||
for (const auto& ring : m_rings) {
|
||||
if (!ring.closed()) {
|
||||
open_rings = true;
|
||||
if (m_config.problem_reporter) {
|
||||
m_config.problem_reporter->report_ring_not_closed(ring.get_segment_front().first().location(), ring.get_segment_back().second().location());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return open_rings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether there are any rings that can be combined with the
|
||||
* given ring to one larger ring by appending the other ring to
|
||||
* the end of this ring.
|
||||
* If the rings can be combined they are and the function returns
|
||||
* true.
|
||||
*/
|
||||
bool possibly_combine_rings_back(ProtoRing& ring) {
|
||||
const osmium::NodeRef& nr = ring.get_segment_back().second();
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " possibly_combine_rings_back()\n";
|
||||
}
|
||||
for (auto it = m_rings.begin(); it != m_rings.end(); ++it) {
|
||||
if (&*it != &ring && !it->closed()) {
|
||||
if (has_same_location(nr, it->get_segment_front().first())) {
|
||||
if (debug()) {
|
||||
std::cerr << " ring.last=it->first\n";
|
||||
}
|
||||
ring.merge_ring(*it, debug());
|
||||
m_rings.erase(it);
|
||||
return true;
|
||||
}
|
||||
if (has_same_location(nr, it->get_segment_back().second())) {
|
||||
if (debug()) {
|
||||
std::cerr << " ring.last=it->last\n";
|
||||
}
|
||||
ring.merge_ring_reverse(*it, debug());
|
||||
m_rings.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether there are any rings that can be combined with the
|
||||
* given ring to one larger ring by prepending the other ring to
|
||||
* the start of this ring.
|
||||
* If the rings can be combined they are and the function returns
|
||||
* true.
|
||||
*/
|
||||
bool possibly_combine_rings_front(ProtoRing& ring) {
|
||||
const osmium::NodeRef& nr = ring.get_segment_front().first();
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " possibly_combine_rings_front()\n";
|
||||
}
|
||||
for (auto it = m_rings.begin(); it != m_rings.end(); ++it) {
|
||||
if (&*it != &ring && !it->closed()) {
|
||||
if (has_same_location(nr, it->get_segment_back().second())) {
|
||||
if (debug()) {
|
||||
std::cerr << " ring.first=it->last\n";
|
||||
}
|
||||
ring.swap_segments(*it);
|
||||
ring.merge_ring(*it, debug());
|
||||
m_rings.erase(it);
|
||||
return true;
|
||||
}
|
||||
if (has_same_location(nr, it->get_segment_front().first())) {
|
||||
if (debug()) {
|
||||
std::cerr << " ring.first=it->first\n";
|
||||
}
|
||||
ring.reverse();
|
||||
ring.merge_ring(*it, debug());
|
||||
m_rings.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void split_off_subring(osmium::area::detail::ProtoRing& ring, osmium::area::detail::ProtoRing::segments_type::iterator it, osmium::area::detail::ProtoRing::segments_type::iterator it_begin, osmium::area::detail::ProtoRing::segments_type::iterator it_end) {
|
||||
if (debug()) {
|
||||
std::cerr << " subring found at: " << *it << "\n";
|
||||
}
|
||||
ProtoRing new_ring(it_begin, it_end);
|
||||
ring.remove_segments(it_begin, it_end);
|
||||
if (debug()) {
|
||||
std::cerr << " split into two rings:\n";
|
||||
std::cerr << " " << new_ring << "\n";
|
||||
std::cerr << " " << ring << "\n";
|
||||
}
|
||||
m_rings.push_back(std::move(new_ring));
|
||||
}
|
||||
|
||||
bool has_closed_subring_back(ProtoRing& ring, const NodeRef& nr) {
|
||||
if (ring.segments().size() < 3) {
|
||||
return false;
|
||||
}
|
||||
if (debug()) {
|
||||
std::cerr << " has_closed_subring_back()\n";
|
||||
}
|
||||
auto end = ring.segments().end();
|
||||
for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
|
||||
if (has_same_location(nr, it->first())) {
|
||||
split_off_subring(ring, it, it, end);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_closed_subring_front(ProtoRing& ring, const NodeRef& nr) {
|
||||
if (ring.segments().size() < 3) {
|
||||
return false;
|
||||
}
|
||||
if (debug()) {
|
||||
std::cerr << " has_closed_subring_front()\n";
|
||||
}
|
||||
auto end = ring.segments().end();
|
||||
for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
|
||||
if (has_same_location(nr, it->second())) {
|
||||
split_off_subring(ring, it, ring.segments().begin(), it+1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_for_closed_subring(ProtoRing& ring) {
|
||||
if (debug()) {
|
||||
std::cerr << " check_for_closed_subring()\n";
|
||||
}
|
||||
|
||||
osmium::area::detail::ProtoRing::segments_type segments(ring.segments().size());
|
||||
std::copy(ring.segments().begin(), ring.segments().end(), segments.begin());
|
||||
std::sort(segments.begin(), segments.end());
|
||||
auto it = std::adjacent_find(segments.begin(), segments.end(), [this](const osmium::area::detail::NodeRefSegment& s1, const osmium::area::detail::NodeRefSegment& s2) {
|
||||
return has_same_location(s1.first(), s2.first());
|
||||
});
|
||||
if (it == segments.end()) {
|
||||
return false;
|
||||
}
|
||||
auto r1 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it, it+1);
|
||||
assert(r1 != ring.segments().end());
|
||||
auto r2 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it+1, it+2);
|
||||
assert(r2 != ring.segments().end());
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " found subring in ring " << ring << " at " << it->first() << "\n";
|
||||
}
|
||||
|
||||
auto m = std::minmax(r1, r2);
|
||||
|
||||
ProtoRing new_ring(m.first, m.second);
|
||||
ring.remove_segments(m.first, m.second);
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " split ring1=" << new_ring << "\n";
|
||||
std::cerr << " split ring2=" << ring << "\n";
|
||||
}
|
||||
|
||||
m_rings.emplace_back(new_ring);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void combine_rings_front(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) {
|
||||
if (debug()) {
|
||||
std::cerr << " => match at front of ring\n";
|
||||
}
|
||||
ring.add_segment_front(segment);
|
||||
has_closed_subring_front(ring, segment.first());
|
||||
if (possibly_combine_rings_front(ring)) {
|
||||
check_for_closed_subring(ring);
|
||||
}
|
||||
}
|
||||
|
||||
void combine_rings_back(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) {
|
||||
if (debug()) {
|
||||
std::cerr << " => match at back of ring\n";
|
||||
}
|
||||
ring.add_segment_back(segment);
|
||||
has_closed_subring_back(ring, segment.second());
|
||||
if (possibly_combine_rings_back(ring)) {
|
||||
check_for_closed_subring(ring);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append each outer ring together with its inner rings to the
|
||||
* area in the buffer.
|
||||
*/
|
||||
void add_rings_to_area(osmium::builder::AreaBuilder& builder) const {
|
||||
for (const ProtoRing* ring : m_outer_rings) {
|
||||
if (debug()) {
|
||||
std::cerr << " ring " << *ring << " is outer\n";
|
||||
}
|
||||
{
|
||||
osmium::builder::OuterRingBuilder ring_builder(builder.buffer(), &builder);
|
||||
ring_builder.add_node_ref(ring->get_segment_front().first());
|
||||
for (const auto& segment : ring->segments()) {
|
||||
ring_builder.add_node_ref(segment.second());
|
||||
}
|
||||
}
|
||||
for (ProtoRing* inner : ring->inner_rings()) {
|
||||
osmium::builder::InnerRingBuilder ring_builder(builder.buffer(), &builder);
|
||||
ring_builder.add_node_ref(inner->get_segment_front().first());
|
||||
for (const auto& segment : inner->segments()) {
|
||||
ring_builder.add_node_ref(segment.second());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool add_to_existing_ring(osmium::area::detail::NodeRefSegment segment) {
|
||||
int n=0;
|
||||
for (auto& ring : m_rings) {
|
||||
if (debug()) {
|
||||
std::cerr << " check against ring " << n << " " << ring;
|
||||
}
|
||||
if (ring.closed()) {
|
||||
if (debug()) {
|
||||
std::cerr << " => ring CLOSED\n";
|
||||
}
|
||||
} else {
|
||||
if (has_same_location(ring.get_segment_back().second(), segment.first())) {
|
||||
combine_rings_back(segment, ring);
|
||||
return true;
|
||||
}
|
||||
if (has_same_location(ring.get_segment_back().second(), segment.second())) {
|
||||
segment.swap_locations();
|
||||
combine_rings_back(segment, ring);
|
||||
return true;
|
||||
}
|
||||
if (has_same_location(ring.get_segment_front().first(), segment.first())) {
|
||||
segment.swap_locations();
|
||||
combine_rings_front(segment, ring);
|
||||
return true;
|
||||
}
|
||||
if (has_same_location(ring.get_segment_front().first(), segment.second())) {
|
||||
combine_rings_front(segment, ring);
|
||||
return true;
|
||||
}
|
||||
if (debug()) {
|
||||
std::cerr << " => no match\n";
|
||||
}
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void check_inner_outer(ProtoRing& ring) {
|
||||
const osmium::NodeRef& min_node = ring.min_node();
|
||||
if (debug()) {
|
||||
std::cerr << " check_inner_outer min_node=" << min_node << "\n";
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int above = 0;
|
||||
|
||||
for (auto it = m_segment_list.begin(); it != m_segment_list.end() && it->first().location().x() <= min_node.location().x(); ++it) {
|
||||
if (!ring.contains(*it)) {
|
||||
if (debug()) {
|
||||
std::cerr << " segments for count: " << *it;
|
||||
}
|
||||
if (it->to_left_of(min_node.location())) {
|
||||
++count;
|
||||
if (debug()) {
|
||||
std::cerr << " counted\n";
|
||||
}
|
||||
} else {
|
||||
if (debug()) {
|
||||
std::cerr << " not counted\n";
|
||||
}
|
||||
}
|
||||
if (it->first().location() == min_node.location()) {
|
||||
if (it->second().location().y() > min_node.location().y()) {
|
||||
++above;
|
||||
}
|
||||
}
|
||||
if (it->second().location() == min_node.location()) {
|
||||
if (it->first().location().y() > min_node.location().y()) {
|
||||
++above;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " count=" << count << " above=" << above << "\n";
|
||||
}
|
||||
|
||||
count += above % 2;
|
||||
|
||||
if (count % 2) {
|
||||
ring.set_inner();
|
||||
}
|
||||
}
|
||||
|
||||
void check_inner_outer_roles() {
|
||||
if (debug()) {
|
||||
std::cerr << " check_inner_outer_roles\n";
|
||||
}
|
||||
|
||||
for (const auto ringptr : m_outer_rings) {
|
||||
for (const auto segment : ringptr->segments()) {
|
||||
if (!segment.role_outer()) {
|
||||
++m_inner_outer_mismatches;
|
||||
if (debug()) {
|
||||
std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'outer'\n";
|
||||
}
|
||||
if (m_config.problem_reporter) {
|
||||
m_config.problem_reporter->report_role_should_be_outer(segment.way()->id(), segment.first().location(), segment.second().location());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto ringptr : m_inner_rings) {
|
||||
for (const auto segment : ringptr->segments()) {
|
||||
if (!segment.role_inner()) {
|
||||
++m_inner_outer_mismatches;
|
||||
if (debug()) {
|
||||
std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'inner'\n";
|
||||
}
|
||||
if (m_config.problem_reporter) {
|
||||
m_config.problem_reporter->report_role_should_be_inner(segment.way()->id(), segment.first().location(), segment.second().location());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create rings from segments.
|
||||
*/
|
||||
bool create_rings() {
|
||||
m_segment_list.sort();
|
||||
m_segment_list.erase_duplicate_segments();
|
||||
|
||||
// Now we look for segments crossing each other. If there are
|
||||
// any, the multipolygon is invalid.
|
||||
// In the future this could be improved by trying to fix those
|
||||
// cases.
|
||||
if (m_segment_list.find_intersections(m_config.problem_reporter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now iterator over all segments and add them to rings. Each segment
|
||||
// is tacked on to either end of an existing ring if possible, or a
|
||||
// new ring is started with it.
|
||||
for (const auto& segment : m_segment_list) {
|
||||
if (debug()) {
|
||||
std::cerr << " checking segment " << segment << "\n";
|
||||
}
|
||||
if (!add_to_existing_ring(segment)) {
|
||||
if (debug()) {
|
||||
std::cerr << " new ring for segment " << segment << "\n";
|
||||
}
|
||||
m_rings.emplace_back(segment);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " Rings:\n";
|
||||
for (const auto& ring : m_rings) {
|
||||
std::cerr << " " << ring;
|
||||
if (ring.closed()) {
|
||||
std::cerr << " (closed)";
|
||||
}
|
||||
std::cerr << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (check_for_open_rings()) {
|
||||
if (debug()) {
|
||||
std::cerr << " not all rings are closed\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << " Find inner/outer...\n";
|
||||
}
|
||||
|
||||
if (m_rings.size() == 1) {
|
||||
m_outer_rings.push_back(&m_rings.front());
|
||||
} else {
|
||||
for (auto& ring : m_rings) {
|
||||
check_inner_outer(ring);
|
||||
if (ring.outer()) {
|
||||
if (!ring.is_cw()) {
|
||||
ring.reverse();
|
||||
}
|
||||
m_outer_rings.push_back(&ring);
|
||||
} else {
|
||||
if (ring.is_cw()) {
|
||||
ring.reverse();
|
||||
}
|
||||
m_inner_rings.push_back(&ring);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_outer_rings.size() == 1) {
|
||||
for (auto inner : m_inner_rings) {
|
||||
m_outer_rings.front()->add_inner_ring(inner);
|
||||
}
|
||||
} else {
|
||||
// sort outer rings by size, smallest first
|
||||
std::sort(m_outer_rings.begin(), m_outer_rings.end(), [](ProtoRing* a, ProtoRing* b) {
|
||||
return a->area() < b->area();
|
||||
});
|
||||
for (auto inner : m_inner_rings) {
|
||||
for (auto outer : m_outer_rings) {
|
||||
if (inner->is_in(outer)) {
|
||||
outer->add_inner_ring(inner);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check_inner_outer_roles();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef osmium::area::AssemblerConfig config_type;
|
||||
|
||||
explicit Assembler(const config_type& config) :
|
||||
m_config(config),
|
||||
m_segment_list(config.debug) {
|
||||
}
|
||||
|
||||
~Assembler() = default;
|
||||
|
||||
/**
|
||||
* Assemble an area from the given way.
|
||||
* The resulting area is put into the out_buffer.
|
||||
*/
|
||||
void operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) {
|
||||
if (m_config.problem_reporter) {
|
||||
m_config.problem_reporter->set_object(osmium::item_type::way, way.id());
|
||||
}
|
||||
|
||||
if (!way.ends_have_same_id()) {
|
||||
if (m_config.problem_reporter) {
|
||||
m_config.problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location());
|
||||
}
|
||||
}
|
||||
|
||||
m_segment_list.extract_segments_from_way(way, "outer");
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << "\nBuild way id()=" << way.id() << " segments.size()=" << m_segment_list.size() << "\n";
|
||||
}
|
||||
|
||||
// Now create the Area object and add the attributes and tags
|
||||
// from the relation.
|
||||
{
|
||||
osmium::builder::AreaBuilder builder(out_buffer);
|
||||
builder.initialize_from_object(way);
|
||||
|
||||
if (create_rings()) {
|
||||
add_tags_to_area(builder, way);
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
}
|
||||
out_buffer.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble an area from the given relation and its members.
|
||||
* All members are to be found in the in_buffer at the offsets
|
||||
* given by the members parameter.
|
||||
* The resulting area is put into the out_buffer.
|
||||
*/
|
||||
void operator()(const osmium::Relation& relation, const std::vector<size_t>& members, const osmium::memory::Buffer& in_buffer, osmium::memory::Buffer& out_buffer) {
|
||||
if (m_config.problem_reporter) {
|
||||
m_config.problem_reporter->set_object(osmium::item_type::relation, relation.id());
|
||||
}
|
||||
|
||||
m_segment_list.extract_segments_from_ways(relation, members, in_buffer);
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << "\nBuild relation id()=" << relation.id() << " members.size()=" << members.size() << " segments.size()=" << m_segment_list.size() << "\n";
|
||||
}
|
||||
|
||||
size_t area_offset = out_buffer.committed();
|
||||
|
||||
// Now create the Area object and add the attributes and tags
|
||||
// from the relation.
|
||||
{
|
||||
osmium::builder::AreaBuilder builder(out_buffer);
|
||||
builder.initialize_from_object(relation);
|
||||
|
||||
if (create_rings()) {
|
||||
add_tags_to_area(builder, relation);
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
}
|
||||
out_buffer.commit();
|
||||
|
||||
const osmium::TagList& area_tags = out_buffer.get<osmium::Area>(area_offset).tags(); // tags of the area we just built
|
||||
|
||||
// Find all closed ways that are inner rings and check their
|
||||
// tags. If they are not the same as the tags of the area we
|
||||
// just built, add them to a list and later build areas for
|
||||
// them, too.
|
||||
std::vector<const osmium::Way*> ways_that_should_be_areas;
|
||||
if (m_inner_outer_mismatches == 0) {
|
||||
auto memit = relation.members().begin();
|
||||
for (size_t offset : members) {
|
||||
if (!std::strcmp(memit->role(), "inner")) {
|
||||
const osmium::Way& way = in_buffer.get<const osmium::Way>(offset);
|
||||
if (way.is_closed() && way.tags().size() > 0) {
|
||||
auto d = std::count_if(way.tags().begin(), way.tags().end(), filter());
|
||||
if (d > 0) {
|
||||
osmium::tags::KeyFilter::iterator way_fi_begin(filter(), way.tags().begin(), way.tags().end());
|
||||
osmium::tags::KeyFilter::iterator way_fi_end(filter(), way.tags().end(), way.tags().end());
|
||||
osmium::tags::KeyFilter::iterator area_fi_begin(filter(), area_tags.begin(), area_tags.end());
|
||||
osmium::tags::KeyFilter::iterator area_fi_end(filter(), area_tags.end(), area_tags.end());
|
||||
|
||||
if (!std::equal(way_fi_begin, way_fi_end, area_fi_begin) || d != std::distance(area_fi_begin, area_fi_end)) {
|
||||
ways_that_should_be_areas.push_back(&way);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++memit;
|
||||
}
|
||||
}
|
||||
|
||||
// Now build areas for all ways found in the last step.
|
||||
for (const osmium::Way* way : ways_that_should_be_areas) {
|
||||
Assembler assembler(m_config);
|
||||
assembler(*way, out_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
}; // class Assembler
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_ASSEMBLER_HPP
|
262
ThirdParty/osmium/area/detail/node_ref_segment.hpp
vendored
Normal file
262
ThirdParty/osmium/area/detail/node_ref_segment.hpp
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
#ifndef OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP
|
||||
#define OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iosfwd>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
class Way;
|
||||
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* @brief Namespace for Osmium internal use
|
||||
*/
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* This helper class for the Assembler class models a segment.
|
||||
* Segments are the connection between
|
||||
* two nodes and they all have their smaller coordinate at the
|
||||
* beginning of the segment. Smaller, in this case, means smaller x
|
||||
* coordinate, and if they are the same smaller y coordinate.
|
||||
*/
|
||||
class NodeRefSegment {
|
||||
|
||||
osmium::NodeRef m_first;
|
||||
osmium::NodeRef m_second;
|
||||
|
||||
/// Role of the member this segment was from.
|
||||
const char* m_role;
|
||||
|
||||
/// Way this segment was from.
|
||||
const osmium::Way* m_way;
|
||||
|
||||
public:
|
||||
|
||||
void swap_locations() {
|
||||
using std::swap;
|
||||
swap(m_first, m_second);
|
||||
}
|
||||
|
||||
explicit NodeRefSegment() noexcept :
|
||||
m_first(),
|
||||
m_second(),
|
||||
m_role(nullptr),
|
||||
m_way(nullptr) {
|
||||
}
|
||||
|
||||
explicit NodeRefSegment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2, const char* role, const osmium::Way* way) :
|
||||
m_first(nr1),
|
||||
m_second(nr2),
|
||||
m_role(role),
|
||||
m_way(way) {
|
||||
if (nr2.location() < nr1.location()) {
|
||||
swap_locations();
|
||||
}
|
||||
}
|
||||
|
||||
NodeRefSegment(const NodeRefSegment&) = default;
|
||||
NodeRefSegment(NodeRefSegment&&) = default;
|
||||
|
||||
NodeRefSegment& operator=(const NodeRefSegment&) = default;
|
||||
NodeRefSegment& operator=(NodeRefSegment&&) = default;
|
||||
|
||||
~NodeRefSegment() = default;
|
||||
|
||||
/// Return first NodeRef of Segment according to sorting order (bottom left to top right).
|
||||
const osmium::NodeRef& first() const noexcept {
|
||||
return m_first;
|
||||
}
|
||||
|
||||
/// Return second NodeRef of Segment according to sorting order (bottom left to top right).
|
||||
const osmium::NodeRef& second() const noexcept {
|
||||
return m_second;
|
||||
}
|
||||
|
||||
bool to_left_of(const osmium::Location location) const {
|
||||
// std::cerr << "segment " << first() << "--" << second() << " to_left_of(" << location << "\n";
|
||||
|
||||
if (first().location() == location || second().location() == location) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::pair<osmium::Location, osmium::Location> mm = std::minmax(first().location(), second().location(), [](const osmium::Location a, const osmium::Location b) {
|
||||
return a.y() < b.y();
|
||||
});
|
||||
|
||||
if (mm.first.y() >= location.y() || mm.second.y() < location.y() || first().location().x() > location.x()) {
|
||||
// std::cerr << " false\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t ax = mm.first.x();
|
||||
int64_t bx = mm.second.x();
|
||||
int64_t lx = location.x();
|
||||
int64_t ay = mm.first.y();
|
||||
int64_t by = mm.second.y();
|
||||
int64_t ly = location.y();
|
||||
return ((bx - ax)*(ly - ay) - (by - ay)*(lx - ax)) <= 0;
|
||||
}
|
||||
|
||||
bool role_outer() const noexcept {
|
||||
return !strcmp(m_role, "outer");
|
||||
}
|
||||
|
||||
bool role_inner() const noexcept {
|
||||
return !strcmp(m_role, "inner");
|
||||
}
|
||||
|
||||
const osmium::Way* way() const noexcept {
|
||||
return m_way;
|
||||
}
|
||||
|
||||
}; // class NodeRefSegment
|
||||
|
||||
/// NodeRefSegments are equal if both their locations are equal
|
||||
inline bool operator==(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
return lhs.first().location() == rhs.first().location() && lhs.second().location() == rhs.second().location();
|
||||
}
|
||||
|
||||
inline bool operator!=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* NodeRefSegments are "smaller" if they are to the left and down of another
|
||||
* segment. The first() location is checked first() and only if they have the
|
||||
* same first() location the second() location is taken into account.
|
||||
*/
|
||||
inline bool operator<(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
return (lhs.first().location() == rhs.first().location() && lhs.second().location() < rhs.second().location()) || lhs.first().location() < rhs.first().location();
|
||||
}
|
||||
|
||||
inline bool operator>(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
inline bool operator<=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
return ! (rhs < lhs);
|
||||
}
|
||||
|
||||
inline bool operator>=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
return ! (lhs < rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits>
|
||||
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const NodeRefSegment& segment) {
|
||||
return out << segment.first() << "--" << segment.second();
|
||||
}
|
||||
|
||||
inline bool outside_x_range(const NodeRefSegment& s1, const NodeRefSegment& s2) noexcept {
|
||||
if (s1.first().location().x() > s2.second().location().x()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool y_range_overlap(const NodeRefSegment& s1, const NodeRefSegment& s2) {
|
||||
auto m1 = std::minmax(s1.first().location().y(), s1.second().location().y());
|
||||
auto m2 = std::minmax(s2.first().location().y(), s2.second().location().y());
|
||||
if (m1.first > m2.second || m2.first > m1.second) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the intersection between to NodeRefSegments. The result is returned
|
||||
* as a Location. Note that because the Location uses integers with limited
|
||||
* precision internally, the result might be slightly different than the
|
||||
* numerically correct location.
|
||||
*
|
||||
* If the segments touch in one of their endpoints, it doesn't count as an
|
||||
* intersection.
|
||||
*
|
||||
* If the segments intersect not in a single point but in multiple points, ie
|
||||
* if they overlap, this is NOT detected.
|
||||
*
|
||||
* @returns Undefined osmium::Location if there is no intersection or a defined
|
||||
* Location if the segments intersect.
|
||||
*/
|
||||
inline osmium::Location calculate_intersection(const NodeRefSegment& s1, const NodeRefSegment& s2) {
|
||||
if (s1.first().location() == s2.first().location() ||
|
||||
s1.first().location() == s2.second().location() ||
|
||||
s1.second().location() == s2.first().location() ||
|
||||
s1.second().location() == s2.second().location()) {
|
||||
return osmium::Location();
|
||||
}
|
||||
|
||||
auto d = (static_cast<int64_t>(s2.second().y()) - static_cast<int64_t>(s2.first().y())) *
|
||||
(static_cast<int64_t>(s1.second().x()) - static_cast<int64_t>(s1.first().x())) -
|
||||
(static_cast<int64_t>(s2.second().x()) - static_cast<int64_t>(s2.first().x())) *
|
||||
(static_cast<int64_t>(s1.second().y()) - static_cast<int64_t>(s1.first().y()));
|
||||
|
||||
if (d != 0) {
|
||||
double denom = ((s2.second().lat() - s2.first().lat())*(s1.second().lon() - s1.first().lon())) -
|
||||
((s2.second().lon() - s2.first().lon())*(s1.second().lat() - s1.first().lat()));
|
||||
|
||||
double nume_a = ((s2.second().lon() - s2.first().lon())*(s1.first().lat() - s2.first().lat())) -
|
||||
((s2.second().lat() - s2.first().lat())*(s1.first().lon() - s2.first().lon()));
|
||||
|
||||
double nume_b = ((s1.second().lon() - s1.first().lon())*(s1.first().lat() - s2.first().lat())) -
|
||||
((s1.second().lat() - s1.first().lat())*(s1.first().lon() - s2.first().lon()));
|
||||
|
||||
if ((denom > 0 && nume_a >= 0 && nume_a <= denom && nume_b >= 0 && nume_b <= denom) ||
|
||||
(denom < 0 && nume_a <= 0 && nume_a >= denom && nume_b <= 0 && nume_b >= denom)) {
|
||||
double ua = nume_a / denom;
|
||||
double ix = s1.first().lon() + ua*(s1.second().lon() - s1.first().lon());
|
||||
double iy = s1.first().lat() + ua*(s1.second().lat() - s1.first().lat());
|
||||
return osmium::Location(ix, iy);
|
||||
}
|
||||
}
|
||||
|
||||
return osmium::Location();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP
|
274
ThirdParty/osmium/area/detail/proto_ring.hpp
vendored
Normal file
274
ThirdParty/osmium/area/detail/proto_ring.hpp
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
#ifndef OSMIUM_AREA_DETAIL_PROTO_RING_HPP
|
||||
#define OSMIUM_AREA_DETAIL_PROTO_RING_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/area/detail/node_ref_segment.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* A ring in the process of being built by the Assembler object.
|
||||
*/
|
||||
class ProtoRing {
|
||||
|
||||
public:
|
||||
|
||||
typedef std::vector<NodeRefSegment> segments_type;
|
||||
|
||||
private:
|
||||
|
||||
// segments in this ring
|
||||
segments_type m_segments;
|
||||
|
||||
bool m_outer {true};
|
||||
|
||||
// if this is an outer ring, these point to it's inner rings (if any)
|
||||
std::vector<ProtoRing*> m_inner;
|
||||
|
||||
public:
|
||||
|
||||
explicit ProtoRing(const NodeRefSegment& segment) noexcept :
|
||||
m_segments() {
|
||||
add_segment_back(segment);
|
||||
}
|
||||
|
||||
explicit ProtoRing(segments_type::const_iterator sbegin, segments_type::const_iterator send) :
|
||||
m_segments(static_cast<size_t>(std::distance(sbegin, send))) {
|
||||
std::copy(sbegin, send, m_segments.begin());
|
||||
}
|
||||
|
||||
bool outer() const noexcept {
|
||||
return m_outer;
|
||||
}
|
||||
|
||||
void set_inner() noexcept {
|
||||
m_outer = false;
|
||||
}
|
||||
|
||||
segments_type& segments() noexcept {
|
||||
return m_segments;
|
||||
}
|
||||
|
||||
const segments_type& segments() const noexcept {
|
||||
return m_segments;
|
||||
}
|
||||
|
||||
void remove_segments(segments_type::iterator sbegin, segments_type::iterator send) {
|
||||
m_segments.erase(sbegin, send);
|
||||
}
|
||||
|
||||
void add_segment_front(const NodeRefSegment& segment) {
|
||||
m_segments.insert(m_segments.begin(), segment);
|
||||
}
|
||||
|
||||
void add_segment_back(const NodeRefSegment& segment) {
|
||||
m_segments.push_back(segment);
|
||||
}
|
||||
|
||||
const NodeRefSegment& get_segment_front() const {
|
||||
return m_segments.front();
|
||||
}
|
||||
|
||||
NodeRefSegment& get_segment_front() {
|
||||
return m_segments.front();
|
||||
}
|
||||
|
||||
const NodeRefSegment& get_segment_back() const {
|
||||
return m_segments.back();
|
||||
}
|
||||
|
||||
NodeRefSegment& get_segment_back() {
|
||||
return m_segments.back();
|
||||
}
|
||||
|
||||
bool closed() const {
|
||||
return m_segments.front().first().location() == m_segments.back().second().location();
|
||||
}
|
||||
|
||||
int64_t sum() const {
|
||||
int64_t sum = 0;
|
||||
|
||||
for (const auto& segment : m_segments) {
|
||||
sum += static_cast<int64_t>(segment.first().location().x()) * static_cast<int64_t>(segment.second().location().y()) -
|
||||
static_cast<int64_t>(segment.second().location().x()) * static_cast<int64_t>(segment.first().location().y());
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
bool is_cw() const {
|
||||
return sum() <= 0;
|
||||
}
|
||||
|
||||
int64_t area() const {
|
||||
return std::abs(sum()) / 2;
|
||||
}
|
||||
|
||||
void swap_segments(ProtoRing& other) {
|
||||
std::swap(m_segments, other.m_segments);
|
||||
}
|
||||
|
||||
void add_inner_ring(ProtoRing* ring) {
|
||||
m_inner.push_back(ring);
|
||||
}
|
||||
|
||||
const std::vector<ProtoRing*> inner_rings() const {
|
||||
return m_inner;
|
||||
}
|
||||
|
||||
void print(std::ostream& out) const {
|
||||
out << "[";
|
||||
bool first = true;
|
||||
for (const auto& segment : m_segments) {
|
||||
if (first) {
|
||||
out << segment.first().ref();
|
||||
}
|
||||
out << ',' << segment.second().ref();
|
||||
first = false;
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
|
||||
void reverse() {
|
||||
std::for_each(m_segments.begin(), m_segments.end(), [](NodeRefSegment& segment) {
|
||||
segment.swap_locations();
|
||||
});
|
||||
std::reverse(m_segments.begin(), m_segments.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge other ring to end of this ring.
|
||||
*/
|
||||
void merge_ring(const ProtoRing& other, bool debug) {
|
||||
if (debug) {
|
||||
std::cerr << " MERGE rings ";
|
||||
print(std::cerr);
|
||||
std::cerr << " to ";
|
||||
other.print(std::cerr);
|
||||
std::cerr << "\n";
|
||||
}
|
||||
m_segments.insert(m_segments.end(), other.m_segments.begin(), other.m_segments.end());
|
||||
if (debug) {
|
||||
std::cerr << " result ring: ";
|
||||
print(std::cerr);
|
||||
std::cerr << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void merge_ring_reverse(const ProtoRing& other, bool debug) {
|
||||
if (debug) {
|
||||
std::cerr << " MERGE rings (reverse) ";
|
||||
print(std::cerr);
|
||||
std::cerr << " to ";
|
||||
other.print(std::cerr);
|
||||
std::cerr << "\n";
|
||||
}
|
||||
size_t n = m_segments.size();
|
||||
m_segments.resize(n + other.m_segments.size());
|
||||
std::transform(other.m_segments.rbegin(), other.m_segments.rend(), m_segments.begin() + static_cast<segments_type::difference_type>(n), [](NodeRefSegment segment) {
|
||||
segment.swap_locations();
|
||||
return segment;
|
||||
});
|
||||
if (debug) {
|
||||
std::cerr << " result ring: ";
|
||||
print(std::cerr);
|
||||
std::cerr << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
const NodeRef& min_node() const {
|
||||
auto it = std::min_element(m_segments.begin(), m_segments.end());
|
||||
if (location_less()(it->first(), it->second())) {
|
||||
return it->first();
|
||||
} else {
|
||||
return it->second();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_in(ProtoRing* outer) {
|
||||
osmium::Location testpoint = segments().front().first().location();
|
||||
bool is_in = false;
|
||||
|
||||
for (size_t i = 0, j = outer->segments().size()-1; i < outer->segments().size(); j = i++) {
|
||||
if (((outer->segments()[i].first().location().y() > testpoint.y()) != (outer->segments()[j].first().location().y() > testpoint.y())) &&
|
||||
(testpoint.x() < (outer->segments()[j].first().location().x() - outer->segments()[i].first().location().x()) * (testpoint.y() - outer->segments()[i].first().location().y()) / (outer->segments()[j].first().location().y() - outer->segments()[i].first().location().y()) + outer->segments()[i].first().location().x()) ) {
|
||||
is_in = !is_in;
|
||||
}
|
||||
}
|
||||
|
||||
return is_in;
|
||||
}
|
||||
|
||||
void get_ways(std::set<const osmium::Way*>& ways) {
|
||||
for (const auto& segment : m_segments) {
|
||||
ways.insert(segment.way());
|
||||
}
|
||||
}
|
||||
|
||||
bool contains(const NodeRefSegment& segment) const {
|
||||
for (const auto& s : m_segments) {
|
||||
if (s == segment || (s.first() == segment.second() && s.second() == segment.first())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}; // class ProtoRing
|
||||
|
||||
template <typename TChar, typename TTraits>
|
||||
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const ProtoRing& ring) {
|
||||
ring.print(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_DETAIL_PROTO_RING_HPP
|
216
ThirdParty/osmium/area/detail/segment_list.hpp
vendored
Normal file
216
ThirdParty/osmium/area/detail/segment_list.hpp
vendored
Normal file
@ -0,0 +1,216 @@
|
||||
#ifndef OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP
|
||||
#define OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/problem_reporter.hpp>
|
||||
#include <osmium/area/detail/node_ref_segment.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* This is a helper class for the area assembler. It models
|
||||
* a list of segments.
|
||||
*/
|
||||
class SegmentList {
|
||||
|
||||
typedef std::vector<NodeRefSegment> slist_type;
|
||||
|
||||
slist_type m_segments;
|
||||
|
||||
bool m_debug;
|
||||
|
||||
public:
|
||||
|
||||
explicit SegmentList(bool debug) noexcept :
|
||||
m_debug(debug) {
|
||||
}
|
||||
|
||||
~SegmentList() = default;
|
||||
|
||||
SegmentList(const SegmentList& other) = delete;
|
||||
SegmentList(SegmentList&& other) = delete;
|
||||
|
||||
SegmentList& operator=(const SegmentList& other) = delete;
|
||||
SegmentList& operator=(SegmentList&& other) = delete;
|
||||
|
||||
/// The number of segments in the list.
|
||||
size_t size() const noexcept {
|
||||
return m_segments.size();
|
||||
}
|
||||
|
||||
bool empty() const noexcept {
|
||||
return m_segments.empty();
|
||||
}
|
||||
|
||||
typedef slist_type::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const noexcept {
|
||||
return m_segments.begin();
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept {
|
||||
return m_segments.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable debug output to stderr. This is for Osmium
|
||||
* developers only.
|
||||
*/
|
||||
void enable_debug_output(bool debug=true) noexcept {
|
||||
m_debug = debug;
|
||||
}
|
||||
|
||||
/// Clear the list of segments. All segments are removed.
|
||||
void clear() {
|
||||
m_segments.clear();
|
||||
}
|
||||
|
||||
/// Sort the list of segments.
|
||||
void sort() {
|
||||
std::sort(m_segments.begin(), m_segments.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract segments from given way and add them to the list.
|
||||
*
|
||||
* Segments connecting two nodes with the same location (ie same
|
||||
* node or different node with same location) are removed.
|
||||
*
|
||||
* XXX should two nodes with same location be reported?
|
||||
*/
|
||||
void extract_segments_from_way(const osmium::Way& way, const char* role) {
|
||||
osmium::NodeRef last_nr;
|
||||
for (const osmium::NodeRef& nr : way.nodes()) {
|
||||
if (last_nr.location() && last_nr.location() != nr.location()) {
|
||||
m_segments.emplace_back(last_nr, nr, role, &way);
|
||||
}
|
||||
last_nr = nr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all segments from all ways that make up this
|
||||
* multipolygon relation and add them to the list.
|
||||
*/
|
||||
void extract_segments_from_ways(const osmium::Relation& relation, const std::vector<size_t>& members, const osmium::memory::Buffer& in_buffer) {
|
||||
auto member_it = relation.members().begin();
|
||||
for (size_t offset : members) {
|
||||
const osmium::Way& way = in_buffer.get<const osmium::Way>(offset);
|
||||
extract_segments_from_way(way, member_it->role());
|
||||
++member_it;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find duplicate segments (ie same start and end point) in the
|
||||
* list and remove them. This will always remove pairs of the same
|
||||
* segment. So if there are three, for instance, two will be
|
||||
* removed and one will be left.
|
||||
*/
|
||||
void erase_duplicate_segments() {
|
||||
while (true) {
|
||||
auto it = std::adjacent_find(m_segments.begin(), m_segments.end());
|
||||
if (it == m_segments.end()) {
|
||||
return;
|
||||
}
|
||||
if (m_debug) {
|
||||
std::cerr << " erase duplicate segment: " << *it << "\n";
|
||||
}
|
||||
m_segments.erase(it, it+2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find intersection between segments.
|
||||
*
|
||||
* @param problem_reporter Any intersections found are reported to this object.
|
||||
* @returns true if there are intersections.
|
||||
*/
|
||||
bool find_intersections(osmium::area::ProblemReporter* problem_reporter) const {
|
||||
if (m_segments.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool found_intersections = false;
|
||||
|
||||
for (auto it1 = m_segments.begin(); it1 != m_segments.end()-1; ++it1) {
|
||||
const NodeRefSegment& s1 = *it1;
|
||||
for (auto it2 = it1+1; it2 != m_segments.end(); ++it2) {
|
||||
const NodeRefSegment& s2 = *it2;
|
||||
|
||||
assert(s1 != s2); // erase_duplicate_segments() should have made sure of that
|
||||
|
||||
if (outside_x_range(s2, s1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (y_range_overlap(s1, s2)) {
|
||||
osmium::Location intersection = calculate_intersection(s1, s2);
|
||||
if (intersection) {
|
||||
found_intersections = true;
|
||||
if (m_debug) {
|
||||
std::cerr << " segments " << s1 << " and " << s2 << " intersecting at " << intersection << "\n";
|
||||
}
|
||||
if (problem_reporter) {
|
||||
problem_reporter->report_intersection(s1.way()->id(), s1.first().location(), s1.second().location(), s2.way()->id(), s2.first().location(), s2.second().location(), intersection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found_intersections;
|
||||
}
|
||||
|
||||
}; // class SegmentList
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP
|
211
ThirdParty/osmium/area/multipolygon_collector.hpp
vendored
Normal file
211
ThirdParty/osmium/area/multipolygon_collector.hpp
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
#ifndef OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
|
||||
#define OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/relations/collector.hpp>
|
||||
#include <osmium/relations/detail/member_meta.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
struct invalid_location;
|
||||
|
||||
namespace relations {
|
||||
class RelationMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Code related to the building of areas (multipolygons) from relations.
|
||||
*/
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* This class collects all data needed for creating areas from
|
||||
* relations tagged with type=multipolygon or type=boundary.
|
||||
* Most of its functionality is derived from the parent class
|
||||
* osmium::relations::Collector.
|
||||
*
|
||||
* The actual assembling of the areas is done by the assembler
|
||||
* class given as template argument.
|
||||
*
|
||||
* @tparam TAssembler Multipolygon Assembler class.
|
||||
*/
|
||||
template <class TAssembler>
|
||||
class MultipolygonCollector : public osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> {
|
||||
|
||||
typedef typename osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> collector_type;
|
||||
|
||||
typedef typename TAssembler::config_type assembler_config_type;
|
||||
const assembler_config_type m_assembler_config;
|
||||
|
||||
osmium::memory::Buffer m_output_buffer;
|
||||
|
||||
static constexpr size_t initial_output_buffer_size = 1024 * 1024;
|
||||
static constexpr size_t max_buffer_size_for_flush = 100 * 1024;
|
||||
|
||||
void flush_output_buffer() {
|
||||
if (this->callback()) {
|
||||
this->callback()(m_output_buffer);
|
||||
m_output_buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void possibly_flush_output_buffer() {
|
||||
if (m_output_buffer.committed() > max_buffer_size_for_flush) {
|
||||
flush_output_buffer();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit MultipolygonCollector(const assembler_config_type& assembler_config) :
|
||||
collector_type(),
|
||||
m_assembler_config(assembler_config),
|
||||
m_output_buffer(initial_output_buffer_size, osmium::memory::Buffer::auto_grow::yes) {
|
||||
}
|
||||
|
||||
/**
|
||||
* We are interested in all relations tagged with type=multipolygon or
|
||||
* type=boundary.
|
||||
*
|
||||
* Overwritten from the base class.
|
||||
*/
|
||||
bool keep_relation(const osmium::Relation& relation) const {
|
||||
const char* type = relation.tags().get_value_by_key("type");
|
||||
|
||||
// ignore relations without "type" tag
|
||||
if (!type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!strcmp(type, "multipolygon")) || (!strcmp(type, "boundary"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten from the base class.
|
||||
*/
|
||||
bool keep_member(const osmium::relations::RelationMeta& /*relation_meta*/, const osmium::RelationMember& member) const {
|
||||
// We are only interested in members of type way.
|
||||
return member.type() == osmium::item_type::way;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a way is not in any multipolygon
|
||||
* relation.
|
||||
*
|
||||
* Overwritten from the base class.
|
||||
*/
|
||||
void way_not_in_any_relation(const osmium::Way& way) {
|
||||
if (way.ends_have_same_location() && way.nodes().size() > 3) {
|
||||
// way is closed and has enough nodes, build simple multipolygon
|
||||
try {
|
||||
TAssembler assembler(m_assembler_config);
|
||||
assembler(way, m_output_buffer);
|
||||
possibly_flush_output_buffer();
|
||||
} catch (osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void complete_relation(osmium::relations::RelationMeta& relation_meta) {
|
||||
const osmium::Relation& relation = this->get_relation(relation_meta);
|
||||
std::vector<size_t> offsets;
|
||||
for (const auto& member : relation.members()) {
|
||||
if (member.ref() != 0) {
|
||||
offsets.push_back(this->get_offset(member.type(), member.ref()));
|
||||
}
|
||||
}
|
||||
try {
|
||||
TAssembler assembler(m_assembler_config);
|
||||
assembler(relation, offsets, this->members_buffer(), m_output_buffer);
|
||||
possibly_flush_output_buffer();
|
||||
} catch (osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
|
||||
// clear member metas
|
||||
for (const auto& member : relation.members()) {
|
||||
if (member.ref() != 0) {
|
||||
auto& mmv = this->member_meta(member.type());
|
||||
auto range = std::equal_range(mmv.begin(), mmv.end(), osmium::relations::MemberMeta(member.ref()));
|
||||
assert(range.first != range.second);
|
||||
|
||||
// if this is the last time this object was needed
|
||||
// then mark it as removed
|
||||
if (osmium::relations::count_not_removed(range.first, range.second) == 1) {
|
||||
this->get_member(range.first->buffer_offset()).set_removed(true);
|
||||
}
|
||||
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
if (!it->removed() && relation.id() == this->get_relation(it->relation_pos()).id()) {
|
||||
it->remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flush() {
|
||||
flush_output_buffer();
|
||||
}
|
||||
|
||||
osmium::memory::Buffer read() {
|
||||
osmium::memory::Buffer buffer(initial_output_buffer_size, osmium::memory::Buffer::auto_grow::yes);
|
||||
std::swap(buffer, m_output_buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}; // class MultipolygonCollector
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
|
149
ThirdParty/osmium/area/problem_reporter.hpp
vendored
Normal file
149
ThirdParty/osmium/area/problem_reporter.hpp
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
#ifndef OSMIUM_AREA_PROBLEM_REPORTER_HPP
|
||||
#define OSMIUM_AREA_PROBLEM_REPORTER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* When assembling a multipolygon/area from a multipolygon relation
|
||||
* or a closed way several problems can be detected. This includes
|
||||
* intersections between lines, wrong role attributes on relation
|
||||
* members etc. These problems are reported by the area::Assembler
|
||||
* class to the ProblemReporter class or one of its child classes.
|
||||
*
|
||||
* This is the parent class which does nothing with the reports.
|
||||
* Child classes are expected to implement different ways of
|
||||
* reporting the problems.
|
||||
*/
|
||||
class ProblemReporter {
|
||||
|
||||
protected:
|
||||
|
||||
// Type of object we are currently working on
|
||||
osmium::item_type m_object_type;
|
||||
|
||||
// ID of the relation/way we are currently working on
|
||||
osmium::object_id_type m_object_id;
|
||||
|
||||
public:
|
||||
|
||||
ProblemReporter() = default;
|
||||
|
||||
virtual ~ProblemReporter() = default;
|
||||
|
||||
/**
|
||||
* Set the object the next problem reports will be on.
|
||||
*
|
||||
* @param object_type The type of the object.
|
||||
* @param object_id The ID of the object.
|
||||
*/
|
||||
void set_object(osmium::item_type object_type, osmium::object_id_type object_id) noexcept {
|
||||
m_object_type = object_type;
|
||||
m_object_id = object_id;
|
||||
}
|
||||
|
||||
// Disable "unused-parameter" warning, so that the compiler will not complain.
|
||||
// We can't remove the parameter names, because then doxygen will complain.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
/**
|
||||
* Report a duplicate node, ie. two nodes with the same location.
|
||||
*
|
||||
* @param node_id1 ID of the first node.
|
||||
* @param node_id2 ID of the second node.
|
||||
* @param location Location of both nodes.
|
||||
*/
|
||||
virtual void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an intersection between two segments.
|
||||
*
|
||||
* @param way1_id ID of the first involved way.
|
||||
* @param way1_seg_start Location where the segment of the first way with the intersection starts
|
||||
* @param way1_seg_end Location where the segment of the first way with the intersection ends
|
||||
* @param way2_id ID of the second involved way.
|
||||
* @param way2_seg_start Location where the segment of the second way with the intersection starts
|
||||
* @param way2_seg_end Location where the segment of the second way with the intersection ends
|
||||
* @param intersection Location of the intersection. This might be slightly off the correct location due to rounding.
|
||||
*/
|
||||
virtual void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end,
|
||||
osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an open ring.
|
||||
*
|
||||
* @param end1 Location of the first open end.
|
||||
* @param end2 Location of the second open end.
|
||||
*/
|
||||
virtual void report_ring_not_closed(osmium::Location end1, osmium::Location end2) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a segment that should have role "outer", but has a different role.
|
||||
*
|
||||
* @param way_id ID of the way this segment is in.
|
||||
* @param seg_start Start of the segment with the wrong role.
|
||||
* @param seg_end End of the segment with the wrong role.
|
||||
*/
|
||||
virtual void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a segment that should have role "inner", but has a different role.
|
||||
*
|
||||
* @param way_id ID of the way this segment is in.
|
||||
* @param seg_start Start of the segment with the wrong role.
|
||||
* @param seg_end End of the segment with the wrong role.
|
||||
*/
|
||||
virtual void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) {
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
}; // class ProblemReporter
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_PROBLEM_REPORTER_HPP
|
96
ThirdParty/osmium/area/problem_reporter_exception.hpp
vendored
Normal file
96
ThirdParty/osmium/area/problem_reporter_exception.hpp
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP
|
||||
#define OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <osmium/area/problem_reporter_stream.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
class ProblemReporterException : public ProblemReporterStream {
|
||||
|
||||
std::stringstream m_sstream;
|
||||
|
||||
public:
|
||||
|
||||
ProblemReporterException() :
|
||||
ProblemReporterStream(m_sstream) {
|
||||
}
|
||||
|
||||
virtual ~ProblemReporterException() = default;
|
||||
|
||||
void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override {
|
||||
m_sstream.str();
|
||||
ProblemReporterStream::report_duplicate_node(node_id1, node_id2, location);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
}
|
||||
|
||||
void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end,
|
||||
osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override {
|
||||
m_sstream.str();
|
||||
ProblemReporterStream::report_intersection(way1_id, way1_seg_start, way1_seg_end, way2_id, way2_seg_start, way2_seg_end, intersection);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
}
|
||||
|
||||
void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override {
|
||||
m_sstream.str();
|
||||
ProblemReporterStream::report_ring_not_closed(end1, end2);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
}
|
||||
|
||||
void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||
m_sstream.str();
|
||||
ProblemReporterStream::report_role_should_be_outer(way_id, seg_start, seg_end);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
}
|
||||
|
||||
void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||
m_sstream.str();
|
||||
ProblemReporterStream::report_role_should_be_inner(way_id, seg_start, seg_end);
|
||||
throw std::runtime_error(m_sstream.str());
|
||||
}
|
||||
|
||||
}; // class ProblemReporterException
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP
|
206
ThirdParty/osmium/area/problem_reporter_ogr.hpp
vendored
Normal file
206
ThirdParty/osmium/area/problem_reporter_ogr.hpp
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
#ifndef OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP
|
||||
#define OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#define OSMIUM_COMPILE_WITH_CFLAGS_OGR `gdal-config --cflags`
|
||||
#define OSMIUM_LINK_WITH_LIBS_OGR `gdal-config --libs`
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#ifdef __clang__
|
||||
# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wpadded"
|
||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
# include <ogr_api.h>
|
||||
# include <ogrsf_frmts.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <osmium/area/problem_reporter.hpp>
|
||||
#include <osmium/geom/ogr.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* Report problems when assembling areas by adding them to
|
||||
* layers in an OGR datasource.
|
||||
*/
|
||||
class ProblemReporterOGR : public ProblemReporter {
|
||||
|
||||
osmium::geom::OGRFactory<> m_ogr_factory;
|
||||
|
||||
OGRDataSource* m_data_source;
|
||||
|
||||
OGRLayer* m_layer_perror;
|
||||
OGRLayer* m_layer_lerror;
|
||||
|
||||
void write_point(const char* problem_type, osmium::object_id_type id1, osmium::object_id_type id2, osmium::Location location) {
|
||||
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_perror->GetLayerDefn());
|
||||
std::unique_ptr<OGRPoint> ogr_point = m_ogr_factory.create_point(location);
|
||||
feature->SetGeometry(ogr_point.get());
|
||||
feature->SetField("id1", static_cast<double>(id1));
|
||||
feature->SetField("id2", static_cast<double>(id2));
|
||||
feature->SetField("problem_type", problem_type);
|
||||
|
||||
if (m_layer_perror->CreateFeature(feature) != OGRERR_NONE) {
|
||||
std::runtime_error("Failed to create feature on layer 'perrors'");
|
||||
}
|
||||
|
||||
OGRFeature::DestroyFeature(feature);
|
||||
}
|
||||
|
||||
void write_line(const char* problem_type, osmium::object_id_type id1, osmium::object_id_type id2, osmium::Location loc1, osmium::Location loc2) {
|
||||
std::unique_ptr<OGRPoint> ogr_point1 = m_ogr_factory.create_point(loc1);
|
||||
std::unique_ptr<OGRPoint> ogr_point2 = m_ogr_factory.create_point(loc2);
|
||||
std::unique_ptr<OGRLineString> ogr_linestring = std::unique_ptr<OGRLineString>(new OGRLineString());
|
||||
ogr_linestring->addPoint(ogr_point1.get());
|
||||
ogr_linestring->addPoint(ogr_point2.get());
|
||||
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_lerror->GetLayerDefn());
|
||||
feature->SetGeometry(ogr_linestring.get());
|
||||
feature->SetField("id1", static_cast<double>(id1));
|
||||
feature->SetField("id2", static_cast<double>(id2));
|
||||
feature->SetField("problem_type", problem_type);
|
||||
|
||||
if (m_layer_lerror->CreateFeature(feature) != OGRERR_NONE) {
|
||||
std::runtime_error("Failed to create feature on layer 'lerrors'");
|
||||
}
|
||||
|
||||
OGRFeature::DestroyFeature(feature);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit ProblemReporterOGR(OGRDataSource* data_source) :
|
||||
m_data_source(data_source) {
|
||||
|
||||
OGRSpatialReference sparef;
|
||||
sparef.SetWellKnownGeogCS("WGS84");
|
||||
|
||||
m_layer_perror = m_data_source->CreateLayer("perrors", &sparef, wkbPoint, nullptr);
|
||||
if (!m_layer_perror) {
|
||||
std::runtime_error("Layer creation failed for layer 'perrors'");
|
||||
}
|
||||
|
||||
OGRFieldDefn layer_perror_field_id1("id1", OFTReal);
|
||||
layer_perror_field_id1.SetWidth(10);
|
||||
|
||||
if (m_layer_perror->CreateField(&layer_perror_field_id1) != OGRERR_NONE) {
|
||||
std::runtime_error("Creating field 'id1' failed for layer 'perrors'");
|
||||
}
|
||||
|
||||
OGRFieldDefn layer_perror_field_id2("id2", OFTReal);
|
||||
layer_perror_field_id2.SetWidth(10);
|
||||
|
||||
if (m_layer_perror->CreateField(&layer_perror_field_id2) != OGRERR_NONE) {
|
||||
std::runtime_error("Creating field 'id2' failed for layer 'perrors'");
|
||||
}
|
||||
|
||||
OGRFieldDefn layer_perror_field_problem_type("problem_type", OFTString);
|
||||
layer_perror_field_problem_type.SetWidth(30);
|
||||
|
||||
if (m_layer_perror->CreateField(&layer_perror_field_problem_type) != OGRERR_NONE) {
|
||||
std::runtime_error("Creating field 'problem_type' failed for layer 'perrors'");
|
||||
}
|
||||
|
||||
/**************/
|
||||
|
||||
m_layer_lerror = m_data_source->CreateLayer("lerrors", &sparef, wkbLineString, nullptr);
|
||||
if (!m_layer_lerror) {
|
||||
std::runtime_error("Layer creation failed for layer 'lerrors'");
|
||||
}
|
||||
|
||||
OGRFieldDefn layer_lerror_field_id1("id1", OFTReal);
|
||||
layer_lerror_field_id1.SetWidth(10);
|
||||
|
||||
if (m_layer_lerror->CreateField(&layer_lerror_field_id1) != OGRERR_NONE) {
|
||||
std::runtime_error("Creating field 'id1' failed for layer 'lerrors'");
|
||||
}
|
||||
|
||||
OGRFieldDefn layer_lerror_field_id2("id2", OFTReal);
|
||||
layer_lerror_field_id2.SetWidth(10);
|
||||
|
||||
if (m_layer_lerror->CreateField(&layer_lerror_field_id2) != OGRERR_NONE) {
|
||||
std::runtime_error("Creating field 'id2' failed for layer 'lerrors'");
|
||||
}
|
||||
|
||||
OGRFieldDefn layer_lerror_field_problem_type("problem_type", OFTString);
|
||||
layer_lerror_field_problem_type.SetWidth(30);
|
||||
|
||||
if (m_layer_lerror->CreateField(&layer_lerror_field_problem_type) != OGRERR_NONE) {
|
||||
std::runtime_error("Creating field 'problem_type' failed for layer 'lerrors'");
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~ProblemReporterOGR() = default;
|
||||
|
||||
void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override {
|
||||
write_point("duplicate_node", node_id1, node_id2, location);
|
||||
}
|
||||
|
||||
void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end,
|
||||
osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override {
|
||||
write_point("intersection", m_object_id, 0, intersection);
|
||||
write_line("intersection", m_object_id, way1_id, way1_seg_start, way1_seg_end);
|
||||
write_line("intersection", m_object_id, way2_id, way2_seg_start, way2_seg_end);
|
||||
}
|
||||
|
||||
void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override {
|
||||
write_point("ring_not_closed", m_object_id, 0, end1);
|
||||
write_point("ring_not_closed", m_object_id, 0, end2);
|
||||
}
|
||||
|
||||
void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||
write_line("role_should_be_outer", m_object_id, way_id, seg_start, seg_end);
|
||||
}
|
||||
|
||||
void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||
write_line("role_should_be_inner", m_object_id, way_id, seg_start, seg_end);
|
||||
}
|
||||
|
||||
}; // class ProblemReporterOGR
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP
|
96
ThirdParty/osmium/area/problem_reporter_stream.hpp
vendored
Normal file
96
ThirdParty/osmium/area/problem_reporter_stream.hpp
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP
|
||||
#define OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include <osmium/area/problem_reporter.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
class ProblemReporterStream : public ProblemReporter {
|
||||
|
||||
std::ostream* m_out;
|
||||
|
||||
public:
|
||||
|
||||
explicit ProblemReporterStream(std::ostream& out) :
|
||||
m_out(&out) {
|
||||
}
|
||||
|
||||
virtual ~ProblemReporterStream() = default;
|
||||
|
||||
void header(const char* msg) {
|
||||
*m_out << "DATA PROBLEM: " << msg << " on " << item_type_to_char(m_object_type) << m_object_id << ": ";
|
||||
}
|
||||
|
||||
void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override {
|
||||
header("duplicate node");
|
||||
*m_out << "node_id1=" << node_id1 << " node_id2=" << node_id2 << " location=" << location << "\n";
|
||||
}
|
||||
|
||||
void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end,
|
||||
osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override {
|
||||
header("intersection");
|
||||
*m_out << "way1_id=" << way1_id << " way1_seg_start=" << way1_seg_start << " way1_seg_end=" << way1_seg_end
|
||||
<< " way2_id=" << way2_id << " way2_seg_start=" << way2_seg_start << " way2_seg_end=" << way2_seg_end << " intersection=" << intersection << "\n";
|
||||
}
|
||||
|
||||
void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override {
|
||||
header("ring not closed");
|
||||
*m_out << "end1=" << end1 << " end2=" << end2 << "\n";
|
||||
}
|
||||
|
||||
void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||
header("role should be outer");
|
||||
*m_out << "way_id=" << way_id << " seg_start=" << seg_start << " seg_end=" << seg_end << "\n";
|
||||
}
|
||||
|
||||
void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||
header("role should be inner");
|
||||
*m_out << "way_id=" << way_id << " seg_start=" << seg_start << " seg_end=" << seg_end << "\n";
|
||||
}
|
||||
|
||||
}; // class ProblemReporterStream
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP
|
220
ThirdParty/osmium/builder/builder.hpp
vendored
Normal file
220
ThirdParty/osmium/builder/builder.hpp
vendored
Normal file
@ -0,0 +1,220 @@
|
||||
#ifndef OSMIUM_BUILDER_BUILDER_HPP
|
||||
#define OSMIUM_BUILDER_BUILDER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* @brief Classes for building OSM objects and other items in buffers
|
||||
*/
|
||||
namespace builder {
|
||||
|
||||
class Builder {
|
||||
|
||||
osmium::memory::Buffer& m_buffer;
|
||||
Builder* m_parent;
|
||||
size_t m_item_offset;
|
||||
|
||||
Builder(const Builder&) = delete;
|
||||
Builder(Builder&&) = delete;
|
||||
|
||||
Builder& operator=(const Builder&) = delete;
|
||||
Builder& operator=(Builder&&) = delete;
|
||||
|
||||
protected:
|
||||
|
||||
explicit Builder(osmium::memory::Buffer& buffer, Builder* parent, osmium::memory::item_size_type size) :
|
||||
m_buffer(buffer),
|
||||
m_parent(parent),
|
||||
m_item_offset(buffer.written()) {
|
||||
m_buffer.reserve_space(size);
|
||||
assert(buffer.is_aligned());
|
||||
if (m_parent) {
|
||||
m_parent->add_size(size);
|
||||
}
|
||||
}
|
||||
|
||||
~Builder() = default;
|
||||
|
||||
osmium::memory::Item& item() const {
|
||||
return *reinterpret_cast<osmium::memory::Item*>(m_buffer.data() + m_item_offset);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Add padding to buffer (if needed) to align data properly.
|
||||
*
|
||||
* This calculates how many padding bytes are needed and adds
|
||||
* as many zero bytes to the buffer. It also adds this number
|
||||
* to the size of the current item (if the "self" param is
|
||||
* true) and recursively to all the parent items.
|
||||
*
|
||||
* @param self If true add number of padding bytes to size
|
||||
* of current item. Size is always added to
|
||||
* parent item (if any).
|
||||
*
|
||||
*/
|
||||
void add_padding(bool self=false) {
|
||||
auto padding = osmium::memory::align_bytes - (size() % osmium::memory::align_bytes);
|
||||
if (padding != osmium::memory::align_bytes) {
|
||||
std::memset(m_buffer.reserve_space(padding), 0, padding);
|
||||
if (self) {
|
||||
add_size(padding);
|
||||
} else if (m_parent) {
|
||||
m_parent->add_size(padding);
|
||||
assert(m_parent->size() % osmium::memory::align_bytes == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_size(uint32_t size) {
|
||||
item().add_size(size);
|
||||
if (m_parent) {
|
||||
m_parent->add_size(size);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t size() const noexcept {
|
||||
return item().byte_size();
|
||||
}
|
||||
|
||||
void add_item(const osmium::memory::Item* item) {
|
||||
std::memcpy(m_buffer.reserve_space(item->padded_size()), item, item->padded_size());
|
||||
add_size(item->padded_size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve space for an object of class T in buffer and return
|
||||
* pointer to it.
|
||||
*/
|
||||
template <class T>
|
||||
T* reserve_space_for() {
|
||||
assert(m_buffer.is_aligned());
|
||||
return reinterpret_cast<T*>(m_buffer.reserve_space(sizeof(T)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append data to buffer.
|
||||
*
|
||||
* @param data Pointer to data.
|
||||
* @param length Length of data in bytes. If data is a
|
||||
* \0-terminated string, length must contain the
|
||||
* \0 byte.
|
||||
*/
|
||||
osmium::memory::item_size_type append(const char* data, const osmium::memory::item_size_type length) {
|
||||
std::memcpy(m_buffer.reserve_space(length), data, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append \0-terminated string to buffer.
|
||||
*/
|
||||
osmium::memory::item_size_type append(const char* str) {
|
||||
return append(str, static_cast<osmium::memory::item_size_type>(std::strlen(str) + 1));
|
||||
}
|
||||
|
||||
/// Return the buffer this builder is using.
|
||||
osmium::memory::Buffer& buffer() noexcept {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
}; // class Builder
|
||||
|
||||
template <class TItem>
|
||||
class ObjectBuilder : public Builder {
|
||||
|
||||
static_assert(std::is_base_of<osmium::memory::Item, TItem>::value,
|
||||
"ObjectBuilder can only build objects derived from osmium::memory::Item");
|
||||
|
||||
public:
|
||||
|
||||
explicit ObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) :
|
||||
Builder(buffer, parent, sizeof(TItem)) {
|
||||
new (&item()) TItem();
|
||||
}
|
||||
|
||||
TItem& object() noexcept {
|
||||
return static_cast<TItem&>(item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add user name to buffer.
|
||||
*
|
||||
* @param user Pointer to user name.
|
||||
* @param length Length of user name including \0 byte.
|
||||
*/
|
||||
void add_user(const char* user, const string_size_type length) {
|
||||
object().set_user_size(length);
|
||||
add_size(append(user, length));
|
||||
add_padding(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add user name to buffer.
|
||||
*
|
||||
* @param user Pointer to \0-terminated user name.
|
||||
*/
|
||||
void add_user(const char* user) {
|
||||
add_user(user, static_cast_with_assert<string_size_type>(std::strlen(user) + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add user name to buffer.
|
||||
*
|
||||
* @param user User name.
|
||||
*/
|
||||
void add_user(const std::string& user) {
|
||||
add_user(user.data(), static_cast_with_assert<string_size_type>(user.size() + 1));
|
||||
}
|
||||
|
||||
}; // class ObjectBuilder
|
||||
|
||||
} // namespace builder
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_BUILDER_BUILDER_HPP
|
103
ThirdParty/osmium/builder/builder_helper.hpp
vendored
Normal file
103
ThirdParty/osmium/builder/builder_helper.hpp
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
#ifndef OSMIUM_BUILDER_BUILDER_HELPER_HPP
|
||||
#define OSMIUM_BUILDER_BUILDER_HELPER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
class NodeRef;
|
||||
class TagList;
|
||||
class WayNodeList;
|
||||
|
||||
namespace builder {
|
||||
|
||||
inline const osmium::WayNodeList& build_way_node_list(osmium::memory::Buffer& buffer, const std::initializer_list<osmium::NodeRef>& nodes) {
|
||||
size_t pos = buffer.committed();
|
||||
{
|
||||
osmium::builder::WayNodeListBuilder wnl_builder(buffer);
|
||||
for (const auto& node_ref : nodes) {
|
||||
wnl_builder.add_node_ref(node_ref);
|
||||
}
|
||||
}
|
||||
buffer.commit();
|
||||
return buffer.get<const osmium::WayNodeList>(pos);
|
||||
}
|
||||
|
||||
inline const osmium::TagList& build_tag_list(osmium::memory::Buffer& buffer, const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||
size_t pos = buffer.committed();
|
||||
{
|
||||
osmium::builder::TagListBuilder tl_builder(buffer);
|
||||
for (const auto& p : tags) {
|
||||
tl_builder.add_tag(p.first, p.second);
|
||||
}
|
||||
}
|
||||
buffer.commit();
|
||||
return buffer.get<const osmium::TagList>(pos);
|
||||
}
|
||||
|
||||
inline const osmium::TagList& build_tag_list_from_map(osmium::memory::Buffer& buffer, const std::map<const char*, const char*>& tags) {
|
||||
size_t pos = buffer.committed();
|
||||
{
|
||||
osmium::builder::TagListBuilder tl_builder(buffer);
|
||||
for (const auto& p : tags) {
|
||||
tl_builder.add_tag(p.first, p.second);
|
||||
}
|
||||
}
|
||||
buffer.commit();
|
||||
return buffer.get<const osmium::TagList>(pos);
|
||||
}
|
||||
|
||||
inline const osmium::TagList& build_tag_list_from_func(osmium::memory::Buffer& buffer, std::function<void(osmium::builder::TagListBuilder&)> func) {
|
||||
size_t pos = buffer.committed();
|
||||
{
|
||||
osmium::builder::TagListBuilder tl_builder(buffer);
|
||||
func(tl_builder);
|
||||
}
|
||||
buffer.commit();
|
||||
return buffer.get<const osmium::TagList>(pos);
|
||||
}
|
||||
|
||||
} // namespace builder
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_BUILDER_BUILDER_HELPER_HPP
|
283
ThirdParty/osmium/builder/osm_object_builder.hpp
vendored
Normal file
283
ThirdParty/osmium/builder/osm_object_builder.hpp
vendored
Normal file
@ -0,0 +1,283 @@
|
||||
#ifndef OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
|
||||
#define OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/builder/builder.hpp>
|
||||
#include <osmium/osm.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/object.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace memory {
|
||||
class Buffer;
|
||||
}
|
||||
|
||||
namespace builder {
|
||||
|
||||
class TagListBuilder : public ObjectBuilder<TagList> {
|
||||
|
||||
public:
|
||||
|
||||
explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) :
|
||||
ObjectBuilder<TagList>(buffer, parent) {
|
||||
}
|
||||
|
||||
~TagListBuilder() {
|
||||
add_padding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add tag to buffer.
|
||||
*
|
||||
* @param key Tag key.
|
||||
* @param value Tag value.
|
||||
*/
|
||||
void add_tag(const char* key, const char* value) {
|
||||
add_size(append(key) + append(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add tag to buffer.
|
||||
*
|
||||
* @param key Tag key.
|
||||
* @param value Tag value.
|
||||
*/
|
||||
void add_tag(const std::string& key, const std::string& value) {
|
||||
add_size(append(key.data(), static_cast_with_assert<string_size_type>(key.size() + 1)) +
|
||||
append(value.data(), static_cast_with_assert<string_size_type>(value.size() + 1)));
|
||||
}
|
||||
|
||||
}; // class TagListBuilder
|
||||
|
||||
template <class T>
|
||||
class NodeRefListBuilder : public ObjectBuilder<T> {
|
||||
|
||||
public:
|
||||
|
||||
explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) :
|
||||
ObjectBuilder<T>(buffer, parent) {
|
||||
}
|
||||
|
||||
~NodeRefListBuilder() {
|
||||
static_cast<Builder*>(this)->add_padding();
|
||||
}
|
||||
|
||||
void add_node_ref(const NodeRef& node_ref) {
|
||||
new (static_cast<Builder*>(this)->reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
|
||||
static_cast<Builder*>(this)->add_size(sizeof(osmium::NodeRef));
|
||||
}
|
||||
|
||||
void add_node_ref(const object_id_type ref, const osmium::Location location=Location()) {
|
||||
add_node_ref(NodeRef(ref, location));
|
||||
}
|
||||
|
||||
}; // class NodeRefListBuilder
|
||||
|
||||
typedef NodeRefListBuilder<WayNodeList> WayNodeListBuilder;
|
||||
typedef NodeRefListBuilder<OuterRing> OuterRingBuilder;
|
||||
typedef NodeRefListBuilder<InnerRing> InnerRingBuilder;
|
||||
|
||||
class RelationMemberListBuilder : public ObjectBuilder<RelationMemberList> {
|
||||
|
||||
/**
|
||||
* Add role to buffer.
|
||||
*
|
||||
* @param member Relation member object where the length of the role
|
||||
* will be set.
|
||||
* @param role The role.
|
||||
* @param length Length of role string including \0 termination.
|
||||
*/
|
||||
void add_role(osmium::RelationMember& member, const char* role, const string_size_type length) {
|
||||
member.set_role_size(length);
|
||||
add_size(append(role, length));
|
||||
add_padding(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add role to buffer.
|
||||
*
|
||||
* @param member Relation member object where the length of the role
|
||||
* will be set.
|
||||
* @param role \0-terminated role.
|
||||
*/
|
||||
void add_role(osmium::RelationMember& member, const char* role) {
|
||||
add_role(member, role, static_cast_with_assert<string_size_type>(std::strlen(role) + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add role to buffer.
|
||||
*
|
||||
* @param member Relation member object where the length of the role
|
||||
* will be set.
|
||||
* @param role Role.
|
||||
*/
|
||||
void add_role(osmium::RelationMember& member, const std::string& role) {
|
||||
add_role(member, role.data(), static_cast_with_assert<string_size_type>(role.size() + 1));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) :
|
||||
ObjectBuilder<RelationMemberList>(buffer, parent) {
|
||||
}
|
||||
|
||||
~RelationMemberListBuilder() {
|
||||
add_padding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a member to the relation.
|
||||
*
|
||||
* @param type The type (node, way, or relation).
|
||||
* @param ref The ID of the member.
|
||||
* @param role The role of the member.
|
||||
* @param full_member Optional pointer to the member object. If it
|
||||
* is available a copy will be added to the
|
||||
* relation.
|
||||
*/
|
||||
void add_member(osmium::item_type type, object_id_type ref, const char* role, const osmium::OSMObject* full_member = nullptr) {
|
||||
osmium::RelationMember* member = reserve_space_for<osmium::RelationMember>();
|
||||
new (member) osmium::RelationMember(ref, type, full_member != nullptr);
|
||||
add_size(sizeof(RelationMember));
|
||||
add_role(*member, role);
|
||||
if (full_member) {
|
||||
add_item(full_member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a member to the relation.
|
||||
*
|
||||
* @param type The type (node, way, or relation).
|
||||
* @param ref The ID of the member.
|
||||
* @param role The role of the member.
|
||||
* @param full_member Optional pointer to the member object. If it
|
||||
* is available a copy will be added to the
|
||||
* relation.
|
||||
*/
|
||||
void add_member(osmium::item_type type, object_id_type ref, const std::string& role, const osmium::OSMObject* full_member = nullptr) {
|
||||
osmium::RelationMember* member = reserve_space_for<osmium::RelationMember>();
|
||||
new (member) osmium::RelationMember(ref, type, full_member != nullptr);
|
||||
add_size(sizeof(RelationMember));
|
||||
add_role(*member, role);
|
||||
if (full_member) {
|
||||
add_item(full_member);
|
||||
}
|
||||
}
|
||||
|
||||
}; // class RelationMemberListBuilder
|
||||
|
||||
template <class T>
|
||||
class OSMObjectBuilder : public ObjectBuilder<T> {
|
||||
|
||||
public:
|
||||
|
||||
explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) :
|
||||
ObjectBuilder<T>(buffer, parent) {
|
||||
static_cast<Builder*>(this)->reserve_space_for<string_size_type>();
|
||||
static_cast<Builder*>(this)->add_size(sizeof(string_size_type));
|
||||
}
|
||||
|
||||
void add_tags(const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||
osmium::builder::TagListBuilder tl_builder(static_cast<Builder*>(this)->buffer(), this);
|
||||
for (const auto& p : tags) {
|
||||
tl_builder.add_tag(p.first, p.second);
|
||||
}
|
||||
}
|
||||
|
||||
}; // class OSMObjectBuilder
|
||||
|
||||
typedef OSMObjectBuilder<osmium::Node> NodeBuilder;
|
||||
typedef OSMObjectBuilder<osmium::Relation> RelationBuilder;
|
||||
|
||||
class WayBuilder : public OSMObjectBuilder<osmium::Way> {
|
||||
|
||||
public:
|
||||
|
||||
explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) :
|
||||
OSMObjectBuilder<osmium::Way>(buffer, parent) {
|
||||
}
|
||||
|
||||
void add_node_refs(const std::initializer_list<osmium::NodeRef>& nodes) {
|
||||
osmium::builder::WayNodeListBuilder builder(buffer(), this);
|
||||
for (const auto& node_ref : nodes) {
|
||||
builder.add_node_ref(node_ref);
|
||||
}
|
||||
}
|
||||
|
||||
}; // class WayBuilder
|
||||
|
||||
class AreaBuilder : public OSMObjectBuilder<osmium::Area> {
|
||||
|
||||
public:
|
||||
|
||||
explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) :
|
||||
OSMObjectBuilder<osmium::Area>(buffer, parent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize area attributes from the attributes of the given object.
|
||||
*/
|
||||
void initialize_from_object(const osmium::OSMObject& source) {
|
||||
osmium::Area& area = object();
|
||||
area.set_id(osmium::object_id_to_area_id(source.id(), source.type()));
|
||||
area.set_version(source.version());
|
||||
area.set_changeset(source.changeset());
|
||||
area.set_timestamp(source.timestamp());
|
||||
area.set_visible(source.visible());
|
||||
area.set_uid(source.uid());
|
||||
|
||||
add_user(source.user());
|
||||
}
|
||||
|
||||
}; // class AreaBuilder
|
||||
|
||||
typedef ObjectBuilder<osmium::Changeset> ChangesetBuilder;
|
||||
|
||||
} // namespace builder
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
|
43
ThirdParty/osmium/config/constexpr.hpp
vendored
Normal file
43
ThirdParty/osmium/config/constexpr.hpp
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef OSMIUM_CONFIG_CONSTEXPR_HPP
|
||||
#define OSMIUM_CONFIG_CONSTEXPR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Workaround for MSVC which doesn't support constexpr in all cases yet
|
||||
#ifdef _MSC_VER
|
||||
# define OSMIUM_CONSTEXPR
|
||||
#else
|
||||
# define OSMIUM_CONSTEXPR constexpr
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_CONFIG_CONSTEXPR_HPP
|
67
ThirdParty/osmium/diff_handler.hpp
vendored
Normal file
67
ThirdParty/osmium/diff_handler.hpp
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef OSMIUM_DIFF_HANDLER_HPP
|
||||
#define OSMIUM_DIFF_HANDLER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/osm/diff_object.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* @brief Osmium diff handlers provide access to differences between OSM object versions
|
||||
*/
|
||||
namespace diff_handler {
|
||||
|
||||
class DiffHandler {
|
||||
|
||||
public:
|
||||
|
||||
DiffHandler() {
|
||||
}
|
||||
|
||||
void node(const osmium::DiffNode&) const {
|
||||
}
|
||||
|
||||
void way(const osmium::DiffWay&) const {
|
||||
}
|
||||
|
||||
void relation(const osmium::DiffRelation&) const {
|
||||
}
|
||||
|
||||
}; // class DiffHandler
|
||||
|
||||
} // namespace diff_handler
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_DIFF_HANDLER_HPP
|
129
ThirdParty/osmium/diff_iterator.hpp
vendored
Normal file
129
ThirdParty/osmium/diff_iterator.hpp
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
#ifndef OSMIUM_DIFF_ITERATOR_HPP
|
||||
#define OSMIUM_DIFF_ITERATOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include <osmium/osm/diff_object.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
class OSMObject;
|
||||
|
||||
template <class TBasicIterator>
|
||||
class DiffIterator : public std::iterator<std::input_iterator_tag, const osmium::DiffObject> {
|
||||
|
||||
static_assert(std::is_base_of<osmium::OSMObject, typename TBasicIterator::value_type>::value, "TBasicIterator::value_type must derive from osmium::OSMObject");
|
||||
|
||||
TBasicIterator m_prev;
|
||||
TBasicIterator m_curr;
|
||||
TBasicIterator m_next;
|
||||
|
||||
const TBasicIterator m_end;
|
||||
|
||||
mutable osmium::DiffObject m_diff;
|
||||
|
||||
void set_diff() const {
|
||||
assert(m_curr != m_end);
|
||||
|
||||
TBasicIterator prev = m_prev;
|
||||
if (prev->type() != m_curr->type() || prev->id() != m_curr->id()) {
|
||||
prev = m_curr;
|
||||
}
|
||||
|
||||
TBasicIterator next = m_next;
|
||||
if (next == m_end || next->type() != m_curr->type() || next->id() != m_curr->id()) {
|
||||
next = m_curr;
|
||||
}
|
||||
|
||||
m_diff = osmium::DiffObject(*prev, *m_curr, *next);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit DiffIterator(TBasicIterator begin, TBasicIterator end) :
|
||||
m_prev(begin),
|
||||
m_curr(begin),
|
||||
m_next(begin == end ? begin : ++begin),
|
||||
m_end(end) {
|
||||
}
|
||||
|
||||
DiffIterator(const DiffIterator& other) = default;
|
||||
DiffIterator& operator=(const DiffIterator& other) = default;
|
||||
|
||||
DiffIterator(DiffIterator&& other) = default;
|
||||
DiffIterator& operator=(DiffIterator&& other) = default;
|
||||
|
||||
DiffIterator& operator++() {
|
||||
m_prev = std::move(m_curr);
|
||||
m_curr = m_next;
|
||||
|
||||
if (m_next != m_end) {
|
||||
++m_next;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DiffIterator operator++(int) {
|
||||
DiffIterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const DiffIterator& rhs) const {
|
||||
return m_curr == rhs.m_curr && m_end == rhs.m_end;
|
||||
}
|
||||
|
||||
bool operator!=(const DiffIterator& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
reference operator*() const {
|
||||
set_diff();
|
||||
return m_diff;
|
||||
}
|
||||
|
||||
pointer operator->() const {
|
||||
set_diff();
|
||||
return &m_diff;
|
||||
}
|
||||
|
||||
}; // class DiffIterator
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_DIFF_ITERATOR_HPP
|
104
ThirdParty/osmium/diff_visitor.hpp
vendored
Normal file
104
ThirdParty/osmium/diff_visitor.hpp
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
#ifndef OSMIUM_DIFF_VISITOR_HPP
|
||||
#define OSMIUM_DIFF_VISITOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/diff_iterator.hpp>
|
||||
#include <osmium/io/input_iterator.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/diff_object.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class THandler>
|
||||
inline void apply_diff_iterator_recurse(const osmium::DiffObject& diff, THandler& handler) {
|
||||
switch (diff.type()) {
|
||||
case osmium::item_type::node:
|
||||
handler.node(static_cast<const osmium::DiffNode&>(diff));
|
||||
break;
|
||||
case osmium::item_type::way:
|
||||
handler.way(static_cast<const osmium::DiffWay&>(diff));
|
||||
break;
|
||||
case osmium::item_type::relation:
|
||||
handler.relation(static_cast<const osmium::DiffRelation&>(diff));
|
||||
break;
|
||||
default:
|
||||
throw osmium::unknown_type();
|
||||
}
|
||||
}
|
||||
|
||||
template <class THandler, class ...TRest>
|
||||
inline void apply_diff_iterator_recurse(const osmium::DiffObject& diff, THandler& handler, TRest&... more) {
|
||||
apply_diff_iterator_recurse(diff, handler);
|
||||
apply_diff_iterator_recurse(diff, more...);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class TIterator, class ...THandlers>
|
||||
inline void apply_diff(TIterator it, TIterator end, THandlers&... handlers) {
|
||||
typedef osmium::DiffIterator<TIterator> diff_iterator;
|
||||
|
||||
diff_iterator dit(it, end);
|
||||
diff_iterator dend(end, end);
|
||||
|
||||
for (; dit != dend; ++dit) {
|
||||
detail::apply_diff_iterator_recurse(*dit, handlers...);
|
||||
}
|
||||
}
|
||||
|
||||
class OSMObject;
|
||||
|
||||
template <class TSource, class ...THandlers>
|
||||
inline void apply_diff(TSource& source, THandlers&... handlers) {
|
||||
apply_diff(osmium::io::InputIterator<TSource, osmium::OSMObject> {source},
|
||||
osmium::io::InputIterator<TSource, osmium::OSMObject> {},
|
||||
handlers...);
|
||||
}
|
||||
|
||||
template <class ...THandlers>
|
||||
inline void apply_diff(osmium::memory::Buffer& buffer, THandlers&... handlers) {
|
||||
apply_diff(buffer.begin(), buffer.end(), handlers...);
|
||||
}
|
||||
|
||||
template <class ...THandlers>
|
||||
inline void apply_diff(const osmium::memory::Buffer& buffer, THandlers&... handlers) {
|
||||
apply_diff(buffer.cbegin(), buffer.cend(), handlers...);
|
||||
}
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_DIFF_VISITOR_HPP
|
195
ThirdParty/osmium/dynamic_handler.hpp
vendored
Normal file
195
ThirdParty/osmium/dynamic_handler.hpp
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
#ifndef OSMIUM_DYNAMIC_HANDLER_HPP
|
||||
#define OSMIUM_DYNAMIC_HANDLER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/handler.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
class Node;
|
||||
class Way;
|
||||
class Relation;
|
||||
class Area;
|
||||
class Changeset;
|
||||
|
||||
namespace handler {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class HandlerWrapperBase {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~HandlerWrapperBase() {
|
||||
}
|
||||
|
||||
virtual void node(const osmium::Node&) {
|
||||
}
|
||||
|
||||
virtual void way(const osmium::Way&) {
|
||||
}
|
||||
|
||||
virtual void relation(const osmium::Relation&) {
|
||||
}
|
||||
|
||||
virtual void area(const osmium::Area&) {
|
||||
}
|
||||
|
||||
virtual void changeset(const osmium::Changeset&) {
|
||||
}
|
||||
|
||||
virtual void flush() {
|
||||
}
|
||||
|
||||
}; // class HandlerWrapperBase
|
||||
|
||||
|
||||
// The following uses trick from
|
||||
// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence
|
||||
// to either call handler style functions or visitor style operator().
|
||||
|
||||
#define OSMIUM_DYNAMIC_HANDLER_DISPATCH(_name_, _type_) \
|
||||
template <class THandler> \
|
||||
auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, int) -> decltype(handler._name_(object), void()) { \
|
||||
handler._name_(object); \
|
||||
} \
|
||||
template <class THandler> \
|
||||
auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, long) -> decltype(handler(object), void()) { \
|
||||
handler(object); \
|
||||
}
|
||||
|
||||
OSMIUM_DYNAMIC_HANDLER_DISPATCH(node, Node)
|
||||
OSMIUM_DYNAMIC_HANDLER_DISPATCH(way, Way)
|
||||
OSMIUM_DYNAMIC_HANDLER_DISPATCH(relation, Relation)
|
||||
OSMIUM_DYNAMIC_HANDLER_DISPATCH(changeset, Changeset)
|
||||
OSMIUM_DYNAMIC_HANDLER_DISPATCH(area, Area)
|
||||
|
||||
template <class THandler>
|
||||
auto flush_dispatch(THandler& handler, int) -> decltype(handler.flush(), void()) {
|
||||
handler.flush();
|
||||
}
|
||||
|
||||
template <class THandler>
|
||||
void flush_dispatch(THandler&, long) {}
|
||||
|
||||
template <class THandler>
|
||||
class HandlerWrapper : public HandlerWrapperBase {
|
||||
|
||||
THandler m_handler;
|
||||
|
||||
public:
|
||||
|
||||
template <class... TArgs>
|
||||
HandlerWrapper(TArgs&&... args) :
|
||||
m_handler(std::forward<TArgs>(args)...) {
|
||||
}
|
||||
|
||||
void node(const osmium::Node& node) override final {
|
||||
node_dispatch(m_handler, node, 0);
|
||||
}
|
||||
|
||||
void way(const osmium::Way& way) override final {
|
||||
way_dispatch(m_handler, way, 0);
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation& relation) override final {
|
||||
relation_dispatch(m_handler, relation, 0);
|
||||
}
|
||||
|
||||
void area(const osmium::Area& area) override final {
|
||||
area_dispatch(m_handler, area, 0);
|
||||
}
|
||||
|
||||
void changeset(const osmium::Changeset& changeset) override final {
|
||||
changeset_dispatch(m_handler, changeset, 0);
|
||||
}
|
||||
|
||||
void flush() override final {
|
||||
flush_dispatch(m_handler, 0);
|
||||
}
|
||||
|
||||
}; // class HandlerWrapper
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class DynamicHandler : public osmium::handler::Handler {
|
||||
|
||||
typedef std::unique_ptr<osmium::handler::detail::HandlerWrapperBase> impl_ptr;
|
||||
impl_ptr m_impl;
|
||||
|
||||
public:
|
||||
|
||||
DynamicHandler() :
|
||||
m_impl(impl_ptr(new osmium::handler::detail::HandlerWrapperBase)) {
|
||||
}
|
||||
|
||||
template <class THandler, class... TArgs>
|
||||
void set(TArgs&&... args) {
|
||||
m_impl = impl_ptr(new osmium::handler::detail::HandlerWrapper<THandler>(std::forward<TArgs>(args)...));
|
||||
}
|
||||
|
||||
void node(const osmium::Node& node) {
|
||||
m_impl->node(node);
|
||||
}
|
||||
|
||||
void way(const osmium::Way& way) {
|
||||
m_impl->way(way);
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation& relation) {
|
||||
m_impl->relation(relation);
|
||||
}
|
||||
|
||||
void area(const osmium::Area& area) {
|
||||
m_impl->area(area);
|
||||
}
|
||||
|
||||
void changeset(const osmium::Changeset& changeset) {
|
||||
m_impl->changeset(changeset);
|
||||
}
|
||||
|
||||
void flush() {
|
||||
m_impl->flush();
|
||||
}
|
||||
|
||||
}; // class DynamicHandler
|
||||
|
||||
} // namspace handler
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_DYNAMIC_HANDLER_HPP
|
97
ThirdParty/osmium/geom/coordinates.hpp
vendored
Normal file
97
ThirdParty/osmium/geom/coordinates.hpp
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
#ifndef OSMIUM_GEOM_COORDINATES_HPP
|
||||
#define OSMIUM_GEOM_COORDINATES_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/util/double.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
struct Coordinates {
|
||||
|
||||
double x;
|
||||
double y;
|
||||
|
||||
explicit Coordinates(double cx, double cy) noexcept : x(cx), y(cy) {
|
||||
}
|
||||
|
||||
Coordinates(const osmium::Location& location) : x(location.lon()), y(location.lat()) {
|
||||
}
|
||||
|
||||
void append_to_string(std::string& s, const char infix, int precision) const {
|
||||
osmium::util::double2string(s, x, precision);
|
||||
s += infix;
|
||||
osmium::util::double2string(s, y, precision);
|
||||
}
|
||||
|
||||
void append_to_string(std::string& s, const char prefix, const char infix, const char suffix, int precision) const {
|
||||
s += prefix;
|
||||
append_to_string(s, infix, precision);
|
||||
s += suffix;
|
||||
}
|
||||
|
||||
}; // struct coordinates
|
||||
|
||||
/**
|
||||
* Compare whether two Coordinates are identical. Might not give the
|
||||
* right result if the coordinates have been the result of some
|
||||
* calculation that introduced rounding errors.
|
||||
*/
|
||||
inline bool operator==(const Coordinates& lhs, const Coordinates& rhs) noexcept {
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
return lhs.x == rhs.x && lhs.y == rhs.y;
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
inline bool operator!=(const Coordinates& lhs, const Coordinates& rhs) noexcept {
|
||||
return ! operator==(lhs, rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits>
|
||||
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const Coordinates& c) {
|
||||
return out << '(' << c.x << ',' << c.y << ')';
|
||||
}
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_COORDINATES_HPP
|
328
ThirdParty/osmium/geom/factory.hpp
vendored
Normal file
328
ThirdParty/osmium/geom/factory.hpp
vendored
Normal file
@ -0,0 +1,328 @@
|
||||
#ifndef OSMIUM_GEOM_FACTORY_HPP
|
||||
#define OSMIUM_GEOM_FACTORY_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/memory/collection.hpp>
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/osm/area.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* Exception thrown when an invalid geometry is encountered. An example
|
||||
* would be a linestring with less than two points.
|
||||
*/
|
||||
struct geometry_error : public std::runtime_error {
|
||||
|
||||
geometry_error(const std::string& what) :
|
||||
std::runtime_error(what) {
|
||||
}
|
||||
|
||||
geometry_error(const char* what) :
|
||||
std::runtime_error(what) {
|
||||
}
|
||||
|
||||
}; // struct geometry_error
|
||||
|
||||
/**
|
||||
* @brief Everything related to geometry handling.
|
||||
*/
|
||||
namespace geom {
|
||||
|
||||
/**
|
||||
* Which nodes of a way to use for a linestring.
|
||||
*/
|
||||
enum class use_nodes : bool {
|
||||
unique = true, ///< Remove consecutive nodes with same location.
|
||||
all = false ///< Use all nodes.
|
||||
}; // enum class use_nodes
|
||||
|
||||
/**
|
||||
* Which direction the linestring created from a way
|
||||
* should have.
|
||||
*/
|
||||
enum class direction : bool {
|
||||
backward = true, ///< Linestring has reverse direction.
|
||||
forward = false ///< Linestring has same direction as way.
|
||||
}; // enum class direction
|
||||
|
||||
/**
|
||||
* This pseudo projection just returns its WGS84 input unchanged.
|
||||
* Used as a template parameter if a real projection is not needed.
|
||||
*/
|
||||
class IdentityProjection {
|
||||
|
||||
public:
|
||||
|
||||
Coordinates operator()(osmium::Location location) const {
|
||||
return Coordinates{location.lon(), location.lat()};
|
||||
}
|
||||
|
||||
int epsg() const noexcept {
|
||||
return 4326;
|
||||
}
|
||||
|
||||
std::string proj_string() const {
|
||||
return "+proj=longlat +datum=WGS84 +no_defs";
|
||||
}
|
||||
|
||||
}; // class IdentityProjection
|
||||
|
||||
/**
|
||||
* Geometry factory.
|
||||
*/
|
||||
template <class TGeomImpl, class TProjection = IdentityProjection>
|
||||
class GeometryFactory {
|
||||
|
||||
/**
|
||||
* Add all points of an outer or inner ring to a multipolygon.
|
||||
*/
|
||||
void add_points(const osmium::OuterRing& nodes) {
|
||||
osmium::Location last_location;
|
||||
for (const osmium::NodeRef& node_ref : nodes) {
|
||||
if (last_location != node_ref.location()) {
|
||||
last_location = node_ref.location();
|
||||
m_impl.multipolygon_add_location(m_projection(last_location));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TProjection m_projection;
|
||||
TGeomImpl m_impl;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for default initialized projection.
|
||||
*/
|
||||
template <class... TArgs>
|
||||
GeometryFactory<TGeomImpl, TProjection>(TArgs&&... args) :
|
||||
m_projection(),
|
||||
m_impl(std::forward<TArgs>(args)...) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for explicitly initialized projection. Note that the
|
||||
* projection is moved into the GeometryFactory.
|
||||
*/
|
||||
template <class... TArgs>
|
||||
GeometryFactory<TGeomImpl, TProjection>(TProjection&& projection, TArgs&&... args) :
|
||||
m_projection(std::move(projection)),
|
||||
m_impl(std::forward<TArgs>(args)...) {
|
||||
}
|
||||
|
||||
typedef typename TGeomImpl::point_type point_type;
|
||||
typedef typename TGeomImpl::linestring_type linestring_type;
|
||||
typedef typename TGeomImpl::polygon_type polygon_type;
|
||||
typedef typename TGeomImpl::multipolygon_type multipolygon_type;
|
||||
typedef typename TGeomImpl::ring_type ring_type;
|
||||
|
||||
int epsg() const {
|
||||
return m_projection.epsg();
|
||||
}
|
||||
|
||||
std::string proj_string() const {
|
||||
return m_projection.proj_string();
|
||||
}
|
||||
|
||||
/* Point */
|
||||
|
||||
point_type create_point(const osmium::Location location) const {
|
||||
return m_impl.make_point(m_projection(location));
|
||||
}
|
||||
|
||||
point_type create_point(const osmium::Node& node) {
|
||||
return create_point(node.location());
|
||||
}
|
||||
|
||||
point_type create_point(const osmium::NodeRef& node_ref) {
|
||||
return create_point(node_ref.location());
|
||||
}
|
||||
|
||||
/* LineString */
|
||||
|
||||
void linestring_start() {
|
||||
m_impl.linestring_start();
|
||||
}
|
||||
|
||||
template <class TIter>
|
||||
size_t fill_linestring(TIter it, TIter end) {
|
||||
size_t num_points = 0;
|
||||
for (; it != end; ++it, ++num_points) {
|
||||
m_impl.linestring_add_location(m_projection(it->location()));
|
||||
}
|
||||
return num_points;
|
||||
}
|
||||
|
||||
template <class TIter>
|
||||
size_t fill_linestring_unique(TIter it, TIter end) {
|
||||
size_t num_points = 0;
|
||||
osmium::Location last_location;
|
||||
for (; it != end; ++it) {
|
||||
if (last_location != it->location()) {
|
||||
last_location = it->location();
|
||||
m_impl.linestring_add_location(m_projection(last_location));
|
||||
++num_points;
|
||||
}
|
||||
}
|
||||
return num_points;
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t num_points) {
|
||||
return m_impl.linestring_finish(num_points);
|
||||
}
|
||||
|
||||
linestring_type create_linestring(const osmium::WayNodeList& wnl, use_nodes un=use_nodes::unique, direction dir=direction::forward) {
|
||||
linestring_start();
|
||||
size_t num_points = 0;
|
||||
|
||||
if (un == use_nodes::unique) {
|
||||
osmium::Location last_location;
|
||||
switch (dir) {
|
||||
case direction::forward:
|
||||
num_points = fill_linestring_unique(wnl.cbegin(), wnl.cend());
|
||||
break;
|
||||
case direction::backward:
|
||||
num_points = fill_linestring_unique(wnl.crbegin(), wnl.crend());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (dir) {
|
||||
case direction::forward:
|
||||
num_points = fill_linestring(wnl.cbegin(), wnl.cend());
|
||||
break;
|
||||
case direction::backward:
|
||||
num_points = fill_linestring(wnl.crbegin(), wnl.crend());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_points < 2) {
|
||||
throw osmium::geometry_error("not enough points for linestring");
|
||||
}
|
||||
|
||||
return linestring_finish(num_points);
|
||||
}
|
||||
|
||||
linestring_type create_linestring(const osmium::Way& way, use_nodes un=use_nodes::unique, direction dir=direction::forward) {
|
||||
return create_linestring(way.nodes(), un, dir);
|
||||
}
|
||||
|
||||
/* Polygon */
|
||||
|
||||
void polygon_start() {
|
||||
m_impl.polygon_start();
|
||||
}
|
||||
|
||||
template <class TIter>
|
||||
size_t fill_polygon(TIter it, TIter end) {
|
||||
size_t num_points = 0;
|
||||
for (; it != end; ++it, ++num_points) {
|
||||
m_impl.polygon_add_location(m_projection(it->location()));
|
||||
}
|
||||
return num_points;
|
||||
}
|
||||
|
||||
template <class TIter>
|
||||
size_t fill_polygon_unique(TIter it, TIter end) {
|
||||
size_t num_points = 0;
|
||||
osmium::Location last_location;
|
||||
for (; it != end; ++it) {
|
||||
if (last_location != it->location()) {
|
||||
last_location = it->location();
|
||||
m_impl.polygon_add_location(m_projection(last_location));
|
||||
++num_points;
|
||||
}
|
||||
}
|
||||
return num_points;
|
||||
}
|
||||
|
||||
polygon_type polygon_finish(size_t num_points) {
|
||||
return m_impl.polygon_finish(num_points);
|
||||
}
|
||||
|
||||
/* MultiPolygon */
|
||||
|
||||
multipolygon_type create_multipolygon(const osmium::Area& area) {
|
||||
size_t num_polygons = 0;
|
||||
size_t num_rings = 0;
|
||||
m_impl.multipolygon_start();
|
||||
|
||||
for (auto it = area.cbegin(); it != area.cend(); ++it) {
|
||||
const osmium::OuterRing& ring = static_cast<const osmium::OuterRing&>(*it);
|
||||
if (it->type() == osmium::item_type::outer_ring) {
|
||||
if (num_polygons > 0) {
|
||||
m_impl.multipolygon_polygon_finish();
|
||||
}
|
||||
m_impl.multipolygon_polygon_start();
|
||||
m_impl.multipolygon_outer_ring_start();
|
||||
add_points(ring);
|
||||
m_impl.multipolygon_outer_ring_finish();
|
||||
++num_rings;
|
||||
++num_polygons;
|
||||
} else if (it->type() == osmium::item_type::inner_ring) {
|
||||
m_impl.multipolygon_inner_ring_start();
|
||||
add_points(ring);
|
||||
m_impl.multipolygon_inner_ring_finish();
|
||||
++num_rings;
|
||||
}
|
||||
}
|
||||
|
||||
// if there are no rings, this area is invalid
|
||||
if (num_rings == 0) {
|
||||
throw osmium::geometry_error("invalid area");
|
||||
}
|
||||
|
||||
m_impl.multipolygon_polygon_finish();
|
||||
return m_impl.multipolygon_finish();
|
||||
}
|
||||
|
||||
}; // class GeometryFactory
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_FACTORY_HPP
|
152
ThirdParty/osmium/geom/geojson.hpp
vendored
Normal file
152
ThirdParty/osmium/geom/geojson.hpp
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
#ifndef OSMIUM_GEOM_GEOJSON_HPP
|
||||
#define OSMIUM_GEOM_GEOJSON_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/geom/factory.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class GeoJSONFactoryImpl {
|
||||
|
||||
std::string m_str;
|
||||
int m_precision;
|
||||
|
||||
public:
|
||||
|
||||
typedef std::string point_type;
|
||||
typedef std::string linestring_type;
|
||||
typedef std::string polygon_type;
|
||||
typedef std::string multipolygon_type;
|
||||
typedef std::string ring_type;
|
||||
|
||||
GeoJSONFactoryImpl(int precision = 7) :
|
||||
m_precision(precision) {
|
||||
}
|
||||
|
||||
/* Point */
|
||||
|
||||
// { "type": "Point", "coordinates": [100.0, 0.0] }
|
||||
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||
std::string str {"{\"type\":\"Point\",\"coordinates\":"};
|
||||
xy.append_to_string(str, '[', ',', ']', m_precision);
|
||||
str += "}";
|
||||
return str;
|
||||
}
|
||||
|
||||
/* LineString */
|
||||
|
||||
// { "type": "LineString", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] }
|
||||
void linestring_start() {
|
||||
m_str = "{\"type\":\"LineString\",\"coordinates\":[";
|
||||
}
|
||||
|
||||
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||
xy.append_to_string(m_str, '[', ',', ']', m_precision);
|
||||
m_str += ',';
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t /* num_points */) {
|
||||
assert(!m_str.empty());
|
||||
std::string str;
|
||||
std::swap(str, m_str);
|
||||
str.back() = ']';
|
||||
str += "}";
|
||||
return str;
|
||||
}
|
||||
|
||||
/* MultiPolygon */
|
||||
|
||||
void multipolygon_start() {
|
||||
m_str = "{\"type\":\"MultiPolygon\",\"coordinates\":[";
|
||||
}
|
||||
|
||||
void multipolygon_polygon_start() {
|
||||
m_str += '[';
|
||||
}
|
||||
|
||||
void multipolygon_polygon_finish() {
|
||||
m_str += "],";
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_start() {
|
||||
m_str += '[';
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_finish() {
|
||||
assert(!m_str.empty());
|
||||
m_str.back() = ']';
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_start() {
|
||||
m_str += ",[";
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_finish() {
|
||||
assert(!m_str.empty());
|
||||
m_str.back() = ']';
|
||||
}
|
||||
|
||||
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
xy.append_to_string(m_str, '[', ',', ']', m_precision);
|
||||
m_str += ',';
|
||||
}
|
||||
|
||||
multipolygon_type multipolygon_finish() {
|
||||
assert(!m_str.empty());
|
||||
m_str.back() = ']';
|
||||
m_str += "}";
|
||||
return std::move(m_str);
|
||||
}
|
||||
|
||||
}; // class GeoJSONFactoryImpl
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class TProjection = IdentityProjection>
|
||||
using GeoJSONFactory = GeometryFactory<osmium::geom::detail::GeoJSONFactoryImpl, TProjection>;
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_GEOJSON_HPP
|
224
ThirdParty/osmium/geom/geos.hpp
vendored
Normal file
224
ThirdParty/osmium/geom/geos.hpp
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
#ifndef OSMIUM_GEOM_GEOS_HPP
|
||||
#define OSMIUM_GEOM_GEOS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#define OSMIUM_COMPILE_WITH_CFLAGS_GEOS `geos-config --cflags`
|
||||
#define OSMIUM_LINK_WITH_LIBS_GEOS `geos-config --libs`
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <geos/geom/Coordinate.h>
|
||||
#include <geos/geom/CoordinateSequence.h>
|
||||
#include <geos/geom/CoordinateSequenceFactory.h>
|
||||
#include <geos/geom/GeometryFactory.h>
|
||||
#include <geos/geom/LinearRing.h>
|
||||
#include <geos/geom/MultiPolygon.h>
|
||||
#include <geos/geom/Point.h>
|
||||
#include <geos/geom/Polygon.h>
|
||||
#include <geos/geom/PrecisionModel.h>
|
||||
#include <geos/util/GEOSException.h>
|
||||
|
||||
#include <osmium/geom/factory.hpp>
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
|
||||
// MSVC doesn't support throw_with_nested yet
|
||||
#ifdef _MSC_VER
|
||||
# define THROW throw
|
||||
#else
|
||||
# define THROW std::throw_with_nested
|
||||
#endif
|
||||
|
||||
namespace osmium {
|
||||
|
||||
struct geos_geometry_error : public geometry_error {
|
||||
|
||||
geos_geometry_error() :
|
||||
geometry_error("geometry creation failed in GEOS library, see nested exception for details") {
|
||||
}
|
||||
|
||||
}; // struct geos_geometry_error
|
||||
|
||||
namespace geom {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class GEOSFactoryImpl {
|
||||
|
||||
geos::geom::PrecisionModel m_precision_model;
|
||||
geos::geom::GeometryFactory m_geos_factory;
|
||||
|
||||
std::unique_ptr<geos::geom::CoordinateSequence> m_coordinate_sequence;
|
||||
std::vector<std::unique_ptr<geos::geom::LinearRing>> m_rings;
|
||||
std::vector<std::unique_ptr<geos::geom::Polygon>> m_polygons;
|
||||
|
||||
public:
|
||||
|
||||
typedef std::unique_ptr<geos::geom::Point> point_type;
|
||||
typedef std::unique_ptr<geos::geom::LineString> linestring_type;
|
||||
typedef std::unique_ptr<geos::geom::Polygon> polygon_type;
|
||||
typedef std::unique_ptr<geos::geom::MultiPolygon> multipolygon_type;
|
||||
typedef std::unique_ptr<geos::geom::LinearRing> ring_type;
|
||||
|
||||
explicit GEOSFactoryImpl(int srid = -1) :
|
||||
m_precision_model(),
|
||||
m_geos_factory(&m_precision_model, srid) {
|
||||
}
|
||||
|
||||
/* Point */
|
||||
|
||||
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||
try {
|
||||
return point_type(m_geos_factory.createPoint(geos::geom::Coordinate(xy.x, xy.y)));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
/* LineString */
|
||||
|
||||
void linestring_start() {
|
||||
try {
|
||||
m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||
try {
|
||||
m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t /* num_points */) {
|
||||
try {
|
||||
return linestring_type(m_geos_factory.createLineString(m_coordinate_sequence.release()));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
/* MultiPolygon */
|
||||
|
||||
void multipolygon_start() {
|
||||
m_polygons.clear();
|
||||
}
|
||||
|
||||
void multipolygon_polygon_start() {
|
||||
m_rings.clear();
|
||||
}
|
||||
|
||||
void multipolygon_polygon_finish() {
|
||||
try {
|
||||
assert(!m_rings.empty());
|
||||
auto inner_rings = new std::vector<geos::geom::Geometry*>;
|
||||
std::transform(std::next(m_rings.begin(), 1), m_rings.end(), std::back_inserter(*inner_rings), [](std::unique_ptr<geos::geom::LinearRing>& r) {
|
||||
return r.release();
|
||||
});
|
||||
m_polygons.emplace_back(m_geos_factory.createPolygon(m_rings[0].release(), inner_rings));
|
||||
m_rings.clear();
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_start() {
|
||||
try {
|
||||
m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_finish() {
|
||||
try {
|
||||
m_rings.emplace_back(m_geos_factory.createLinearRing(m_coordinate_sequence.release()));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_start() {
|
||||
try {
|
||||
m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_finish() {
|
||||
try {
|
||||
m_rings.emplace_back(m_geos_factory.createLinearRing(m_coordinate_sequence.release()));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
try {
|
||||
m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
multipolygon_type multipolygon_finish() {
|
||||
try {
|
||||
auto polygons = new std::vector<geos::geom::Geometry*>;
|
||||
std::transform(m_polygons.begin(), m_polygons.end(), std::back_inserter(*polygons), [](std::unique_ptr<geos::geom::Polygon>& p) {
|
||||
return p.release();
|
||||
});
|
||||
m_polygons.clear();
|
||||
return multipolygon_type(m_geos_factory.createMultiPolygon(polygons));
|
||||
} catch (geos::util::GEOSException&) {
|
||||
THROW(osmium::geos_geometry_error());
|
||||
}
|
||||
}
|
||||
|
||||
}; // class GEOSFactoryImpl
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class TProjection = IdentityProjection>
|
||||
using GEOSFactory = GeometryFactory<osmium::geom::detail::GEOSFactoryImpl, TProjection>;
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#undef THROW
|
||||
|
||||
#endif // OSMIUM_GEOM_GEOS_HPP
|
94
ThirdParty/osmium/geom/haversine.hpp
vendored
Normal file
94
ThirdParty/osmium/geom/haversine.hpp
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
#ifndef OSMIUM_GEOM_HAVERSINE_HPP
|
||||
#define OSMIUM_GEOM_HAVERSINE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <iterator>
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/geom/util.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
/**
|
||||
* @brief Functions to calculate arc distance on Earth using the haversine formula.
|
||||
*
|
||||
* See http://en.wikipedia.org/wiki/Haversine_formula
|
||||
*
|
||||
* Implementation derived from
|
||||
* http://blog.julien.cayzac.name/2008/10/arc-and-distance-between-two-points-on.html
|
||||
*/
|
||||
namespace haversine {
|
||||
|
||||
/// @brief Earth's quadratic mean radius for WGS84
|
||||
constexpr double EARTH_RADIUS_IN_METERS = 6372797.560856;
|
||||
|
||||
/**
|
||||
* Calculate distance in meters between two sets of coordinates.
|
||||
*/
|
||||
inline double distance(const osmium::geom::Coordinates& c1, const osmium::geom::Coordinates& c2) {
|
||||
double lonh = sin(deg_to_rad(c1.x - c2.x) * 0.5);
|
||||
lonh *= lonh;
|
||||
double lath = sin(deg_to_rad(c1.y - c2.y) * 0.5);
|
||||
lath *= lath;
|
||||
const double tmp = cos(deg_to_rad(c1.y)) * cos(deg_to_rad(c2.y));
|
||||
return 2.0 * EARTH_RADIUS_IN_METERS * asin(sqrt(lath + tmp*lonh));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate length of way.
|
||||
*/
|
||||
inline double distance(const osmium::WayNodeList& wnl) {
|
||||
double sum_length=0;
|
||||
|
||||
for (auto it = wnl.begin(); it != wnl.end(); ++it) {
|
||||
if (std::next(it) != wnl.end()) {
|
||||
sum_length += distance(it->location(), std::next(it)->location());
|
||||
}
|
||||
}
|
||||
|
||||
return sum_length;
|
||||
}
|
||||
|
||||
} // namespace haversine
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_HAVERSINE_HPP
|
109
ThirdParty/osmium/geom/mercator_projection.hpp
vendored
Normal file
109
ThirdParty/osmium/geom/mercator_projection.hpp
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
#ifndef OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
|
||||
#define OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/geom/util.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr double earth_radius_for_epsg3857 = 6378137.0;
|
||||
|
||||
constexpr inline double lon_to_x(double lon) {
|
||||
return earth_radius_for_epsg3857 * deg_to_rad(lon);
|
||||
}
|
||||
|
||||
inline double lat_to_y(double lat) { // not constexpr because math functions aren't
|
||||
return earth_radius_for_epsg3857 * std::log(std::tan(osmium::geom::PI/4 + deg_to_rad(lat)/2));
|
||||
}
|
||||
|
||||
constexpr inline double x_to_lon(double x) {
|
||||
return rad_to_deg(x) / earth_radius_for_epsg3857;
|
||||
}
|
||||
|
||||
inline double y_to_lat(double y) { // not constexpr because math functions aren't
|
||||
return rad_to_deg(2 * std::atan(std::exp(y / earth_radius_for_epsg3857)) - osmium::geom::PI/2);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* The maximum latitude that can be projected with the Web Mercator
|
||||
* (EPSG:3857) projection.
|
||||
*/
|
||||
constexpr double MERCATOR_MAX_LAT = 85.0511288;
|
||||
|
||||
inline Coordinates lonlat_to_mercator(const Coordinates& c) {
|
||||
return Coordinates(detail::lon_to_x(c.x), detail::lat_to_y(c.y));
|
||||
}
|
||||
|
||||
inline Coordinates mercator_to_lonlat(const Coordinates& c) {
|
||||
return Coordinates(detail::x_to_lon(c.x), detail::y_to_lat(c.y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Functor that does projection from WGS84 (EPSG:4326) to "Web
|
||||
* Mercator" (EPSG:3857)
|
||||
*/
|
||||
class MercatorProjection {
|
||||
|
||||
public:
|
||||
|
||||
Coordinates operator()(osmium::Location location) const {
|
||||
return Coordinates {detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())};
|
||||
}
|
||||
|
||||
int epsg() const noexcept {
|
||||
return 3857;
|
||||
}
|
||||
|
||||
std::string proj_string() const {
|
||||
return "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs";
|
||||
}
|
||||
|
||||
}; // class MercatorProjection
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
|
179
ThirdParty/osmium/geom/ogr.hpp
vendored
Normal file
179
ThirdParty/osmium/geom/ogr.hpp
vendored
Normal file
@ -0,0 +1,179 @@
|
||||
#ifndef OSMIUM_GEOM_OGR_HPP
|
||||
#define OSMIUM_GEOM_OGR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#define OSMIUM_COMPILE_WITH_CFLAGS_OGR `gdal-config --cflags`
|
||||
#define OSMIUM_LINK_WITH_LIBS_OGR `gdal-config --libs`
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#ifdef __clang__
|
||||
# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#pragma GCC diagnostic ignored "-Wpadded"
|
||||
# include <ogr_geometry.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/geom/factory.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class OGRFactoryImpl {
|
||||
|
||||
public:
|
||||
|
||||
typedef std::unique_ptr<OGRPoint> point_type;
|
||||
typedef std::unique_ptr<OGRLineString> linestring_type;
|
||||
typedef std::unique_ptr<OGRPolygon> polygon_type;
|
||||
typedef std::unique_ptr<OGRMultiPolygon> multipolygon_type;
|
||||
typedef std::unique_ptr<OGRLinearRing> ring_type;
|
||||
|
||||
private:
|
||||
|
||||
linestring_type m_linestring;
|
||||
multipolygon_type m_multipolygon;
|
||||
polygon_type m_polygon;
|
||||
ring_type m_ring;
|
||||
|
||||
public:
|
||||
|
||||
OGRFactoryImpl() = default;
|
||||
|
||||
/* Point */
|
||||
|
||||
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||
return point_type(new OGRPoint(xy.x, xy.y));
|
||||
}
|
||||
|
||||
/* LineString */
|
||||
|
||||
void linestring_start() {
|
||||
m_linestring = std::unique_ptr<OGRLineString>(new OGRLineString());
|
||||
}
|
||||
|
||||
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||
assert(!!m_linestring);
|
||||
m_linestring->addPoint(xy.x, xy.y);
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t /* num_points */) {
|
||||
return std::move(m_linestring);
|
||||
}
|
||||
|
||||
/* Polygon */
|
||||
|
||||
void polygon_start() {
|
||||
m_ring = std::unique_ptr<OGRLinearRing>(new OGRLinearRing());
|
||||
}
|
||||
|
||||
void polygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
assert(!!m_ring);
|
||||
m_ring->addPoint(xy.x, xy.y);
|
||||
}
|
||||
|
||||
polygon_type polygon_finish(size_t /* num_points */) {
|
||||
std::unique_ptr<OGRPolygon> polygon = std::unique_ptr<OGRPolygon>(new OGRPolygon());
|
||||
polygon->addRingDirectly(m_ring.release());
|
||||
return polygon;
|
||||
}
|
||||
|
||||
/* MultiPolygon */
|
||||
|
||||
void multipolygon_start() {
|
||||
m_multipolygon.reset(new OGRMultiPolygon());
|
||||
}
|
||||
|
||||
void multipolygon_polygon_start() {
|
||||
m_polygon.reset(new OGRPolygon());
|
||||
}
|
||||
|
||||
void multipolygon_polygon_finish() {
|
||||
assert(!!m_multipolygon);
|
||||
assert(!!m_polygon);
|
||||
m_multipolygon->addGeometryDirectly(m_polygon.release());
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_start() {
|
||||
m_ring.reset(new OGRLinearRing());
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_finish() {
|
||||
assert(!!m_polygon);
|
||||
assert(!!m_ring);
|
||||
m_polygon->addRingDirectly(m_ring.release());
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_start() {
|
||||
m_ring.reset(new OGRLinearRing());
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_finish() {
|
||||
assert(!!m_polygon);
|
||||
assert(!!m_ring);
|
||||
m_polygon->addRingDirectly(m_ring.release());
|
||||
}
|
||||
|
||||
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
assert(!!m_polygon);
|
||||
assert(!!m_ring);
|
||||
m_ring->addPoint(xy.x, xy.y);
|
||||
}
|
||||
|
||||
multipolygon_type multipolygon_finish() {
|
||||
assert(!!m_multipolygon);
|
||||
return std::move(m_multipolygon);
|
||||
}
|
||||
|
||||
}; // class OGRFactoryImpl
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class TProjection = IdentityProjection>
|
||||
using OGRFactory = GeometryFactory<osmium::geom::detail::OGRFactoryImpl, TProjection>;
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_OGR_HPP
|
159
ThirdParty/osmium/geom/projection.hpp
vendored
Normal file
159
ThirdParty/osmium/geom/projection.hpp
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
#ifndef OSMIUM_GEOM_PROJECTION_HPP
|
||||
#define OSMIUM_GEOM_PROJECTION_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#define OSMIUM_LINK_WITH_LIBS_PROJ -lproj
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <proj_api.h>
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/geom/util.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
/**
|
||||
* C++ wrapper for a Coordinate Reference System of the proj library.
|
||||
*/
|
||||
class CRS {
|
||||
|
||||
struct ProjCRSDeleter {
|
||||
void operator()(void* crs) {
|
||||
pj_free(crs);
|
||||
}
|
||||
}; // struct ProjCRSDeleter
|
||||
|
||||
std::unique_ptr<void, ProjCRSDeleter> m_crs;
|
||||
|
||||
projPJ get() const {
|
||||
return m_crs.get();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
CRS(const std::string& crs) :
|
||||
m_crs(pj_init_plus(crs.c_str()), ProjCRSDeleter()) {
|
||||
if (!m_crs) {
|
||||
throw osmium::projection_error(std::string("creation of CRS failed: ") + pj_strerrno(*pj_get_errno_ref()));
|
||||
}
|
||||
}
|
||||
|
||||
CRS(int epsg) :
|
||||
CRS(std::string("+init=epsg:") + std::to_string(epsg)) {
|
||||
}
|
||||
|
||||
bool is_latlong() const {
|
||||
return pj_is_latlong(m_crs.get());
|
||||
}
|
||||
|
||||
bool is_geocent() const {
|
||||
return pj_is_geocent(m_crs.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform coordinates from one CRS into another. Wraps the same function
|
||||
* of the proj library.
|
||||
*
|
||||
* Coordinates have to be in radians and are produced in radians.
|
||||
*
|
||||
* @throws osmmium::projection_error if the projection fails
|
||||
*/
|
||||
friend Coordinates transform(const CRS& src, const CRS& dest, Coordinates c) {
|
||||
int result = pj_transform(src.get(), dest.get(), 1, 1, &c.x, &c.y, nullptr);
|
||||
if (result != 0) {
|
||||
throw osmium::projection_error(std::string("projection failed: ") + pj_strerrno(result));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
}; // class CRS
|
||||
|
||||
/**
|
||||
* Functor that does projection from WGS84 (EPSG:4326) in to the given
|
||||
* CRS.
|
||||
*/
|
||||
class Projection {
|
||||
|
||||
int m_epsg;
|
||||
std::string m_proj_string;
|
||||
CRS m_crs_wgs84 {4326};
|
||||
CRS m_crs_user;
|
||||
|
||||
public:
|
||||
|
||||
Projection(const std::string& proj_string) :
|
||||
m_epsg(-1),
|
||||
m_proj_string(proj_string),
|
||||
m_crs_user(proj_string) {
|
||||
}
|
||||
|
||||
Projection(int epsg) :
|
||||
m_epsg(epsg),
|
||||
m_proj_string(std::string("+init=epsg:") + std::to_string(epsg)),
|
||||
m_crs_user(epsg) {
|
||||
}
|
||||
|
||||
Coordinates operator()(osmium::Location location) const {
|
||||
if (m_epsg == 4326) {
|
||||
return Coordinates(location.lon(), location.lat());
|
||||
} else {
|
||||
Coordinates c = transform(m_crs_wgs84, m_crs_user, Coordinates(deg_to_rad(location.lon()), deg_to_rad(location.lat())));
|
||||
if (m_crs_user.is_latlong()) {
|
||||
c.x = rad_to_deg(c.x);
|
||||
c.y = rad_to_deg(c.y);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
int epsg() const noexcept {
|
||||
return m_epsg;
|
||||
}
|
||||
|
||||
std::string proj_string() const {
|
||||
return m_proj_string;
|
||||
}
|
||||
|
||||
}; // class Projection
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_PROJECTION_HPP
|
57
ThirdParty/osmium/geom/relations.hpp
vendored
Normal file
57
ThirdParty/osmium/geom/relations.hpp
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef OSMIUM_GEOM_RELATIONS_HPP
|
||||
#define OSMIUM_GEOM_RELATIONS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/osm/box.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
/**
|
||||
* Check whether one geometry contains another.
|
||||
*/
|
||||
inline bool contains(const osmium::Box& a, const osmium::Box& b) {
|
||||
return ((a.bottom_left().x() >= b.bottom_left().x()) &&
|
||||
(a.top_right().x() <= b.top_right().x()) &&
|
||||
(a.bottom_left().y() >= b.bottom_left().y()) &&
|
||||
(a.top_right().y() <= b.top_right().y()));
|
||||
}
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_RELATIONS_HPP
|
75
ThirdParty/osmium/geom/util.hpp
vendored
Normal file
75
ThirdParty/osmium/geom/util.hpp
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef OSMIUM_GEOM_UTIL_HPP
|
||||
#define OSMIUM_GEOM_UTIL_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* Exception thrown when a projection object can not be initialized or the
|
||||
* projection of some coordinates can not be calculated.
|
||||
*/
|
||||
struct projection_error : public std::runtime_error {
|
||||
|
||||
projection_error(const std::string& what) :
|
||||
std::runtime_error(what) {
|
||||
}
|
||||
|
||||
projection_error(const char* what) :
|
||||
std::runtime_error(what) {
|
||||
}
|
||||
|
||||
}; // struct projection_error
|
||||
|
||||
namespace geom {
|
||||
|
||||
constexpr double PI = 3.14159265358979323846;
|
||||
|
||||
/// Convert angle from degrees to radians.
|
||||
inline constexpr double deg_to_rad(double degree) noexcept {
|
||||
return degree * (PI / 180.0);
|
||||
}
|
||||
|
||||
/// Convert angle from radians to degrees.
|
||||
inline constexpr double rad_to_deg(double radians) noexcept {
|
||||
return radians * (180.0 / PI);
|
||||
}
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_UTIL_HPP
|
279
ThirdParty/osmium/geom/wkb.hpp
vendored
Normal file
279
ThirdParty/osmium/geom/wkb.hpp
vendored
Normal file
@ -0,0 +1,279 @@
|
||||
#ifndef OSMIUM_GEOM_WKB_HPP
|
||||
#define OSMIUM_GEOM_WKB_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
// Windows is only available for little endian architectures
|
||||
// http://stackoverflow.com/questions/6449468/can-i-safely-assume-that-windows-installations-will-always-be-little-endian
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
# include <endian.h>
|
||||
#else
|
||||
# define __LITTLE_ENDIAN 1234
|
||||
# define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/geom/factory.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
enum class wkb_type : bool {
|
||||
wkb = false,
|
||||
ewkb = true
|
||||
}; // enum class wkb_type
|
||||
|
||||
enum class out_type : bool {
|
||||
binary = false,
|
||||
hex = true
|
||||
}; // enum class out_type
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
inline void str_push(std::string& str, T data) {
|
||||
size_t size = str.size();
|
||||
str.resize(size + sizeof(T));
|
||||
std::memcpy(const_cast<char *>(&str[size]), reinterpret_cast<char*>(&data), sizeof(T));
|
||||
}
|
||||
|
||||
inline std::string convert_to_hex(std::string& str) {
|
||||
static const char* lookup_hex = "0123456789ABCDEF";
|
||||
std::string out;
|
||||
|
||||
for (char c : str) {
|
||||
out += lookup_hex[(c >> 4) & 0xf];
|
||||
out += lookup_hex[c & 0xf];
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
class WKBFactoryImpl {
|
||||
|
||||
/// OSM data always uses SRID 4326 (WGS84).
|
||||
static constexpr uint32_t srid = 4326;
|
||||
|
||||
/**
|
||||
* Type of WKB geometry.
|
||||
* These definitions are from
|
||||
* 99-049_OpenGIS_Simple_Features_Specification_For_SQL_Rev_1.1.pdf (for WKB)
|
||||
* and http://trac.osgeo.org/postgis/browser/trunk/doc/ZMSgeoms.txt (for EWKB).
|
||||
* They are used to encode geometries into the WKB format.
|
||||
*/
|
||||
enum wkbGeometryType : uint32_t {
|
||||
wkbPoint = 1,
|
||||
wkbLineString = 2,
|
||||
wkbPolygon = 3,
|
||||
wkbMultiPoint = 4,
|
||||
wkbMultiLineString = 5,
|
||||
wkbMultiPolygon = 6,
|
||||
wkbGeometryCollection = 7,
|
||||
|
||||
// SRID-presence flag (EWKB)
|
||||
wkbSRID = 0x20000000
|
||||
}; // enum wkbGeometryType
|
||||
|
||||
/**
|
||||
* Byte order marker in WKB geometry.
|
||||
*/
|
||||
enum class wkb_byte_order_type : uint8_t {
|
||||
XDR = 0, // Big Endian
|
||||
NDR = 1 // Little Endian
|
||||
}; // enum class wkb_byte_order_type
|
||||
|
||||
std::string m_data;
|
||||
uint32_t m_points {0};
|
||||
wkb_type m_wkb_type;
|
||||
out_type m_out_type;
|
||||
|
||||
size_t m_linestring_size_offset = 0;
|
||||
size_t m_polygons = 0;
|
||||
size_t m_rings = 0;
|
||||
size_t m_multipolygon_size_offset = 0;
|
||||
size_t m_polygon_size_offset = 0;
|
||||
size_t m_ring_size_offset = 0;
|
||||
|
||||
size_t header(std::string& str, wkbGeometryType type, bool add_length) const {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
str_push(str, wkb_byte_order_type::NDR);
|
||||
#else
|
||||
str_push(str, wkb_byte_order_type::XDR);
|
||||
#endif
|
||||
if (m_wkb_type == wkb_type::ewkb) {
|
||||
str_push(str, type | wkbSRID);
|
||||
str_push(str, srid);
|
||||
} else {
|
||||
str_push(str, type);
|
||||
}
|
||||
size_t offset = str.size();
|
||||
if (add_length) {
|
||||
str_push(str, static_cast<uint32_t>(0));
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
void set_size(const size_t offset, const size_t size) {
|
||||
const uint32_t s = static_cast_with_assert<uint32_t>(size);
|
||||
memcpy(&m_data[offset], &s, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef std::string point_type;
|
||||
typedef std::string linestring_type;
|
||||
typedef std::string polygon_type;
|
||||
typedef std::string multipolygon_type;
|
||||
typedef std::string ring_type;
|
||||
|
||||
explicit WKBFactoryImpl(wkb_type wtype=wkb_type::wkb, out_type otype=out_type::binary) :
|
||||
m_wkb_type(wtype),
|
||||
m_out_type(otype) {
|
||||
}
|
||||
|
||||
/* Point */
|
||||
|
||||
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||
std::string data;
|
||||
header(data, wkbPoint, false);
|
||||
str_push(data, xy.x);
|
||||
str_push(data, xy.y);
|
||||
|
||||
if (m_out_type == out_type::hex) {
|
||||
return convert_to_hex(data);
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/* LineString */
|
||||
|
||||
void linestring_start() {
|
||||
m_data.clear();
|
||||
m_linestring_size_offset = header(m_data, wkbLineString, true);
|
||||
}
|
||||
|
||||
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||
str_push(m_data, xy.x);
|
||||
str_push(m_data, xy.y);
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t num_points) {
|
||||
set_size(m_linestring_size_offset, num_points);
|
||||
std::string data;
|
||||
std::swap(data, m_data);
|
||||
|
||||
if (m_out_type == out_type::hex) {
|
||||
return convert_to_hex(data);
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/* MultiPolygon */
|
||||
|
||||
void multipolygon_start() {
|
||||
m_data.clear();
|
||||
m_polygons = 0;
|
||||
m_multipolygon_size_offset = header(m_data, wkbMultiPolygon, true);
|
||||
}
|
||||
|
||||
void multipolygon_polygon_start() {
|
||||
++m_polygons;
|
||||
m_rings = 0;
|
||||
m_polygon_size_offset = header(m_data, wkbPolygon, true);
|
||||
}
|
||||
|
||||
void multipolygon_polygon_finish() {
|
||||
set_size(m_polygon_size_offset, m_rings);
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_start() {
|
||||
++m_rings;
|
||||
m_points = 0;
|
||||
m_ring_size_offset = m_data.size();
|
||||
str_push(m_data, static_cast<uint32_t>(0));
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_finish() {
|
||||
set_size(m_ring_size_offset, m_points);
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_start() {
|
||||
++m_rings;
|
||||
m_points = 0;
|
||||
m_ring_size_offset = m_data.size();
|
||||
str_push(m_data, static_cast<uint32_t>(0));
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_finish() {
|
||||
set_size(m_ring_size_offset, m_points);
|
||||
}
|
||||
|
||||
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
str_push(m_data, xy.x);
|
||||
str_push(m_data, xy.y);
|
||||
++m_points;
|
||||
}
|
||||
|
||||
multipolygon_type multipolygon_finish() {
|
||||
set_size(m_multipolygon_size_offset, m_polygons);
|
||||
std::string data;
|
||||
std::swap(data, m_data);
|
||||
|
||||
if (m_out_type == out_type::hex) {
|
||||
return convert_to_hex(data);
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
}; // class WKBFactoryImpl
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class TProjection = IdentityProjection>
|
||||
using WKBFactory = GeometryFactory<osmium::geom::detail::WKBFactoryImpl, TProjection>;
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_WKB_HPP
|
148
ThirdParty/osmium/geom/wkt.hpp
vendored
Normal file
148
ThirdParty/osmium/geom/wkt.hpp
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
#ifndef OSMIUM_GEOM_WKT_HPP
|
||||
#define OSMIUM_GEOM_WKT_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
#include <osmium/geom/factory.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class WKTFactoryImpl {
|
||||
|
||||
std::string m_str;
|
||||
int m_precision;
|
||||
|
||||
public:
|
||||
|
||||
typedef std::string point_type;
|
||||
typedef std::string linestring_type;
|
||||
typedef std::string polygon_type;
|
||||
typedef std::string multipolygon_type;
|
||||
typedef std::string ring_type;
|
||||
|
||||
WKTFactoryImpl(int precision = 7) :
|
||||
m_precision(precision) {
|
||||
}
|
||||
|
||||
/* Point */
|
||||
|
||||
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||
std::string str {"POINT"};
|
||||
xy.append_to_string(str, '(', ' ', ')', m_precision);
|
||||
return str;
|
||||
}
|
||||
|
||||
/* LineString */
|
||||
|
||||
void linestring_start() {
|
||||
m_str = "LINESTRING(";
|
||||
}
|
||||
|
||||
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||
xy.append_to_string(m_str, ' ', m_precision);
|
||||
m_str += ',';
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(size_t /* num_points */) {
|
||||
assert(!m_str.empty());
|
||||
std::string str;
|
||||
std::swap(str, m_str);
|
||||
str.back() = ')';
|
||||
return str;
|
||||
}
|
||||
|
||||
/* MultiPolygon */
|
||||
|
||||
void multipolygon_start() {
|
||||
m_str = "MULTIPOLYGON(";
|
||||
}
|
||||
|
||||
void multipolygon_polygon_start() {
|
||||
m_str += '(';
|
||||
}
|
||||
|
||||
void multipolygon_polygon_finish() {
|
||||
m_str += "),";
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_start() {
|
||||
m_str += '(';
|
||||
}
|
||||
|
||||
void multipolygon_outer_ring_finish() {
|
||||
assert(!m_str.empty());
|
||||
m_str.back() = ')';
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_start() {
|
||||
m_str += ",(";
|
||||
}
|
||||
|
||||
void multipolygon_inner_ring_finish() {
|
||||
assert(!m_str.empty());
|
||||
m_str.back() = ')';
|
||||
}
|
||||
|
||||
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||
xy.append_to_string(m_str, ' ', m_precision);
|
||||
m_str += ',';
|
||||
}
|
||||
|
||||
multipolygon_type multipolygon_finish() {
|
||||
assert(!m_str.empty());
|
||||
m_str.back() = ')';
|
||||
return std::move(m_str);
|
||||
}
|
||||
|
||||
}; // class WKTFactoryImpl
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class TProjection = IdentityProjection>
|
||||
using WKTFactory = GeometryFactory<osmium::geom::detail::WKTFactoryImpl, TProjection>;
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_WKT_HPP
|
101
ThirdParty/osmium/handler.hpp
vendored
Normal file
101
ThirdParty/osmium/handler.hpp
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef OSMIUM_HANDLER_HPP
|
||||
#define OSMIUM_HANDLER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
namespace osmium {
|
||||
|
||||
class OSMObject;
|
||||
class Node;
|
||||
class Way;
|
||||
class Relation;
|
||||
class Area;
|
||||
class Changeset;
|
||||
class TagList;
|
||||
class WayNodeList;
|
||||
class RelationMemberList;
|
||||
class OuterRing;
|
||||
class InnerRing;
|
||||
|
||||
/**
|
||||
* @brief Osmium handlers provide callbacks for OSM objects
|
||||
*/
|
||||
namespace handler {
|
||||
|
||||
class Handler {
|
||||
|
||||
public:
|
||||
|
||||
void osm_object(const osmium::OSMObject&) const {
|
||||
}
|
||||
|
||||
void node(const osmium::Node&) const {
|
||||
}
|
||||
|
||||
void way(const osmium::Way&) const {
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation&) const {
|
||||
}
|
||||
|
||||
void area(const osmium::Area&) const {
|
||||
}
|
||||
|
||||
void changeset(const osmium::Changeset&) const {
|
||||
}
|
||||
|
||||
void tag_list(const osmium::TagList&) const {
|
||||
}
|
||||
|
||||
void way_node_list(const osmium::WayNodeList&) const {
|
||||
}
|
||||
|
||||
void relation_member_list(const osmium::RelationMemberList&) const {
|
||||
}
|
||||
|
||||
void outer_ring(const osmium::OuterRing&) const {
|
||||
}
|
||||
|
||||
void inner_ring(const osmium::InnerRing&) const {
|
||||
}
|
||||
|
||||
void flush() const {
|
||||
}
|
||||
|
||||
}; // class Handler
|
||||
|
||||
} // namspace handler
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_HANDLER_HPP
|
128
ThirdParty/osmium/handler/chain.hpp
vendored
Normal file
128
ThirdParty/osmium/handler/chain.hpp
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
#ifndef OSMIUM_HANDLER_CHAIN_HPP
|
||||
#define OSMIUM_HANDLER_CHAIN_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include <osmium/handler.hpp>
|
||||
|
||||
#define OSMIUM_CHAIN_HANDLER_CALL(_func_, _type_) \
|
||||
template <int N, int SIZE, class THandlers> \
|
||||
struct call_ ## _func_ { \
|
||||
void operator()(THandlers& handlers, osmium::_type_& object) { \
|
||||
std::get<N>(handlers)._func_(object); \
|
||||
call_ ## _func_<N+1, SIZE, THandlers>()(handlers, object); \
|
||||
} \
|
||||
}; \
|
||||
template <int SIZE, class THandlers> \
|
||||
struct call_ ## _func_<SIZE, SIZE, THandlers> { \
|
||||
void operator()(THandlers&, osmium::_type_&) {} \
|
||||
};
|
||||
|
||||
namespace osmium {
|
||||
|
||||
class Node;
|
||||
class Way;
|
||||
class Relation;
|
||||
class Area;
|
||||
class Changeset;
|
||||
|
||||
namespace handler {
|
||||
|
||||
/**
|
||||
* This handler allows chaining of any number of handlers into a single
|
||||
* handler.
|
||||
*/
|
||||
template <class ...THandler>
|
||||
class ChainHandler : public osmium::handler::Handler {
|
||||
|
||||
typedef std::tuple<THandler&...> handlers_type;
|
||||
handlers_type m_handlers;
|
||||
|
||||
template <int N, int SIZE, class THandlers>
|
||||
struct call_flush {
|
||||
void operator()(THandlers& handlers) {
|
||||
std::get<N>(handlers).flush();
|
||||
call_flush<N+1, SIZE, THandlers>()(handlers);
|
||||
}
|
||||
}; // struct call_flush
|
||||
|
||||
template <int SIZE, class THandlers>
|
||||
struct call_flush<SIZE, SIZE, THandlers> {
|
||||
void operator()(THandlers&) {}
|
||||
}; // struct call_flush
|
||||
|
||||
OSMIUM_CHAIN_HANDLER_CALL(node, Node)
|
||||
OSMIUM_CHAIN_HANDLER_CALL(way, Way)
|
||||
OSMIUM_CHAIN_HANDLER_CALL(relation, Relation)
|
||||
OSMIUM_CHAIN_HANDLER_CALL(changeset, Changeset)
|
||||
OSMIUM_CHAIN_HANDLER_CALL(area, Area)
|
||||
|
||||
public:
|
||||
|
||||
explicit ChainHandler(THandler&... handlers) :
|
||||
m_handlers(handlers...) {
|
||||
}
|
||||
|
||||
void node(osmium::Node& node) {
|
||||
call_node<0, sizeof...(THandler), handlers_type>()(m_handlers, node);
|
||||
}
|
||||
|
||||
void way(osmium::Way& way) {
|
||||
call_way<0, sizeof...(THandler), handlers_type>()(m_handlers, way);
|
||||
}
|
||||
|
||||
void relation(osmium::Relation& relation) {
|
||||
call_relation<0, sizeof...(THandler), handlers_type>()(m_handlers, relation);
|
||||
}
|
||||
|
||||
void changeset( osmium::Changeset& changeset) {
|
||||
call_changeset<0, sizeof...(THandler), handlers_type>()(m_handlers, changeset);
|
||||
}
|
||||
|
||||
void area(osmium::Area& area) {
|
||||
call_area<0, sizeof...(THandler), handlers_type>()(m_handlers, area);
|
||||
}
|
||||
|
||||
void flush() {
|
||||
call_flush<0, sizeof...(THandler), handlers_type>()(m_handlers);
|
||||
}
|
||||
|
||||
}; // class ChainHandler
|
||||
|
||||
} // namespace handler
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_HANDLER_CHAIN_HPP
|
111
ThirdParty/osmium/handler/disk_store.hpp
vendored
Normal file
111
ThirdParty/osmium/handler/disk_store.hpp
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
#ifndef OSMIUM_HANDLER_DISK_STORE_HPP
|
||||
#define OSMIUM_HANDLER_DISK_STORE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/index/map.hpp>
|
||||
#include <osmium/io/detail/read_write.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/memory/item_iterator.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace handler {
|
||||
|
||||
/**
|
||||
*
|
||||
* Note: This handler will only work if either all object IDs are
|
||||
* positive or all object IDs are negative.
|
||||
*/
|
||||
class DiskStore : public osmium::handler::Handler {
|
||||
|
||||
typedef osmium::index::map::Map<unsigned_object_id_type, size_t> offset_index_type;
|
||||
|
||||
size_t m_offset = 0;
|
||||
int m_data_fd;
|
||||
|
||||
offset_index_type& m_node_index;
|
||||
offset_index_type& m_way_index;
|
||||
offset_index_type& m_relation_index;
|
||||
|
||||
public:
|
||||
|
||||
explicit DiskStore(int data_fd, offset_index_type& node_index, offset_index_type& way_index, offset_index_type& relation_index) :
|
||||
m_data_fd(data_fd),
|
||||
m_node_index(node_index),
|
||||
m_way_index(way_index),
|
||||
m_relation_index(relation_index) {
|
||||
}
|
||||
|
||||
DiskStore(const DiskStore&) = delete;
|
||||
DiskStore& operator=(const DiskStore&) = delete;
|
||||
|
||||
~DiskStore() noexcept = default;
|
||||
|
||||
void node(const osmium::Node& node) {
|
||||
m_node_index.set(node.positive_id(), m_offset);
|
||||
m_offset += node.byte_size();
|
||||
}
|
||||
|
||||
void way(const osmium::Way& way) {
|
||||
m_way_index.set(way.positive_id(), m_offset);
|
||||
m_offset += way.byte_size();
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation& relation) {
|
||||
m_relation_index.set(relation.positive_id(), m_offset);
|
||||
m_offset += relation.byte_size();
|
||||
}
|
||||
|
||||
// XXX
|
||||
void operator()(const osmium::memory::Buffer& buffer) {
|
||||
osmium::io::detail::reliable_write(m_data_fd, buffer.data(), buffer.committed());
|
||||
|
||||
osmium::apply(buffer.begin(), buffer.end(), *this);
|
||||
}
|
||||
|
||||
}; // class DiskStore
|
||||
|
||||
} // namespace handler
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_HANDLER_DISK_STORE_HPP
|
294
ThirdParty/osmium/handler/dump.hpp
vendored
Normal file
294
ThirdParty/osmium/handler/dump.hpp
vendored
Normal file
@ -0,0 +1,294 @@
|
||||
#ifndef OSMIUM_HANDLER_DUMP_HPP
|
||||
#define OSMIUM_HANDLER_DUMP_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/memory/collection.hpp>
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/osm/area.hpp>
|
||||
#include <osmium/osm/box.hpp>
|
||||
#include <osmium/osm/changeset.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/object.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/timestamp.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace handler {
|
||||
|
||||
class Dump : public osmium::handler::Handler {
|
||||
|
||||
std::ostream* m_out;
|
||||
bool m_with_size;
|
||||
std::string m_prefix;
|
||||
|
||||
void print_title(const char* title, const osmium::memory::Item& item) {
|
||||
*m_out << m_prefix
|
||||
<< title
|
||||
<< ":";
|
||||
|
||||
if (m_with_size) {
|
||||
*m_out << " ["
|
||||
<< item.byte_size()
|
||||
<< "]";
|
||||
}
|
||||
|
||||
*m_out << "\n";
|
||||
}
|
||||
|
||||
void print_meta(const osmium::OSMObject& object) {
|
||||
*m_out << m_prefix
|
||||
<< " id="
|
||||
<< object.id()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " version="
|
||||
<< object.version()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " uid="
|
||||
<< object.uid()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " user=|"
|
||||
<< object.user()
|
||||
<< "|\n";
|
||||
*m_out << m_prefix
|
||||
<< " changeset="
|
||||
<< object.changeset()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " timestamp="
|
||||
<< object.timestamp().to_iso()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " visible="
|
||||
<< (object.visible() ? "yes" : "no")
|
||||
<< "\n";
|
||||
|
||||
Dump dump(*m_out, m_with_size, m_prefix + " ");
|
||||
osmium::apply(object.cbegin(), object.cend(), dump);
|
||||
}
|
||||
|
||||
void print_location(const osmium::Node& node) {
|
||||
const osmium::Location& location = node.location();
|
||||
|
||||
if (location) {
|
||||
*m_out << m_prefix
|
||||
<< " lon="
|
||||
<< std::fixed
|
||||
<< std::setprecision(7)
|
||||
<< location.lon_without_check()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " lat="
|
||||
<< location.lat_without_check()
|
||||
<< "\n";
|
||||
} else {
|
||||
*m_out << m_prefix
|
||||
<< " lon=\n"
|
||||
<< m_prefix
|
||||
<< " lat=\n";
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit Dump(std::ostream& out, bool with_size=true, const std::string& prefix="") :
|
||||
m_out(&out),
|
||||
m_with_size(with_size),
|
||||
m_prefix(prefix) {
|
||||
}
|
||||
|
||||
void tag_list(const osmium::TagList& tags) {
|
||||
print_title("TAGS", tags);
|
||||
for (const auto& tag : tags) {
|
||||
*m_out << m_prefix
|
||||
<< " k=|"
|
||||
<< tag.key()
|
||||
<< "| v=|"
|
||||
<< tag.value()
|
||||
<< "|"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void way_node_list(const osmium::WayNodeList& wnl) {
|
||||
print_title("NODES", wnl);
|
||||
for (const auto& node_ref : wnl) {
|
||||
*m_out << m_prefix
|
||||
<< " ref="
|
||||
<< node_ref.ref();
|
||||
if (node_ref.location()) {
|
||||
*m_out << " pos="
|
||||
<< node_ref.location();
|
||||
}
|
||||
*m_out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void relation_member_list(const osmium::RelationMemberList& rml) {
|
||||
print_title("MEMBERS", rml);
|
||||
for (const auto& member : rml) {
|
||||
*m_out << m_prefix
|
||||
<< " type="
|
||||
<< item_type_to_name(member.type())
|
||||
<< " ref="
|
||||
<< member.ref()
|
||||
<< " role=|"
|
||||
<< member.role()
|
||||
<< "|\n";
|
||||
if (member.full_member()) {
|
||||
Dump dump(*m_out, m_with_size, m_prefix + " | ");
|
||||
osmium::apply_item(member.get_object(), dump);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void outer_ring(const osmium::OuterRing& ring) {
|
||||
print_title("OUTER RING", ring);
|
||||
for (const auto& node_ref : ring) {
|
||||
*m_out << m_prefix
|
||||
<< " ref="
|
||||
<< node_ref.ref();
|
||||
if (node_ref.location()) {
|
||||
*m_out << " pos="
|
||||
<< node_ref.location();
|
||||
}
|
||||
*m_out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void inner_ring(const osmium::InnerRing& ring) {
|
||||
print_title("INNER RING", ring);
|
||||
for (const auto& node_ref : ring) {
|
||||
*m_out << m_prefix
|
||||
<< " ref="
|
||||
<< node_ref.ref();
|
||||
if (node_ref.location()) {
|
||||
*m_out << " pos="
|
||||
<< node_ref.location();
|
||||
}
|
||||
*m_out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void node(const osmium::Node& node) {
|
||||
print_title("NODE", node);
|
||||
print_meta(node);
|
||||
print_location(node);
|
||||
}
|
||||
|
||||
void way(const osmium::Way& way) {
|
||||
print_title("WAY", way);
|
||||
print_meta(way);
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation& relation) {
|
||||
print_title("RELATION", relation);
|
||||
print_meta(relation);
|
||||
}
|
||||
|
||||
void area(const osmium::Area& area) {
|
||||
print_title("AREA", area);
|
||||
print_meta(area);
|
||||
}
|
||||
|
||||
void changeset(const osmium::Changeset& changeset) {
|
||||
print_title("CHANGESET", changeset);
|
||||
*m_out << m_prefix
|
||||
<< " id="
|
||||
<< changeset.id()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " num_changes="
|
||||
<< changeset.num_changes()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " uid="
|
||||
<< changeset.uid()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " user=|"
|
||||
<< changeset.user()
|
||||
<< "|\n";
|
||||
*m_out << m_prefix
|
||||
<< " created_at="
|
||||
<< changeset.created_at().to_iso()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " closed_at="
|
||||
<< changeset.closed_at().to_iso()
|
||||
<< "\n";
|
||||
*m_out << m_prefix
|
||||
<< " bounds=";
|
||||
|
||||
if (changeset.bounds()) {
|
||||
*m_out << '('
|
||||
<< changeset.bounds().bottom_left().lon_without_check()
|
||||
<< ','
|
||||
<< changeset.bounds().bottom_left().lat_without_check()
|
||||
<< ','
|
||||
<< changeset.bounds().top_right().lon_without_check()
|
||||
<< ','
|
||||
<< changeset.bounds().top_right().lat_without_check()
|
||||
<< ')';
|
||||
} else {
|
||||
*m_out << "(undefined)";
|
||||
}
|
||||
|
||||
*m_out << "\n";
|
||||
|
||||
Dump dump(*m_out, m_with_size, m_prefix + " ");
|
||||
osmium::apply(changeset.cbegin(), changeset.cend(), dump);
|
||||
}
|
||||
|
||||
}; // class Dump
|
||||
|
||||
} // namespace handler
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_HANDLER_DUMP_HPP
|
170
ThirdParty/osmium/handler/node_locations_for_ways.hpp
vendored
Normal file
170
ThirdParty/osmium/handler/node_locations_for_ways.hpp
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
#ifndef OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP
|
||||
#define OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/index/index.hpp>
|
||||
#include <osmium/index/map/dummy.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace handler {
|
||||
|
||||
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> dummy_type;
|
||||
|
||||
/**
|
||||
* Handler to retrieve locations from nodes and add them to ways.
|
||||
*
|
||||
* @tparam TStoragePosIDs Class that handles the actual storage of the node locations
|
||||
* (for positive IDs). It must support the set(id, value) and
|
||||
* get(id) methods.
|
||||
* @tparam TStorageNegIDs Same but for negative IDs.
|
||||
*/
|
||||
template <class TStoragePosIDs, class TStorageNegIDs = dummy_type>
|
||||
class NodeLocationsForWays : public osmium::handler::Handler {
|
||||
|
||||
static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStoragePosIDs>::value,
|
||||
"Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
|
||||
|
||||
static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStorageNegIDs>::value,
|
||||
"Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
|
||||
|
||||
/// Object that handles the actual storage of the node locations (with positive IDs).
|
||||
TStoragePosIDs& m_storage_pos;
|
||||
|
||||
/// Object that handles the actual storage of the node locations (with negative IDs).
|
||||
TStorageNegIDs& m_storage_neg;
|
||||
|
||||
bool m_ignore_errors {false};
|
||||
|
||||
bool m_must_sort {false};
|
||||
|
||||
// It is okay to have this static dummy instance, even when using several threads,
|
||||
// because it is read-only.
|
||||
static dummy_type& get_dummy() {
|
||||
static dummy_type instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit NodeLocationsForWays(TStoragePosIDs& storage_pos,
|
||||
TStorageNegIDs& storage_neg = get_dummy()) :
|
||||
m_storage_pos(storage_pos),
|
||||
m_storage_neg(storage_neg) {
|
||||
}
|
||||
|
||||
NodeLocationsForWays(const NodeLocationsForWays&) = delete;
|
||||
NodeLocationsForWays& operator=(const NodeLocationsForWays&) = delete;
|
||||
|
||||
~NodeLocationsForWays() noexcept = default;
|
||||
|
||||
void ignore_errors() {
|
||||
m_ignore_errors = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the location of the node in the storage.
|
||||
*/
|
||||
void node(const osmium::Node& node) {
|
||||
m_must_sort = true;
|
||||
const osmium::object_id_type id = node.id();
|
||||
if (id >= 0) {
|
||||
m_storage_pos.set(static_cast<osmium::unsigned_object_id_type>( id), node.location());
|
||||
} else {
|
||||
m_storage_neg.set(static_cast<osmium::unsigned_object_id_type>(-id), node.location());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get location of node with given id.
|
||||
*/
|
||||
osmium::Location get_node_location(const osmium::object_id_type id) const {
|
||||
if (id >= 0) {
|
||||
return m_storage_pos.get(static_cast<osmium::unsigned_object_id_type>( id));
|
||||
} else {
|
||||
return m_storage_neg.get(static_cast<osmium::unsigned_object_id_type>(-id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve locations of all nodes in the way from storage and add
|
||||
* them to the way object.
|
||||
*/
|
||||
void way(osmium::Way& way) {
|
||||
if (m_must_sort) {
|
||||
m_storage_pos.sort();
|
||||
m_storage_neg.sort();
|
||||
m_must_sort = false;
|
||||
}
|
||||
bool error = false;
|
||||
for (auto& node_ref : way.nodes()) {
|
||||
try {
|
||||
node_ref.set_location(get_node_location(node_ref.ref()));
|
||||
if (!node_ref.location()) {
|
||||
error = true;
|
||||
}
|
||||
} catch (osmium::not_found&) {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
if (error && !m_ignore_errors) {
|
||||
throw osmium::not_found("location for one or more nodes not found in node location index");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call clear on the location indexes. Makes the
|
||||
* NodeLocationsForWays handler unusable. Used to explicitly free
|
||||
* memory if thats needed.
|
||||
*/
|
||||
void clear() {
|
||||
m_storage_pos.clear();
|
||||
m_storage_neg.clear();
|
||||
}
|
||||
|
||||
}; // class NodeLocationsForWays
|
||||
|
||||
} // namespace handler
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP
|
106
ThirdParty/osmium/handler/object_relations.hpp
vendored
Normal file
106
ThirdParty/osmium/handler/object_relations.hpp
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
#ifndef OSMIUM_HANDLER_OBJECT_RELATIONS_HPP
|
||||
#define OSMIUM_HANDLER_OBJECT_RELATIONS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/index/multimap.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace handler {
|
||||
|
||||
/**
|
||||
*
|
||||
* Note: This handler will only work if either all object IDs are
|
||||
* positive or all object IDs are negative.
|
||||
*/
|
||||
class ObjectRelations : public osmium::handler::Handler {
|
||||
|
||||
typedef osmium::index::multimap::Multimap<unsigned_object_id_type, unsigned_object_id_type> index_type;
|
||||
|
||||
index_type& m_index_n2w;
|
||||
index_type& m_index_n2r;
|
||||
index_type& m_index_w2r;
|
||||
index_type& m_index_r2r;
|
||||
|
||||
public:
|
||||
|
||||
explicit ObjectRelations(index_type& n2w, index_type& n2r, index_type& w2r, index_type& r2r) :
|
||||
m_index_n2w(n2w),
|
||||
m_index_n2r(n2r),
|
||||
m_index_w2r(w2r),
|
||||
m_index_r2r(r2r) {
|
||||
}
|
||||
|
||||
ObjectRelations(const ObjectRelations&) = delete;
|
||||
ObjectRelations& operator=(const ObjectRelations&) = delete;
|
||||
|
||||
~ObjectRelations() noexcept = default;
|
||||
|
||||
void way(const osmium::Way& way) {
|
||||
for (const auto& node_ref : way.nodes()) {
|
||||
m_index_n2w.set(node_ref.positive_ref(), way.positive_id());
|
||||
}
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation& relation) {
|
||||
for (const auto& member : relation.members()) {
|
||||
switch (member.type()) {
|
||||
case osmium::item_type::node:
|
||||
m_index_n2r.set(member.positive_ref(), relation.positive_id());
|
||||
break;
|
||||
case osmium::item_type::way:
|
||||
m_index_w2r.set(member.positive_ref(), relation.positive_id());
|
||||
break;
|
||||
case osmium::item_type::relation:
|
||||
m_index_r2r.set(member.positive_ref(), relation.positive_id());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}; // class ObjectRelations
|
||||
|
||||
} // namespace handler
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_HANDLER_OBJECT_RELATIONS_HPP
|
78
ThirdParty/osmium/index/detail/mmap_vector_anon.hpp
vendored
Normal file
78
ThirdParty/osmium/index/detail/mmap_vector_anon.hpp
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP
|
||||
#define OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <osmium/index/detail/typed_mmap.hpp>
|
||||
#include <osmium/index/detail/mmap_vector_base.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* This class looks and behaves like STL vector, but uses mmap internally.
|
||||
*/
|
||||
template <typename T>
|
||||
class mmap_vector_anon : public mmap_vector_base<T, mmap_vector_anon> {
|
||||
|
||||
public:
|
||||
|
||||
mmap_vector_anon() :
|
||||
mmap_vector_base<T, osmium::detail::mmap_vector_anon>(
|
||||
-1,
|
||||
osmium::detail::mmap_vector_size_increment,
|
||||
0,
|
||||
osmium::detail::typed_mmap<T>::map(osmium::detail::mmap_vector_size_increment)) {
|
||||
}
|
||||
|
||||
void reserve(size_t new_capacity) {
|
||||
if (new_capacity > this->capacity()) {
|
||||
this->data(osmium::detail::typed_mmap<T>::remap(this->data(), this->capacity(), new_capacity));
|
||||
this->m_capacity = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
}; // class mmap_vector_anon
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
#endif // OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP
|
183
ThirdParty/osmium/index/detail/mmap_vector_base.hpp
vendored
Normal file
183
ThirdParty/osmium/index/detail/mmap_vector_base.hpp
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
#ifndef OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP
|
||||
#define OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <osmium/index/detail/typed_mmap.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr size_t mmap_vector_size_increment = 1024 * 1024;
|
||||
|
||||
/**
|
||||
* This is a base class for implementing classes that look like
|
||||
* STL vector but use mmap internally. This class can not be used
|
||||
* on it's own. Use the derived classes mmap_vector_anon or
|
||||
* mmap_vector_file.
|
||||
*/
|
||||
template <typename T, template <typename> class TDerived>
|
||||
class mmap_vector_base {
|
||||
|
||||
protected:
|
||||
|
||||
int m_fd;
|
||||
size_t m_capacity;
|
||||
size_t m_size;
|
||||
T* m_data;
|
||||
|
||||
explicit mmap_vector_base(int fd, size_t capacity, size_t size, T* data) noexcept :
|
||||
m_fd(fd),
|
||||
m_capacity(capacity),
|
||||
m_size(size),
|
||||
m_data(data) {
|
||||
}
|
||||
|
||||
explicit mmap_vector_base(int fd, size_t capacity, size_t size) :
|
||||
m_fd(fd),
|
||||
m_capacity(capacity),
|
||||
m_size(size),
|
||||
m_data(osmium::detail::typed_mmap<T>::grow_and_map(capacity, m_fd)) {
|
||||
}
|
||||
|
||||
void data(T* data) {
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
~mmap_vector_base() {
|
||||
osmium::detail::typed_mmap<T>::unmap(m_data, m_capacity);
|
||||
}
|
||||
|
||||
size_t capacity() const noexcept {
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
size_t size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
bool empty() const noexcept {
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
const T* data() const noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
T* data() noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
T& operator[](size_t n) {
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
T at(size_t n) const {
|
||||
if (n >= m_size) {
|
||||
throw std::out_of_range("out of range");
|
||||
}
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
void clear() noexcept {
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void shrink_to_fit() {
|
||||
// XXX do something here
|
||||
}
|
||||
|
||||
void push_back(const T& value) {
|
||||
if (m_size >= m_capacity) {
|
||||
resize(m_size+1);
|
||||
}
|
||||
m_data[m_size] = value;
|
||||
++m_size;
|
||||
}
|
||||
|
||||
void resize(size_t new_size) {
|
||||
if (new_size > capacity()) {
|
||||
static_cast<TDerived<T>*>(this)->reserve(new_size + osmium::detail::mmap_vector_size_increment);
|
||||
}
|
||||
if (new_size > size()) {
|
||||
new (data() + size()) T[new_size - size()];
|
||||
}
|
||||
m_size = new_size;
|
||||
}
|
||||
|
||||
iterator begin() noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
iterator end() noexcept {
|
||||
return m_data + m_size;
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept {
|
||||
return m_data + m_size;
|
||||
}
|
||||
|
||||
const_iterator cbegin() noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const_iterator cend() noexcept {
|
||||
return m_data + m_size;
|
||||
}
|
||||
|
||||
}; // class mmap_vector_base
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP
|
82
ThirdParty/osmium/index/detail/mmap_vector_file.hpp
vendored
Normal file
82
ThirdParty/osmium/index/detail/mmap_vector_file.hpp
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
#ifndef OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP
|
||||
#define OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <osmium/index/detail/typed_mmap.hpp>
|
||||
#include <osmium/index/detail/mmap_vector_base.hpp>
|
||||
#include <osmium/index/detail/tmpfile.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* This class looks and behaves like STL vector, but mmap's a file internally.
|
||||
*/
|
||||
template <typename T>
|
||||
class mmap_vector_file : public mmap_vector_base<T, mmap_vector_file> {
|
||||
|
||||
public:
|
||||
|
||||
explicit mmap_vector_file() :
|
||||
mmap_vector_base<T, osmium::detail::mmap_vector_file>(
|
||||
osmium::detail::create_tmp_file(),
|
||||
osmium::detail::mmap_vector_size_increment,
|
||||
0) {
|
||||
}
|
||||
|
||||
explicit mmap_vector_file(int fd) :
|
||||
mmap_vector_base<T, osmium::detail::mmap_vector_file>(
|
||||
fd,
|
||||
osmium::detail::typed_mmap<T>::file_size(fd) == 0 ? osmium::detail::mmap_vector_size_increment : osmium::detail::typed_mmap<T>::file_size(fd),
|
||||
osmium::detail::typed_mmap<T>::file_size(fd)) {
|
||||
}
|
||||
|
||||
void reserve(size_t new_capacity) {
|
||||
if (new_capacity > this->capacity()) {
|
||||
osmium::detail::typed_mmap<T>::unmap(this->data(), this->capacity());
|
||||
this->data(osmium::detail::typed_mmap<T>::grow_and_map(new_capacity, this->m_fd));
|
||||
this->m_capacity = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
}; // class mmap_vector_file
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP
|
62
ThirdParty/osmium/index/detail/tmpfile.hpp
vendored
Normal file
62
ThirdParty/osmium/index/detail/tmpfile.hpp
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef OSMIUM_DETAIL_TMPFILE_HPP
|
||||
#define OSMIUM_DETAIL_TMPFILE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <system_error>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* Create and open a temporary file. It is removed after opening.
|
||||
*
|
||||
* @returns File descriptor of temporary file.
|
||||
* @throws std::system_error if something went wrong.
|
||||
*/
|
||||
inline int create_tmp_file() {
|
||||
FILE* file = ::tmpfile();
|
||||
if (!file) {
|
||||
throw std::system_error(errno, std::system_category(), "tempfile failed");
|
||||
}
|
||||
return fileno(file);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_DETAIL_TMPFILE
|
229
ThirdParty/osmium/index/detail/typed_mmap.hpp
vendored
Normal file
229
ThirdParty/osmium/index/detail/typed_mmap.hpp
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
#ifndef OSMIUM_DETAIL_TYPED_MMAP_HPP
|
||||
#define OSMIUM_DETAIL_TYPED_MMAP_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <sys/mman.h>
|
||||
#else
|
||||
# include <mmap_for_windows.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# define ftruncate _chsize
|
||||
#endif
|
||||
|
||||
// for bsd systems
|
||||
#ifndef MAP_ANONYMOUS
|
||||
# define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
|
||||
#include <osmium/util/cast.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* @brief Namespace for Osmium internal use
|
||||
*/
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* This is a helper class for working with memory mapped files and
|
||||
* anonymous shared memory. It wraps the necessary system calls
|
||||
* adding:
|
||||
* - error checking: all functions throw exceptions where needed
|
||||
* - internal casts and size calculations allow use with user defined
|
||||
* type T instead of void*
|
||||
*
|
||||
* This class only contains static functions. It should never be
|
||||
* instantiated.
|
||||
*
|
||||
* @tparam T Type of objects we want to store.
|
||||
*/
|
||||
template <typename T>
|
||||
class typed_mmap {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create anonymous private memory mapping with enough space for size
|
||||
* objects of type T.
|
||||
*
|
||||
* Note that no constructor is called for any of the objects in this memory!
|
||||
*
|
||||
* @param size Number of objects of type T that should fit into this memory
|
||||
* @returns Pointer to mapped memory
|
||||
* @throws std::system_error If mmap(2) failed
|
||||
*/
|
||||
static T* map(size_t size) {
|
||||
void* addr = ::mmap(nullptr, sizeof(T) * size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
if (addr == MAP_FAILED) {
|
||||
throw std::system_error(errno, std::system_category(), "mmap failed");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
return reinterpret_cast<T*>(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create shared memory mapping of a file with enough space for size
|
||||
* objects of type T. The file must already have at least the
|
||||
* required size.
|
||||
*
|
||||
* Note that no constructor is called for any of the objects in this memory!
|
||||
*
|
||||
* @param size Number of objects of type T that should fit into this memory
|
||||
* @param fd File descriptor
|
||||
* @param write True if data should be writable
|
||||
* @returns Pointer to mapped memory
|
||||
* @throws std::system_error If mmap(2) failed
|
||||
*/
|
||||
static T* map(size_t size, int fd, bool write = false) {
|
||||
int prot = PROT_READ;
|
||||
if (write) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
void* addr = ::mmap(nullptr, sizeof(T) * size, prot, MAP_SHARED, fd, 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
if (addr == MAP_FAILED) {
|
||||
throw std::system_error(errno, std::system_category(), "mmap failed");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
return reinterpret_cast<T*>(addr);
|
||||
}
|
||||
|
||||
// mremap(2) is only available on linux systems
|
||||
#ifdef __linux__
|
||||
/**
|
||||
* Grow memory mapping created with map().
|
||||
*
|
||||
* Note that no constructor is called for any of the objects in this memory!
|
||||
*
|
||||
* @param data Pointer to current mapping (as returned by typed_mmap())
|
||||
* @param old_size Number of objects currently stored in this memory
|
||||
* @param new_size Number of objects we want to have space for
|
||||
* @throws std::system_error If mremap(2) call failed
|
||||
*/
|
||||
static T* remap(T* data, size_t old_size, size_t new_size) {
|
||||
void* addr = ::mremap(reinterpret_cast<void*>(data), sizeof(T) * old_size, sizeof(T) * new_size, MREMAP_MAYMOVE);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
if (addr == MAP_FAILED) {
|
||||
throw std::system_error(errno, std::system_category(), "mremap failed");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
return reinterpret_cast<T*>(addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Release memory from map() call.
|
||||
*
|
||||
* Note that no destructor is called for the objects in this memory!
|
||||
*
|
||||
* @param data Pointer to the data
|
||||
* @param size Number of objects of type T stored
|
||||
* @throws std::system_error If munmap(2) call failed
|
||||
*/
|
||||
static void unmap(T* data, size_t size) {
|
||||
if (::munmap(reinterpret_cast<void*>(data), sizeof(T) * size) != 0) {
|
||||
throw std::system_error(errno, std::system_category(), "munmap failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of objects of type T that would fit into a file.
|
||||
*
|
||||
* @param fd File descriptor
|
||||
* @returns Number of objects of type T in this file
|
||||
* @throws std::system_error If fstat(2) call failed
|
||||
* @throws std::length_error If size of the file isn't a multiple of sizeof(T)
|
||||
*/
|
||||
static size_t file_size(int fd) {
|
||||
struct stat s;
|
||||
if (fstat(fd, &s) < 0) {
|
||||
throw std::system_error(errno, std::system_category(), "fstat failed");
|
||||
}
|
||||
if (static_cast<size_t>(s.st_size) % sizeof(T) != 0) {
|
||||
throw std::length_error("file size has to be multiple of object size");
|
||||
}
|
||||
return static_cast<size_t>(s.st_size) / sizeof(T);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow file so there is enough space for at least new_size objects
|
||||
* of type T. If the file is large enough already, nothing is done.
|
||||
* The file is never shrunk.
|
||||
*
|
||||
* @param new_size Number of objects of type T that should fit into this file
|
||||
* @param fd File descriptor
|
||||
* @throws std::system_error If ftruncate(2) call failed
|
||||
*/
|
||||
static void grow_file(size_t new_size, int fd) {
|
||||
if (file_size(fd) < new_size) {
|
||||
if (::ftruncate(fd, static_cast_with_assert<off_t>(sizeof(T) * new_size)) < 0) {
|
||||
throw std::system_error(errno, std::system_category(), "ftruncate failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow file to given size (if it is smaller) and mmap it.
|
||||
*
|
||||
* @param size Number of objects of type T that should fit into this file
|
||||
* @param fd File descriptor
|
||||
* @throws Errors thrown by grow_file() or map()
|
||||
*/
|
||||
static T* grow_and_map(size_t size, int fd) {
|
||||
grow_file(size, fd);
|
||||
return map(size, fd, true);
|
||||
}
|
||||
|
||||
}; // class typed_mmap
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_DETAIL_TYPED_MMAP_HPP
|
100
ThirdParty/osmium/index/index.hpp
vendored
Normal file
100
ThirdParty/osmium/index/index.hpp
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
#ifndef OSMIUM_INDEX_INDEX_HPP
|
||||
#define OSMIUM_INDEX_INDEX_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* Exception signaling that an element could not be
|
||||
* found in an index.
|
||||
*/
|
||||
struct not_found : public std::runtime_error {
|
||||
|
||||
not_found(const std::string& what) :
|
||||
std::runtime_error(what) {
|
||||
}
|
||||
|
||||
not_found(const char* what) :
|
||||
std::runtime_error(what) {
|
||||
}
|
||||
|
||||
}; // struct not_found
|
||||
|
||||
/**
|
||||
* @brief Indexing of OSM data, Locations, etc.
|
||||
*/
|
||||
namespace index {
|
||||
|
||||
template <typename TKey>
|
||||
OSMIUM_NORETURN void not_found_error(TKey key) {
|
||||
std::stringstream s;
|
||||
s << "id " << key << " no found";
|
||||
throw not_found(s.str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Some of the index classes need an "empty" value that can
|
||||
* never appear in real data. This function must return this
|
||||
* empty value for any class used as a value in an index.
|
||||
* The default implementation returns a default constructed
|
||||
* object, but it can be specialized.
|
||||
*/
|
||||
template <typename T>
|
||||
inline constexpr T empty_value() {
|
||||
return T{};
|
||||
}
|
||||
|
||||
/**
|
||||
* The size_t value in indexes is usually used for offsets
|
||||
* into a buffer or file. It is unlikely that we ever need
|
||||
* the full range, so the max value is a good "empty" value.
|
||||
*/
|
||||
template <>
|
||||
inline OSMIUM_CONSTEXPR size_t empty_value<size_t>() {
|
||||
return std::numeric_limits<size_t>::max();
|
||||
}
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_INDEX_HPP
|
155
ThirdParty/osmium/index/map.hpp
vendored
Normal file
155
ThirdParty/osmium/index/map.hpp
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
#ifndef OSMIUM_INDEX_MAP_HPP
|
||||
#define OSMIUM_INDEX_MAP_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
#include <osmium/index/index.hpp> // IWYU pragma: export
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
/**
|
||||
* @brief Key-value containers with unique integer values for a key
|
||||
*/
|
||||
namespace map {
|
||||
|
||||
/**
|
||||
* This abstract class defines an interface to storage classes
|
||||
* intended for storing small pieces of data (such as coordinates)
|
||||
* indexed by a positive integer (such as an object ID). The
|
||||
* storage must be very space efficient and able to scale to billions
|
||||
* of objects.
|
||||
*
|
||||
* Subclasses have different implementations that store the
|
||||
* data in different ways in memory and/or on disk. Some storage
|
||||
* classes are better suited when working with the whole planet,
|
||||
* some are better for data extracts.
|
||||
*
|
||||
* Note that these classes are not required to track "empty" fields.
|
||||
* When reading data you have to be sure you have put something in
|
||||
* there before.
|
||||
*
|
||||
* A typical use for this and derived classes is storage of node
|
||||
* locations indexed by node ID. These indexes will only work
|
||||
* on 64 bit systems if used in this case. 32 bit systems just
|
||||
* can't address that much memory!
|
||||
*
|
||||
* @tparam TId Id type, usually osmium::unsigned_object_id_type,
|
||||
* must be an unsigned integral type.
|
||||
* @tparam TValue Value type, usually osmium::Location or size_t.
|
||||
* Copied by value, so should be "small" type.
|
||||
*/
|
||||
template <typename TId, typename TValue>
|
||||
class Map {
|
||||
|
||||
static_assert(std::is_integral<TId>::value && std::is_unsigned<TId>::value,
|
||||
"TId template parameter for class Map must be unsigned integral type");
|
||||
|
||||
Map(const Map&) = delete;
|
||||
Map& operator=(const Map&) = delete;
|
||||
|
||||
protected:
|
||||
|
||||
Map(Map&&) = default;
|
||||
Map& operator=(Map&&) = default;
|
||||
|
||||
public:
|
||||
|
||||
/// The "key" type, usually osmium::unsigned_object_id_type.
|
||||
typedef TId key_type;
|
||||
|
||||
/// The "value" type, usually a Location or size_t.
|
||||
typedef TValue value_type;
|
||||
|
||||
Map() = default;
|
||||
|
||||
virtual ~Map() = default;
|
||||
|
||||
virtual void reserve(const size_t) {
|
||||
// default implementation is empty
|
||||
}
|
||||
|
||||
/// Set the field with id to value.
|
||||
virtual void set(const TId id, const TValue value) = 0;
|
||||
|
||||
/// Retrieve value by id. Does not check for overflow or empty fields.
|
||||
virtual const TValue get(const TId id) const = 0;
|
||||
|
||||
/**
|
||||
* Get the approximate number of items in the storage. The storage
|
||||
* might allocate memory in blocks, so this size might not be
|
||||
* accurate. You can not use this to find out how much memory the
|
||||
* storage uses. Use used_memory() for that.
|
||||
*/
|
||||
virtual size_t size() const = 0;
|
||||
|
||||
/**
|
||||
* Get the memory used for this storage in bytes. Note that this
|
||||
* is not necessarily entirely accurate but an approximation.
|
||||
* For storage classes that store the data in memory, this is
|
||||
* the main memory used, for storage classes storing data on disk
|
||||
* this is the memory used on disk.
|
||||
*/
|
||||
virtual size_t used_memory() const = 0;
|
||||
|
||||
/**
|
||||
* Clear memory used for this storage. After this you can not
|
||||
* use the storage container any more.
|
||||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
/**
|
||||
* Sort data in map. Call this after writing all data and
|
||||
* before reading. Not all implementations need this.
|
||||
*/
|
||||
virtual void sort() {
|
||||
// default implementation is empty
|
||||
}
|
||||
|
||||
virtual void dump_as_list(int /*fd*/) const {
|
||||
std::runtime_error("can't dump as list");
|
||||
}
|
||||
|
||||
}; // class Map
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_HPP
|
87
ThirdParty/osmium/index/map/dummy.hpp
vendored
Normal file
87
ThirdParty/osmium/index/map/dummy.hpp
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef OSMIUM_INDEX_MAP_DUMMY_HPP
|
||||
#define OSMIUM_INDEX_MAP_DUMMY_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <osmium/index/map.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace map {
|
||||
|
||||
/**
|
||||
* Pseudo map.
|
||||
* Use this class if you don't need a map, but you
|
||||
* need an object that behaves like one.
|
||||
*/
|
||||
template <typename TId, typename TValue>
|
||||
class Dummy : public osmium::index::map::Map<TId, TValue> {
|
||||
|
||||
public:
|
||||
|
||||
Dummy() = default;
|
||||
|
||||
~Dummy() override final = default;
|
||||
|
||||
void set(const TId, const TValue) override final {
|
||||
// intentionally left blank
|
||||
}
|
||||
|
||||
const TValue get(const TId id) const override final {
|
||||
not_found_error(id);
|
||||
}
|
||||
|
||||
size_t size() const override final {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t used_memory() const override final {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clear() override final {
|
||||
}
|
||||
|
||||
}; // class Dummy
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_DUMMY_HPP
|
61
ThirdParty/osmium/index/map/mmap_vector_anon.hpp
vendored
Normal file
61
ThirdParty/osmium/index/map/mmap_vector_anon.hpp
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP
|
||||
#define OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <osmium/index/map/vector.hpp>
|
||||
#include <osmium/index/detail/mmap_vector_anon.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace map {
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
using DenseMapMmap = VectorBasedDenseMap<osmium::detail::mmap_vector_anon<TValue>, TId, TValue>;
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
using SparseMapMmap = VectorBasedSparseMap<TId, TValue, osmium::detail::mmap_vector_anon>;
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP
|
57
ThirdParty/osmium/index/map/mmap_vector_file.hpp
vendored
Normal file
57
ThirdParty/osmium/index/map/mmap_vector_file.hpp
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP
|
||||
#define OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/index/map/vector.hpp>
|
||||
#include <osmium/index/detail/mmap_vector_file.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace map {
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
using DenseMapFile = VectorBasedDenseMap<osmium::detail::mmap_vector_file<TValue>, TId, TValue>;
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
using SparseMapFile = VectorBasedSparseMap<TId, TValue, osmium::detail::mmap_vector_file>;
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP
|
140
ThirdParty/osmium/index/map/sparse_table.hpp
vendored
Normal file
140
ThirdParty/osmium/index/map/sparse_table.hpp
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
#ifndef OSMIUM_INDEX_MAP_SPARSE_TABLE_HPP
|
||||
#define OSMIUM_INDEX_MAP_SPARSE_TABLE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <google/sparsetable>
|
||||
|
||||
#include <osmium/index/map.hpp>
|
||||
#include <osmium/io/detail/read_write.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace map {
|
||||
|
||||
/**
|
||||
* The SparseTable index stores elements in a Google sparsetable,
|
||||
* a data structure that can hold sparsly filled tables in a
|
||||
* very space efficient way. It will resize automatically.
|
||||
*
|
||||
* Use this index if the ID space is only sparsly
|
||||
* populated, such as when working with smaller OSM files (like
|
||||
* country extracts).
|
||||
*
|
||||
* This will only work on 64 bit machines.
|
||||
*/
|
||||
template <typename TId, typename TValue>
|
||||
class SparseTable : public osmium::index::map::Map<TId, TValue> {
|
||||
|
||||
TId m_grow_size;
|
||||
|
||||
google::sparsetable<TValue> m_elements;
|
||||
|
||||
static_assert(sizeof(typename google::sparsetable<TValue>::size_type) >= 8, "google::sparsetable needs 64bit machine");
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param grow_size The initial size of the index (ie number of
|
||||
* elements that fit into the index).
|
||||
* The storage will grow by at least this size
|
||||
* every time it runs out of space.
|
||||
*/
|
||||
explicit SparseTable(const TId grow_size=10000) :
|
||||
m_grow_size(grow_size),
|
||||
m_elements(grow_size) {
|
||||
}
|
||||
|
||||
~SparseTable() override final = default;
|
||||
|
||||
void set(const TId id, const TValue value) override final {
|
||||
if (id >= m_elements.size()) {
|
||||
m_elements.resize(id + m_grow_size);
|
||||
}
|
||||
m_elements[id] = value;
|
||||
}
|
||||
|
||||
const TValue get(const TId id) const override final {
|
||||
if (id >= m_elements.size()) {
|
||||
not_found_error(id);
|
||||
}
|
||||
if (m_elements[id] == osmium::index::empty_value<TValue>()) {
|
||||
not_found_error(id);
|
||||
}
|
||||
return m_elements[id];
|
||||
}
|
||||
|
||||
size_t size() const override final {
|
||||
return m_elements.size();
|
||||
}
|
||||
|
||||
size_t used_memory() const override final {
|
||||
// unused elements use 1 bit, used elements sizeof(TValue) bytes
|
||||
// http://google-sparsehash.googlecode.com/svn/trunk/doc/sparsetable.html
|
||||
return (m_elements.size() / 8) + (m_elements.num_nonempty() * sizeof(TValue));
|
||||
}
|
||||
|
||||
void clear() override final {
|
||||
m_elements.clear();
|
||||
}
|
||||
|
||||
void dump_as_list(const int fd) const override final {
|
||||
std::vector<std::pair<TId, TValue>> v;
|
||||
int n=0;
|
||||
for (const TValue value : m_elements) {
|
||||
if (value != osmium::index::empty_value<TValue>()) {
|
||||
v.emplace_back(n, value);
|
||||
}
|
||||
++n;
|
||||
}
|
||||
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(v.data()), sizeof(std::pair<TId, TValue>) * v.size());
|
||||
}
|
||||
|
||||
}; // class SparseTable
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_BYID_SPARSE_TABLE_HPP
|
112
ThirdParty/osmium/index/map/stl_map.hpp
vendored
Normal file
112
ThirdParty/osmium/index/map/stl_map.hpp
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
#ifndef OSMIUM_INDEX_MAP_STL_MAP_HPP
|
||||
#define OSMIUM_INDEX_MAP_STL_MAP_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/index/map.hpp>
|
||||
#include <osmium/io/detail/read_write.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace map {
|
||||
|
||||
/**
|
||||
* This implementation uses std::map internally. It uses rather a
|
||||
* lot of memory, but might make sense for small maps.
|
||||
*/
|
||||
template <typename TId, typename TValue>
|
||||
class StlMap : public osmium::index::map::Map<TId, TValue> {
|
||||
|
||||
// This is a rough estimate for the memory needed for each
|
||||
// element in the map (id + value + pointers to left, right,
|
||||
// and parent plus some overhead for color of red-black-tree
|
||||
// or similar).
|
||||
static constexpr size_t element_size = sizeof(TId) + sizeof(TValue) + sizeof(void*) * 4;
|
||||
|
||||
std::map<TId, TValue> m_elements;
|
||||
|
||||
public:
|
||||
|
||||
StlMap() = default;
|
||||
|
||||
~StlMap() override final = default;
|
||||
|
||||
void set(const TId id, const TValue value) override final {
|
||||
m_elements[id] = value;
|
||||
}
|
||||
|
||||
const TValue get(const TId id) const override final {
|
||||
try {
|
||||
return m_elements.at(id);
|
||||
} catch (std::out_of_range&) {
|
||||
not_found_error(id);
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const override final {
|
||||
return m_elements.size();
|
||||
}
|
||||
|
||||
size_t used_memory() const override final {
|
||||
return element_size * m_elements.size();
|
||||
}
|
||||
|
||||
void clear() override final {
|
||||
m_elements.clear();
|
||||
}
|
||||
|
||||
void dump_as_list(const int fd) const override final {
|
||||
typedef typename std::map<TId, TValue>::value_type t;
|
||||
std::vector<t> v;
|
||||
std::copy(m_elements.begin(), m_elements.end(), std::back_inserter(v));
|
||||
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(v.data()), sizeof(t) * v.size());
|
||||
}
|
||||
|
||||
}; // class StlMap
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_STL_MAP_HPP
|
61
ThirdParty/osmium/index/map/stl_vector.hpp
vendored
Normal file
61
ThirdParty/osmium/index/map/stl_vector.hpp
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef OSMIUM_INDEX_MAP_STL_VECTOR_HPP
|
||||
#define OSMIUM_INDEX_MAP_STL_VECTOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/index/map/vector.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace map {
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
using DenseMapMem = VectorBasedDenseMap<std::vector<TValue>, TId, TValue>;
|
||||
|
||||
template <typename T>
|
||||
using StdVectorWrap = std::vector<T>;
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
using SparseMapMem = VectorBasedSparseMap<TId, TValue, StdVectorWrap>;
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_STL_VECTOR_HPP
|
208
ThirdParty/osmium/index/map/vector.hpp
vendored
Normal file
208
ThirdParty/osmium/index/map/vector.hpp
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
#ifndef OSMIUM_INDEX_MAP_VECTOR_HPP
|
||||
#define OSMIUM_INDEX_MAP_VECTOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/index/map.hpp>
|
||||
#include <osmium/io/detail/read_write.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace map {
|
||||
|
||||
template <class TVector, typename TId, typename TValue>
|
||||
class VectorBasedDenseMap : public Map<TId, TValue> {
|
||||
|
||||
TVector m_vector;
|
||||
|
||||
public:
|
||||
|
||||
VectorBasedDenseMap() :
|
||||
m_vector() {
|
||||
}
|
||||
|
||||
explicit VectorBasedDenseMap(int fd) :
|
||||
m_vector(fd) {
|
||||
}
|
||||
|
||||
~VectorBasedDenseMap() {}
|
||||
|
||||
void reserve(const size_t size) override final {
|
||||
m_vector.reserve(size);
|
||||
}
|
||||
|
||||
void set(const TId id, const TValue value) override final {
|
||||
if (size() <= id) {
|
||||
m_vector.resize(id+1);
|
||||
}
|
||||
m_vector[id] = value;
|
||||
}
|
||||
|
||||
const TValue get(const TId id) const override final {
|
||||
try {
|
||||
const TValue& value = m_vector.at(id);
|
||||
if (value == osmium::index::empty_value<TValue>()) {
|
||||
not_found_error(id);
|
||||
}
|
||||
return value;
|
||||
} catch (std::out_of_range&) {
|
||||
not_found_error(id);
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const override final {
|
||||
return m_vector.size();
|
||||
}
|
||||
|
||||
size_t used_memory() const override final {
|
||||
return sizeof(TValue) * size();
|
||||
}
|
||||
|
||||
void clear() override final {
|
||||
m_vector.clear();
|
||||
m_vector.shrink_to_fit();
|
||||
}
|
||||
|
||||
}; // class VectorBasedDenseMap
|
||||
|
||||
|
||||
template <typename TId, typename TValue, template<typename...> class TVector>
|
||||
class VectorBasedSparseMap : public Map<TId, TValue> {
|
||||
|
||||
public:
|
||||
|
||||
typedef typename std::pair<TId, TValue> element_type;
|
||||
typedef TVector<element_type> vector_type;
|
||||
typedef typename vector_type::iterator iterator;
|
||||
typedef typename vector_type::const_iterator const_iterator;
|
||||
|
||||
private:
|
||||
|
||||
vector_type m_vector;
|
||||
|
||||
public:
|
||||
|
||||
VectorBasedSparseMap() :
|
||||
m_vector() {
|
||||
}
|
||||
|
||||
VectorBasedSparseMap(int fd) :
|
||||
m_vector(fd) {
|
||||
}
|
||||
|
||||
~VectorBasedSparseMap() override final = default;
|
||||
|
||||
void set(const TId id, const TValue value) override final {
|
||||
m_vector.push_back(element_type(id, value));
|
||||
}
|
||||
|
||||
const TValue get(const TId id) const override final {
|
||||
const element_type element {
|
||||
id,
|
||||
osmium::index::empty_value<TValue>()
|
||||
};
|
||||
const auto result = std::lower_bound(m_vector.begin(), m_vector.end(), element, [](const element_type& a, const element_type& b) {
|
||||
return a.first < b.first;
|
||||
});
|
||||
if (result == m_vector.end() || result->first != id) {
|
||||
not_found_error(id);
|
||||
} else {
|
||||
return result->second;
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const override final {
|
||||
return m_vector.size();
|
||||
}
|
||||
|
||||
size_t byte_size() const {
|
||||
return m_vector.size() * sizeof(element_type);
|
||||
}
|
||||
|
||||
size_t used_memory() const override final {
|
||||
return sizeof(element_type) * size();
|
||||
}
|
||||
|
||||
void clear() override final {
|
||||
m_vector.clear();
|
||||
m_vector.shrink_to_fit();
|
||||
}
|
||||
|
||||
void sort() override final {
|
||||
std::sort(m_vector.begin(), m_vector.end());
|
||||
}
|
||||
|
||||
void dump_as_list(int fd) const override final {
|
||||
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return m_vector.begin();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return m_vector.end();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const {
|
||||
return m_vector.cbegin();
|
||||
}
|
||||
|
||||
const_iterator cend() const {
|
||||
return m_vector.cend();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return m_vector.cbegin();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return m_vector.cend();
|
||||
}
|
||||
|
||||
}; // class VectorBasedSparseMap
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MAP_VECTOR_HPP
|
129
ThirdParty/osmium/index/multimap.hpp
vendored
Normal file
129
ThirdParty/osmium/index/multimap.hpp
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
#ifndef OSMIUM_INDEX_MULTIMAP_HPP
|
||||
#define OSMIUM_INDEX_MULTIMAP_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/index/index.hpp> // IWYU pragma: export
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
/**
|
||||
* @brief Key-value containers with multiple values for an integer key
|
||||
*/
|
||||
namespace multimap {
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
class Multimap {
|
||||
|
||||
static_assert(std::is_integral<TId>::value && std::is_unsigned<TId>::value,
|
||||
"TId template parameter for class Multimap must be unsigned integral type");
|
||||
|
||||
typedef typename std::pair<TId, TValue> element_type;
|
||||
|
||||
Multimap(const Multimap&) = delete;
|
||||
Multimap& operator=(const Multimap&) = delete;
|
||||
|
||||
protected:
|
||||
|
||||
Multimap(Multimap&&) = default;
|
||||
Multimap& operator=(Multimap&&) = default;
|
||||
|
||||
public:
|
||||
|
||||
/// The "key" type, usually osmium::unsigned_object_id_type.
|
||||
typedef TId key_type;
|
||||
|
||||
/// The "value" type, usually a Location or size_t.
|
||||
typedef TValue value_type;
|
||||
|
||||
Multimap() = default;
|
||||
|
||||
virtual ~Multimap() noexcept = default;
|
||||
|
||||
/// Set the field with id to value.
|
||||
virtual void set(const TId id, const TValue value) = 0;
|
||||
|
||||
typedef element_type* iterator;
|
||||
|
||||
// virtual std::pair<iterator, iterator> get_all(const TId id) const = 0;
|
||||
|
||||
/**
|
||||
* Get the approximate number of items in the storage. The storage
|
||||
* might allocate memory in blocks, so this size might not be
|
||||
* accurate. You can not use this to find out how much memory the
|
||||
* storage uses. Use used_memory() for that.
|
||||
*/
|
||||
virtual size_t size() const = 0;
|
||||
|
||||
/**
|
||||
* Get the memory used for this storage in bytes. Note that this
|
||||
* is not necessarily entirely accurate but an approximation.
|
||||
* For storage classes that store the data in memory, this is
|
||||
* the main memory used, for storage classes storing data on disk
|
||||
* this is the memory used on disk.
|
||||
*/
|
||||
virtual size_t used_memory() const = 0;
|
||||
|
||||
/**
|
||||
* Clear memory used for this storage. After this you can not
|
||||
* use the storage container any more.
|
||||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
/**
|
||||
* Sort data in map. Call this after writing all data and
|
||||
* before reading. Not all implementations need this.
|
||||
*/
|
||||
virtual void sort() {
|
||||
// default implementation is empty
|
||||
}
|
||||
|
||||
virtual void dump_as_list(int /*fd*/) const {
|
||||
std::runtime_error("can't dump as list");
|
||||
}
|
||||
|
||||
}; // class Multimap
|
||||
|
||||
} // namespace map
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MULTIMAP_HPP
|
199
ThirdParty/osmium/index/multimap/hybrid.hpp
vendored
Normal file
199
ThirdParty/osmium/index/multimap/hybrid.hpp
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
#ifndef OSMIUM_INDEX_MULTIMAP_HYBRID_HPP
|
||||
#define OSMIUM_INDEX_MULTIMAP_HYBRID_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/index/multimap.hpp>
|
||||
#include <osmium/index/multimap/stl_vector.hpp>
|
||||
#include <osmium/index/multimap/stl_multimap.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace multimap {
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
class HybridIterator {
|
||||
|
||||
typedef SparseMultimapMem<TId, TValue> main_map_type;
|
||||
typedef StlMultimap<TId, TValue> extra_map_type;
|
||||
|
||||
typedef typename std::pair<TId, TValue> element_type;
|
||||
|
||||
typename main_map_type::iterator m_begin_main;
|
||||
typename main_map_type::iterator m_end_main;
|
||||
typename extra_map_type::iterator m_begin_extra;
|
||||
typename extra_map_type::iterator m_end_extra;
|
||||
|
||||
public:
|
||||
|
||||
explicit HybridIterator(typename main_map_type::iterator begin_main,
|
||||
typename main_map_type::iterator end_main,
|
||||
typename extra_map_type::iterator begin_extra,
|
||||
typename extra_map_type::iterator end_extra) :
|
||||
m_begin_main(begin_main),
|
||||
m_end_main(end_main),
|
||||
m_begin_extra(begin_extra),
|
||||
m_end_extra(end_extra) {
|
||||
}
|
||||
|
||||
HybridIterator& operator++() {
|
||||
if (m_begin_main == m_end_main) {
|
||||
++m_begin_extra;
|
||||
} else {
|
||||
++m_begin_main;
|
||||
while (m_begin_main != m_end_main && m_begin_main->second == osmium::index::empty_value<TValue>()) { // ignore removed elements
|
||||
++m_begin_main;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
HybridIterator<TId, TValue> operator++(int) {
|
||||
auto tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const HybridIterator& rhs) const {
|
||||
return m_begin_main == rhs.m_begin_main &&
|
||||
m_end_main == rhs.m_end_main &&
|
||||
m_begin_extra == rhs.m_begin_extra &&
|
||||
m_end_extra == rhs.m_end_extra;
|
||||
}
|
||||
|
||||
bool operator!=(const HybridIterator& rhs) const {
|
||||
return ! operator==(rhs);
|
||||
}
|
||||
|
||||
const element_type& operator*() {
|
||||
if (m_begin_main == m_end_main) {
|
||||
return *m_begin_extra;
|
||||
} else {
|
||||
return *m_begin_main;
|
||||
}
|
||||
}
|
||||
|
||||
const element_type* operator->() {
|
||||
return &operator*();
|
||||
}
|
||||
|
||||
}; // class HybridIterator
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
class Hybrid : public Multimap<TId, TValue> {
|
||||
|
||||
typedef SparseMultimapMem<TId, TValue> main_map_type;
|
||||
typedef StlMultimap<TId, TValue> extra_map_type;
|
||||
|
||||
main_map_type m_main;
|
||||
extra_map_type m_extra;
|
||||
|
||||
public:
|
||||
|
||||
typedef HybridIterator<TId, TValue> iterator;
|
||||
typedef const HybridIterator<TId, TValue> const_iterator;
|
||||
|
||||
Hybrid() :
|
||||
m_main(),
|
||||
m_extra() {
|
||||
}
|
||||
|
||||
size_t size() const override final {
|
||||
return m_main.size() + m_extra.size();
|
||||
}
|
||||
|
||||
size_t used_memory() const override final {
|
||||
return m_main.used_memory() + m_extra.used_memory();
|
||||
}
|
||||
|
||||
void reserve(const size_t size) {
|
||||
m_main.reserve(size);
|
||||
}
|
||||
|
||||
void unsorted_set(const TId id, const TValue value) {
|
||||
m_main.set(id, value);
|
||||
}
|
||||
|
||||
void set(const TId id, const TValue value) override final {
|
||||
m_extra.set(id, value);
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator> get_all(const TId id) {
|
||||
auto result_main = m_main.get_all(id);
|
||||
auto result_extra = m_extra.get_all(id);
|
||||
return std::make_pair(iterator(result_main.first, result_main.second, result_extra.first, result_extra.second),
|
||||
iterator(result_main.second, result_main.second, result_extra.second, result_extra.second));
|
||||
}
|
||||
|
||||
void remove(const TId id, const TValue value) {
|
||||
m_main.remove(id, value);
|
||||
m_extra.remove(id, value);
|
||||
}
|
||||
|
||||
void consolidate() {
|
||||
m_main.erase_removed();
|
||||
for (const auto& element : m_extra) {
|
||||
m_main.set(element.first, element.second);
|
||||
}
|
||||
m_extra.clear();
|
||||
m_main.sort();
|
||||
}
|
||||
|
||||
void dump_as_list(int fd) override final {
|
||||
consolidate();
|
||||
m_main.dump_as_list(fd);
|
||||
}
|
||||
|
||||
void clear() override final {
|
||||
m_main.clear();
|
||||
m_extra.clear();
|
||||
}
|
||||
|
||||
void sort() override final {
|
||||
m_main.sort();
|
||||
}
|
||||
|
||||
}; // class Hybrid
|
||||
|
||||
} // namespace multimap
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MULTIMAP_HYBRID_HPP
|
58
ThirdParty/osmium/index/multimap/mmap_vector_anon.hpp
vendored
Normal file
58
ThirdParty/osmium/index/multimap/mmap_vector_anon.hpp
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP
|
||||
#define OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <osmium/index/multimap/vector.hpp>
|
||||
#include <osmium/index/detail/mmap_vector_anon.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace multimap {
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
using SparseMultimapMmap = VectorBasedSparseMultimap<TId, TValue, osmium::detail::mmap_vector_anon>;
|
||||
|
||||
} // namespace multimap
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
#endif // OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP
|
54
ThirdParty/osmium/index/multimap/mmap_vector_file.hpp
vendored
Normal file
54
ThirdParty/osmium/index/multimap/mmap_vector_file.hpp
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP
|
||||
#define OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/index/multimap/vector.hpp>
|
||||
#include <osmium/index/detail/mmap_vector_file.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace multimap {
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
using SparseMultimapFile = VectorBasedSparseMultimap<TId, TValue, osmium::detail::mmap_vector_file>;
|
||||
|
||||
} // namespace multimap
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP
|
151
ThirdParty/osmium/index/multimap/stl_multimap.hpp
vendored
Normal file
151
ThirdParty/osmium/index/multimap/stl_multimap.hpp
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
#ifndef OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP
|
||||
#define OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/index/multimap.hpp>
|
||||
#include <osmium/io/detail/read_write.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace multimap {
|
||||
|
||||
/**
|
||||
* This implementation uses std::multimap internally. It uses rather a
|
||||
* lot of memory, but might make sense for small maps.
|
||||
*/
|
||||
template <typename TId, typename TValue>
|
||||
class StlMultimap : public osmium::index::multimap::Multimap<TId, TValue> {
|
||||
|
||||
// This is a rough estimate for the memory needed for each
|
||||
// element in the map (id + value + pointers to left, right,
|
||||
// and parent plus some overhead for color of red-black-tree
|
||||
// or similar).
|
||||
static constexpr size_t element_size = sizeof(TId) + sizeof(TValue) + sizeof(void*) * 4;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename std::multimap<const TId, TValue> collection_type;
|
||||
typedef typename collection_type::iterator iterator;
|
||||
typedef typename collection_type::const_iterator const_iterator;
|
||||
typedef typename collection_type::value_type value_type;
|
||||
|
||||
typedef typename std::pair<TId, TValue> element_type;
|
||||
|
||||
private:
|
||||
|
||||
collection_type m_elements;
|
||||
|
||||
public:
|
||||
|
||||
StlMultimap() = default;
|
||||
|
||||
~StlMultimap() noexcept override final = default;
|
||||
|
||||
void unsorted_set(const TId id, const TValue value) {
|
||||
m_elements.emplace(id, value);
|
||||
}
|
||||
|
||||
void set(const TId id, const TValue value) override final {
|
||||
m_elements.emplace(id, value);
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator> get_all(const TId id) {
|
||||
return m_elements.equal_range(id);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator> get_all(const TId id) const {
|
||||
return m_elements.equal_range(id);
|
||||
}
|
||||
|
||||
void remove(const TId id, const TValue value) {
|
||||
std::pair<iterator, iterator> r = get_all(id);
|
||||
for (iterator it = r.first; it != r.second; ++it) {
|
||||
if (it->second == value) {
|
||||
m_elements.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return m_elements.begin();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return m_elements.end();
|
||||
}
|
||||
|
||||
size_t size() const override final {
|
||||
return m_elements.size();
|
||||
}
|
||||
|
||||
size_t used_memory() const override final {
|
||||
return element_size * m_elements.size();
|
||||
}
|
||||
|
||||
void clear() override final {
|
||||
m_elements.clear();
|
||||
}
|
||||
|
||||
void consolidate() {
|
||||
// intentionally left blank
|
||||
}
|
||||
|
||||
void dump_as_list(const int fd) const override final {
|
||||
std::vector<element_type> v;
|
||||
for (const auto& element : m_elements) {
|
||||
v.emplace_back(element.first, element.second);
|
||||
}
|
||||
// std::copy(m_elements.cbegin(), m_elements.cend(), std::back_inserter(v));
|
||||
std::sort(v.begin(), v.end());
|
||||
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(v.data()), sizeof(element_type) * v.size());
|
||||
}
|
||||
|
||||
}; // class StlMultimap
|
||||
|
||||
} // namespace multimap
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP
|
58
ThirdParty/osmium/index/multimap/stl_vector.hpp
vendored
Normal file
58
ThirdParty/osmium/index/multimap/stl_vector.hpp
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP
|
||||
#define OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/index/multimap/vector.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace multimap {
|
||||
|
||||
template <typename T>
|
||||
using StdVectorWrap = std::vector<T>;
|
||||
|
||||
template <typename TId, typename TValue>
|
||||
using SparseMultimapMem = VectorBasedSparseMultimap<TId, TValue, StdVectorWrap>;
|
||||
|
||||
} // namespace multimap
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP
|
151
ThirdParty/osmium/index/multimap/vector.hpp
vendored
Normal file
151
ThirdParty/osmium/index/multimap/vector.hpp
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
#ifndef OSMIUM_INDEX_MULTIMAP_VECTOR_HPP
|
||||
#define OSMIUM_INDEX_MULTIMAP_VECTOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/index/multimap.hpp>
|
||||
#include <osmium/io/detail/read_write.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace index {
|
||||
|
||||
namespace multimap {
|
||||
|
||||
template <typename TId, typename TValue, template<typename...> class TVector>
|
||||
class VectorBasedSparseMultimap : public Multimap<TId, TValue> {
|
||||
|
||||
public:
|
||||
|
||||
typedef typename std::pair<TId, TValue> element_type;
|
||||
typedef TVector<element_type> vector_type;
|
||||
typedef typename vector_type::iterator iterator;
|
||||
typedef typename vector_type::const_iterator const_iterator;
|
||||
|
||||
private:
|
||||
|
||||
vector_type m_vector;
|
||||
|
||||
static bool is_removed(element_type& element) {
|
||||
return element.second == osmium::index::empty_value<TValue>();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void set(const TId id, const TValue value) override final {
|
||||
m_vector.push_back(element_type(id, value));
|
||||
}
|
||||
|
||||
void unsorted_set(const TId id, const TValue value) {
|
||||
m_vector.push_back(element_type(id, value));
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator> get_all(const TId id) {
|
||||
const element_type element {
|
||||
id,
|
||||
osmium::index::empty_value<TValue>()
|
||||
};
|
||||
return std::equal_range(m_vector.begin(), m_vector.end(), element, [](const element_type& a, const element_type& b) {
|
||||
return a.first < b.first;
|
||||
});
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator> get_all(const TId id) const {
|
||||
const element_type element {
|
||||
id,
|
||||
osmium::index::empty_value<TValue>()
|
||||
};
|
||||
return std::equal_range(m_vector.cbegin(), m_vector.cend(), element, [](const element_type& a, const element_type& b) {
|
||||
return a.first < b.first;
|
||||
});
|
||||
}
|
||||
|
||||
size_t size() const override final {
|
||||
return m_vector.size();
|
||||
}
|
||||
|
||||
size_t byte_size() const {
|
||||
return m_vector.size() * sizeof(element_type);
|
||||
}
|
||||
|
||||
size_t used_memory() const override final {
|
||||
return sizeof(element_type) * size();
|
||||
}
|
||||
|
||||
void clear() override final {
|
||||
m_vector.clear();
|
||||
m_vector.shrink_to_fit();
|
||||
}
|
||||
|
||||
void sort() override final {
|
||||
std::sort(m_vector.begin(), m_vector.end());
|
||||
}
|
||||
|
||||
void remove(const TId id, const TValue value) {
|
||||
auto r = get_all(id);
|
||||
for (auto it = r.first; it != r.second; ++it) {
|
||||
if (it->second == value) {
|
||||
it->second = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void consolidate() {
|
||||
std::sort(m_vector.begin(), m_vector.end());
|
||||
}
|
||||
|
||||
void erase_removed() {
|
||||
m_vector.erase(
|
||||
std::remove_if(m_vector.begin(), m_vector.end(), is_removed),
|
||||
m_vector.end()
|
||||
);
|
||||
}
|
||||
|
||||
void dump_as_list(int fd) const override final {
|
||||
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
|
||||
}
|
||||
|
||||
}; // class VectorBasedSparseMultimap
|
||||
|
||||
} // namespace multimap
|
||||
|
||||
} // namespace index
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_INDEX_MULTIMAP_VECTOR_HPP
|
39
ThirdParty/osmium/io/any_compression.hpp
vendored
Normal file
39
ThirdParty/osmium/io/any_compression.hpp
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef OSMIUM_IO_ANY_COMPRESSION_HPP
|
||||
#define OSMIUM_IO_ANY_COMPRESSION_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/io/bzip2_compression.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/gzip_compression.hpp> // IWYU pragma: export
|
||||
|
||||
#endif // OSMIUM_IO_ANY_COMPRESSION_HPP
|
41
ThirdParty/osmium/io/any_input.hpp
vendored
Normal file
41
ThirdParty/osmium/io/any_input.hpp
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef OSMIUM_IO_ANY_INPUT_HPP
|
||||
#define OSMIUM_IO_ANY_INPUT_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/io/any_compression.hpp> // IWYU pragma: export
|
||||
|
||||
#include <osmium/io/pbf_input.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/xml_input.hpp> // IWYU pragma: export
|
||||
|
||||
#endif // OSMIUM_IO_ANY_INPUT_HPP
|
42
ThirdParty/osmium/io/any_output.hpp
vendored
Normal file
42
ThirdParty/osmium/io/any_output.hpp
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef OSMIUM_IO_ANY_OUTPUT_HPP
|
||||
#define OSMIUM_IO_ANY_OUTPUT_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osmium/io/any_compression.hpp> // IWYU pragma: export
|
||||
|
||||
#include <osmium/io/opl_output.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/pbf_output.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/xml_output.hpp> // IWYU pragma: export
|
||||
|
||||
#endif // OSMIUM_IO_ANY_OUTPUT_HPP
|
277
ThirdParty/osmium/io/bzip2_compression.hpp
vendored
Normal file
277
ThirdParty/osmium/io/bzip2_compression.hpp
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
#ifndef OSMIUM_IO_BZIP2_COMPRESSION_HPP
|
||||
#define OSMIUM_IO_BZIP2_COMPRESSION_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#define OSMIUM_LINK_WITH_LIBS_BZ2LIB -lbz2
|
||||
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <bzlib.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <osmium/io/compression.hpp>
|
||||
#include <osmium/io/file_compression.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* Exception thrown when there are problems compressing or
|
||||
* decompressing bzip2 files.
|
||||
*/
|
||||
struct bzip2_error : public std::runtime_error {
|
||||
|
||||
int bzip2_error_code;
|
||||
int system_errno;
|
||||
|
||||
bzip2_error(const std::string& what, int error_code) :
|
||||
std::runtime_error(what),
|
||||
bzip2_error_code(error_code),
|
||||
system_errno(error_code == BZ_IO_ERROR ? errno : 0) {
|
||||
}
|
||||
|
||||
}; // struct bzip2_error
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
OSMIUM_NORETURN inline void throw_bzip2_error(BZFILE* bzfile, const char* msg, int bzlib_error=0) {
|
||||
std::string error("bzip2 error: ");
|
||||
error += msg;
|
||||
error += ": ";
|
||||
int errnum = bzlib_error;
|
||||
if (bzlib_error) {
|
||||
error += std::to_string(bzlib_error);
|
||||
} else {
|
||||
error += ::BZ2_bzerror(bzfile, &errnum);
|
||||
}
|
||||
throw osmium::bzip2_error(error, errnum);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class Bzip2Compressor : public Compressor {
|
||||
|
||||
FILE* m_file;
|
||||
int m_bzerror;
|
||||
BZFILE* m_bzfile;
|
||||
|
||||
public:
|
||||
|
||||
explicit Bzip2Compressor(int fd) :
|
||||
Compressor(),
|
||||
m_file(fdopen(dup(fd), "wb")),
|
||||
m_bzerror(BZ_OK),
|
||||
m_bzfile(::BZ2_bzWriteOpen(&m_bzerror, m_file, 6, 0, 0)) {
|
||||
if (!m_bzfile) {
|
||||
detail::throw_bzip2_error(m_bzfile, "write open failed", m_bzerror);
|
||||
}
|
||||
}
|
||||
|
||||
~Bzip2Compressor() override final {
|
||||
close();
|
||||
}
|
||||
|
||||
void write(const std::string& data) override final {
|
||||
int error;
|
||||
::BZ2_bzWrite(&error, m_bzfile, const_cast<char*>(data.data()), static_cast_with_assert<int>(data.size()));
|
||||
if (error != BZ_OK && error != BZ_STREAM_END) {
|
||||
detail::throw_bzip2_error(m_bzfile, "write failed", error);
|
||||
}
|
||||
}
|
||||
|
||||
void close() override final {
|
||||
if (m_bzfile) {
|
||||
int error;
|
||||
::BZ2_bzWriteClose(&error, m_bzfile, 0, nullptr, nullptr);
|
||||
m_bzfile = nullptr;
|
||||
if (m_file) {
|
||||
fclose(m_file);
|
||||
}
|
||||
if (error != BZ_OK) {
|
||||
detail::throw_bzip2_error(m_bzfile, "write close failed", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}; // class Bzip2Compressor
|
||||
|
||||
class Bzip2Decompressor : public Decompressor {
|
||||
|
||||
FILE* m_file;
|
||||
int m_bzerror;
|
||||
BZFILE* m_bzfile;
|
||||
bool m_stream_end {false};
|
||||
|
||||
public:
|
||||
|
||||
Bzip2Decompressor(int fd) :
|
||||
Decompressor(),
|
||||
m_file(fdopen(dup(fd), "rb")),
|
||||
m_bzerror(BZ_OK),
|
||||
m_bzfile(::BZ2_bzReadOpen(&m_bzerror, m_file, 0, 0, nullptr, 0)) {
|
||||
if (!m_bzfile) {
|
||||
detail::throw_bzip2_error(m_bzfile, "read open failed", m_bzerror);
|
||||
}
|
||||
}
|
||||
|
||||
~Bzip2Decompressor() override final {
|
||||
close();
|
||||
}
|
||||
|
||||
std::string read() override final {
|
||||
if (m_stream_end) {
|
||||
return std::string();
|
||||
}
|
||||
std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0');
|
||||
int error;
|
||||
int nread = ::BZ2_bzRead(&error, m_bzfile, const_cast<char*>(buffer.data()), static_cast_with_assert<int>(buffer.size()));
|
||||
if (error != BZ_OK && error != BZ_STREAM_END) {
|
||||
detail::throw_bzip2_error(m_bzfile, "read failed", error);
|
||||
}
|
||||
if (error == BZ_STREAM_END) {
|
||||
void* unused;
|
||||
int nunused;
|
||||
if (! feof(m_file)) {
|
||||
::BZ2_bzReadGetUnused(&error, m_bzfile, &unused, &nunused);
|
||||
if (error != BZ_OK) {
|
||||
detail::throw_bzip2_error(m_bzfile, "get unused failed", error);
|
||||
}
|
||||
std::string unused_data(static_cast<const char*>(unused), static_cast<std::string::size_type>(nunused));
|
||||
::BZ2_bzReadClose(&error, m_bzfile);
|
||||
if (error != BZ_OK) {
|
||||
detail::throw_bzip2_error(m_bzfile, "read close failed", error);
|
||||
}
|
||||
m_bzfile = ::BZ2_bzReadOpen(&error, m_file, 0, 0, const_cast<void*>(static_cast<const void*>(unused_data.data())), static_cast_with_assert<int>(unused_data.size()));
|
||||
if (error != BZ_OK) {
|
||||
detail::throw_bzip2_error(m_bzfile, "read open failed", error);
|
||||
}
|
||||
} else {
|
||||
m_stream_end = true;
|
||||
}
|
||||
}
|
||||
buffer.resize(static_cast<std::string::size_type>(nread));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void close() override final {
|
||||
if (m_bzfile) {
|
||||
int error;
|
||||
::BZ2_bzReadClose(&error, m_bzfile);
|
||||
m_bzfile = nullptr;
|
||||
if (m_file) {
|
||||
fclose(m_file);
|
||||
}
|
||||
if (error != BZ_OK) {
|
||||
detail::throw_bzip2_error(m_bzfile, "read close failed", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}; // class Bzip2Decompressor
|
||||
|
||||
class Bzip2BufferDecompressor : public Decompressor {
|
||||
|
||||
const char* m_buffer;
|
||||
size_t m_buffer_size;
|
||||
bz_stream m_bzstream;
|
||||
|
||||
public:
|
||||
|
||||
Bzip2BufferDecompressor(const char* buffer, size_t size) :
|
||||
m_buffer(buffer),
|
||||
m_buffer_size(size),
|
||||
m_bzstream() {
|
||||
m_bzstream.next_in = const_cast<char*>(buffer);
|
||||
m_bzstream.avail_in = static_cast_with_assert<unsigned int>(size);
|
||||
int result = BZ2_bzDecompressInit(&m_bzstream, 0, 0);
|
||||
if (result != BZ_OK) {
|
||||
std::string message("bzip2 error: decompression init failed: ");
|
||||
throw bzip2_error(message, result);
|
||||
}
|
||||
}
|
||||
|
||||
~Bzip2BufferDecompressor() override final {
|
||||
BZ2_bzDecompressEnd(&m_bzstream);
|
||||
}
|
||||
|
||||
std::string read() override final {
|
||||
if (!m_buffer) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const size_t buffer_size = 10240;
|
||||
std::string output(buffer_size, '\0');
|
||||
m_bzstream.next_out = const_cast<char*>(output.data());
|
||||
m_bzstream.avail_out = buffer_size;
|
||||
int result = BZ2_bzDecompress(&m_bzstream);
|
||||
|
||||
if (result != BZ_OK) {
|
||||
m_buffer = nullptr;
|
||||
m_buffer_size = 0;
|
||||
}
|
||||
|
||||
if (result != BZ_OK && result != BZ_STREAM_END) {
|
||||
std::string message("bzip2 error: decompress failed: ");
|
||||
throw bzip2_error(message, result);
|
||||
}
|
||||
|
||||
output.resize(static_cast<unsigned long>(m_bzstream.next_out - output.data()));
|
||||
return output;
|
||||
}
|
||||
|
||||
}; // class Bzip2BufferDecompressor
|
||||
|
||||
namespace {
|
||||
|
||||
const bool registered_bzip2_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::bzip2,
|
||||
[](int fd) { return new osmium::io::Bzip2Compressor(fd); },
|
||||
[](int fd) { return new osmium::io::Bzip2Decompressor(fd); },
|
||||
[](const char* buffer, size_t size) { return new osmium::io::Bzip2BufferDecompressor(buffer, size); }
|
||||
);
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_BZIP2_COMPRESSION_HPP
|
279
ThirdParty/osmium/io/compression.hpp
vendored
Normal file
279
ThirdParty/osmium/io/compression.hpp
vendored
Normal file
@ -0,0 +1,279 @@
|
||||
#ifndef OSMIUM_IO_COMPRESSION_HPP
|
||||
#define OSMIUM_IO_COMPRESSION_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> and others (see README).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <cerrno>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <utility>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include <osmium/io/detail/read_write.hpp>
|
||||
#include <osmium/io/file_compression.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace io {
|
||||
|
||||
class Compressor {
|
||||
|
||||
public:
|
||||
|
||||
Compressor() = default;
|
||||
|
||||
virtual ~Compressor() {
|
||||
}
|
||||
|
||||
virtual void write(const std::string& data) = 0;
|
||||
|
||||
virtual void close() = 0;
|
||||
|
||||
}; // class Compressor
|
||||
|
||||
class Decompressor {
|
||||
|
||||
public:
|
||||
|
||||
static constexpr size_t input_buffer_size = 256 * 1024;
|
||||
|
||||
Decompressor() = default;
|
||||
|
||||
Decompressor(const Decompressor&) = delete;
|
||||
Decompressor& operator=(const Decompressor&) = delete;
|
||||
|
||||
Decompressor(Decompressor&&) = delete;
|
||||
Decompressor& operator=(Decompressor&&) = delete;
|
||||
|
||||
virtual ~Decompressor() {
|
||||
}
|
||||
|
||||
virtual std::string read() = 0;
|
||||
|
||||
virtual void close() {
|
||||
}
|
||||
|
||||
}; // class Decompressor
|
||||
|
||||
/**
|
||||
* This singleton factory class is used to register compression
|
||||
* algorithms used for reading and writing OSM files.
|
||||
*
|
||||
* For each algorithm we store two functions that construct
|
||||
* a compressor and decompressor object, respectively.
|
||||
*/
|
||||
class CompressionFactory {
|
||||
|
||||
public:
|
||||
|
||||
typedef std::function<osmium::io::Compressor*(int)> create_compressor_type;
|
||||
typedef std::function<osmium::io::Decompressor*(int)> create_decompressor_type_fd;
|
||||
typedef std::function<osmium::io::Decompressor*(const char*, size_t)> create_decompressor_type_buffer;
|
||||
|
||||
private:
|
||||
|
||||
typedef std::map<const osmium::io::file_compression, std::tuple<create_compressor_type, create_decompressor_type_fd, create_decompressor_type_buffer>> compression_map_type;
|
||||
|
||||
compression_map_type m_callbacks;
|
||||
|
||||
CompressionFactory() = default;
|
||||
|
||||
CompressionFactory(const CompressionFactory&) = delete;
|
||||
CompressionFactory& operator=(const CompressionFactory&) = delete;
|
||||
|
||||
CompressionFactory(CompressionFactory&&) = delete;
|
||||
CompressionFactory& operator=(CompressionFactory&&) = delete;
|
||||
|
||||
OSMIUM_NORETURN void error(osmium::io::file_compression compression) {
|
||||
std::string error_message {"Support for compression '"};
|
||||
error_message += as_string(compression);
|
||||
error_message += "' not compiled into this binary.";
|
||||
throw std::runtime_error(error_message);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static CompressionFactory& instance() {
|
||||
static CompressionFactory factory;
|
||||
return factory;
|
||||
}
|
||||
|
||||
bool register_compression(
|
||||
osmium::io::file_compression compression,
|
||||
create_compressor_type create_compressor,
|
||||
create_decompressor_type_fd create_decompressor_fd,
|
||||
create_decompressor_type_buffer create_decompressor_buffer) {
|
||||
|
||||
compression_map_type::value_type cc(compression, std::make_tuple(create_compressor, create_decompressor_fd, create_decompressor_buffer));
|
||||
return m_callbacks.insert(cc).second;
|
||||
}
|
||||
|
||||
std::unique_ptr<osmium::io::Compressor> create_compressor(osmium::io::file_compression compression, int fd) {
|
||||
auto it = m_callbacks.find(compression);
|
||||
|
||||
if (it != m_callbacks.end()) {
|
||||
return std::unique_ptr<osmium::io::Compressor>(std::get<0>(it->second)(fd));
|
||||
}
|
||||
|
||||
error(compression);
|
||||
}
|
||||
|
||||
std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, int fd) {
|
||||
auto it = m_callbacks.find(compression);
|
||||
|
||||
if (it != m_callbacks.end()) {
|
||||
return std::unique_ptr<osmium::io::Decompressor>(std::get<1>(it->second)(fd));
|
||||
}
|
||||
|
||||
error(compression);
|
||||
}
|
||||
|
||||
std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, const char* buffer, size_t size) {
|
||||
auto it = m_callbacks.find(compression);
|
||||
|
||||
if (it != m_callbacks.end()) {
|
||||
return std::unique_ptr<osmium::io::Decompressor>(std::get<2>(it->second)(buffer, size));
|
||||
}
|
||||
|
||||
error(compression);
|
||||
}
|
||||
|
||||
}; // class CompressionFactory
|
||||
|
||||
class NoCompressor : public Compressor {
|
||||
|
||||
int m_fd;
|
||||
|
||||
public:
|
||||
|
||||
NoCompressor(int fd) :
|
||||
Compressor(),
|
||||
m_fd(fd) {
|
||||
}
|
||||
|
||||
~NoCompressor() override final {
|
||||
close();
|
||||
}
|
||||
|
||||
void write(const std::string& data) override final {
|
||||
osmium::io::detail::reliable_write(m_fd, data.data(), data.size());
|
||||
}
|
||||
|
||||
void close() override final {
|
||||
if (m_fd >= 0) {
|
||||
::close(m_fd);
|
||||
m_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
}; // class NoCompressor
|
||||
|
||||
class NoDecompressor : public Decompressor {
|
||||
|
||||
int m_fd;
|
||||
const char *m_buffer;
|
||||
size_t m_buffer_size;
|
||||
|
||||
public:
|
||||
|
||||
NoDecompressor(int fd) :
|
||||
Decompressor(),
|
||||
m_fd(fd),
|
||||
m_buffer(nullptr),
|
||||
m_buffer_size(0) {
|
||||
}
|
||||
|
||||
NoDecompressor(const char* buffer, size_t size) :
|
||||
Decompressor(),
|
||||
m_fd(-1),
|
||||
m_buffer(buffer),
|
||||
m_buffer_size(size) {
|
||||
}
|
||||
|
||||
~NoDecompressor() override final {
|
||||
close();
|
||||
}
|
||||
|
||||
std::string read() override final {
|
||||
if (m_buffer) {
|
||||
if (m_buffer_size == 0) {
|
||||
return std::string();
|
||||
}
|
||||
size_t size = m_buffer_size;
|
||||
m_buffer_size = 0;
|
||||
return std::string(m_buffer, size);
|
||||
} else {
|
||||
std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0');
|
||||
ssize_t nread = ::read(m_fd, const_cast<char*>(buffer.data()), buffer.size());
|
||||
if (nread < 0) {
|
||||
throw std::system_error(errno, std::system_category(), "Read failed");
|
||||
}
|
||||
buffer.resize(static_cast<size_t>(nread));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void close() override final {
|
||||
if (m_fd >= 0) {
|
||||
::close(m_fd);
|
||||
m_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
}; // class NoDecompressor
|
||||
|
||||
namespace {
|
||||
|
||||
const bool registered_no_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::none,
|
||||
[](int fd) { return new osmium::io::NoCompressor(fd); },
|
||||
[](int fd) { return new osmium::io::NoDecompressor(fd); },
|
||||
[](const char* buffer, size_t size) { return new osmium::io::NoDecompressor(buffer, size); }
|
||||
);
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_COMPRESSION_HPP
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user