2021-10-07 16:32:44 -07:00
|
|
|
#define _CRT_NO_VA_START_VALIDATION
|
2021-08-23 00:52:42 +02:00
|
|
|
#include "map_drawer.h"
|
|
|
|
|
#include "nlohmann/json.hpp"
|
|
|
|
|
#include <fstream>
|
2021-09-16 17:50:53 +02:00
|
|
|
#include "shapefile.h"
|
2021-08-23 00:52:42 +02:00
|
|
|
|
|
|
|
|
namespace map
|
|
|
|
|
{
|
2024-05-09 01:16:08 +02:00
|
|
|
void drawProjectedMapGeoJson(std::vector<std::string> shapeFiles, image::Image &map_image, std::vector<double> color, std::function<std::pair<int, int>(double, double, int, int)> projectionFunc, int maxLength)
|
2021-08-23 00:52:42 +02:00
|
|
|
{
|
|
|
|
|
for (std::string currentShapeFile : shapeFiles)
|
|
|
|
|
{
|
|
|
|
|
nlohmann::json shapeFile;
|
|
|
|
|
{
|
|
|
|
|
std::ifstream istream(currentShapeFile);
|
|
|
|
|
istream >> shapeFile;
|
|
|
|
|
istream.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const nlohmann::json &mapStruct : shapeFile.at("features"))
|
|
|
|
|
{
|
|
|
|
|
if (mapStruct["type"] != "Feature")
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
std::string geometryType = mapStruct["geometry"]["type"];
|
|
|
|
|
|
|
|
|
|
if (geometryType == "Polygon")
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::vector<std::vector<std::pair<double, double>>> all_coordinates = mapStruct["geometry"]["coordinates"].get<std::vector<std::vector<std::pair<double, double>>>>();
|
2021-08-23 00:52:42 +02:00
|
|
|
|
2024-02-24 22:38:54 +01:00
|
|
|
for (std::vector<std::pair<double, double>> coordinates : all_coordinates)
|
2021-08-23 00:52:42 +02:00
|
|
|
{
|
|
|
|
|
for (int i = 0; i < (int)coordinates.size() - 1; i++)
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> start = projectionFunc(coordinates[i].second, coordinates[i].first,
|
|
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
std::pair<double, double> end = projectionFunc(coordinates[i + 1].second, coordinates[i + 1].first,
|
2021-08-23 00:52:42 +02:00
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
|
2021-11-12 19:50:05 +01:00
|
|
|
if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength)
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-08-23 00:52:42 +02:00
|
|
|
if (start.first == -1 || end.first == -1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
map_image.draw_line(start.first, start.second, end.first, end.second, color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> start = projectionFunc(coordinates[0].second, coordinates[0].first,
|
|
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
std::pair<double, double> end = projectionFunc(coordinates[coordinates.size() - 1].second, coordinates[coordinates.size() - 1].first,
|
2021-08-23 00:52:42 +02:00
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
|
2021-11-12 19:50:05 +01:00
|
|
|
if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength)
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-08-23 00:52:42 +02:00
|
|
|
if (start.first == -1 || end.first == -1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
map_image.draw_line(start.first, start.second, end.first, end.second, color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (geometryType == "MultiPolygon")
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::vector<std::vector<std::vector<std::pair<double, double>>>> all_all_coordinates = mapStruct["geometry"]["coordinates"].get<std::vector<std::vector<std::vector<std::pair<double, double>>>>>();
|
2021-08-23 00:52:42 +02:00
|
|
|
|
2024-02-24 22:38:54 +01:00
|
|
|
for (std::vector<std::vector<std::pair<double, double>>> all_coordinates : all_all_coordinates)
|
2021-08-23 00:52:42 +02:00
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
for (std::vector<std::pair<double, double>> coordinates : all_coordinates)
|
2021-08-23 00:52:42 +02:00
|
|
|
{
|
|
|
|
|
for (int i = 0; i < (int)coordinates.size() - 1; i++)
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> start = projectionFunc(coordinates[i].second, coordinates[i].first,
|
|
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
std::pair<double, double> end = projectionFunc(coordinates[i + 1].second, coordinates[i + 1].first,
|
2021-08-23 00:52:42 +02:00
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
|
2021-11-12 19:50:05 +01:00
|
|
|
if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength)
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-08-23 00:52:42 +02:00
|
|
|
if (start.first == -1 || end.first == -1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
map_image.draw_line(start.first, start.second, end.first, end.second, color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> start = projectionFunc(coordinates[0].second, coordinates[0].first,
|
|
|
|
|
map_image.height(), map_image.width());
|
2021-08-23 00:52:42 +02:00
|
|
|
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> end = projectionFunc(coordinates[coordinates.size() - 1].second, coordinates[coordinates.size() - 1].first,
|
|
|
|
|
map_image.height(),
|
|
|
|
|
map_image.width());
|
2021-11-12 19:50:05 +01:00
|
|
|
if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength)
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-08-23 00:52:42 +02:00
|
|
|
if (start.first == -1 || end.first == -1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
map_image.draw_line(start.first, start.second, end.first, end.second, color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (geometryType == "LineString")
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::vector<std::pair<double, double>> coordinates = mapStruct["geometry"]["coordinates"].get<std::vector<std::pair<double, double>>>();
|
2021-08-23 00:52:42 +02:00
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)coordinates.size() - 1; i++)
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> start = projectionFunc(coordinates[i].second, coordinates[i].first,
|
|
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
std::pair<double, double> end = projectionFunc(coordinates[i + 1].second, coordinates[i + 1].first,
|
2021-08-23 00:52:42 +02:00
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
|
2021-11-12 19:50:05 +01:00
|
|
|
if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength)
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-08-23 00:52:42 +02:00
|
|
|
if (start.first == -1 || end.first == -1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
map_image.draw_line(start.first, start.second, end.first, end.second, color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> start = projectionFunc(coordinates[0].second, coordinates[0].first,
|
|
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
std::pair<double, double> end = projectionFunc(coordinates[coordinates.size() - 1].second, coordinates[coordinates.size() - 1].first,
|
2021-08-23 00:52:42 +02:00
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
|
2021-11-12 19:50:05 +01:00
|
|
|
if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength)
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-08-23 00:52:42 +02:00
|
|
|
if (start.first == -1 || end.first == -1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
map_image.draw_line(start.first, start.second, end.first, end.second, color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (geometryType == "Point")
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> coordinates = mapStruct["geometry"]["coordinates"].get<std::pair<double, double>>();
|
|
|
|
|
std::pair<double, double> cc = projectionFunc(coordinates.second, coordinates.first,
|
|
|
|
|
map_image.height(), map_image.width());
|
2021-08-23 00:52:42 +02:00
|
|
|
|
|
|
|
|
if (cc.first == -1 || cc.first == -1)
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-12-22 21:00:11 +01:00
|
|
|
map_image.draw_pixel(cc.first, cc.second, color);
|
2021-08-23 00:52:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 01:16:08 +02:00
|
|
|
void drawProjectedCitiesGeoJson(std::vector<std::string> shapeFiles, image::Image &map_image, image::TextDrawer &text_drawer, std::vector<double> color, std::function<std::pair<int, int>(double, double, int, int)> projectionFunc, int font_size, int cities_type, int cities_scale_rank)
|
2023-08-26 16:44:25 +07:00
|
|
|
{
|
2024-05-08 22:37:37 +02:00
|
|
|
if (!text_drawer.font_ready())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (std::string currentShapeFile : shapeFiles)
|
|
|
|
|
{
|
|
|
|
|
nlohmann::json shapeFile;
|
|
|
|
|
{
|
|
|
|
|
std::ifstream istream(currentShapeFile);
|
|
|
|
|
istream >> shapeFile;
|
|
|
|
|
istream.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const nlohmann::json &mapStruct : shapeFile.at("features"))
|
|
|
|
|
{
|
|
|
|
|
if (mapStruct["type"] != "Feature" || mapStruct["geometry"]["type"] != "Point")
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
std::string featurecla = mapStruct["properties"]["featurecla"].get<std::string>();
|
|
|
|
|
|
|
|
|
|
if ((cities_type == 0 && featurecla == "Admin-0 capital") || (cities_type == 1 && (featurecla == "Admin-1 capital" || featurecla == "Admin-0 capital")) || (cities_type == 2 && mapStruct["properties"]["scalerank"] <= cities_scale_rank))
|
|
|
|
|
{
|
|
|
|
|
std::pair<double, double> coordinates = mapStruct["geometry"]["coordinates"].get<std::pair<double, double>>();
|
|
|
|
|
std::pair<double, double> cc = projectionFunc(coordinates.second, coordinates.first,
|
|
|
|
|
map_image.height(), map_image.width());
|
|
|
|
|
|
|
|
|
|
if (cc.first == -1 || cc.second == -1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
map_image.draw_line(cc.first - font_size * 0.3, cc.second - font_size * 0.3, cc.first + font_size * 0.3, cc.second + font_size * 0.3, color);
|
|
|
|
|
map_image.draw_line(cc.first + font_size * 0.3, cc.second - font_size * 0.3, cc.first - font_size * 0.3, cc.second + font_size * 0.3, color);
|
|
|
|
|
map_image.draw_circle(cc.first, cc.second, 0.15 * font_size, color, true);
|
|
|
|
|
|
|
|
|
|
std::string name = mapStruct["properties"]["nameascii"];
|
|
|
|
|
// map_image.draw_text(cc.first, cc.second + 20 * ratio, color, font, name);
|
|
|
|
|
text_drawer.draw_text(map_image, cc.first, cc.second + font_size * 0.15, color, font_size, name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-26 16:44:25 +07:00
|
|
|
}
|
|
|
|
|
|
2024-05-09 01:16:08 +02:00
|
|
|
void drawProjectedMapShapefile(std::vector<std::string> shapeFiles, image::Image &map_image, std::vector<double> color, std::function<std::pair<int, int>(double, double, int, int)> projectionFunc)
|
2021-09-16 17:50:53 +02:00
|
|
|
{
|
|
|
|
|
for (std::string currentShapeFile : shapeFiles)
|
|
|
|
|
{
|
|
|
|
|
std::ifstream inputFile(currentShapeFile, std::ios::binary);
|
|
|
|
|
shapefile::Shapefile shape_file(inputFile);
|
|
|
|
|
|
2023-10-17 18:34:35 +02:00
|
|
|
std::function<void(std::vector<std::vector<shapefile::point_t>>)> polylineDraw = [color, &map_image, &projectionFunc](std::vector<std::vector<shapefile::point_t>> parts)
|
2021-09-16 17:50:53 +02:00
|
|
|
{
|
2024-03-17 23:46:09 -04:00
|
|
|
int width = map_image.width();
|
|
|
|
|
int height = map_image.height();
|
|
|
|
|
|
2021-09-16 17:50:53 +02:00
|
|
|
for (std::vector<shapefile::point_t> coordinates : parts)
|
|
|
|
|
{
|
2024-03-17 23:46:09 -04:00
|
|
|
std::pair<double, double> start = projectionFunc(coordinates[0].y, coordinates[0].x, height, width);
|
|
|
|
|
for (int i = 1; i < (int)coordinates.size() - 1; i++)
|
2021-09-16 17:50:53 +02:00
|
|
|
{
|
2024-03-17 23:46:09 -04:00
|
|
|
std::pair<double, double> end = projectionFunc(coordinates[i].y, coordinates[i].x, height, width);
|
|
|
|
|
if (start.first != -1 && start.second != -1 && end.first != -1 && end.second != -1)
|
|
|
|
|
map_image.draw_line(start.first, start.second, end.first, end.second, color);
|
2021-09-16 17:50:53 +02:00
|
|
|
|
2024-03-17 23:46:09 -04:00
|
|
|
start = end;
|
2021-09-16 17:50:53 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::function<void(shapefile::point_t)> pointDraw = [color, &map_image, &projectionFunc](shapefile::point_t coordinates)
|
|
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> cc = projectionFunc(coordinates.y, coordinates.x,
|
|
|
|
|
map_image.height(), map_image.width());
|
2021-09-16 17:50:53 +02:00
|
|
|
|
2024-02-28 16:54:33 +01:00
|
|
|
if (cc.first == -1 || cc.second == -1)
|
2021-09-16 17:50:53 +02:00
|
|
|
return;
|
|
|
|
|
|
2021-12-22 21:00:11 +01:00
|
|
|
map_image.draw_pixel(cc.first, cc.second, color);
|
2021-09-16 17:50:53 +02:00
|
|
|
};
|
|
|
|
|
|
2024-03-17 23:46:09 -04:00
|
|
|
for (shapefile::PolyLineRecord &polylineRecord : shape_file.polyline_records)
|
2021-09-16 17:50:53 +02:00
|
|
|
polylineDraw(polylineRecord.parts_points);
|
|
|
|
|
|
2024-03-17 23:46:09 -04:00
|
|
|
for (shapefile::PolygonRecord &polygonRecord : shape_file.polygon_records)
|
2021-09-16 17:50:53 +02:00
|
|
|
polylineDraw(polygonRecord.parts_points);
|
|
|
|
|
|
2024-03-17 23:46:09 -04:00
|
|
|
for (shapefile::PointRecord &pointRecord : shape_file.point_records)
|
2021-09-16 17:50:53 +02:00
|
|
|
pointDraw(pointRecord.point);
|
|
|
|
|
|
2024-03-17 23:46:09 -04:00
|
|
|
for (shapefile::MultiPointRecord &multipointRecord : shape_file.multipoint_records)
|
2021-09-16 17:50:53 +02:00
|
|
|
for (shapefile::point_t p : multipointRecord.points)
|
|
|
|
|
pointDraw(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 01:16:08 +02:00
|
|
|
void drawProjectedMapLatLonGrid(image::Image &image, std::vector<double> color, std::function<std::pair<int, int>(double, double, int, int)> projectionFunc)
|
2023-10-14 22:25:43 +02:00
|
|
|
{
|
|
|
|
|
for (float lon = -180; lon < 180; lon += 10)
|
|
|
|
|
{
|
|
|
|
|
float last_lat = -90;
|
2023-10-15 21:46:56 +02:00
|
|
|
for (float lat = -90; lat < 90; lat += 0.05)
|
2023-10-14 22:25:43 +02:00
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> start = projectionFunc(last_lat, lon,
|
|
|
|
|
image.height(), image.width());
|
|
|
|
|
std::pair<double, double> end = projectionFunc(lat, lon,
|
2023-10-14 22:25:43 +02:00
|
|
|
image.height(), image.width());
|
|
|
|
|
|
|
|
|
|
if (start.first != -1 && start.second != -1 && end.first != -1 && end.second != -1)
|
|
|
|
|
image.draw_line(start.first, start.second, end.first, end.second, color);
|
|
|
|
|
|
|
|
|
|
last_lat = lat;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (float lat = -90; lat < 90; lat += 10)
|
|
|
|
|
{
|
2023-10-18 14:20:08 +02:00
|
|
|
float last_lon = -180;
|
2023-10-15 21:46:56 +02:00
|
|
|
for (float lon = -180; lon < 180; lon += 0.05)
|
2023-10-14 22:25:43 +02:00
|
|
|
{
|
2024-02-24 22:38:54 +01:00
|
|
|
std::pair<double, double> start = projectionFunc(lat, last_lon,
|
|
|
|
|
image.height(), image.width());
|
|
|
|
|
std::pair<double, double> end = projectionFunc(lat, lon,
|
2023-10-14 22:25:43 +02:00
|
|
|
image.height(), image.width());
|
|
|
|
|
|
|
|
|
|
if (start.first != -1 && start.second != -1 && end.first != -1 && end.second != -1)
|
|
|
|
|
image.draw_line(start.first, start.second, end.first, end.second, color);
|
|
|
|
|
|
|
|
|
|
last_lon = lon;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 01:16:08 +02:00
|
|
|
/* void drawProjectedLabels(std::vector<CustomLabel> labels, image::Image &image, image::TextDrawer &text_drawer, std::vector<double> color, std::function<std::pair<int, int>(double, double, int, int)> projectionFunc, double ratio)
|
2024-05-08 22:37:37 +02:00
|
|
|
{
|
|
|
|
|
if (!text_drawer.font_ready())
|
|
|
|
|
return;
|
2021-12-22 21:00:11 +01:00
|
|
|
|
2024-05-08 22:37:37 +02:00
|
|
|
for (CustomLabel ¤tLabel : labels)
|
|
|
|
|
{
|
|
|
|
|
std::pair<double, double> cc = projectionFunc(currentLabel.lat, currentLabel.lon,
|
|
|
|
|
image.height(), image.width());
|
2021-11-03 16:47:52 +01:00
|
|
|
|
2024-05-08 22:37:37 +02:00
|
|
|
if (cc.first == -1 || cc.first == -1)
|
|
|
|
|
continue;
|
2021-11-03 16:47:52 +01:00
|
|
|
|
2024-05-08 22:37:37 +02:00
|
|
|
image.draw_line(cc.first - 20 * ratio, cc.second - 20 * ratio, cc.first + 20 * ratio, cc.second + 20 * ratio, color);
|
|
|
|
|
image.draw_line(cc.first + 20 * ratio, cc.second - 20 * ratio, cc.first - 20 * ratio, cc.second + 20 * ratio, color);
|
|
|
|
|
image.draw_circle(cc.first, cc.second, 10 * ratio, color, true);
|
2021-11-03 16:47:52 +01:00
|
|
|
|
2024-05-08 22:37:37 +02:00
|
|
|
text_drawer .draw_text(image,cc.first, cc.second + 20 * ratio, color, font, currentLabel.label);
|
|
|
|
|
//text_drawer.draw_text(map_image, cc.first, cc.second + font_size * 0.15, color, font_size, name);
|
|
|
|
|
}
|
|
|
|
|
} */
|
2021-08-23 00:52:42 +02:00
|
|
|
}
|