Finished triangulation
This commit is contained in:
parent
fe87e22b16
commit
bc373aa019
|
@ -40,4 +40,5 @@ add_custom_command(TARGET mapviewer POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/res/map.osm $<TARGET_FILE_DIR:mapviewer>
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/res/map.osm $<TARGET_FILE_DIR:mapviewer>
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/res/bigmap.osm $<TARGET_FILE_DIR:mapviewer>
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/res/bigmap.osm $<TARGET_FILE_DIR:mapviewer>
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/res/leipzig.osm $<TARGET_FILE_DIR:mapviewer>
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/res/leipzig.osm $<TARGET_FILE_DIR:mapviewer>
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/res/jp.osm $<TARGET_FILE_DIR:mapviewer>
|
||||||
)
|
)
|
|
@ -12,7 +12,12 @@ class Multipolygon
|
||||||
public:
|
public:
|
||||||
Multipolygon(const std::shared_ptr<osmp::Relation>& relation, int width, int height, osmp::Bounds bounds);
|
Multipolygon(const std::shared_ptr<osmp::Relation>& relation, int width, int height, osmp::Bounds bounds);
|
||||||
|
|
||||||
void Draw(SDL_Renderer* renderer, int r, int g, int b);
|
void SetColor(int r, int g, int b);
|
||||||
|
void Draw(SDL_Renderer* renderer);
|
||||||
|
|
||||||
|
bool operator < (const Multipolygon& other) const {
|
||||||
|
return (rendering < other.rendering);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
|
@ -21,7 +26,17 @@ private:
|
||||||
struct Polygon {
|
struct Polygon {
|
||||||
std::vector<Vertex> vertices;
|
std::vector<Vertex> vertices;
|
||||||
std::vector<int> indices;
|
std::vector<int> indices;
|
||||||
|
std::vector<int> segments;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Polygon> polygons;
|
std::vector<Polygon> polygons;
|
||||||
|
int r;
|
||||||
|
int g;
|
||||||
|
int b;
|
||||||
|
bool visible;
|
||||||
|
enum RenderType {
|
||||||
|
FILL,
|
||||||
|
OUTLINE,
|
||||||
|
INDOOR
|
||||||
|
} rendering;
|
||||||
};
|
};
|
73478
res/jp.osm
Normal file
73478
res/jp.osm
Normal file
File diff suppressed because it is too large
Load diff
|
@ -693432,10 +693432,6 @@
|
||||||
<tag k="natural" v="wood"/>
|
<tag k="natural" v="wood"/>
|
||||||
</way>
|
</way>
|
||||||
<way id="918469182" version="1" timestamp="2021-03-17T23:09:16Z" changeset="101217162" uid="548109" user="Rosalo">
|
<way id="918469182" version="1" timestamp="2021-03-17T23:09:16Z" changeset="101217162" uid="548109" user="Rosalo">
|
||||||
<nd ref="8530248522"/>
|
|
||||||
<nd ref="8530248523"/>
|
|
||||||
<nd ref="4894705783"/>
|
|
||||||
<nd ref="413317529"/>
|
|
||||||
<nd ref="1487713202"/>
|
<nd ref="1487713202"/>
|
||||||
<nd ref="8530244804"/>
|
<nd ref="8530244804"/>
|
||||||
<nd ref="413317528"/>
|
<nd ref="413317528"/>
|
||||||
|
|
131
src/main.cpp
131
src/main.cpp
|
@ -1,6 +1,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <osmp.hpp>
|
#include <osmp.hpp>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
@ -10,13 +11,6 @@
|
||||||
// Map values from one interval [A, B] to another [a, b]
|
// Map values from one interval [A, B] to another [a, b]
|
||||||
inline float Map(float A, float B, float a, float b, float x);
|
inline float Map(float A, float B, float a, float b, float x);
|
||||||
|
|
||||||
// A structure to hold a sequence of 2D points
|
|
||||||
typedef struct sRenderableWay
|
|
||||||
{
|
|
||||||
size_t length;
|
|
||||||
SDL_FPoint* points;
|
|
||||||
} RenderableWay;
|
|
||||||
|
|
||||||
typedef struct sArea
|
typedef struct sArea
|
||||||
{
|
{
|
||||||
size_t length;
|
size_t length;
|
||||||
|
@ -47,10 +41,8 @@ int main(int argc, char** argv)
|
||||||
std::vector<std::shared_ptr<osmp::Way>> ways = obj->GetWays();
|
std::vector<std::shared_ptr<osmp::Way>> 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<RenderableWay> rWays;
|
std::vector<Area> buildings;
|
||||||
std::vector<Area> areas;
|
|
||||||
std::vector<Highway> highways;
|
std::vector<Highway> highways;
|
||||||
std::vector<Highway> railways;
|
|
||||||
for (std::shared_ptr<osmp::Way> way : ways)
|
for (std::shared_ptr<osmp::Way> way : ways)
|
||||||
{
|
{
|
||||||
const std::vector<std::shared_ptr<osmp::Node>>& nodes = way->GetNodes();
|
const std::vector<std::shared_ptr<osmp::Node>>& nodes = way->GetNodes();
|
||||||
|
@ -58,72 +50,27 @@ int main(int argc, char** argv)
|
||||||
std::string railwayVal = way->GetTag("railway");
|
std::string railwayVal = way->GetTag("railway");
|
||||||
if (way->area)
|
if (way->area)
|
||||||
{
|
{
|
||||||
|
if (way->GetTag("building") == "")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Area area;
|
Area area;
|
||||||
area.length = nodes.size();
|
area.length = nodes.size();
|
||||||
area.x = new Sint16[area.length];
|
area.x = new Sint16[area.length];
|
||||||
area.y = new Sint16[area.length];
|
area.y = new Sint16[area.length];
|
||||||
|
|
||||||
|
area.r = 150;
|
||||||
|
area.g = 150;
|
||||||
|
area.b = 150;
|
||||||
|
|
||||||
for (int i = 0; i < area.length; i++)
|
for (int i = 0; i < area.length; i++)
|
||||||
{
|
{
|
||||||
area.x[i] = Map(bounds.minlon, bounds.maxlon, 0, windowWidth, nodes[i]->lon);
|
area.x[i] = Map(bounds.minlon, bounds.maxlon, 0, windowWidth, nodes[i]->lon);
|
||||||
area.y[i] = windowHeight - Map(bounds.minlat, bounds.maxlat, 0, windowHeight, nodes[i]->lat);
|
area.y[i] = windowHeight - Map(bounds.minlat, bounds.maxlat, 0, windowHeight, nodes[i]->lat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildings.push_back(area);
|
||||||
std::string tag = "";
|
|
||||||
tag = way->GetTag("building");
|
|
||||||
if (tag != "")
|
|
||||||
{
|
|
||||||
area.r = 100;
|
|
||||||
area.g = 100;
|
|
||||||
area.b = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
tag = way->GetTag("natural");
|
|
||||||
if (tag != "")
|
|
||||||
{
|
|
||||||
if (tag == "wood" || tag == "scrub" || tag == "heath") {
|
|
||||||
area.r = 47;
|
|
||||||
area.g = 157;
|
|
||||||
area.b = 0;
|
|
||||||
}
|
|
||||||
else if (tag == "water" || tag == "floodplain") {
|
|
||||||
area.r = 106;
|
|
||||||
area.g = 151;
|
|
||||||
area.b = 255;
|
|
||||||
}
|
|
||||||
else if (tag == "grassland" || tag == "grass") {
|
|
||||||
area.r = 143;
|
|
||||||
area.g = 255;
|
|
||||||
area.b = 106;
|
|
||||||
}
|
|
||||||
else if (tag == "sand") {
|
|
||||||
area.r = 244;
|
|
||||||
area.g = 255;
|
|
||||||
area.b = 106;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << "Unknown natural: " << tag << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tag = way->GetTag("water");
|
|
||||||
if (tag != "")
|
|
||||||
{
|
|
||||||
area.r = 106;
|
|
||||||
area.g = 151;
|
|
||||||
area.b = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
tag = way->GetTag("waterway");
|
|
||||||
if (tag != "")
|
|
||||||
{
|
|
||||||
area.r = 106;
|
|
||||||
area.g = 151;
|
|
||||||
area.b = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
areas.push_back(area);
|
|
||||||
}
|
}
|
||||||
else if (highwayVal != "")
|
else if (highwayVal != "")
|
||||||
{
|
{
|
||||||
|
@ -142,7 +89,8 @@ int main(int argc, char** argv)
|
||||||
else if (highwayVal == "primary") { highway.r = 252; highway.g = 206; highway.b = 144; }
|
else if (highwayVal == "primary") { highway.r = 252; highway.g = 206; highway.b = 144; }
|
||||||
else if (highwayVal == "secondary") { highway.r = 244; highway.g = 251; highway.b = 173; }
|
else if (highwayVal == "secondary") { highway.r = 244; highway.g = 251; highway.b = 173; }
|
||||||
else if (highwayVal == "tertiary") { highway.r = 244; highway.g = 244; highway.b = 250; }
|
else if (highwayVal == "tertiary") { highway.r = 244; highway.g = 244; highway.b = 250; }
|
||||||
else { highway.r = 244; highway.g = 244; highway.b = 250; }
|
else if (highwayVal == "footway") { highway.r = 233; highway.g = 140; highway.b = 124; }
|
||||||
|
else { highway.r = 15; highway.g = 15; highway.b = 20; }
|
||||||
|
|
||||||
highways.push_back(highway);
|
highways.push_back(highway);
|
||||||
}
|
}
|
||||||
|
@ -162,20 +110,6 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
highways.push_back(railway);
|
highways.push_back(railway);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
RenderableWay rWay;
|
|
||||||
rWay.length = nodes.size();
|
|
||||||
rWay.points = new SDL_FPoint[rWay.length];
|
|
||||||
|
|
||||||
for (int i = 0; i < rWay.length; i++)
|
|
||||||
{
|
|
||||||
rWay.points[i].x = Map(bounds.minlon, bounds.maxlon, 0, windowWidth, nodes[i]->lon);
|
|
||||||
rWay.points[i].y = windowHeight - Map(bounds.minlat, bounds.maxlat, 0, windowHeight, nodes[i]->lat);
|
|
||||||
}
|
|
||||||
|
|
||||||
rWays.push_back(rWay);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch all relations
|
// Fetch all relations
|
||||||
|
@ -190,8 +124,12 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::sort(multipolygons.begin(), multipolygons.end());
|
||||||
|
|
||||||
|
|
||||||
// Release map data
|
// Release map data
|
||||||
|
relations.clear();
|
||||||
|
ways.clear();
|
||||||
delete obj;
|
delete obj;
|
||||||
|
|
||||||
// Initiaize graphics API
|
// Initiaize graphics API
|
||||||
|
@ -230,39 +168,23 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 10, 255);
|
SDL_SetRenderDrawColor(renderer, 240, 240, 250, 255);
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
// Render the ways
|
|
||||||
/*
|
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 245, 245, 255);
|
|
||||||
for (RenderableWay& rWay : rWays)
|
|
||||||
{
|
|
||||||
SDL_RenderDrawLinesF(renderer, rWay.points, rWay.length);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (Area& area : areas)
|
for (Multipolygon& multipolygon : multipolygons) {
|
||||||
|
multipolygon.Draw(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Area& area : buildings)
|
||||||
{
|
{
|
||||||
filledPolygonRGBA(renderer, area.x, area.y, area.length, area.r, area.g, area.b, 255);
|
filledPolygonRGBA(renderer, area.x, area.y, area.length, area.r, area.g, area.b, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (Highway& highway : highways)
|
for (Highway& highway : highways)
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(renderer, highway.r, highway.g, highway.b, 255);
|
SDL_SetRenderDrawColor(renderer, highway.r, highway.g, highway.b, 255);
|
||||||
SDL_RenderDrawLinesF(renderer, highway.points, highway.length);
|
SDL_RenderDrawLinesF(renderer, highway.points, highway.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Highway& railway : railways)
|
|
||||||
{
|
|
||||||
SDL_SetRenderDrawColor(renderer, railway.r, railway.g, railway.b, 255);
|
|
||||||
SDL_RenderDrawLinesF(renderer, railway.points, railway.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Multipolygon& multipolygon : multipolygons) {
|
|
||||||
multipolygon.Draw(renderer, 255, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
|
@ -274,7 +196,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
for (Area& area : areas) {
|
for (Area& area : buildings) {
|
||||||
delete[] area.x;
|
delete[] area.x;
|
||||||
delete[] area.y;
|
delete[] area.y;
|
||||||
}
|
}
|
||||||
|
@ -282,9 +204,6 @@ int main(int argc, char** argv)
|
||||||
for (Highway& highway : highways)
|
for (Highway& highway : highways)
|
||||||
delete[] highway.points;
|
delete[] highway.points;
|
||||||
|
|
||||||
for (RenderableWay& rWay : rWays)
|
|
||||||
delete[] rWay.points;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "..\include\multipolygon.hpp"
|
#include "..\include\multipolygon.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <triangle.h>
|
#include <triangle.h>
|
||||||
#include <osmway.hpp>
|
#include <osmway.hpp>
|
||||||
|
@ -8,6 +9,8 @@
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL2_gfxPrimitives.h>
|
#include <SDL2_gfxPrimitives.h>
|
||||||
|
|
||||||
|
#define BREAKIF(x) if(relation->id == x) __debugbreak()
|
||||||
|
|
||||||
struct TriangulationData {
|
struct TriangulationData {
|
||||||
std::vector<REAL> vertices, holes;
|
std::vector<REAL> vertices, holes;
|
||||||
std::vector<int> segments;
|
std::vector<int> segments;
|
||||||
|
@ -19,119 +22,172 @@ inline double Map(double A, double B, double a, double b, double x)
|
||||||
return (x - A) * (b - a) / (B - A) + a;
|
return (x - A) * (b - a) / (B - A) + a;
|
||||||
}
|
}
|
||||||
|
|
||||||
Multipolygon::Multipolygon(const std::shared_ptr<osmp::Relation>& relation, int width, int height, osmp::Bounds bounds)
|
Multipolygon::Multipolygon(const std::shared_ptr<osmp::Relation>& relation, int width, int height, osmp::Bounds bounds) :
|
||||||
|
r(255), g(0), b(255), visible(true), rendering(RenderType::FILL)
|
||||||
{
|
{
|
||||||
if (relation->HasNullMembers())
|
if (relation->HasNullMembers())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<TriangulationData> data;
|
std::vector<TriangulationData> data;
|
||||||
|
|
||||||
if (relation->id == 3363659) {
|
std::vector<osmp::Relation::Member> ways = relation->GetWays();
|
||||||
__debugbreak();
|
std::vector<std::shared_ptr<osmp::Node>> nodes;
|
||||||
|
int run = 1;
|
||||||
|
|
||||||
|
bool lastWasInner = false;
|
||||||
|
bool hasSeenOuter = false;
|
||||||
|
std::vector<std::vector<osmp::Relation::Member>> outerWays;
|
||||||
|
std::vector<std::vector<osmp::Relation::Member>> innerWays;
|
||||||
|
// Pre processing
|
||||||
|
for (osmp::Relation::Member member : ways) {
|
||||||
|
std::shared_ptr<osmp::Way> way = std::dynamic_pointer_cast<osmp::Way>(member.member);
|
||||||
|
if (member.role == "inner")
|
||||||
|
{
|
||||||
|
if (hasSeenOuter) // TODO: Find better way to sort things
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (innerWays.empty() || !lastWasInner)
|
||||||
|
innerWays.push_back({});
|
||||||
|
|
||||||
|
innerWays.back().push_back(member);
|
||||||
|
lastWasInner = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hasSeenOuter = true;
|
||||||
|
if (outerWays.empty() || lastWasInner)
|
||||||
|
outerWays.push_back({});
|
||||||
|
|
||||||
|
outerWays.back().push_back(member);
|
||||||
|
lastWasInner = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<osmp::Relation::Member>& ways = relation->GetWays();
|
if (outerWays.empty()) // There must always be an outer ring, anything else makes no sense
|
||||||
std::vector<std::shared_ptr<osmp::Node>> nodes;
|
return;
|
||||||
std::shared_ptr<osmp::Node> lastNode = nullptr;
|
|
||||||
std::shared_ptr<osmp::Way> nextNode = nullptr;
|
auto jt = outerWays.begin();
|
||||||
int run = 1;
|
bool currentIsInner = false;
|
||||||
int total = 0;
|
while (!outerWays.empty() || !innerWays.empty())
|
||||||
for (osmp::Relation::Member member : ways)
|
|
||||||
{
|
{
|
||||||
std::shared_ptr<osmp::Way> way = std::dynamic_pointer_cast<osmp::Way>(member.member);
|
std::vector<osmp::Relation::Member> member = *jt;
|
||||||
|
auto it = member.begin();
|
||||||
|
while (!member.empty())
|
||||||
|
{
|
||||||
|
if (it == member.end())
|
||||||
|
it = member.begin();
|
||||||
|
std::shared_ptr<osmp::Way> way = std::dynamic_pointer_cast<osmp::Way>(it->member);
|
||||||
|
|
||||||
// Several possible scenarios:
|
// Several possible scenarios:
|
||||||
// Closed way
|
// Closed way
|
||||||
// Outer edge
|
// Outer edge
|
||||||
// Append all nodes to the triangulation data
|
// Append all nodes to the triangulation data
|
||||||
// Inner edge
|
// Inner edge
|
||||||
// Append all nodes to the triangulation data
|
// Append all nodes to the triangulation data
|
||||||
// Calculate average of nodes to get coordinates of the hole
|
// Calculate average of nodes to get coordinates of the hole
|
||||||
//
|
//
|
||||||
// Open way
|
// Open way
|
||||||
// Read next way until way is closed. This MUST happen, if the way remains open the OSM data is faulty and should be discarded
|
// Read next way until way is closed. This MUST happen, if the way remains open the OSM data is faulty and should be discarded
|
||||||
// Continue with Closed way algorithm
|
// Continue with Closed way algorithm
|
||||||
|
|
||||||
bool inner = (member.role == "inner");
|
bool inner = (it->role == "inner");
|
||||||
std::vector<std::shared_ptr<osmp::Node>> wayNodes = way->GetNodes();
|
std::vector<std::shared_ptr<osmp::Node>> wayNodes = way->GetNodes();
|
||||||
|
|
||||||
if (run == 1) {
|
if (run == 1) {
|
||||||
nodes.insert(nodes.begin(), wayNodes.begin(), wayNodes.end());
|
nodes.insert(nodes.begin(), wayNodes.begin(), wayNodes.end());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (nodes.back() == wayNodes.front()) {
|
||||||
|
nodes.insert(nodes.end(), wayNodes.begin() + 1, wayNodes.end());
|
||||||
|
}
|
||||||
|
else if (nodes.back() == wayNodes.back()) {
|
||||||
|
nodes.insert(nodes.end(), wayNodes.rbegin() + 1, wayNodes.rend());
|
||||||
|
}
|
||||||
|
else if (nodes.front() == wayNodes.back()) {
|
||||||
|
nodes.insert(nodes.begin(), wayNodes.begin(), wayNodes.end() - 1);
|
||||||
|
}
|
||||||
|
else if (nodes.front() == wayNodes.front()) {
|
||||||
|
nodes.insert(nodes.begin(), wayNodes.rbegin(), wayNodes.rend() - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it = member.erase(it);
|
||||||
|
|
||||||
|
run++;
|
||||||
|
|
||||||
|
if (!(way->closed)) {
|
||||||
|
if (nodes.size() > 1 && nodes.front() == nodes.back())
|
||||||
|
{
|
||||||
|
// nodes.pop_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.pop_back();
|
||||||
|
|
||||||
|
if (!inner || data.empty())
|
||||||
|
{
|
||||||
|
data.push_back({});
|
||||||
|
}
|
||||||
|
TriangulationData& td = data.back();
|
||||||
|
|
||||||
|
// Push all vertices to data
|
||||||
|
std::vector<REAL> vertices;
|
||||||
|
for (const std::shared_ptr<osmp::Node>& node : nodes) {
|
||||||
|
vertices.push_back(Map(bounds.minlon, bounds.maxlon, 0, width, node->lon));
|
||||||
|
vertices.push_back(height - Map(bounds.minlat, bounds.maxlat, 0, height, node->lat));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inner)
|
||||||
|
{
|
||||||
|
// Calculate data of hole by using the average position of all inner vertices (that should work right?, probably not...)
|
||||||
|
REAL holeX = 0.0f;
|
||||||
|
REAL holeY = 0.0f;;
|
||||||
|
for (int i = 0; i < vertices.size(); i += 2)
|
||||||
|
{
|
||||||
|
holeX += vertices[i];
|
||||||
|
holeY += vertices[i + 1];
|
||||||
|
}
|
||||||
|
holeX /= (vertices.size() / 2);
|
||||||
|
holeY /= (vertices.size() / 2);
|
||||||
|
|
||||||
|
td.holes.push_back(holeX);
|
||||||
|
td.holes.push_back(holeY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get segments
|
||||||
|
int segNum = td.vertices.size() / 2;
|
||||||
|
for (int i = 0; i < vertices.size(); i += 2) {
|
||||||
|
td.segments.push_back(segNum);
|
||||||
|
td.segments.push_back(++segNum);
|
||||||
|
}
|
||||||
|
td.segments.back() = td.vertices.size() / 2;
|
||||||
|
|
||||||
|
td.vertices.insert(td.vertices.end(), vertices.begin(), vertices.end());
|
||||||
|
nodes.clear();
|
||||||
|
run = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentIsInner) {
|
||||||
|
innerWays.erase(innerWays.begin());
|
||||||
|
jt = outerWays.begin();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (nodes.back() == wayNodes.front()) {
|
outerWays.erase(outerWays.begin());
|
||||||
nodes.insert(nodes.end(), wayNodes.begin() + 1, wayNodes.end());
|
jt = innerWays.begin();
|
||||||
}
|
|
||||||
else if (nodes.back() == wayNodes.back()) {
|
|
||||||
nodes.insert(nodes.end(), wayNodes.rbegin() + 1, wayNodes.rend());
|
|
||||||
}
|
|
||||||
else if (nodes.front() == wayNodes.back()) {
|
|
||||||
nodes.insert(nodes.begin(), wayNodes.begin(), wayNodes.end() - 1);
|
|
||||||
}
|
|
||||||
else /*if (nodes.front() == wayNodes.front())*/ {
|
|
||||||
nodes.insert(nodes.begin(), wayNodes.rbegin(), wayNodes.rend() - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run++;
|
currentIsInner = !currentIsInner;
|
||||||
|
|
||||||
if (!(way->closed)) {
|
|
||||||
if (nodes.size() > 1 && nodes.front() == nodes.back())
|
|
||||||
{
|
|
||||||
// nodes.pop_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodes.pop_back();
|
|
||||||
|
|
||||||
if (!inner || data.empty())
|
|
||||||
{
|
|
||||||
data.push_back({});
|
|
||||||
}
|
|
||||||
TriangulationData& td = data.back();
|
|
||||||
|
|
||||||
// Push all vertices to data
|
|
||||||
std::vector<REAL> vertices;
|
|
||||||
for (const std::shared_ptr<osmp::Node>& node : nodes) {
|
|
||||||
vertices.push_back(Map(bounds.minlon, bounds.maxlon, 0, width, node->lon));
|
|
||||||
vertices.push_back(height - Map(bounds.minlat, bounds.maxlat, 0, height, node->lat));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inner)
|
|
||||||
{
|
|
||||||
// Calculate data of hole by using the average position of all inner vertices (that should work right?, probably not...)
|
|
||||||
REAL holeX = 0.0f;
|
|
||||||
REAL holeY = 0.0f;;
|
|
||||||
for (int i = 0; i < vertices.size(); i += 2)
|
|
||||||
{
|
|
||||||
holeX += vertices[i];
|
|
||||||
holeY += vertices[i + 1];
|
|
||||||
}
|
|
||||||
holeX /= (vertices.size() / 2);
|
|
||||||
holeY /= (vertices.size() / 2);
|
|
||||||
|
|
||||||
td.holes.push_back(holeX);
|
|
||||||
td.holes.push_back(holeY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get segments
|
|
||||||
int segNum = td.vertices.size() / 2;
|
|
||||||
for (int i = 0; i < vertices.size(); i += 2) {
|
|
||||||
td.segments.push_back(segNum);
|
|
||||||
td.segments.push_back(++segNum);
|
|
||||||
}
|
|
||||||
td.segments.back() = td.vertices.size() / 2;
|
|
||||||
|
|
||||||
td.vertices.insert(td.vertices.end(), vertices.begin(), vertices.end());
|
|
||||||
nodes.clear();
|
|
||||||
lastNode = nullptr;
|
|
||||||
run = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* triswitches = "zpNBV";
|
char* triswitches = "zpNBQ";
|
||||||
for (TriangulationData& td : data)
|
for (TriangulationData& td : data)
|
||||||
{
|
{
|
||||||
triangulateio in;
|
triangulateio in;
|
||||||
|
@ -159,6 +215,7 @@ Multipolygon::Multipolygon(const std::shared_ptr<osmp::Relation>& relation, int
|
||||||
out.trianglelist = NULL;
|
out.trianglelist = NULL;
|
||||||
out.segmentlist = NULL;
|
out.segmentlist = NULL;
|
||||||
out.segmentmarkerlist = NULL;
|
out.segmentmarkerlist = NULL;
|
||||||
|
|
||||||
triangulate(triswitches, &in, &out, NULL);
|
triangulate(triswitches, &in, &out, NULL);
|
||||||
|
|
||||||
// TODO: memory leak go brrrr
|
// TODO: memory leak go brrrr
|
||||||
|
@ -170,20 +227,451 @@ Multipolygon::Multipolygon(const std::shared_ptr<osmp::Relation>& relation, int
|
||||||
for (int i = 0; i < out.numberoftriangles * 3; i++) {
|
for (int i = 0; i < out.numberoftriangles * 3; i++) {
|
||||||
polygons.back().indices.push_back(out.trianglelist[i]);
|
polygons.back().indices.push_back(out.trianglelist[i]);
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < in.numberofsegments * 2; i++) {
|
||||||
|
polygons.back().segments.push_back(in.segmentlist[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
trifree(out.trianglelist);
|
||||||
|
trifree(out.segmentlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Make a color map
|
||||||
|
|
||||||
|
std::string tag = "";
|
||||||
|
tag = relation->GetTag("indoor");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
rendering = RenderType::INDOOR;
|
||||||
|
r = 150;
|
||||||
|
g = 150;
|
||||||
|
b = 150;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("building");
|
||||||
|
if (tag != "" || relation->GetTag("building:colour") != "" || relation->GetTag("building:material") != "" || relation->GetTag("building:part") != "")
|
||||||
|
{
|
||||||
|
r = 150;
|
||||||
|
g = 150;
|
||||||
|
b = 150;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("natural");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "wood") {
|
||||||
|
r = 157;
|
||||||
|
g = 202;
|
||||||
|
b = 138;
|
||||||
|
}
|
||||||
|
else if (tag == "scrub") {
|
||||||
|
r = 200;
|
||||||
|
g = 215;
|
||||||
|
b = 171;
|
||||||
|
}
|
||||||
|
else if (tag == "heath") {
|
||||||
|
r = 214;
|
||||||
|
g = 217;
|
||||||
|
b = 159;
|
||||||
|
}
|
||||||
|
else if (tag == "water") {
|
||||||
|
r = 166;
|
||||||
|
g = 198;
|
||||||
|
b = 198;
|
||||||
|
}
|
||||||
|
else if (tag == "grassland") {
|
||||||
|
r = 205;
|
||||||
|
g = 235;
|
||||||
|
b = 176;
|
||||||
|
}
|
||||||
|
else if (tag == "floodplain") {
|
||||||
|
r = 174;
|
||||||
|
g = 236;
|
||||||
|
b = 190;
|
||||||
|
}
|
||||||
|
else if (tag == "sand") {
|
||||||
|
r = 234;
|
||||||
|
g = 222;
|
||||||
|
b = 189;
|
||||||
|
}
|
||||||
|
else if (tag == "scree") {
|
||||||
|
r = 237;
|
||||||
|
g = 228;
|
||||||
|
b = 220;
|
||||||
|
}
|
||||||
|
else if (tag == "bare_rock") {
|
||||||
|
r = 213;
|
||||||
|
g = 209;
|
||||||
|
b = 204;
|
||||||
|
}
|
||||||
|
else if (tag == "tree_row") {
|
||||||
|
r = 169;
|
||||||
|
g = 206;
|
||||||
|
b = 161;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("water");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
r = 106;
|
||||||
|
g = 151;
|
||||||
|
b = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("waterway");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
r = 106;
|
||||||
|
g = 151;
|
||||||
|
b = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("landuse");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "grass")
|
||||||
|
{
|
||||||
|
r = 207;
|
||||||
|
g = 237;
|
||||||
|
b = 165;
|
||||||
|
}
|
||||||
|
else if (tag == "commercial")
|
||||||
|
{
|
||||||
|
r = 238;
|
||||||
|
g = 205;
|
||||||
|
b = 205;
|
||||||
|
}
|
||||||
|
else if (tag == "residential")
|
||||||
|
{
|
||||||
|
r = 218;
|
||||||
|
g = 218;
|
||||||
|
b = 218;
|
||||||
|
}
|
||||||
|
else if (tag == "forest")
|
||||||
|
{
|
||||||
|
r = 157;
|
||||||
|
g = 202;
|
||||||
|
b = 138;
|
||||||
|
}
|
||||||
|
else if (tag == "basin")
|
||||||
|
{
|
||||||
|
r = 170;
|
||||||
|
g = 211;
|
||||||
|
b = 223;
|
||||||
|
}
|
||||||
|
else if (tag == "allotments")
|
||||||
|
{
|
||||||
|
r = 201;
|
||||||
|
g = 225;
|
||||||
|
b = 191;
|
||||||
|
}
|
||||||
|
else if (tag == "railway")
|
||||||
|
{
|
||||||
|
r = 230;
|
||||||
|
g = 209;
|
||||||
|
b = 227;
|
||||||
|
}
|
||||||
|
else if (tag == "construction")
|
||||||
|
{
|
||||||
|
r = 199;
|
||||||
|
g = 199;
|
||||||
|
b = 180;
|
||||||
|
}
|
||||||
|
else if (tag == "retail")
|
||||||
|
{
|
||||||
|
r = 254;
|
||||||
|
g = 202;
|
||||||
|
b = 197;
|
||||||
|
}
|
||||||
|
else if (tag == "village_green")
|
||||||
|
{
|
||||||
|
r = 205;
|
||||||
|
g = 235;
|
||||||
|
b = 176;
|
||||||
|
}
|
||||||
|
else if (tag == "meadow")
|
||||||
|
{
|
||||||
|
r = 205;
|
||||||
|
g = 236;
|
||||||
|
b = 176;
|
||||||
|
}
|
||||||
|
else if (tag == "cemetery")
|
||||||
|
{
|
||||||
|
r = 170;
|
||||||
|
g = 203;
|
||||||
|
b = 175;
|
||||||
|
}
|
||||||
|
else if (tag == "brownfield") {
|
||||||
|
r = 167;
|
||||||
|
g = 168;
|
||||||
|
b = 126;
|
||||||
|
}
|
||||||
|
else if (tag == "recreation_ground") {
|
||||||
|
r = 223;
|
||||||
|
g = 252;
|
||||||
|
b = 226;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("leisure");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "park")
|
||||||
|
{
|
||||||
|
r = 205;
|
||||||
|
g = 247;
|
||||||
|
b = 201;
|
||||||
|
}
|
||||||
|
else if (tag == "garden")
|
||||||
|
{
|
||||||
|
r = 205;
|
||||||
|
g = 235;
|
||||||
|
b = 176;
|
||||||
|
}
|
||||||
|
else if (tag == "pitch")
|
||||||
|
{
|
||||||
|
r = 170;
|
||||||
|
g = 224;
|
||||||
|
b = 203;
|
||||||
|
}
|
||||||
|
else if (tag == "sports_centre")
|
||||||
|
{
|
||||||
|
r = 223;
|
||||||
|
g = 252;
|
||||||
|
b = 226;
|
||||||
|
}
|
||||||
|
else if (tag == "track")
|
||||||
|
{
|
||||||
|
r = 170;
|
||||||
|
g = 224;
|
||||||
|
b = 203;
|
||||||
|
}
|
||||||
|
else if (tag == "slipway")
|
||||||
|
{
|
||||||
|
r = 0;
|
||||||
|
g = 146;
|
||||||
|
b = 218;
|
||||||
|
}
|
||||||
|
else if (tag == "playground")
|
||||||
|
{
|
||||||
|
r = 223;
|
||||||
|
g = 252;
|
||||||
|
b = 226;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("tourism");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "zoo") {
|
||||||
|
rendering = RenderType::OUTLINE;
|
||||||
|
r = 147;
|
||||||
|
g = 84;
|
||||||
|
b = 115;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("man_made");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "bridge") {
|
||||||
|
r = 184;
|
||||||
|
g = 184;
|
||||||
|
b = 184;
|
||||||
|
}
|
||||||
|
else if (tag == "wastewater_plant") {
|
||||||
|
r = 230;
|
||||||
|
g = 209;
|
||||||
|
b = 227;
|
||||||
|
}
|
||||||
|
else if (tag == "pier") {
|
||||||
|
r = 250;
|
||||||
|
g = 250;
|
||||||
|
b = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("amenity");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "parking" || tag == "bicycle_parking") {
|
||||||
|
r = 100;
|
||||||
|
g = 100;
|
||||||
|
b = 120;
|
||||||
|
}
|
||||||
|
else if (tag == "school" || tag == "university" || tag == "kindergarten") {
|
||||||
|
r = 255;
|
||||||
|
g = 255;
|
||||||
|
b = 229;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("place");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
r = 180;
|
||||||
|
g = 180;
|
||||||
|
b = 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("public_transport");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "platform")
|
||||||
|
{
|
||||||
|
r = 180;
|
||||||
|
g = 180;
|
||||||
|
b = 190;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("highway");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "pedestrian")
|
||||||
|
{
|
||||||
|
r = 213;
|
||||||
|
g = 212;
|
||||||
|
b = 227;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("area:highway");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "primary")
|
||||||
|
{
|
||||||
|
r = 255;
|
||||||
|
g = 255;
|
||||||
|
b = 229;
|
||||||
|
}
|
||||||
|
else if (tag == "secondary")
|
||||||
|
{
|
||||||
|
r = 244;
|
||||||
|
g = 251;
|
||||||
|
b = 173;
|
||||||
|
}
|
||||||
|
else if (tag == "footway" || tag == "cycleway" || tag == "footway;cycleway") // TODO: Apparently you can list values??? check with the standard.
|
||||||
|
{
|
||||||
|
r = 233;
|
||||||
|
g = 140;
|
||||||
|
b = 124;
|
||||||
|
}
|
||||||
|
else if (tag == "emergency")
|
||||||
|
{
|
||||||
|
r = 250;
|
||||||
|
g = 250;
|
||||||
|
b = 255;
|
||||||
|
}
|
||||||
|
else if (tag == "unclassified" || tag == "emergency" || tag == "residential" || tag == "service" || tag == "traffic_island")
|
||||||
|
{
|
||||||
|
r = 15;
|
||||||
|
g = 15;
|
||||||
|
b = 20;
|
||||||
|
}
|
||||||
|
else if (tag == "bus") {
|
||||||
|
r = 150;
|
||||||
|
g = 150;
|
||||||
|
b = 150;
|
||||||
|
}
|
||||||
|
else if (tag == "reserved") { // TODO: Not a keyword I'm aware of
|
||||||
|
r = 0; g = 0; b = 0;
|
||||||
|
visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("area:railway");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
if (tag == "tram") {
|
||||||
|
r = 150;
|
||||||
|
g = 150;
|
||||||
|
b = 150;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("bridge:support");
|
||||||
|
if (tag != "")
|
||||||
|
{
|
||||||
|
r = 184;
|
||||||
|
g = 184;
|
||||||
|
b = 184;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = relation->GetTag("tunnel");
|
||||||
|
if (tag == "yes")
|
||||||
|
{
|
||||||
|
r = 240;
|
||||||
|
g = 240;
|
||||||
|
b = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == 255 && b == 255) {
|
||||||
|
std::cout << relation->id << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Multipolygon::Draw(SDL_Renderer* renderer, int r, int g, int b)
|
void Multipolygon::SetColor(int r, int g, int b)
|
||||||
{
|
{
|
||||||
|
this->r = r;
|
||||||
|
this->g = g;
|
||||||
|
this->b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Multipolygon::Draw(SDL_Renderer* renderer)
|
||||||
|
{
|
||||||
|
if (!visible)
|
||||||
|
return;
|
||||||
|
|
||||||
for (const Polygon& polygon : polygons) {
|
for (const Polygon& polygon : polygons) {
|
||||||
for (int i = 0; i < polygon.indices.size(); i += 3) // Be a graphics card
|
switch(rendering)
|
||||||
{
|
{
|
||||||
filledTrigonRGBA(renderer,
|
case RenderType::FILL:
|
||||||
polygon.vertices[polygon.indices[i + 0]].x, polygon.vertices[polygon.indices[i + 0]].y,
|
for (int i = 0; i < polygon.indices.size(); i += 3) // Be a graphics card
|
||||||
polygon.vertices[polygon.indices[i + 1]].x, polygon.vertices[polygon.indices[i + 1]].y,
|
{
|
||||||
polygon.vertices[polygon.indices[i + 2]].x, polygon.vertices[polygon.indices[i + 2]].y,
|
|
||||||
r, g, b, 255
|
filledTrigonRGBA(renderer,
|
||||||
|
polygon.vertices[polygon.indices[i + 0]].x, polygon.vertices[polygon.indices[i + 0]].y,
|
||||||
|
polygon.vertices[polygon.indices[i + 1]].x, polygon.vertices[polygon.indices[i + 1]].y,
|
||||||
|
polygon.vertices[polygon.indices[i + 2]].x, polygon.vertices[polygon.indices[i + 2]].y,
|
||||||
|
r, g, b, 255
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RenderType::OUTLINE:
|
||||||
|
for(int i = 0; i < polygon.segments.size(); i += 2)
|
||||||
|
{
|
||||||
|
thickLineRGBA(renderer,
|
||||||
|
polygon.vertices[polygon.segments[i + 0]].x, polygon.vertices[polygon.segments[i + 0]].y,
|
||||||
|
polygon.vertices[polygon.segments[i + 1]].x, polygon.vertices[polygon.segments[i + 1]].y,
|
||||||
|
5, r, g, b, 255
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RenderType::INDOOR:
|
||||||
|
for (int i = 0; i < polygon.indices.size(); i += 3) // Be a graphics card
|
||||||
|
{
|
||||||
|
|
||||||
|
filledTrigonRGBA(renderer,
|
||||||
|
polygon.vertices[polygon.indices[i + 0]].x, polygon.vertices[polygon.indices[i + 0]].y,
|
||||||
|
polygon.vertices[polygon.indices[i + 1]].x, polygon.vertices[polygon.indices[i + 1]].y,
|
||||||
|
polygon.vertices[polygon.indices[i + 2]].x, polygon.vertices[polygon.indices[i + 2]].y,
|
||||||
|
r, g, b, 255
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < polygon.segments.size(); i += 2)
|
||||||
|
{
|
||||||
|
lineRGBA(renderer,
|
||||||
|
polygon.vertices[polygon.segments[i + 0]].x, polygon.vertices[polygon.segments[i + 0]].y,
|
||||||
|
polygon.vertices[polygon.segments[i + 1]].x, polygon.vertices[polygon.segments[i + 1]].y,
|
||||||
|
10, 10, 15, 255
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue