#define _CRT_NO_VA_START_VALIDATION #include "map_drawer.h" #include "nlohmann/json.hpp" #include #include "shapefile.h" namespace map { template void drawProjectedMapGeoJson(std::vector shapeFiles, image::Image &map_image, T color[3], std::function(float, float, int, int)> projectionFunc, int maxLength) { 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") { std::vector>> all_coordinates = mapStruct["geometry"]["coordinates"].get>>>(); for (std::vector> coordinates : all_coordinates) { for (int i = 0; i < (int)coordinates.size() - 1; i++) { std::pair start = projectionFunc(coordinates[i].second, coordinates[i].first, map_image.height(), map_image.width()); std::pair end = projectionFunc(coordinates[i + 1].second, coordinates[i + 1].first, map_image.height(), map_image.width()); if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength) continue; if (start.first == -1 || end.first == -1) continue; map_image.draw_line(start.first, start.second, end.first, end.second, color); } { std::pair start = projectionFunc(coordinates[0].second, coordinates[0].first, map_image.height(), map_image.width()); std::pair end = projectionFunc(coordinates[coordinates.size() - 1].second, coordinates[coordinates.size() - 1].first, map_image.height(), map_image.width()); if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength) continue; 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") { std::vector>>> all_all_coordinates = mapStruct["geometry"]["coordinates"].get>>>>(); for (std::vector>> all_coordinates : all_all_coordinates) { for (std::vector> coordinates : all_coordinates) { for (int i = 0; i < (int)coordinates.size() - 1; i++) { std::pair start = projectionFunc(coordinates[i].second, coordinates[i].first, map_image.height(), map_image.width()); std::pair end = projectionFunc(coordinates[i + 1].second, coordinates[i + 1].first, map_image.height(), map_image.width()); if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength) continue; if (start.first == -1 || end.first == -1) continue; map_image.draw_line(start.first, start.second, end.first, end.second, color); } { std::pair start = projectionFunc(coordinates[0].second, coordinates[0].first, map_image.height(), map_image.width()); std::pair end = projectionFunc(coordinates[coordinates.size() - 1].second, coordinates[coordinates.size() - 1].first, map_image.height(), map_image.width()); if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength) continue; 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") { std::vector> coordinates = mapStruct["geometry"]["coordinates"].get>>(); for (int i = 0; i < (int)coordinates.size() - 1; i++) { std::pair start = projectionFunc(coordinates[i].second, coordinates[i].first, map_image.height(), map_image.width()); std::pair end = projectionFunc(coordinates[i + 1].second, coordinates[i + 1].first, map_image.height(), map_image.width()); if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength) continue; if (start.first == -1 || end.first == -1) continue; map_image.draw_line(start.first, start.second, end.first, end.second, color); } { std::pair start = projectionFunc(coordinates[0].second, coordinates[0].first, map_image.height(), map_image.width()); std::pair end = projectionFunc(coordinates[coordinates.size() - 1].second, coordinates[coordinates.size() - 1].first, map_image.height(), map_image.width()); if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength) continue; 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") { std::pair coordinates = mapStruct["geometry"]["coordinates"].get>(); std::pair cc = projectionFunc(coordinates.second, coordinates.first, map_image.height(), map_image.width()); if (cc.first == -1 || cc.first == -1) continue; map_image.draw_pixel(cc.first, cc.second, color); } } } } template void drawProjectedMapGeoJson(std::vector, image::Image &, uint8_t[3], std::function(float, float, int, int)>, int); template void drawProjectedMapGeoJson(std::vector, image::Image &, uint16_t[3], std::function(float, float, int, int)>, int); template void drawProjectedCapitalsGeoJson(std::vector shapeFiles, image::Image &map_image, T color[3], std::function(float, float, int, int)> projectionFunc, int font_size) { if (!map_image.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") continue; std::string geometryType = mapStruct["geometry"]["type"]; if (geometryType == "Point") { if (mapStruct["properties"]["featurecla"].get() == "Admin-0 capital") { std::pair coordinates = mapStruct["geometry"]["coordinates"].get>(); std::pair cc = projectionFunc(coordinates.second, coordinates.first, map_image.height(), map_image.width()); if (cc.first == -1 || cc.first == -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); map_image.draw_text(cc.first, cc.second + font_size*0.15, color, font_size, name); } } } } } template void drawProjectedCapitalsGeoJson(std::vector, image::Image &, uint8_t[3], std::function(float, float, int, int)>, int); template void drawProjectedCapitalsGeoJson(std::vector, image::Image &, uint16_t[3], std::function(float, float, int, int)>, int); template void drawProjectedCitiesGeoJson(std::vector shapeFiles, image::Image &map_image, T color[3], std::function(float, float, int, int)> projectionFunc, int font_size, int cities_type, int cities_scale_rank) { if (!map_image.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(); 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 coordinates = mapStruct["geometry"]["coordinates"].get>(); std::pair cc = projectionFunc(coordinates.second, coordinates.first, map_image.height(), map_image.width()); if (cc.first == -1 || cc.first == -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); map_image.draw_text(cc.first, cc.second + font_size*0.15, color, font_size, name); } } } } template void drawProjectedCitiesGeoJson(std::vector, image::Image &, uint8_t[3], std::function(float, float, int, int)>, int, int, int); template void drawProjectedCitiesGeoJson(std::vector, image::Image &, uint16_t[3], std::function(float, float, int, int)>, int, int, int); template void drawProjectedMapShapefile(std::vector shapeFiles, image::Image &map_image, T color[3], std::function(float, float, int, int)> projectionFunc, int maxLength) { for (std::string currentShapeFile : shapeFiles) { std::ifstream inputFile(currentShapeFile, std::ios::binary); shapefile::Shapefile shape_file(inputFile); std::function>)> polylineDraw = [color, maxLength, &map_image, &projectionFunc](std::vector> parts) { for (std::vector coordinates : parts) { for (int i = 0; i < (int)coordinates.size() - 1; i++) { std::pair start = projectionFunc(coordinates[i].y, coordinates[i].x, map_image.height(), map_image.width()); std::pair end = projectionFunc(coordinates[i + 1].y, coordinates[i + 1].x, map_image.height(), map_image.width()); if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength) continue; if (start.first == -1 || end.first == -1) continue; map_image.draw_line(start.first, start.second, end.first, end.second, color); } { std::pair start = projectionFunc(coordinates[0].y, coordinates[0].x, map_image.height(), map_image.width()); std::pair end = projectionFunc(coordinates[coordinates.size() - 1].y, coordinates[coordinates.size() - 1].x, map_image.height(), map_image.width()); if (sqrt(pow(start.first - end.first, 2) + pow(start.second - end.second, 2)) >= maxLength) continue; if (start.first == -1 || end.first == -1) continue; map_image.draw_line(start.first, start.second, end.first, end.second, color); } } }; std::function pointDraw = [color, &map_image, &projectionFunc](shapefile::point_t coordinates) { std::pair cc = projectionFunc(coordinates.y, coordinates.x, map_image.height(), map_image.width()); if (cc.first == -1 || cc.first == -1) return; map_image.draw_pixel(cc.first, cc.second, color); }; for (shapefile::PolyLineRecord polylineRecord : shape_file.polyline_records) polylineDraw(polylineRecord.parts_points); for (shapefile::PolygonRecord polygonRecord : shape_file.polygon_records) polylineDraw(polygonRecord.parts_points); for (shapefile::PointRecord pointRecord : shape_file.point_records) pointDraw(pointRecord.point); for (shapefile::MultiPointRecord multipointRecord : shape_file.multipoint_records) for (shapefile::point_t p : multipointRecord.points) pointDraw(p); } } template void drawProjectedMapShapefile(std::vector, image::Image &, uint8_t[3], std::function(float, float, int, int)>, int); template void drawProjectedMapShapefile(std::vector, image::Image &, uint16_t[3], std::function(float, float, int, int)>, int); template void drawProjectedLabels(std::vector labels, image::Image &image, T color[3], std::function(float, float, int, int)> projectionFunc, float ratio) { std::vector> font = image::make_font(50 * ratio); for (CustomLabel ¤tLabel : labels) { std::pair cc = projectionFunc(currentLabel.lat, currentLabel.lon, image.height(), image.width()); if (cc.first == -1 || cc.first == -1) continue; 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); image.draw_text(cc.first, cc.second + 20 * ratio, color, font, currentLabel.label); } } template void drawProjectedLabels(std::vector, image::Image &, uint8_t[3], std::function(float, float, int, int)>, float); template void drawProjectedLabels(std::vector, image::Image &, uint16_t[3], std::function(float, float, int, int)>, float); }