From a09bcc1ec86c748cf89e5ba8dfe0c67c71e4489e Mon Sep 17 00:00:00 2001 From: Saif Khan <2001559@sit.singaporetech.edu.sg> Date: Tue, 27 May 2025 10:01:20 +0800 Subject: [PATCH 1/9] Change to color all uncolored regions to gray if only some have colors --- .../belgium_population_by_region_2022.csv | 4 ++-- src/inset_state/auto_color.cpp | 23 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/sample_data/belgium_by_region_since_1995/belgium_population_by_region_2022.csv b/sample_data/belgium_by_region_since_1995/belgium_population_by_region_2022.csv index bb275034..5b876339 100644 --- a/sample_data/belgium_by_region_since_1995/belgium_population_by_region_2022.csv +++ b/sample_data/belgium_by_region_since_1995/belgium_population_by_region_2022.csv @@ -1,4 +1,4 @@ shapeName,Population (people),Color,Inset,Label -Brussels-Capital,1222637,#fbb4ae,, -Flanders,6698876,#b3cde3,, +Brussels-Capital,1222637,,, +Flanders,6698876,,, Wallonia,3662495,#ccebc5,, diff --git a/src/inset_state/auto_color.cpp b/src/inset_state/auto_color.cpp index 6a9558d5..4a559c15 100644 --- a/src/inset_state/auto_color.cpp +++ b/src/inset_state/auto_color.cpp @@ -11,18 +11,12 @@ void InsetState::auto_color() std::vector palette; if (colors_.size() > 0) { - // If some colors are already provided, use a different palette - // From https://colorbrewer2.org/#type=qualitative&scheme=Dark2&n=8 - std::cerr << "Some but not all colors provided, using Dark color palette." + // If some but not all of the GeoDivs are colored, use only #f2f2f2 (light + // gray) to color the rest + std::cerr << "Some but not all colors provided, assigning #f2f2f2 (light " + "grey) to uncolored GeoDivs." << std::endl; - palette.emplace_back("#1b9e77"); // aqua green - palette.emplace_back("#d95f02"); // dark orange - palette.emplace_back("#7570b3"); // purple - palette.emplace_back("#e7298a"); // dark pink - palette.emplace_back("#66a61e"); // olive green - palette.emplace_back("#e6ab02"); // dark yellow - palette.emplace_back("#a6761d"); // brown - palette.emplace_back("#666666"); // dark grey + palette.emplace_back("#f2f2f2"); // light gray } else { // Using default palette for now // TODO: Accept palette from user @@ -48,6 +42,13 @@ void InsetState::auto_color() if (color_found(gd.id())) continue; + // If there's only one color in palette, color the div with it without + // checking for color adjacency + if (palette.size() == 1) { + insert_color(gd.id(), palette[0]); + continue; + } + for (unsigned int i = 0; i < palette.size(); ++i) { const Color c = palette[i]; bool shared_color = false; From e95d26b2a729b8f44850e3ca4c15f700a9711f6b Mon Sep 17 00:00:00 2001 From: Saif Khan <2001559@sit.singaporetech.edu.sg> Date: Tue, 27 May 2025 10:49:35 +0800 Subject: [PATCH 2/9] Fix to _C file postfix when there's only one inset --- src/cartogram_info/cartogram_info.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cartogram_info/cartogram_info.cpp b/src/cartogram_info/cartogram_info.cpp index 08762d12..e6f12824 100644 --- a/src/cartogram_info/cartogram_info.cpp +++ b/src/cartogram_info/cartogram_info.cpp @@ -448,7 +448,12 @@ void CartogramInfo::write_svg(const std::string &suffix) for (const InsetState &inset_state : inset_states_) { inset_names += inset_state.pos(); } - insets_combined.write_map( - map_name_ + "_" + inset_names + "_" + suffix, - false); + // Only attach inset names to filename if there's more than inset + if (n_insets() > 1) { + insets_combined.write_map( + map_name_ + "_" + inset_names + "_" + suffix, + false); + } else { + insets_combined.write_map(map_name_ + "_" + suffix, false); + } } \ No newline at end of file From b9f62044cacfdb3ede2f4d6e773c84d893a90c8a Mon Sep 17 00:00:00 2001 From: adisidev <64905594+adisidev@users.noreply.github.com> Date: Thu, 29 May 2025 13:15:08 +0800 Subject: [PATCH 3/9] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/cartogram_info/cartogram_info.cpp | 2 +- src/inset_state/auto_color.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cartogram_info/cartogram_info.cpp b/src/cartogram_info/cartogram_info.cpp index e6f12824..c95c11ff 100644 --- a/src/cartogram_info/cartogram_info.cpp +++ b/src/cartogram_info/cartogram_info.cpp @@ -448,7 +448,7 @@ void CartogramInfo::write_svg(const std::string &suffix) for (const InsetState &inset_state : inset_states_) { inset_names += inset_state.pos(); } - // Only attach inset names to filename if there's more than inset + // Only attach inset names to filename if there's more than one inset if (n_insets() > 1) { insets_combined.write_map( map_name_ + "_" + inset_names + "_" + suffix, diff --git a/src/inset_state/auto_color.cpp b/src/inset_state/auto_color.cpp index 4a559c15..87ec5e64 100644 --- a/src/inset_state/auto_color.cpp +++ b/src/inset_state/auto_color.cpp @@ -14,7 +14,7 @@ void InsetState::auto_color() // If some but not all of the GeoDivs are colored, use only #f2f2f2 (light // gray) to color the rest std::cerr << "Some but not all colors provided, assigning #f2f2f2 (light " - "grey) to uncolored GeoDivs." + "gray) to uncolored GeoDivs." << std::endl; palette.emplace_back("#f2f2f2"); // light gray } else { From 02f8bcea17928e3204ea0994550f71f59ed3c9c3 Mon Sep 17 00:00:00 2001 From: Saif Khan <2001559@sit.singaporetech.edu.sg> Date: Mon, 2 Jun 2025 18:50:53 +0800 Subject: [PATCH 4/9] Change removal of _C file postfix when there's only one inset --- include/inset_state.hpp | 2 +- src/cartogram_info/cartogram_info.cpp | 16 +++++++--------- src/inset_state/integrate.cpp | 8 ++++++-- src/main.cpp | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/inset_state.hpp b/include/inset_state.hpp index b7519b61..c1b7cfeb 100644 --- a/include/inset_state.hpp +++ b/include/inset_state.hpp @@ -194,7 +194,7 @@ class InsetState nlohmann::json inset_to_geojson(bool, bool = false) const; // Function to go from equal area to cartogram - void integrate(ProgressTracker &); + void integrate(ProgressTracker &, size_t n_insets); std::vector intersecting_segments(unsigned int) const; std::vector> intersec_with_parallel_to( diff --git a/src/cartogram_info/cartogram_info.cpp b/src/cartogram_info/cartogram_info.cpp index c95c11ff..695d923c 100644 --- a/src/cartogram_info/cartogram_info.cpp +++ b/src/cartogram_info/cartogram_info.cpp @@ -196,7 +196,7 @@ void CartogramInfo::replace_missing_and_zero_target_areas() double total_start_area_with_data = 0.0; double total_target_area_with_data = 0.0; for (const InsetState &inset_state : inset_states_) { - for (const auto &gd : inset_state.geo_divs()) { + for (const GeoDiv &gd : inset_state.geo_divs()) { if (!inset_state.target_area_is_missing(gd.id())) { total_start_area_with_data += gd.area(); total_target_area_with_data += inset_state.target_area_at(gd.id()); @@ -221,7 +221,7 @@ void CartogramInfo::replace_missing_and_zero_target_areas() bool small_target_area_exists = false; bool missing_target_area_exists = false; for (InsetState &inset_state : inset_states_) { - for (const auto &gd : inset_state.geo_divs()) { + for (const GeoDiv &gd : inset_state.geo_divs()) { const double target_area = inset_state.target_area_at(gd.id()); inset_state.insert_whether_input_target_area_is_missing( gd.id(), @@ -253,7 +253,7 @@ void CartogramInfo::replace_missing_and_zero_target_areas() << std::endl; double min_positive_area = dbl_inf; for (const InsetState &inset_state : inset_states_) { - for (const auto &gd : inset_state.geo_divs()) { + for (const GeoDiv &gd : inset_state.geo_divs()) { min_positive_area = std::min(min_positive_area, gd.area()); } } @@ -262,7 +262,7 @@ void CartogramInfo::replace_missing_and_zero_target_areas() // Replace the small target areas for (InsetState &inset_state : inset_states_) { - for (const auto &gd : inset_state.geo_divs()) { + for (const GeoDiv &gd : inset_state.geo_divs()) { // Current target area const double target_area = inset_state.target_area_at(gd.id()); @@ -295,7 +295,7 @@ void CartogramInfo::replace_missing_and_zero_target_areas() // Assign new target areas to GeoDivs for (InsetState &inset_state : inset_states_) { - for (const auto &gd : inset_state.geo_divs()) { + for (const GeoDiv &gd : inset_state.geo_divs()) { if (inset_state.target_area_is_missing(gd.id())) { double new_target_area; @@ -403,7 +403,7 @@ InsetState CartogramInfo::convert_to_inset_state() InsetState new_inset_state("", args_); for (const InsetState &inset_state : inset_states_) { - for (const auto &geo_div : inset_state.geo_divs()) { + for (const GeoDiv &geo_div : inset_state.geo_divs()) { new_inset_state.push_back(geo_div); new_inset_state.insert_color( geo_div.id(), @@ -448,12 +448,10 @@ void CartogramInfo::write_svg(const std::string &suffix) for (const InsetState &inset_state : inset_states_) { inset_names += inset_state.pos(); } - // Only attach inset names to filename if there's more than one inset + // Only generate inset-named map if there's more than one inset if (n_insets() > 1) { insets_combined.write_map( map_name_ + "_" + inset_names + "_" + suffix, false); - } else { - insets_combined.write_map(map_name_ + "_" + suffix, false); } } \ No newline at end of file diff --git a/src/inset_state/integrate.cpp b/src/inset_state/integrate.cpp index 2438d32b..76aaec4e 100644 --- a/src/inset_state/integrate.cpp +++ b/src/inset_state/integrate.cpp @@ -76,7 +76,7 @@ void InsetState::cleanup_after_integration() ref_to_fluxy_init().free(); } -void InsetState::integrate(ProgressTracker &progress_tracker) +void InsetState::integrate(ProgressTracker &progress_tracker, size_t n_insets) { timer.start(inset_name_); @@ -135,7 +135,11 @@ void InsetState::integrate(ProgressTracker &progress_tracker) // Write SVG for this inset, if requested if (args_.plot_polygons) { - write_map(inset_name() + "_output", args_.plot_grid, false); + if (n_insets > 1) { + write_map(inset_name() + "_output", args_.plot_grid, false); + } else { + write_map(inset_name() + "_cartogram", args_.plot_grid, false); + } } // Project original map with cumulative projection diff --git a/src/main.cpp b/src/main.cpp index cf62e2d7..f505879e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,7 +52,7 @@ int main(const int argc, const char *argv[]) // Iterate over insets and integrate each one for (InsetState &inset_state : cart_info.ref_to_inset_states()) { - inset_state.integrate(progress_tracker); + inset_state.integrate(progress_tracker, cart_info.n_insets()); } // Rescale insets in correct proportion to each other From b5bce1424c5cef415a91f3118f86fe14048f014a Mon Sep 17 00:00:00 2001 From: Saif Khan <2001559@sit.singaporetech.edu.sg> Date: Mon, 2 Jun 2025 19:09:26 +0800 Subject: [PATCH 5/9] Reformat previous gray auto coloring code --- src/inset_state/auto_color.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/inset_state/auto_color.cpp b/src/inset_state/auto_color.cpp index 87ec5e64..1248a956 100644 --- a/src/inset_state/auto_color.cpp +++ b/src/inset_state/auto_color.cpp @@ -16,7 +16,12 @@ void InsetState::auto_color() std::cerr << "Some but not all colors provided, assigning #f2f2f2 (light " "gray) to uncolored GeoDivs." << std::endl; - palette.emplace_back("#f2f2f2"); // light gray + for (GeoDiv &gd : geo_divs_) { + if (!color_found(gd.id())) { + insert_color(gd.id(), Color("#f2f2f2")); + } + } + return; } else { // Using default palette for now // TODO: Accept palette from user @@ -37,24 +42,17 @@ void InsetState::auto_color() create_contiguity_graph(); // Iterate until we are able to color the entire map - for (const auto &gd : geo_divs_) { + for (const GeoDiv &gd : geo_divs_) { // If div already has a provided color, move to the next div if (color_found(gd.id())) continue; - // If there's only one color in palette, color the div with it without - // checking for color adjacency - if (palette.size() == 1) { - insert_color(gd.id(), palette[0]); - continue; - } - for (unsigned int i = 0; i < palette.size(); ++i) { const Color c = palette[i]; bool shared_color = false; // Check whether adjacent GeoDivs have the same color - for (const auto &gd_id : gd.adjacent_geodivs()) { + for (const std::string &gd_id : gd.adjacent_geodivs()) { if (color_found(gd_id)) { if (color_at(gd_id) == c) { shared_color = true; From be388922c3add50dd1eb2f72ee204ce2ee6be639 Mon Sep 17 00:00:00 2001 From: "Nihal Z." <81457724+nihalzp@users.noreply.github.com> Date: Thu, 5 Jun 2025 21:00:20 +0800 Subject: [PATCH 6/9] Rerun CI --- src/cartogram_info/cartogram_info.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cartogram_info/cartogram_info.cpp b/src/cartogram_info/cartogram_info.cpp index 695d923c..22d77273 100644 --- a/src/cartogram_info/cartogram_info.cpp +++ b/src/cartogram_info/cartogram_info.cpp @@ -120,6 +120,7 @@ void CartogramInfo::preprocess() } if (args_.export_preprocessed) { + // Output rescaled GeoJSON write_geojson("input_processed"); // processed = simplified + rescaled @@ -454,4 +455,4 @@ void CartogramInfo::write_svg(const std::string &suffix) map_name_ + "_" + inset_names + "_" + suffix, false); } -} \ No newline at end of file +} From 173834baff1ef5088c2f788e58c4a5b94075f2ab Mon Sep 17 00:00:00 2001 From: "Nihal Z." <81457724+nihalzp@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:27:37 +0800 Subject: [PATCH 7/9] Rerun CI --- src/cartogram_info/cartogram_info.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cartogram_info/cartogram_info.cpp b/src/cartogram_info/cartogram_info.cpp index 22d77273..d7901e7c 100644 --- a/src/cartogram_info/cartogram_info.cpp +++ b/src/cartogram_info/cartogram_info.cpp @@ -120,7 +120,6 @@ void CartogramInfo::preprocess() } if (args_.export_preprocessed) { - // Output rescaled GeoJSON write_geojson("input_processed"); // processed = simplified + rescaled From ebf4151c30d2068d0716a9b6f5357f7ad7a3ceb6 Mon Sep 17 00:00:00 2001 From: "Nihal Z." <81457724+nihalzp@users.noreply.github.com> Date: Fri, 6 Jun 2025 16:08:31 +0800 Subject: [PATCH 8/9] Rerun CI --- src/cartogram_info/cartogram_info.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cartogram_info/cartogram_info.cpp b/src/cartogram_info/cartogram_info.cpp index d7901e7c..164c91d7 100644 --- a/src/cartogram_info/cartogram_info.cpp +++ b/src/cartogram_info/cartogram_info.cpp @@ -122,6 +122,7 @@ void CartogramInfo::preprocess() if (args_.export_preprocessed) { // Output rescaled GeoJSON write_geojson("input_processed"); + // processed = simplified + rescaled // and potentially projected + small polygons removed From 244f6a84e52a184c07d5d8bc19ffa29cdc91bdd0 Mon Sep 17 00:00:00 2001 From: "Nihal Z." <81457724+nihalzp@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:01:39 +0800 Subject: [PATCH 9/9] Rerun CI --- src/cartogram_info/cartogram_info.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cartogram_info/cartogram_info.cpp b/src/cartogram_info/cartogram_info.cpp index 164c91d7..d36acef2 100644 --- a/src/cartogram_info/cartogram_info.cpp +++ b/src/cartogram_info/cartogram_info.cpp @@ -120,6 +120,7 @@ void CartogramInfo::preprocess() } if (args_.export_preprocessed) { + // Output rescaled GeoJSON write_geojson("input_processed");