From 2a9268fae81953503c242cfec02fbb1364aa3a0b Mon Sep 17 00:00:00 2001 From: Artemy Date: Wed, 29 May 2024 20:56:51 +0300 Subject: [PATCH] feat: diff --- src/build.rs | 19 +++++++++---------- src/types.rs | 29 ++++++++++++++++------------- src/utils.rs | 43 ++++++++++++++++++++++++++++--------------- 3 files changed, 53 insertions(+), 38 deletions(-) diff --git a/src/build.rs b/src/build.rs index efbed33..127b56f 100644 --- a/src/build.rs +++ b/src/build.rs @@ -5,25 +5,25 @@ use serde_json::json; use wax::{Glob, Pattern}; use crate::{ - types::CountryData, - utils::{get_country, read_config}, + types::{CountryData, ToFeature, ToFeatures}, + utils::{diff_countries, get_country, read_config}, }; pub fn build() { let config = read_config(); for processing_item in config.processing { - let mut features: Vec = vec![]; + let features: Vec = vec![]; let out_folder = Path::new(&processing_item.output_folder); - let mut countries: Vec = vec![]; - let tags = processing_item.tags.unwrap_or(vec!["*".to_string()]); let globs: Vec = tags.iter().map(|tag| Glob::new(tag).unwrap()).collect(); + let mut countries: Vec = vec![]; + for country_id in &config.main.layers { - let mut country = get_country(country_id.to_owned()); + let country = get_country(country_id.to_owned()); let mut matches = false; for glob in &globs { @@ -38,17 +38,16 @@ pub fn build() { continue; } - features.append(&mut country.geo.features); countries.push(country); } - // TODO: Country diff - // TODO: Add country_rewrite support - // TODO: let countries = vec![rewrite_info]; + + let countries = diff_countries(countries); // TODO: Add nature support + // TODO: Create from Vec let feature_collection = FeatureCollection { bbox: None, features, diff --git a/src/types.rs b/src/types.rs index 0728a3e..e0cef04 100644 --- a/src/types.rs +++ b/src/types.rs @@ -112,9 +112,20 @@ pub struct CountryConfig { pub struct CountryData { pub id: String, pub config: CountryConfig, - pub geo: FeatureCollection, + pub land: MultiPolygon, + pub markers: Vec, } +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct CountryPolyProps { + id: String, + r#type: String, + fill: String, + stroke: String, + tags: Vec, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct Marker { pub coordinates: Point, pub title: String, @@ -145,6 +156,7 @@ impl ToFeature for Marker { } } +#[derive(Debug, Serialize, Deserialize, Clone)] pub enum MarkerType { Capital, City, @@ -172,20 +184,11 @@ impl ToTerritory for MultiPolygon { } } -impl ToCountryFeature for MultiPolygon { - fn to_country_feature(&self, id: &String, config: &CountryConfig) -> geojson::Feature { +impl ToFeature for MultiPolygon { + fn to_feature(&self) -> geojson::Feature { geojson::Feature { geometry: Some(geojson::Geometry::new((self).into())), - properties: Some( - serde_json::Map::from_iter([ - ("id".to_owned(), json!(id)), - ("type".to_owned(), json!("country")), - ("fill".to_owned(), json!(config.fill)), - ("stroke".to_owned(), json!(config.stroke)), - ("tags".to_owned(), json!(config.tags)), - ]) - .into(), - ), + properties: None, bbox: None, id: None, diff --git a/src/utils.rs b/src/utils.rs index 1afc0cb..5b47317 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,11 +1,11 @@ -use std::{fs, path::Path}; +use std::{fs, marker, path::Path}; use geo::{BooleanOps, MultiPolygon}; -use geojson::{FeatureCollection, GeoJson}; +use geojson::{Feature, FeatureCollection, GeoJson}; use crate::types::{ - Config, CountryConfig, CountryData, Territory, ToCountryFeature, ToMultiPolygon, ToSplitGeo, - UnsplitGeo, + Config, CountryConfig, CountryData, Marker, Territory, ToCollection, ToCountryFeature, + ToFeature, ToFeatures, ToMultiPolygon, ToSplitGeo, UnsplitGeo, }; pub fn read_config() -> Config { @@ -37,29 +37,42 @@ pub fn get_country(id: String) -> CountryData { _ => panic!("Invalid geojson, expected FeatureCollection"), }; + let (markers, territories) = geo.split_geo(); + let geo = dissolve_territories(territories); + CountryData { id: id.clone(), config: config.clone(), - geo: dissolve_territory(geo, id, config), + land: geo, + markers, } } -pub fn dissolve_territory( - geo: FeatureCollection, - id: String, - config: CountryConfig, -) -> FeatureCollection { - let (markers, territories) = geo.split_geo(); - +pub fn dissolve_territories(territories: Vec) -> MultiPolygon { let dissolved = territories .iter() .fold(MultiPolygon::new(vec![]), |a, b| match b { Territory::Polygon(p) => a.union(&p.to_mp()), Territory::MultiPolygon(mp) => a.union(mp), - }) - .to_country_feature(&id, &config); + }); - (markers, dissolved).unsplit_geo() + dissolved +} + +pub fn diff_countries(countries: Vec) -> Vec { + let mut countries = countries; + + for i in 0..countries.len() { + for j in 0..countries.len() { + if i == j { + continue; + } + + countries[i].land = countries[i].land.difference(&countries[j].land); + } + } + + countries } pub fn hash_hex_color(s: String) -> String {