Refactored osmp

This commit is contained in:
Robert 2021-04-18 17:34:00 +02:00
parent 87046f5d18
commit 569812c0a5
14 changed files with 171 additions and 92 deletions

View file

@ -10,7 +10,7 @@ struct SDL_Renderer;
class Multipolygon class Multipolygon
{ {
public: public:
Multipolygon(const std::shared_ptr<osmp::Relation>& relation, int width, int height, osmp::Bounds bounds); Multipolygon(const osmp::Relation& relation, int width, int height, const osmp::Bounds& bounds);
void SetColor(int r, int g, int b); void SetColor(int r, int g, int b);
void Draw(SDL_Renderer* renderer); void Draw(SDL_Renderer* renderer);

View file

@ -24,7 +24,7 @@ namespace osmp
[[nodiscard]] IMember::Type GetType() const; [[nodiscard]] IMember::Type GetType() const;
[[nodiscard]] const std::vector<Tag>& GetTags() const; [[nodiscard]] const TagList& GetTags() const;
[[nodiscard]] size_t GetTagsSize() const; [[nodiscard]] size_t GetTagsSize() const;
[[nodiscard]] const Tag& GetTag(size_t index) const; [[nodiscard]] const Tag& GetTag(size_t index) const;
[[nodiscard]] std::string GetTag(const std::string& key) const; [[nodiscard]] std::string GetTag(const std::string& key) const;
@ -36,8 +36,7 @@ namespace osmp
IMember::Type type; IMember::Type type;
Object* parent; Object* parent;
std::vector<Tag> tags; TagList tags;
// std::map<std::string, std::string> tags;
public: public:
uint64_t id; uint64_t id;

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include "util.hpp" #include <util.hpp>
#include <osmimember.hpp> #include <osmimember.hpp>
#include <osmtag.hpp> #include <osmtag.hpp>
@ -9,10 +9,17 @@ namespace osmp
{ {
class Object; class Object;
class Node : public IMember class INode : public IMember
{ {
public: public:
Node(const tinyxml2::XMLElement* xml, Object* parent); INode(const INode& other) = delete;
INode(const INode&& other) = delete;
virtual ~INode() {}
friend Node CreateNode(const tinyxml2::XMLElement* element, Object* parent);
protected:
INode(const tinyxml2::XMLElement* xml, Object* parent);
public: public:
double lat, lon; double lat, lon;

View file

@ -8,27 +8,23 @@
namespace osmp namespace osmp
{ {
class Node;
class Way;
class Relation;
class Object class Object
{ {
public: public:
explicit Object(const std::string& file); explicit Object(const std::string& file);
~Object(); ~Object();
[[nodiscard]] std::vector<std::shared_ptr<Node>> GetNodes() const; [[nodiscard]] Nodes GetNodes() const;
[[nodiscard]] size_t GetNodesSize() const; [[nodiscard]] size_t GetNodesSize() const;
[[nodiscard]] std::shared_ptr<Node> GetNode(uint64_t id) const; [[nodiscard]] Node GetNode(uint64_t id) const;
[[nodiscard]] std::vector<std::shared_ptr<Way>> GetWays() const; [[nodiscard]] Ways GetWays() const;
[[nodiscard]] size_t GetWaysSize() const; [[nodiscard]] size_t GetWaysSize() const;
[[nodiscard]] std::shared_ptr<Way> GetWay(uint64_t id) const; [[nodiscard]] Way GetWay(uint64_t id) const;
[[nodiscard]] std::vector<std::shared_ptr<Relation>> GetRelations() const; [[nodiscard]] Relations GetRelations() const;
[[nodiscard]] size_t GetRelationsSize() const; [[nodiscard]] size_t GetRelationsSize() const;
[[nodiscard]] std::shared_ptr<Relation> GetRelation(uint64_t id) const; [[nodiscard]] Relation GetRelation(uint64_t id) const;
public: public:
const std::string version; const std::string version;
@ -37,8 +33,8 @@ namespace osmp
Bounds bounds; Bounds bounds;
private: private:
std::map<uint64_t, std::shared_ptr<Node>> nodes; std::map<uint64_t, Node> nodes;
std::map<uint64_t, std::shared_ptr<Way>> ways; std::map<uint64_t, Way> ways;
std::map<uint64_t, std::shared_ptr<Relation>> relations; std::map<uint64_t, Relation> relations;
}; };
} }

View file

@ -9,35 +9,50 @@
namespace osmp namespace osmp
{ {
class Object; class Object;
class IMember;
class Relation : public IMember typedef struct sMemberNode {
Node node;
std::string role;
} MemberNode;
typedef struct sMemberWay {
Way way;
std::string role;
} MemberWay;
typedef std::vector<MemberNode> MemberNodes;
typedef std::vector<MemberWay> MemberWays;
class IRelation : public IMember
{ {
public: public:
typedef struct sMember { IRelation(const IRelation& other) = delete;
std::shared_ptr<IMember> member; IRelation(const IRelation&& other) = delete;
std::string role; virtual ~IRelation() {}
} Member;
public: friend Relation CreateRelation(const tinyxml2::XMLElement* xml, Object* parent);
Relation(const tinyxml2::XMLElement* xml, Object* parent);
[[nodiscard]] std::string GetRelationType(); [[nodiscard]] std::string GetRelationType() const;
[[nodiscard]] const std::vector<Member>& GetNodes() const; [[nodiscard]] const MemberNodes& GetNodes() const;
[[nodiscard]] size_t GetNodesSize() const; [[nodiscard]] size_t GetNodesSize() const;
[[nodiscard]] const Member& GetNode(size_t index) const; [[nodiscard]] const MemberNode& GetNode(size_t index) const;
[[nodiscard]] const std::vector<Member>& GetWays() const; [[nodiscard]] const MemberWays& GetWays() const;
[[nodiscard]] size_t GetWaysSize() const; [[nodiscard]] size_t GetWaysSize() const;
[[nodiscard]] const Member& GetWay(size_t index) const; [[nodiscard]] const MemberWay& GetWay(size_t index) const;
[[nodiscard]] bool HasNullMembers() const { return hasNullMembers; } [[nodiscard]] bool HasNullMembers() const { return hasNullMembers; }
protected:
IRelation(const tinyxml2::XMLElement* xml, Object* parent);
private: private:
std::string relationType; std::string relationType;
bool hasNullMembers; bool hasNullMembers;
std::vector<Member> nodes; MemberNodes nodes;
std::vector<Member> ways; MemberWays ways;
}; };
} }

View file

@ -33,4 +33,6 @@ namespace osmp
std::string k; // TODO: Should/could be an enum std::string k; // TODO: Should/could be an enum
std::string v; std::string v;
} Tag; } Tag;
typedef std::vector<Tag> TagList;
} }

View file

@ -9,21 +9,27 @@
namespace osmp namespace osmp
{ {
class Object; class Object;
class Node;
class Way : public IMember class IWay : public IMember
{ {
public: public:
Way(const tinyxml2::XMLElement* way_elem, Object* parent); IWay(const IWay& other) = delete;
IWay(const IWay&& other) = delete;
virtual ~IWay() {}
[[nodiscard]] const std::vector<std::shared_ptr<Node>>& GetNodes() const; friend Way CreateWay(const tinyxml2::XMLElement* way_elem, Object* parent);
[[nodiscard]] const Nodes& GetNodes() const;
[[nodiscard]] size_t GetNodesSize() const; [[nodiscard]] size_t GetNodesSize() const;
[[nodiscard]] const std::shared_ptr<Node>& GetNode(size_t index) const; [[nodiscard]] Node GetNode(size_t index) const;
protected:
IWay(const tinyxml2::XMLElement* way_elem, Object* parent);
public: public:
bool area, closed; // Closed := Startpoint = endpoint, Area := Closed AND certain conditions are not met bool area, closed; // Closed := Startpoint = endpoint, Area := Closed AND certain conditions are not met
private: private:
std::vector<std::shared_ptr<Node>> nodes; Nodes nodes;
}; };
} }

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <string> #include <string>
#include <vector>
#include <memory>
namespace tinyxml2 namespace tinyxml2
{ {
@ -9,6 +11,18 @@ namespace tinyxml2
namespace osmp namespace osmp
{ {
class INode;
class IWay;
class IRelation;
typedef std::shared_ptr<INode> Node;
typedef std::shared_ptr<IWay> Way;
typedef std::shared_ptr<IRelation> Relation;
typedef std::vector<Node> Nodes;
typedef std::vector<Way> Ways;
typedef std::vector<Relation> Relations;
typedef struct sBounds typedef struct sBounds
{ {
double minlat, minlon, maxlat, maxlon; double minlat, minlon, maxlat, maxlon;

View file

@ -6,11 +6,25 @@ namespace xml = tinyxml2;
namespace osmp namespace osmp
{ {
Node::Node(const tinyxml2::XMLElement* node_elem, Object* parent) : INode::INode(const tinyxml2::XMLElement* node_elem, Object* parent) :
IMember(node_elem, parent, IMember::Type::NODE) IMember(node_elem, parent, IMember::Type::NODE)
{ {
// Get Attribute // Get Attribute
lat = GetSafeAttributeFloat(node_elem, "lat"); lat = GetSafeAttributeFloat(node_elem, "lat");
lon = GetSafeAttributeFloat(node_elem, "lon"); lon = GetSafeAttributeFloat(node_elem, "lon");
} }
namespace {
struct ConcreteNode : public INode {
ConcreteNode(const tinyxml2::XMLElement* node_elem, Object* parent) :
INode(node_elem, parent)
{}
};
}
Node CreateNode(const tinyxml2::XMLElement* node_elem, Object* parent)
{
return std::make_shared<ConcreteNode>(node_elem, parent);
}
} }

View file

@ -39,7 +39,7 @@ namespace osmp
xml::XMLElement* node_elem = root->FirstChildElement("node"); xml::XMLElement* node_elem = root->FirstChildElement("node");
while (node_elem != nullptr) while (node_elem != nullptr)
{ {
std::shared_ptr<Node> new_node = std::make_shared<Node>(node_elem, this); Node new_node = CreateNode(node_elem, this);
nodes.insert(std::make_pair(new_node->id, new_node)); nodes.insert(std::make_pair(new_node->id, new_node));
node_elem = node_elem->NextSiblingElement("node"); node_elem = node_elem->NextSiblingElement("node");
@ -49,7 +49,7 @@ namespace osmp
xml::XMLElement* way_elem = root->FirstChildElement("way"); xml::XMLElement* way_elem = root->FirstChildElement("way");
while (way_elem != nullptr) while (way_elem != nullptr)
{ {
std::shared_ptr<Way> new_way = std::make_shared<Way>(way_elem, this); Way new_way = CreateWay(way_elem, this);
ways.insert(std::make_pair(new_way->id, new_way)); ways.insert(std::make_pair(new_way->id, new_way));
way_elem = way_elem->NextSiblingElement("way"); way_elem = way_elem->NextSiblingElement("way");
@ -59,7 +59,7 @@ namespace osmp
xml::XMLElement* relation_elem = root->FirstChildElement("relation"); xml::XMLElement* relation_elem = root->FirstChildElement("relation");
while (relation_elem != nullptr) while (relation_elem != nullptr)
{ {
std::shared_ptr<Relation> new_way = std::make_shared<Relation>(relation_elem, this); Relation new_way = CreateRelation(relation_elem, this);
relations.insert(std::make_pair(new_way->id, new_way)); relations.insert(std::make_pair(new_way->id, new_way));
relation_elem = relation_elem->NextSiblingElement("relation"); relation_elem = relation_elem->NextSiblingElement("relation");
@ -71,10 +71,10 @@ namespace osmp
} }
std::vector<std::shared_ptr<Node>> Object::GetNodes() const Nodes Object::GetNodes() const
{ {
std::vector<std::shared_ptr<Node>> vecNodes; Nodes vecNodes;
for (std::map<uint64_t, std::shared_ptr<Node>>::const_iterator it = nodes.begin(); it != nodes.end(); it++) for (std::map<uint64_t, Node>::const_iterator it = nodes.begin(); it != nodes.end(); it++)
vecNodes.push_back(it->second); vecNodes.push_back(it->second);
return vecNodes; return vecNodes;
@ -85,19 +85,19 @@ namespace osmp
return nodes.size(); return nodes.size();
} }
std::shared_ptr<Node> Object::GetNode(uint64_t id) const Node Object::GetNode(uint64_t id) const
{ {
std::map<uint64_t, std::shared_ptr<Node>>::const_iterator node = nodes.find(id); std::map<uint64_t, Node>::const_iterator node = nodes.find(id);
if (node != nodes.end()) if (node != nodes.end())
return node->second; return node->second;
return nullptr; return nullptr;
} }
std::vector<std::shared_ptr<Way>> Object::GetWays() const Ways Object::GetWays() const
{ {
std::vector<std::shared_ptr<Way>> vecWays; Ways vecWays;
for (std::map<uint64_t, std::shared_ptr<Way>>::const_iterator it = ways.begin(); it != ways.end(); it++) for (std::map<uint64_t, Way>::const_iterator it = ways.begin(); it != ways.end(); it++)
vecWays.push_back(it->second); vecWays.push_back(it->second);
return vecWays; return vecWays;
@ -108,19 +108,19 @@ namespace osmp
return ways.size(); return ways.size();
} }
std::shared_ptr<Way> Object::GetWay(uint64_t id) const Way Object::GetWay(uint64_t id) const
{ {
std::map<uint64_t, std::shared_ptr<Way>>::const_iterator way = ways.find(id); std::map<uint64_t, Way>::const_iterator way = ways.find(id);
if (way != ways.end()) if (way != ways.end())
return way->second; return way->second;
return nullptr; return nullptr;
} }
std::vector<std::shared_ptr<Relation>> Object::GetRelations() const Relations Object::GetRelations() const
{ {
std::vector<std::shared_ptr<Relation>> vecRelations; Relations vecRelations;
for (std::map<uint64_t, std::shared_ptr<Relation>>::const_iterator it = relations.begin(); it != relations.end(); it++) for (std::map<uint64_t, Relation>::const_iterator it = relations.begin(); it != relations.end(); it++)
vecRelations.push_back(it->second); vecRelations.push_back(it->second);
return vecRelations; return vecRelations;
@ -131,9 +131,9 @@ namespace osmp
return relations.size(); return relations.size();
} }
std::shared_ptr<Relation> Object::GetRelation(uint64_t id) const Relation Object::GetRelation(uint64_t id) const
{ {
std::map<uint64_t, std::shared_ptr<Relation>>::const_iterator relation = relations.find(id); std::map<uint64_t, Relation>::const_iterator relation = relations.find(id);
if (relation != relations.end()) if (relation != relations.end())
return relation->second; return relation->second;

View file

@ -1,3 +1,4 @@
#include "..\include\osmrelation.hpp"
#include <osmrelation.hpp> #include <osmrelation.hpp>
#include <memory> #include <memory>
@ -11,7 +12,7 @@ namespace xml = tinyxml2;
namespace osmp namespace osmp
{ {
Relation::Relation(const xml::XMLElement* xml, Object* parent) : IRelation::IRelation(const xml::XMLElement* xml, Object* parent) :
IMember(xml, parent, IMember::Type::RELATION), hasNullMembers(false) IMember(xml, parent, IMember::Type::RELATION), hasNullMembers(false)
{ {
const xml::XMLElement* member_element = xml->FirstChildElement("member"); const xml::XMLElement* member_element = xml->FirstChildElement("member");
@ -21,54 +22,66 @@ namespace osmp
uint64_t ref = GetSafeAttributeUint64(member_element, "ref"); uint64_t ref = GetSafeAttributeUint64(member_element, "ref");
std::string role = GetSafeAttributeString(member_element, "role"); std::string role = GetSafeAttributeString(member_element, "role");
std::shared_ptr<IMember> member = nullptr;
if (memberType == "node") { if (memberType == "node") {
member = parent->GetNode(ref); Node node = parent->GetNode(ref);
nodes.push_back({ member, role }); nodes.push_back({ node, role });
} }
else if (memberType == "way") { else if (memberType == "way") {
member = parent->GetWay(ref); Way way = parent->GetWay(ref);
if (member == nullptr) { if (way == nullptr) {
hasNullMembers = true; hasNullMembers = true;
} }
ways.push_back({ member, role }); ways.push_back({ way, role });
} }
member_element = member_element->NextSiblingElement("member"); member_element = member_element->NextSiblingElement("member");
} }
} }
std::string Relation::GetRelationType() namespace {
struct ConcreteRelation : public IRelation {
ConcreteRelation(const tinyxml2::XMLElement* way_elem, Object* parent) :
IRelation(way_elem, parent)
{}
};
}
Relation CreateRelation(const tinyxml2::XMLElement* xml, Object* parent)
{
return std::make_shared<ConcreteRelation>(xml, parent);
}
std::string IRelation::GetRelationType() const
{ {
return GetTag("type"); return GetTag("type");
} }
const std::vector<Relation::Member>& Relation::GetNodes() const const MemberNodes& IRelation::GetNodes() const
{ {
return nodes; return nodes;
} }
size_t Relation::GetNodesSize() const size_t IRelation::GetNodesSize() const
{ {
return nodes.size(); return nodes.size();
} }
const Relation::Member& Relation::GetNode(size_t index) const const MemberNode& IRelation::GetNode(size_t index) const
{ {
return nodes[index]; return nodes[index];
} }
const std::vector<Relation::Member>& Relation::GetWays() const const MemberWays& IRelation::GetWays() const
{ {
return ways; return ways;
} }
size_t Relation::GetWaysSize() const size_t IRelation::GetWaysSize() const
{ {
return ways.size(); return ways.size();
} }
const Relation::Member& Relation::GetWay(size_t index) const const MemberWay& IRelation::GetWay(size_t index) const
{ {
return ways[index]; return ways[index];
} }

View file

@ -10,7 +10,7 @@ namespace xml = tinyxml2;
namespace osmp namespace osmp
{ {
Way::Way(const tinyxml2::XMLElement* way_elem, Object* parent) : IWay::IWay(const tinyxml2::XMLElement* way_elem, Object* parent) :
IMember(way_elem, parent, IMember::Type::WAY) IMember(way_elem, parent, IMember::Type::WAY)
{ {
area = GetSafeAttributeBool(way_elem, "area"); area = GetSafeAttributeBool(way_elem, "area");
@ -35,17 +35,30 @@ namespace osmp
} }
} }
const std::vector<std::shared_ptr<Node>>& Way::GetNodes() const namespace {
struct ConcreteWay : public IWay {
ConcreteWay(const tinyxml2::XMLElement* way_elem, Object* parent) :
IWay(way_elem, parent)
{}
};
}
Way CreateWay(const tinyxml2::XMLElement* way_elem, Object* parent)
{
return std::make_shared<ConcreteWay>(way_elem, parent);
}
const Nodes& IWay::GetNodes() const
{ {
return nodes; return nodes;
} }
size_t Way::GetNodesSize() const size_t IWay::GetNodesSize() const
{ {
return nodes.size(); return nodes.size();
} }
const std::shared_ptr<Node>& Way::GetNode(size_t index) const Node IWay::GetNode(size_t index) const
{ {
return nodes[index]; return nodes[index];
} }

View file

@ -44,14 +44,14 @@ int main(int argc, char** argv)
int windowWidth = windowHeight * aspectRatio; int windowWidth = windowHeight * aspectRatio;
// Fetch all the ways // Fetch all the ways
std::vector<std::shared_ptr<osmp::Way>> ways = obj->GetWays(); osmp::Ways ways = obj->GetWays();
// Turn them into renderable ways by mapping the global coordinates to screen coordinates (do this smarter in the future pls) // Turn them into renderable ways by mapping the global coordinates to screen coordinates (do this smarter in the future pls)
std::vector<Area> buildings; std::vector<Area> buildings;
std::vector<Highway> highways; std::vector<Highway> highways;
for (std::shared_ptr<osmp::Way> way : ways) for (osmp::Way way : ways)
{ {
const std::vector<std::shared_ptr<osmp::Node>>& nodes = way->GetNodes(); const osmp::Nodes& nodes = way->GetNodes();
std::string highwayVal = way->GetTag("highway"); std::string highwayVal = way->GetTag("highway");
std::string railwayVal = way->GetTag("railway"); std::string railwayVal = way->GetTag("railway");
if (way->area) if (way->area)
@ -119,9 +119,9 @@ int main(int argc, char** argv)
} }
// Fetch all relations // Fetch all relations
std::vector<std::shared_ptr<osmp::Relation>> relations = obj->GetRelations(); osmp::Relations relations = obj->GetRelations();
std::vector<Multipolygon> multipolygons; std::vector<Multipolygon> multipolygons;
for (const std::shared_ptr<osmp::Relation>& relation : relations) for (const osmp::Relation& relation : relations)
{ {
if (relation->GetRelationType() == "multipolygon" && !relation->HasNullMembers()) if (relation->GetRelationType() == "multipolygon" && !relation->HasNullMembers())
{ {
@ -174,9 +174,9 @@ int main(int argc, char** argv)
SDL_SetRenderDrawColor(renderer, 240, 240, 250, 255); SDL_SetRenderDrawColor(renderer, 240, 240, 250, 255);
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
for (Multipolygon& multipolygon : multipolygons) { // for (Multipolygon& multipolygon : multipolygons) {
multipolygon.Draw(renderer); // multipolygon.Draw(renderer);
} // }
//for (Area& area : buildings) //for (Area& area : buildings)
//{ //{

View file

@ -19,7 +19,7 @@ struct TriangulationData {
}; };
struct Ring { struct Ring {
std::vector<osmp::Relation::Member> members; osmp::MemberWays ways;
int ring; int ring;
}; };
@ -33,14 +33,14 @@ inline double Map(double A, double B, double a, double b, double x)
bool SelfIntersecting(const Ring & ring) bool SelfIntersecting(const Ring & ring)
{ {
struct Segment { struct Segment {
std::shared_ptr<osmp::Node> p1, p2; osmp::Node p1, p2;
}; };
// Get all segments // Get all segments
std::vector<Segment> segments; std::vector<Segment> segments;
for (const osmp::Relation::Member member : ring.members) for (const osmp::MemberWay way : ring.ways)
{ {
std::vector<std::shared_ptr<osmp::Node>> nodes = std::dynamic_pointer_cast<osmp::Way>(member.member)->GetNodes(); osmp::Nodes nodes = way.way->GetNodes();
for (auto it = nodes.begin(); it != nodes.end() - 1; it++) for (auto it = nodes.begin(); it != nodes.end() - 1; it++)
{ {
segments.push_back({ segments.push_back({
@ -78,13 +78,13 @@ bool SelfIntersecting(const Ring & ring)
return false; return false;
} }
Multipolygon::Multipolygon(const std::shared_ptr<osmp::Relation>& relation, int width, int height, osmp::Bounds bounds) : Multipolygon::Multipolygon(const osmp::Relation& relation, int width, int height, const osmp::Bounds& bounds) :
r(255), g(0), b(255), visible(true), rendering(RenderType::FILL), id(relation->id) r(255), g(0), b(255), visible(true), rendering(RenderType::FILL), id(relation->id)
{ {
if (relation->HasNullMembers()) if (relation->HasNullMembers())
return; return;
const std::vector<osmp::Relation::Member>& members = relation->GetWays(); const osmp::MemberWays& members = relation->GetWays();
// Implement https://wiki.openstreetmap.org/wiki/Relation:multipolygon/Algorithm // Implement https://wiki.openstreetmap.org/wiki/Relation:multipolygon/Algorithm
// Ring assignment // Ring assignment
@ -97,7 +97,7 @@ Multipolygon::Multipolygon(const std::shared_ptr<osmp::Relation>& relation, int
rings.push_back({ {members[0]}, ringCount }); rings.push_back({ {members[0]}, ringCount });
// RA-3 // RA-3
if (rings[ringCount].members.front().member == rings[ringCount].members.back().member) if (rings[ringCount].ways.front().way == rings[ringCount].ways.back().way)
{ {
if (SelfIntersecting(rings[ringCount])) if (SelfIntersecting(rings[ringCount]))
{ {