diff --git a/include/multipolygon.hpp b/include/multipolygon.hpp index 654e543..c86a836 100644 --- a/include/multipolygon.hpp +++ b/include/multipolygon.hpp @@ -10,7 +10,7 @@ struct SDL_Renderer; class Multipolygon { public: - Multipolygon(const std::shared_ptr& 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 Draw(SDL_Renderer* renderer); diff --git a/lib/osmparser/include/osmimember.hpp b/lib/osmparser/include/osmimember.hpp index cc92650..b9846d9 100644 --- a/lib/osmparser/include/osmimember.hpp +++ b/lib/osmparser/include/osmimember.hpp @@ -24,7 +24,7 @@ namespace osmp [[nodiscard]] IMember::Type GetType() const; - [[nodiscard]] const std::vector& GetTags() const; + [[nodiscard]] const TagList& GetTags() const; [[nodiscard]] size_t GetTagsSize() const; [[nodiscard]] const Tag& GetTag(size_t index) const; [[nodiscard]] std::string GetTag(const std::string& key) const; @@ -36,8 +36,7 @@ namespace osmp IMember::Type type; Object* parent; - std::vector tags; - // std::map tags; + TagList tags; public: uint64_t id; diff --git a/lib/osmparser/include/osmnode.hpp b/lib/osmparser/include/osmnode.hpp index 76d7627..52a538e 100644 --- a/lib/osmparser/include/osmnode.hpp +++ b/lib/osmparser/include/osmnode.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "util.hpp" +#include #include #include @@ -9,10 +9,17 @@ namespace osmp { class Object; - class Node : public IMember + class INode : public IMember { 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: double lat, lon; diff --git a/lib/osmparser/include/osmobject.hpp b/lib/osmparser/include/osmobject.hpp index b8421fe..7cb02c6 100644 --- a/lib/osmparser/include/osmobject.hpp +++ b/lib/osmparser/include/osmobject.hpp @@ -8,27 +8,23 @@ namespace osmp { - class Node; - class Way; - class Relation; - class Object { public: explicit Object(const std::string& file); ~Object(); - [[nodiscard]] std::vector> GetNodes() const; + [[nodiscard]] Nodes GetNodes() const; [[nodiscard]] size_t GetNodesSize() const; - [[nodiscard]] std::shared_ptr GetNode(uint64_t id) const; + [[nodiscard]] Node GetNode(uint64_t id) const; - [[nodiscard]] std::vector> GetWays() const; + [[nodiscard]] Ways GetWays() const; [[nodiscard]] size_t GetWaysSize() const; - [[nodiscard]] std::shared_ptr GetWay(uint64_t id) const; + [[nodiscard]] Way GetWay(uint64_t id) const; - [[nodiscard]] std::vector> GetRelations() const; + [[nodiscard]] Relations GetRelations() const; [[nodiscard]] size_t GetRelationsSize() const; - [[nodiscard]] std::shared_ptr GetRelation(uint64_t id) const; + [[nodiscard]] Relation GetRelation(uint64_t id) const; public: const std::string version; @@ -37,8 +33,8 @@ namespace osmp Bounds bounds; private: - std::map> nodes; - std::map> ways; - std::map> relations; + std::map nodes; + std::map ways; + std::map relations; }; } \ No newline at end of file diff --git a/lib/osmparser/include/osmrelation.hpp b/lib/osmparser/include/osmrelation.hpp index f489ea8..e270a31 100644 --- a/lib/osmparser/include/osmrelation.hpp +++ b/lib/osmparser/include/osmrelation.hpp @@ -9,35 +9,50 @@ namespace osmp { 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 MemberNodes; + typedef std::vector MemberWays; + + class IRelation : public IMember { public: - typedef struct sMember { - std::shared_ptr member; - std::string role; - } Member; + IRelation(const IRelation& other) = delete; + IRelation(const IRelation&& other) = delete; + virtual ~IRelation() {} - public: - Relation(const tinyxml2::XMLElement* xml, Object* parent); + friend Relation CreateRelation(const tinyxml2::XMLElement* xml, Object* parent); - [[nodiscard]] std::string GetRelationType(); + [[nodiscard]] std::string GetRelationType() const; - [[nodiscard]] const std::vector& GetNodes() const; + [[nodiscard]] const MemberNodes& GetNodes() 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& GetWays() const; + [[nodiscard]] const MemberWays& GetWays() 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; } + protected: + IRelation(const tinyxml2::XMLElement* xml, Object* parent); + private: std::string relationType; bool hasNullMembers; - std::vector nodes; - std::vector ways; + MemberNodes nodes; + MemberWays ways; }; } \ No newline at end of file diff --git a/lib/osmparser/include/osmtag.hpp b/lib/osmparser/include/osmtag.hpp index a4e1f22..cdfb098 100644 --- a/lib/osmparser/include/osmtag.hpp +++ b/lib/osmparser/include/osmtag.hpp @@ -33,4 +33,6 @@ namespace osmp std::string k; // TODO: Should/could be an enum std::string v; } Tag; + + typedef std::vector TagList; } diff --git a/lib/osmparser/include/osmway.hpp b/lib/osmparser/include/osmway.hpp index 634a758..66110f5 100644 --- a/lib/osmparser/include/osmway.hpp +++ b/lib/osmparser/include/osmway.hpp @@ -9,21 +9,27 @@ namespace osmp { class Object; - class Node; - class Way : public IMember + class IWay : public IMember { 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>& GetNodes() const; + friend Way CreateWay(const tinyxml2::XMLElement* way_elem, Object* parent); + + [[nodiscard]] const Nodes& GetNodes() const; [[nodiscard]] size_t GetNodesSize() const; - [[nodiscard]] const std::shared_ptr& GetNode(size_t index) const; + [[nodiscard]] Node GetNode(size_t index) const; + + protected: + IWay(const tinyxml2::XMLElement* way_elem, Object* parent); public: bool area, closed; // Closed := Startpoint = endpoint, Area := Closed AND certain conditions are not met private: - std::vector> nodes; + Nodes nodes; }; } \ No newline at end of file diff --git a/lib/osmparser/include/util.hpp b/lib/osmparser/include/util.hpp index 2482127..bfcb169 100644 --- a/lib/osmparser/include/util.hpp +++ b/lib/osmparser/include/util.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include namespace tinyxml2 { @@ -9,6 +11,18 @@ namespace tinyxml2 namespace osmp { + class INode; + class IWay; + class IRelation; + + typedef std::shared_ptr Node; + typedef std::shared_ptr Way; + typedef std::shared_ptr Relation; + + typedef std::vector Nodes; + typedef std::vector Ways; + typedef std::vector Relations; + typedef struct sBounds { double minlat, minlon, maxlat, maxlon; diff --git a/lib/osmparser/src/osmnode.cpp b/lib/osmparser/src/osmnode.cpp index 41a0efa..3770645 100644 --- a/lib/osmparser/src/osmnode.cpp +++ b/lib/osmparser/src/osmnode.cpp @@ -6,11 +6,25 @@ namespace xml = tinyxml2; 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) { // Get Attribute lat = GetSafeAttributeFloat(node_elem, "lat"); 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(node_elem, parent); + } } \ No newline at end of file diff --git a/lib/osmparser/src/osmobject.cpp b/lib/osmparser/src/osmobject.cpp index fca53bb..45e0db8 100644 --- a/lib/osmparser/src/osmobject.cpp +++ b/lib/osmparser/src/osmobject.cpp @@ -39,7 +39,7 @@ namespace osmp xml::XMLElement* node_elem = root->FirstChildElement("node"); while (node_elem != nullptr) { - std::shared_ptr new_node = std::make_shared(node_elem, this); + Node new_node = CreateNode(node_elem, this); nodes.insert(std::make_pair(new_node->id, new_node)); node_elem = node_elem->NextSiblingElement("node"); @@ -49,7 +49,7 @@ namespace osmp xml::XMLElement* way_elem = root->FirstChildElement("way"); while (way_elem != nullptr) { - std::shared_ptr new_way = std::make_shared(way_elem, this); + Way new_way = CreateWay(way_elem, this); ways.insert(std::make_pair(new_way->id, new_way)); way_elem = way_elem->NextSiblingElement("way"); @@ -59,7 +59,7 @@ namespace osmp xml::XMLElement* relation_elem = root->FirstChildElement("relation"); while (relation_elem != nullptr) { - std::shared_ptr new_way = std::make_shared(relation_elem, this); + Relation new_way = CreateRelation(relation_elem, this); relations.insert(std::make_pair(new_way->id, new_way)); relation_elem = relation_elem->NextSiblingElement("relation"); @@ -71,10 +71,10 @@ namespace osmp } - std::vector> Object::GetNodes() const + Nodes Object::GetNodes() const { - std::vector> vecNodes; - for (std::map>::const_iterator it = nodes.begin(); it != nodes.end(); it++) + Nodes vecNodes; + for (std::map::const_iterator it = nodes.begin(); it != nodes.end(); it++) vecNodes.push_back(it->second); return vecNodes; @@ -85,19 +85,19 @@ namespace osmp return nodes.size(); } - std::shared_ptr Object::GetNode(uint64_t id) const + Node Object::GetNode(uint64_t id) const { - std::map>::const_iterator node = nodes.find(id); + std::map::const_iterator node = nodes.find(id); if (node != nodes.end()) return node->second; return nullptr; } - std::vector> Object::GetWays() const + Ways Object::GetWays() const { - std::vector> vecWays; - for (std::map>::const_iterator it = ways.begin(); it != ways.end(); it++) + Ways vecWays; + for (std::map::const_iterator it = ways.begin(); it != ways.end(); it++) vecWays.push_back(it->second); return vecWays; @@ -108,19 +108,19 @@ namespace osmp return ways.size(); } - std::shared_ptr Object::GetWay(uint64_t id) const + Way Object::GetWay(uint64_t id) const { - std::map>::const_iterator way = ways.find(id); + std::map::const_iterator way = ways.find(id); if (way != ways.end()) return way->second; return nullptr; } - std::vector> Object::GetRelations() const + Relations Object::GetRelations() const { - std::vector> vecRelations; - for (std::map>::const_iterator it = relations.begin(); it != relations.end(); it++) + Relations vecRelations; + for (std::map::const_iterator it = relations.begin(); it != relations.end(); it++) vecRelations.push_back(it->second); return vecRelations; @@ -131,9 +131,9 @@ namespace osmp return relations.size(); } - std::shared_ptr Object::GetRelation(uint64_t id) const + Relation Object::GetRelation(uint64_t id) const { - std::map>::const_iterator relation = relations.find(id); + std::map::const_iterator relation = relations.find(id); if (relation != relations.end()) return relation->second; diff --git a/lib/osmparser/src/osmrelation.cpp b/lib/osmparser/src/osmrelation.cpp index 87320e7..0e8f7c0 100644 --- a/lib/osmparser/src/osmrelation.cpp +++ b/lib/osmparser/src/osmrelation.cpp @@ -1,3 +1,4 @@ +#include "..\include\osmrelation.hpp" #include #include @@ -11,7 +12,7 @@ namespace xml = tinyxml2; 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) { const xml::XMLElement* member_element = xml->FirstChildElement("member"); @@ -21,54 +22,66 @@ namespace osmp uint64_t ref = GetSafeAttributeUint64(member_element, "ref"); std::string role = GetSafeAttributeString(member_element, "role"); - std::shared_ptr member = nullptr; if (memberType == "node") { - member = parent->GetNode(ref); - nodes.push_back({ member, role }); + Node node = parent->GetNode(ref); + nodes.push_back({ node, role }); } else if (memberType == "way") { - member = parent->GetWay(ref); - if (member == nullptr) { + Way way = parent->GetWay(ref); + if (way == nullptr) { hasNullMembers = true; } - ways.push_back({ member, role }); + ways.push_back({ way, role }); } 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(xml, parent); + } + + std::string IRelation::GetRelationType() const { return GetTag("type"); } - const std::vector& Relation::GetNodes() const + const MemberNodes& IRelation::GetNodes() const { return nodes; } - size_t Relation::GetNodesSize() const + size_t IRelation::GetNodesSize() const { return nodes.size(); } - const Relation::Member& Relation::GetNode(size_t index) const + const MemberNode& IRelation::GetNode(size_t index) const { return nodes[index]; } - const std::vector& Relation::GetWays() const + const MemberWays& IRelation::GetWays() const { return ways; } - size_t Relation::GetWaysSize() const + size_t IRelation::GetWaysSize() const { return ways.size(); } - const Relation::Member& Relation::GetWay(size_t index) const + const MemberWay& IRelation::GetWay(size_t index) const { return ways[index]; } diff --git a/lib/osmparser/src/osmway.cpp b/lib/osmparser/src/osmway.cpp index 524d9f6..0325966 100644 --- a/lib/osmparser/src/osmway.cpp +++ b/lib/osmparser/src/osmway.cpp @@ -10,7 +10,7 @@ namespace xml = tinyxml2; 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) { area = GetSafeAttributeBool(way_elem, "area"); @@ -35,17 +35,30 @@ namespace osmp } } - const std::vector>& 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(way_elem, parent); + } + + const Nodes& IWay::GetNodes() const { return nodes; } - size_t Way::GetNodesSize() const + size_t IWay::GetNodesSize() const { return nodes.size(); } - const std::shared_ptr& Way::GetNode(size_t index) const + Node IWay::GetNode(size_t index) const { return nodes[index]; } diff --git a/src/main.cpp b/src/main.cpp index 1dba678..db31917 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,14 +44,14 @@ int main(int argc, char** argv) int windowWidth = windowHeight * aspectRatio; // Fetch all the ways - std::vector> 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) std::vector buildings; std::vector highways; - for (std::shared_ptr way : ways) + for (osmp::Way way : ways) { - const std::vector>& nodes = way->GetNodes(); + const osmp::Nodes& nodes = way->GetNodes(); std::string highwayVal = way->GetTag("highway"); std::string railwayVal = way->GetTag("railway"); if (way->area) @@ -119,9 +119,9 @@ int main(int argc, char** argv) } // Fetch all relations - std::vector> relations = obj->GetRelations(); + osmp::Relations relations = obj->GetRelations(); std::vector multipolygons; - for (const std::shared_ptr& relation : relations) + for (const osmp::Relation& relation : relations) { if (relation->GetRelationType() == "multipolygon" && !relation->HasNullMembers()) { @@ -174,9 +174,9 @@ int main(int argc, char** argv) SDL_SetRenderDrawColor(renderer, 240, 240, 250, 255); SDL_RenderClear(renderer); - for (Multipolygon& multipolygon : multipolygons) { - multipolygon.Draw(renderer); - } + // for (Multipolygon& multipolygon : multipolygons) { + // multipolygon.Draw(renderer); + // } //for (Area& area : buildings) //{ diff --git a/src/multipolygon.cpp b/src/multipolygon.cpp index 460e0f6..6bcb6ca 100644 --- a/src/multipolygon.cpp +++ b/src/multipolygon.cpp @@ -19,7 +19,7 @@ struct TriangulationData { }; struct Ring { - std::vector members; + osmp::MemberWays ways; int ring; }; @@ -33,14 +33,14 @@ inline double Map(double A, double B, double a, double b, double x) bool SelfIntersecting(const Ring & ring) { struct Segment { - std::shared_ptr p1, p2; + osmp::Node p1, p2; }; // Get all segments std::vector segments; - for (const osmp::Relation::Member member : ring.members) + for (const osmp::MemberWay way : ring.ways) { - std::vector> nodes = std::dynamic_pointer_cast(member.member)->GetNodes(); + osmp::Nodes nodes = way.way->GetNodes(); for (auto it = nodes.begin(); it != nodes.end() - 1; it++) { segments.push_back({ @@ -78,13 +78,13 @@ bool SelfIntersecting(const Ring & ring) return false; } -Multipolygon::Multipolygon(const std::shared_ptr& 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) { if (relation->HasNullMembers()) return; - const std::vector& members = relation->GetWays(); + const osmp::MemberWays& members = relation->GetWays(); // Implement https://wiki.openstreetmap.org/wiki/Relation:multipolygon/Algorithm // Ring assignment @@ -97,7 +97,7 @@ Multipolygon::Multipolygon(const std::shared_ptr& relation, int rings.push_back({ {members[0]}, ringCount }); // 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])) {