From a90c6413ae39b58a585f10d7540119e9e12e5d9c Mon Sep 17 00:00:00 2001 From: Skalimoi <53193415+skalimoi@users.noreply.github.com> Date: Sat, 4 May 2024 19:16:12 +0200 Subject: [PATCH] Added new weather 2D visualization + soil and veg funcs --- src/hydro.rs | 10 +- src/main.rs | 275 ++++++++++++++++++++++++++++++++++------ src/soil/config.rs | 138 +++----------------- src/soil/hydrology.rs | 6 +- src/soil/insolation.rs | 5 +- src/soil/soilmaker.rs | 115 +++++------------ src/soil_def.rs | 77 ++++++++--- src/ui.fl | 78 +++++++----- src/weather_pane.rs | 199 +++++++++++++---------------- target/.rustc_info.json | 2 +- test.png | Bin 0 -> 24461 bytes test_16.png | Bin 0 -> 478 bytes 12 files changed, 493 insertions(+), 412 deletions(-) create mode 100644 test.png create mode 100644 test_16.png diff --git a/src/hydro.rs b/src/hydro.rs index 6a554e5..c703dc5 100644 --- a/src/hydro.rs +++ b/src/hydro.rs @@ -18,8 +18,16 @@ pub fn erode_heightmap_full(file: &mut FileData, incremental_or_singular: bool) if !incremental_or_singular { let mut discharge_map = vec![0; 8192 * 8192]; - let img: ImageBuffer, Vec> = ImageBuffer::from_raw(8192, 8192, file.clone().raw_full).unwrap(); + let mut img: ImageBuffer, Vec> = ImageBuffer::default(); + + if file.raw_full.is_empty() { + let n: ImageBuffer, Vec> = ImageBuffer::from_raw(512, 512, file.clone().raw_map_512).unwrap(); + img = image_crate::imageops::resize(&n, 8192, 8192, FilterType::CatmullRom); + } else { + let i: ImageBuffer, Vec> = ImageBuffer::from_raw(8192, 8192, file.clone().raw_full).unwrap(); + img = i; + } let heightmap = img.into_raw(); let mut erosion_world = World::new( diff --git a/src/main.rs b/src/main.rs index a37d2fa..2d6ddbc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ #![feature(vec_push_within_capacity)] +#![feature(iter_advance_by)] +use std::collections::HashMap; use crate::topo_settings::TopoSettings; use fltk::app::Sender; use map_range::MapRange; -use fltk::image::SharedImage; +use fltk::image::{RgbImage, SharedImage}; use fltk::{*, prelude::*}; use image_crate::{DynamicImage, EncodableLayout, GenericImageView, ImageBuffer, Luma, Pixel}; use noise::utils::NoiseMapBuilder; @@ -17,6 +19,7 @@ use std::default::Default; use std::fs::File; use std::fs; use std::mem::{replace, swap}; +use std::ops::Index; use std::path::PathBuf; use fastlem::core::units::Elevation; @@ -29,7 +32,9 @@ use topo_settings::NoiseTypesUi; use topography::{DEFAULT_TOPOSETTINGS, DIMENSIONS}; use weather_pane::DEFAULT_WEATHERSETTINGS; use crate::fastlem_opt::generate_terrain; -use crate::soil_def::{base_choice_init, load_and_show_veg}; +use crate::soil::config::GreyscaleImage; +use crate::soil::soilmaker::init_soilmaker; +use crate::soil_def::{base_choice_init, generate_selected_do, load_and_show_veg, SoilType, VegetationCollection, VegetationData, VegetationMaps}; use crate::topography::{max_bounds_do, min_bounds_do, lod_do, erod_scale_do, apply_color_eroded, apply_color}; use crate::ui::HeightmapInterface; use crate::utils::get_height; @@ -114,6 +119,18 @@ enum Message { ImportHeightmap, FullPreviewIncremental, FullPreviewSingular, + GenVegSel, + GenSoil, + DirtCheck, + LoamCheck, + StoneCheck, + GravelCheck, + SiltCheck, + SandCheck, + ClayCheck, + NextVeg, + Vis2D, + Vis3D, } struct ViewState { @@ -123,9 +140,10 @@ struct ViewState { proj: ViewMode } +#[derive(PartialEq)] enum ViewMode { - 2D, - 3D + TwoD, + ThreeD } @@ -315,7 +333,7 @@ fn main() { mode: Init, hour: 0, layer: 0, - proj: ViewMode::3D + proj: ViewMode::ThreeD }; let climates: [Climate; 18] = [koppen_cfa(), koppen_cfb(), koppen_cfc(), koppen_dfb(), koppen_dfc(), koppen_dfa(), koppen_cwc(), koppen_cwb(), koppen_cwa(), koppen_et(), koppen_afam(), koppen_as(), koppen_aw(), koppen_dsc(), koppen_bsh(), koppen_bsk(), koppen_bwh(), koppen_bwk()]; @@ -469,7 +487,7 @@ fn main() { terrain_material.clone(), Arc::new( move |x, y| { - *heightmap_opt.get_pixel(x as u32, y as u32).channels().first().unwrap() as f32 * 0.01 + *heightmap_opt.get_pixel(x as u32, y as u32).channels().first().unwrap() as f32 * 0.001 } ), 512.0, @@ -576,6 +594,24 @@ fn main() { ui.layer_slider.emit(s, Message::Layer); + ui.generate_selected_button.emit(s, Message::GenVegSel); + + ui.prepare_soil_button.emit(s, Message::GenSoil); + + ui.dirt_check.emit(s, Message::DirtCheck); + + ui.loam_check.emit(s, Message::LoamCheck); + + ui.silt_check.emit(s, Message::SiltCheck); + + ui.clay_check.emit(s, Message::ClayCheck); + + ui.stone_check.emit(s, Message::StoneCheck); + + ui.sand_check.emit(s, Message::SandCheck); + + ui.gravel_check.emit(s, Message::GravelCheck); + let target = *camera.target(); let camera_y = camera.position().y; @@ -588,16 +624,178 @@ fn main() { heightmap_importer_ui.browse_button.emit(s, Message::BrowseFile); heightmap_importer_ui.import_button.emit(s, Message::ImportButton); heightmap_importer_ui.file_box.emit(s, Message::FileBox); + + ui.twod_vis.emit(s, Message::Vis2D); + ui.threed_vis.emit(s, Message::Vis3D); base_choice_init(&mut ui.base_soil_choice); load_and_show_veg(&mut ui.vegetation_list); - + + let mut soilchoices: HashMap = HashMap::new(); + soilchoices.insert(SoilType::Dirt, false); + soilchoices.insert(SoilType::Silt, false); + soilchoices.insert(SoilType::Stone, false); + soilchoices.insert(SoilType::Gravel, false); + soilchoices.insert(SoilType::Loam, false); + soilchoices.insert(SoilType::Clay, false); + soilchoices.insert(SoilType::Sand, false); + + let mut vegmaps = VegetationMaps { + insolation: GreyscaleImage::new(vec![]), + edaphology: GreyscaleImage::new(vec![]), + hydrology: GreyscaleImage::new(vec![]), + orography: GreyscaleImage::new(vec![]), + soil_int: vec![] + }; + + let mut soil_veg_params = VegetationData { + base: SoilType::Dirt, + blocklist: soilchoices, + vegetationlist: HashMap::new() + }; + + let mut veg_collection = VegetationCollection { + generated: HashMap::new(), + }; let mut dir: PathBuf = PathBuf::new(); + ui.next_veg.emit(s, Message::NextVeg); + + let mut index_list: Vec = Vec::new(); + + let mut index = 0; + while app.wait() { if let Some(msg) = r.recv() { match msg { + Message::Vis2D => { + view_state.proj = ViewMode::TwoD; + gl_widget.hide(); + } + Message::Vis3D => { + view_state.proj = ViewMode::ThreeD; + gl_widget.show(); + } + Message::NextVeg => { + index+=1; + let element = index_list[index-1].clone(); + let map = veg_collection.clone().generated.get(&element).unwrap().clone(); + let i = RgbImage::new(map.as_slice(), 1024, 1024, ColorDepth::Rgb8).unwrap(); + ui.veg_preview.set_image_scaled(None::); + ui.veg_preview.set_image_scaled(SharedImage::from_image(i).ok()); + ui.veg_preview.redraw(); + ui.veg_name.set_label(format!("Now displaying: {}", element).as_str()); + } + Message::GenVegSel => { + generate_selected_do(&mut ui.vegetation_list, &mut vegmaps, &mut soil_veg_params, &mut file, &mut veg_collection); + for element in veg_collection.clone().generated.into_iter() { + let name = element.0.clone(); + index_list.push(name); + } + } + Message::DirtCheck => { + match ui.dirt_check.is_checked() { + true => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Dirt).unwrap(); + replace(value, true); + } + false => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Dirt).unwrap(); + replace(value, false); + } + } + } + Message::SiltCheck => { + match ui.silt_check.is_checked() { + true => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Silt).unwrap(); + replace(value, true); + } + false => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Silt).unwrap(); + replace(value, false); + } + } + } + Message::StoneCheck => { + match ui.stone_check.is_checked() { + true => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Stone).unwrap(); + replace(value, true); + } + false => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Stone).unwrap(); + replace(value, false); + } + } + } + Message::GravelCheck => { + match ui.gravel_check.is_checked() { + true => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Gravel).unwrap(); + replace(value, true); + } + false => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Gravel).unwrap(); + replace(value, false); + } + } + } + Message::LoamCheck => { + match ui.loam_check.is_checked() { + true => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Loam).unwrap(); + replace(value, true); + } + false => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Loam).unwrap(); + replace(value, false); + } + } + } + Message::ClayCheck => { + match ui.clay_check.is_checked() { + true => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Clay).unwrap(); + replace(value, true); + } + false => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Clay).unwrap(); + replace(value, false); + } + } + } + Message::SandCheck => { + match ui.sand_check.is_checked() { + true => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Sand).unwrap(); + replace(value, true); + } + false => { + let value = soil_veg_params.blocklist.get_mut(&SoilType::Sand).unwrap(); + replace(value, false); + } + } + } + Message::GenSoil => { + let soil_base = match ui.base_soil_choice.choice().unwrap().as_str() { + "Dirt" => SoilType::Dirt, + "Silt" => SoilType::Silt, + "Stone" => SoilType::Stone, + "Gravel" => SoilType::Gravel, + "Loam" => SoilType::Loam, + "Clay" => SoilType::Clay, + "Sand" => SoilType::Sand, + _ => SoilType::Dirt + }; + let i: ImageBuffer, Vec> = ImageBuffer::from_raw(8192, 8192, file.eroded_full.clone()).unwrap(); + let hydro: ImageBuffer, Vec> = ImageBuffer::from_raw(8192, 8192, file.discharge.clone()).unwrap(); + let soil = init_soilmaker(&mut ui.soil_preview, soil_base, &soil_veg_params.blocklist, &i, &hydro); + vegmaps.soil_int = soil; + ui.soil_preview.set_image_scaled(None::); + ui.soil_preview.set_image_scaled(SharedImage::from_image(RgbImage::new(vegmaps.soil_int.as_slice(), 1024, 1024, ColorDepth::Rgb8).unwrap()).ok()); + } Message::ImportHeightmap => { heightmap_importer_win.show(); } @@ -659,6 +857,7 @@ fn main() { hydro::update_hydro_prev(&mut ui.hydro_mask_preview, false, &mut file); } Message::FullPreviewSingular => { + println!("Is empty: {}", file.raw_full.is_empty()); hydro::erode_heightmap_full(&mut file, false); hydro::update_hydro_prev(&mut ui.hydro_preview, true, &mut file); hydro::update_hydro_prev(&mut ui.hydro_mask_preview, false, &mut file); @@ -686,9 +885,11 @@ fn main() { _ => view_state.layer = 0 } match view_state.proj { - ViewMode::3D => weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); - ViewMode::2D => weather_pane::vis_image(&mut ui.putframehere, view_state.hour, &mut file.weather_data, &view_state); - } + ViewMode::ThreeD => {weather_pane::update_grid_at_time(view_state.hour, & mut file.weather_data, & mut mesh_v, & view_state);}, + ViewMode::TwoD => { + weather_pane::vis_image( &mut ui.weather_preview, view_state.hour, & mut file.weather_data, & view_state); + } + }; } Message::WeatherSeedInput => { @@ -709,20 +910,22 @@ fn main() { Message::GenWeather => { let noise: Fbm = Fbm::new(file.weather.seed.unwrap()); let map: ImageBuffer, Vec> = ImageBuffer::from_raw(512, 512, file.eroded_raw_512.clone()).unwrap(); - let map_b = map.clone(); - let terrain_map = Terrain::new( - &context, - terrain_material.clone(), - Arc::new( - move |x, y| { - map_b.clone().get_pixel(x as u32, y as u32).channels().first().unwrap().clone() as f32 * 0.01 - } - ), - 512.0, - 1.0, - three_d::prelude::Vec2::new(255.0, 255.0) - ); - terrain = terrain_map; + if view_state.proj != ViewMode::TwoD { + let map_b = map.clone(); + let terrain_map = Terrain::new( + &context, + terrain_material.clone(), + Arc::new( + move |x, y| { + *map_b.clone().get_pixel(x as u32, y as u32).channels().first().unwrap() as f32 * 0.1 + } + ), + 512.0, + 1.0, + three_d::prelude::Vec2::new(255.0, 255.0), + ); + terrain = terrain_map; + } let component_size = 512.0 / file.weather.clone().grid_size as f64; let min_total = map.iter().as_slice().iter().min().unwrap(); let max_total = map.iter().as_slice().iter().max().unwrap(); @@ -752,8 +955,8 @@ fn main() { Message::ViewHumidity => { weather_pane::set_view_state(&mut view_state, WeatherVisualization::Humidity); match view_state.proj { - ViewMode::3D => weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); - ViewMode::2D => weather_pane::vis_image(&mut ui.putframehere, view_state.hour, &mut file.weather_data, &view_state); + ViewMode::ThreeD => { weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); }, + ViewMode::TwoD => { weather_pane::vis_image(&mut ui.weather_preview, view_state.hour, &mut file.weather_data, &view_state); } } ui.legend_box.set_image(Some(SharedImage::load("icons/humidity_legend.png").unwrap())); ui.legend_box.redraw_label(); @@ -761,8 +964,8 @@ fn main() { Message::ViewPressure => { weather_pane::set_view_state(&mut view_state, WeatherVisualization::Pressure); match view_state.proj { - ViewMode::3D => weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); - ViewMode::2D => weather_pane::vis_image(&mut ui.putframehere, view_state.hour, &mut file.weather_data, &view_state); + ViewMode::ThreeD => { weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); }, + ViewMode::TwoD => { weather_pane::vis_image(&mut ui.weather_preview, view_state.hour, &mut file.weather_data, &view_state); } } ui.legend_box.set_image(Some(SharedImage::load("icons/pressure_legend.png").unwrap())); ui.legend_box.redraw_label(); @@ -770,8 +973,8 @@ fn main() { Message::ViewTemperature => { weather_pane::set_view_state(&mut view_state, WeatherVisualization::Temperature); match view_state.proj { - ViewMode::3D => weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); - ViewMode::2D => weather_pane::vis_image(&mut ui.putframehere, view_state.hour, &mut file.weather_data, &view_state); + ViewMode::ThreeD => { weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); }, + ViewMode::TwoD => { weather_pane::vis_image(&mut ui.weather_preview, view_state.hour, &mut file.weather_data, &view_state); } } ui.legend_box.set_image(Some(SharedImage::load("icons/temp_legend.png").unwrap())); ui.legend_box.redraw_label(); @@ -779,16 +982,16 @@ fn main() { Message::ViewWind => { weather_pane::set_view_state(&mut view_state, WeatherVisualization::Wind); match view_state.proj { - ViewMode::3D => weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); - ViewMode::2D => weather_pane::vis_image(&mut ui.putframehere, view_state.hour, &mut file.weather_data, &view_state); - } + ViewMode::ThreeD => { weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); }, + ViewMode::TwoD => { weather_pane::vis_image(&mut ui.weather_preview, view_state.hour, &mut file.weather_data, &view_state); } + }; }, Message::DaySlider => { weather_pane::set_hour(&mut ui.day_vis_slider, &mut view_state); match view_state.proj { - ViewMode::3D => weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); - ViewMode::2D => weather_pane::vis_image(&mut ui.putframehere, view_state.hour, &mut file.weather_data, &view_state); - } + ViewMode::ThreeD => { weather_pane::update_grid_at_time(view_state.hour, &mut file.weather_data, &mut mesh_v, &view_state); }, + ViewMode::TwoD => { weather_pane::vis_image(&mut ui.weather_preview, view_state.hour, &mut file.weather_data, &view_state); } + }; } Message::SaveFile => { save_file_do(&mut file, &mut is_file_workspace, &mut workspace_path, &mut file_name); diff --git a/src/soil/config.rs b/src/soil/config.rs index 3177d6c..3d02bd2 100644 --- a/src/soil/config.rs +++ b/src/soil/config.rs @@ -13,9 +13,9 @@ use crate::soil::hydrology::calculate_hydrology_map; use crate::soil::insolation::calculate_actual_insolation; use crate::soil::orography::calculate_normal_map; use crate::soil::probabilities::calculate_probabilities; +use crate::soil_def::{VegetationCollection, VegetationMaps}; - -#[derive(Clone)] +#[derive(Clone, Serialize, Deserialize)] pub struct GreyscaleImage { pub image: Vec, len: usize, @@ -112,7 +112,7 @@ pub struct SunConfig { pub struct SimArgs<'a> { pub height_map: GreyscaleImage, - pub soil_ids_map: GreyscaleImage, + pub soil_ids_map: Vec, pub soils: &'a HashMap, pub sun_config: &'a SunConfig, pub reflection_coefficient: f64, @@ -160,18 +160,18 @@ impl SimConfig { } pub fn calculate_maps( &self, - map_name: &str, sun_config: &SunConfig, reflection_coefficient: f64, + mapdata: &mut VegetationMaps ) { let map = &self.maps; let height_map_for_insolation = &map.height_map_path.clone(); let soil_ids_map = &map.texture_map_path.clone(); - ); + let sim_args = SimArgs { - height_map, + height_map: height_map_for_insolation.clone(), soil_ids_map: soil_ids_map.clone(), soils: &self.soil_ids, sun_config, @@ -186,8 +186,8 @@ impl SimConfig { biom: &self.bioms[&map.biom], }; let sim_args_for_insolation = SimArgs { - height_map: height_map_for_insolation, - soil_ids_map, + height_map: height_map_for_insolation.clone(), + soil_ids_map: soil_ids_map.clone(), soils: &self.soil_ids, sun_config, reflection_coefficient, @@ -201,59 +201,15 @@ impl SimConfig { biom: &self.bioms[&map.biom], }; let insolation_map = calculate_actual_insolation(&sim_args_for_insolation); - let insolation_buffer: ImageBuffer, Vec> = ImageBuffer::from_raw(1024, 1024, insolation_map.image.into_iter().map( - |x| { - x as u16 - } - ).collect()).unwrap(); - let insolation_resampled = image_crate::imageops::resize(&insolation_buffer, 8192, 8192, image_crate::imageops::FilterType::Nearest); - let insolation_map = GreyscaleImage::new( - insolation_resampled.into_raw().into_iter().map(|x| { - x as f64 - }).collect()); let orographic_map = calculate_normal_map(&sim_args); let edaphic_map = calculate_soil_depth(&orographic_map, sim_args.map); let hydrology_map = calculate_hydrology_map(&sim_args, &edaphic_map, &insolation_map); + mapdata.insolation = insolation_map; + mapdata.edaphology = edaphic_map; + mapdata.hydrology = hydrology_map; + mapdata.orography = orographic_map; //std::fs::write("insolation_rust.json", serde_json::to_string(&insolation_map.image).unwrap()).unwrap(); - let mut insolation_image = ImageBuffer::, Vec>::from_raw( - insolation_map.len() as u32, - insolation_map.len() as u32, - insolation_map.image.into_iter().map(|x| x as u16).collect(), - ) - .unwrap(); - //std::fs::write("edaphic_rust.json", serde_json::to_string(&edaphic_map.image).unwrap()).unwrap(); - let mut edaphic_image = ImageBuffer::, Vec>::from_raw( - edaphic_map.len() as u32, - edaphic_map.len() as u32, - edaphic_map.image.into_iter().map(|x| x as u16).collect(), - ) - .unwrap(); - //std::fs::write("hydrology_rust.json", serde_json::to_string(&hydrology_map.image).unwrap()).unwrap(); - let hydrology_image = ImageBuffer::, Vec>::from_raw( - hydrology_map.len() as u32, - hydrology_map.len() as u32, - hydrology_map.image.into_iter().map(|x| (x * 1000.0) as u16).collect(), - ) - .unwrap(); - - // std::fs::create_dir_all(format!("data/vegetation_data/{map_name}")).unwrap(); - - insolation_image - .save(format!("insolation.png")) - .unwrap(); - edaphic_image - .save(format!("edaphic.png")) - .unwrap(); - hydrology_image - .save(format!("water.png")) - .unwrap(); - - std::fs::write( - format!("normals.json"), - serde_json::to_string(&orographic_map.image.into_iter().map(|x| [x.x, x.y, x.z]).collect::>()).unwrap(), - ) - .unwrap(); // let orographic_image = ImageBuffer::, Vec>::from_raw( // orographic_map.len() as u32, @@ -266,59 +222,18 @@ impl SimConfig { // TODO: HACER STRUCT SOLO PARA ESTAS IMAGENES Y NO TENER QUE GUARDARLAS // TODO: COMPROBAR EL TEMA IMAGEN SI LO COGE BIEN O NO // TODO: TERMINAR DE CONFIGURAR SOIL_DEF.RS - pub fn calculate_probabilities(&self, map_name: &str, vegetation_names: &[&str], _daylight_hours: i32) { - let soil_ids_map = GreyscaleImage::new( - ImageReader::open(&self.maps.texture_map_path) - .unwrap() - .decode() - .unwrap() - .into_luma8() - .into_raw(), - ); - let insolation_map = GreyscaleImage::new( - ImageReader::open("insolation.png".to_string()) - .unwrap() - .decode() - .unwrap() - .into_luma16() - .into_raw() - .into_iter() - .map(|x| x as f64) - .collect(), - ); - let edaphic_map = GreyscaleImage::new( - ImageReader::open("edaphic.png".to_string()) - .unwrap() - .decode() - .unwrap() - .into_luma16() - .into_raw() - .into_iter() - .map(|x| x as f64) - .collect(), - ); - let hydrology_map = GreyscaleImage::new( - ImageReader::open("water.png".to_string()) - .unwrap() - .decode() - .unwrap() - .into_luma16() - .into_raw() - .into_iter() - .map(|x| x as f64 / 1000.0) - .collect(), - ); + pub fn calculate_probabilities(&self, mapdata: &VegetationMaps, vegetation_names: &[&str], _daylight_hours: i32, vegetation_collection: &mut VegetationCollection) { + let soil_ids_map = GreyscaleImage::new(self.maps.texture_map_path.clone()); for vegetation in vegetation_names { let probabilities_map = calculate_probabilities( &self.vegetations[*vegetation], &soil_ids_map, &self.soil_names, - &insolation_map, - &edaphic_map, - &hydrology_map, + &mapdata.insolation, + &mapdata.edaphology, + &mapdata.hydrology, ); - //std::fs::write("probabilities_rust.json", serde_json::to_string(&probabilities_map.image).unwrap()).unwrap(); let mut probabilities_image = ImageBuffer::, Vec>::from_raw( probabilities_map.len() as u32, probabilities_map.len() as u32, @@ -326,24 +241,7 @@ impl SimConfig { ) .unwrap(); imageproc::contrast::stretch_contrast_mut(&mut probabilities_image, 100, 255); - probabilities_image - .save(format!("total_{}.png", vegetation)) - .unwrap(); + vegetation_collection.generated.insert(vegetation.clone().parse().unwrap(), probabilities_image.into_raw()); } - - - // let to_tiling = image_newest::io::Reader::open(format!("data/vegetation_data/height_map/{vegetation_name}_total.png")).unwrap().decode().unwrap(); - // let brightened = imageproc::contrast::stretch_contrast(&to_tiling.into_luma8(), 0, 2); - // brightened.save(format!("data/vegetation_data/height_map/{vegetation_name}_equalized.png")).unwrap(); - // let blur = imageproc::filter::gaussian_blur_f32(&brightened, 2.0); - // let resampled_blur = image_newest::imageops::resize(&blur, 8193, 8193, FilterType::Gaussian); - // let tile_size: usize = 513; - // for tile_x in 0..=15 { - // for tile_y in 0..=15 { - // let tile = image_newest::imageops::crop_imm(&resampled_blur, (tile_x * tile_size) as u32, (tile_y * tile_size) as u32, tile_size as u32, tile_size as u32); - // tile.to_image().save(format!("data/vegetation_data/height_map/{vegetation_name}_{tile_x}_{tile_y}.png")).unwrap(); - // } - // } - } } diff --git a/src/soil/hydrology.rs b/src/soil/hydrology.rs index 7d28b7a..b89939f 100644 --- a/src/soil/hydrology.rs +++ b/src/soil/hydrology.rs @@ -1,3 +1,6 @@ +use std::ops::Deref; +use image_crate::ImageBuffer; +use image_crate::Luma; use crate::soil::config::{GreyscaleImage, SimArgs}; const K_CALORIES_NEEDED_TO_EVAPORATE_1_G_WATER: f64 = 0.54; @@ -20,7 +23,8 @@ pub fn calculate_hydrology_map( .into_iter() .map(|y| { (0..edaphic_map.len()).into_iter().map(move |x| { - let soil = &sim_args.soils[&sim_args.soil_ids_map[(x, y)]]; + let soil_map: ImageBuffer, Vec> = ImageBuffer::from_raw(1024, 1024, sim_args.soil_ids_map.clone()).unwrap(); + let soil = &sim_args.soils[&soil_map.get_pixel(x as u32, y as u32)[0]]; let depth_coefficient = (edaphic_map[(x, y)] / 100.0).min(1.0); let water_supply = (sim_args.biom.groundwater + sim_args.biom.avg_rainfall_per_day) * depth_coefficient diff --git a/src/soil/insolation.rs b/src/soil/insolation.rs index 6b0cf7a..fad24c8 100644 --- a/src/soil/insolation.rs +++ b/src/soil/insolation.rs @@ -1,3 +1,4 @@ +use image_crate::{ImageBuffer, Luma}; use nalgebra::Vector3; use crate::soil::config::{clamp_idx, GreyscaleImage, Map, round, SimArgs, Sun}; @@ -114,8 +115,8 @@ pub fn calculate_actual_insolation(sim_args: &SimArgs) -> GreyscaleImage { let cloud_reflection_loss = pixel_raw_insolation * sim_args.biom.cloud_reflection / 100.0; let atmospheric_absorption_loss = pixel_raw_insolation * sim_args.biom.atmospheric_absorption / 100.0; let atmospheric_diffusion_loss = pixel_raw_insolation * sim_args.biom.atmospheric_diffusion / 100.0; - let soil = &sim_args.soils[&sim_args.soil_ids_map[(x, y)]]; - insolation_map[(x, y)] = + let soil_map: ImageBuffer, Vec> = ImageBuffer::from_raw(1024, 1024, sim_args.soil_ids_map.clone()).unwrap(); + let soil = &sim_args.soils[&soil_map.get_pixel(x as u32, y as u32)[0]]; insolation_map[(x, y)] = (pixel_raw_insolation - cloud_reflection_loss - atmospheric_absorption_loss - atmospheric_diffusion_loss) * (1.0 - soil.albedo) } diff --git a/src/soil/soilmaker.rs b/src/soil/soilmaker.rs index c6247c2..08d9a1a 100644 --- a/src/soil/soilmaker.rs +++ b/src/soil/soilmaker.rs @@ -5,8 +5,13 @@ use std::io::Read; use imageproc::drawing::Canvas; use color_reduce; use color_reduce::{quantize, BasePalette, QuantizeMethod}; +use fltk::enums::ColorDepth; +use fltk::frame::Frame; +use fltk::image::{PngImage, RgbImage, SharedImage}; +use fltk::prelude::WidgetExt; use image_crate::{ColorType, DynamicImage, GenericImage, ImageBuffer, Luma, Rgb, Rgba}; use image_crate::DynamicImage::{ImageLuma16, ImageLuma8, ImageRgb8, ImageRgba8}; +use image_crate::imageops::FilterType; use image_newest::{ImageBuffer as buffer_old, Rgb as Rgb_old, Rgba as Rgba_old}; use imageproc::distance_transform::Norm; @@ -14,6 +19,7 @@ use noise::{Fbm, MultiFractal, Perlin}; use noise::utils::{NoiseMap, NoiseMapBuilder, PlaneMapBuilder}; use rand::{Rng, thread_rng}; use crate::soil::config::{Biom, GreyscaleImage, Map, SimConfig, Soil, SunConfig, Vegetation}; +use crate::soil_def::SoilType; const DIM: u16 = 8192; @@ -31,18 +37,18 @@ pub enum SoilColor { Sand([u8; 4]) } -pub fn init_soilmaker(base_soil: SoilType, blocklist: &HashMap, heightmap: &ImageBuffer, Vec>, heightmap16: &ImageBuffer, Vec>, hydro_map: &ImageBuffer, Vec>) { - let mut dynamic = DynamicImage::ImageLuma8(heightmap.clone()); +pub fn init_soilmaker(f: &mut Frame, base_soil: SoilType, blocklist: &HashMap, heightmap16: &ImageBuffer, Vec>, hydro_map: &ImageBuffer, Vec>) -> Vec { + let mut dynamic = DynamicImage::ImageLuma16(heightmap16.clone()); let mut dynamic_hydro = DynamicImage::ImageLuma8(hydro_map.clone()); println!("Doing base soil."); let b = init_base(match base_soil { - Dirt => [5,5,5], - Silt => [100,100,100], - Stone => [16,16,16], - Gravel => [32,32,32], - Loam => [64,64,64], - Clay => [128,128,128], - Sand => [200,200,200] + SoilType::Dirt => [5,5,5,255], + SoilType::Silt => [100,100,100, 255], + SoilType::Stone => [16,16,16, 255], + SoilType::Gravel => [32,32,32, 255], + SoilType::Loam => [64,64,64, 255], + SoilType::Clay => [128,128,128, 255], + SoilType::Sand => [200,200,200, 255] }, DIM as u32); println!("Doing height."); let h = generate_height(&mut dynamic); @@ -60,33 +66,30 @@ pub fn init_soilmaker(base_soil: SoilType, blocklist: &HashMap, let c = generate_coast_sediment(&mut dynamic); let d_5 = overlay_with_weights(&d_4, &c, 1.0); let mut old_to_convert: buffer_old, Vec> = buffer_old::from_raw(DIM as u32, DIM as u32, d_5.into_rgb8().into_raw()).unwrap(); - let mut color_vec: Vec<[u8; 4]> = vec![]; - for (value, soil) in blocklist { - if value == true { + let mut color_vec: Vec<[u8; 3]> = vec![]; + for (soil, value) in blocklist.clone() { + if value == false { match soil { - Dirt => color_vec.insert([5,5,5]), - Silt => color_vec.insert([100,100,100]), - Stone => color_vec.insert([16,16,16]), - Gravel => color_vec.insert([32,32,32]), - Loam => color_vec.insert([64,64,64]), - Clay => color_vec.insert([128,128,128]), - Sand => color_vec.insert([200,200,200]) + SoilType::Dirt => color_vec.push([5,5,5]), + SoilType::Silt => color_vec.push([100,100,100]), + SoilType::Stone => color_vec.push([16,16,16]), + SoilType::Gravel => color_vec.push([32,32,32]), + SoilType::Loam => color_vec.push([64,64,64]), + SoilType::Clay => color_vec.push([128,128,128]), + SoilType::Sand => color_vec.push([200,200,200]) } } } let colormap = color_reduce::palette::BasePalette::new( - vec![ - [5,5,5], // dirt - [16,16,16], // stone - [32,32,32], // gravel - [64,64,64], // loam - [100,100,100], // silt - [128,128,128], // clay - [200,200,200] // sand - ] + color_vec ); quantize(&mut old_to_convert, &colormap, QuantizeMethod::CIE2000, None); - old_to_convert.save("soils.png"); + let i = image_newest::imageops::resize(&old_to_convert, 1024, 1024, image_newest::imageops::FilterType::Nearest); + f.set_image_scaled(None::); + let s = RgbImage::new(i.as_raw().as_slice(), 1024, 1024, ColorDepth::Rgb8).unwrap(); + f.set_image(SharedImage::from_image(s).ok()); + f.redraw(); + i.into_raw() } fn init_base(soil: [u8; 4], size: u32) -> DynamicImage { @@ -145,7 +148,6 @@ fn generate_random_clay(i: &mut DynamicImage) -> DynamicImage { fn generate_slope_soil(i: &ImageBuffer, Vec>) -> DynamicImage { let c = sobel(i); c.adjust_contrast(50.0).brighten(50); - c.save("SOBEL.png"); let mut d = DynamicImage::new_luma_a8(i.dimensions().0, i.dimensions().0); // TODO: change gravel for nothing for x in 0..i.dimensions().0 { @@ -278,56 +280,3 @@ fn sobel(input: &ImageBuffer, Vec>) -> DynamicImage { }; ImageLuma16(buff) } - -pub fn generate_yaml_map(biom: &str, height_conversion: f64, height_map_path: &str, max_soil_depth: f64, pixel_size: f64, texture_map_path: f64) { - let map = Map { - biom: biom.to_string(), - height_conversion: height_conversion as f64, - height_map_path: height_map_path.to_string(), - max_soil_depth: max_soil_depth as f64, - pixel_size: pixel_size as f64, - texture_map_path: texture_map_path.to_string() - }; - let yaml = serde_yaml::to_string(&map).unwrap(); - File::create("map.yml").unwrap(); - fs::write("map.yml", yaml).unwrap(); -} - -pub fn generate_veg_mask(map_name: &str, vegetation: &[&str]) { - - let maps = Map { - biom: "PolarZone".to_string(), - height_map_path: "heightmap.png".to_string(), - texture_map_path: "soils.png".to_string(), - height_conversion: 1.0, - max_soil_depth: 700.0, - pixel_size: 100.0, - }; - - let mut data = String::new(); - File::open("bioms.yml").unwrap().read_to_string(&mut data).unwrap(); - let bioms: HashMap = serde_yaml::from_str(&data).unwrap(); - - let mut data = String::new(); - File::open("soil_types.yml").unwrap().read_to_string(&mut data).unwrap(); - let soils: HashMap = serde_yaml::from_str(&data).unwrap(); - - let mut data = String::new(); - File::open("vegetation_types.yaml") - .unwrap() - .read_to_string(&mut data) - .unwrap(); - let vegetations: HashMap = serde_yaml::from_str(&data).unwrap(); - - let sun_config = SunConfig { // sample parameters for Hellion - daylight_hours: 13, - sun_start_elevation: -5.0, - sun_start_azimuth: 92.0, - sun_max_elevation: 50.0, - }; - let reflection_coefficient = 0.1; - - let sim_config = SimConfig::from_configs(maps, bioms, soils, vegetations); - // sim_config.calculate_maps(map_name.to_string().as_str(), &sun_config, reflection_coefficient); // TODO put back - sim_config.calculate_probabilities(map_name.to_string().as_str(), vegetation, sun_config.daylight_hours); -} diff --git a/src/soil_def.rs b/src/soil_def.rs index 2316728..b5483fe 100644 --- a/src/soil_def.rs +++ b/src/soil_def.rs @@ -5,10 +5,14 @@ use std::ops::Deref; use fltk::browser::CheckBrowser; use fltk::button::Button; use fltk::prelude::{BrowserExt, MenuExt}; +use image_newest::{ImageBuffer, Luma}; +use image_newest::imageops::FilterType; +use nalgebra::Vector3; use serde::{Deserialize, Serialize}; -use crate::soil::config::Vegetation; +use crate::FileData; +use crate::soil::config::{Biom, GreyscaleImage, Map, SimConfig, Soil, SunConfig, Vegetation}; -#[derive(Clone, Serialize, Deserialize, Debug)] +#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq, Hash)] pub enum SoilType { Dirt, Silt, @@ -22,48 +26,79 @@ pub enum SoilType { #[derive(Clone, Serialize, Deserialize, Debug)] pub struct VegetationData { pub base: SoilType, - pub blocklist: HashMap, - pub vegetationlist: HashMap + pub blocklist: HashMap, + pub vegetationlist: HashMap } -// one must create as many as needed -#[derive(Clone, Serialize, Deserialize, Debug)] +#[derive(Clone)] pub struct VegetationMaps { - map: Vec> + pub insolation: GreyscaleImage, + pub edaphology: GreyscaleImage, + pub hydrology: GreyscaleImage, + pub orography: GreyscaleImage>, + pub soil_int: Vec } -// TODO: SIGUE EN CONFIG.RS +#[derive(Clone)] +pub struct VegetationCollection { + pub generated: HashMap> +} -pub fn generate_selected_do(c: &mut CheckBrowser, w: &mut Button, data: &mut VegetationData, filedata: &mut FileData, soilmap: Vec) { - collect_values(c, data); - let h: ImageBuffer = ImageBuffer::from_raw(filedata.eroded_full, 8192, 8192).unwrap(); - let h = image_latest::imageops::resize(h, 1024, 1024, FilterType::Nearest); - let h = GreyScaleImage::new(h.into_raw().into_iter() +pub fn generate_selected_do(c: &mut CheckBrowser, vegetation_maps: &mut VegetationMaps, vegdata: &mut VegetationData, filedata: &mut FileData, vegetation_collection: &mut VegetationCollection) { + collect_values(c, vegdata); + let h: ImageBuffer, Vec> = ImageBuffer::from_raw(8192, 8192, filedata.eroded_full.clone()).unwrap(); + let h = image_newest::imageops::resize(&h, 1024, 1024, FilterType::Nearest); + let h = GreyscaleImage::new(h.into_raw().into_iter() .map(|x| x as f64) .collect()); let m = Map { - biom: TemperateZone, + biom: "TemperateZone".parse().unwrap(), height_map_path: h, - texture_map_path: soilmap, - height_conversion: 0.2, + texture_map_path: vegetation_maps.clone().soil_int, + height_conversion: 1.0, max_soil_depth: 300.0, pixel_size: 100.0 }; - let conf = SimConfig::from_configs( + let mut data = String::new(); + File::open("bioms.yml").unwrap().read_to_string(&mut data).unwrap(); + let bioms: HashMap = serde_yaml::from_str(&data).unwrap(); - ) + let mut data = String::new(); + File::open("soil_types.yml").unwrap().read_to_string(&mut data).unwrap(); + let soils: HashMap = serde_yaml::from_str(&data).unwrap(); + let mut data = String::new(); + File::open("vegetation_types.yaml") + .unwrap() + .read_to_string(&mut data) + .unwrap(); + let vegetations: HashMap = serde_yaml::from_str(&data).unwrap(); + let sun_config = SunConfig { // sample parameters for Hellion + daylight_hours: 13, + sun_start_elevation: -5.0, + sun_start_azimuth: 92.0, + sun_max_elevation: 50.0, + }; + let sim_config = SimConfig::from_configs(m, bioms, soils, vegetations); + let mut to_be_generated: Vec<&str> = Vec::new(); + for (vegetation, status) in &vegdata.vegetationlist { + if status.clone() == true { + to_be_generated.push(vegetation.as_str()); + } + } + let reflection_coefficient = 0.1; + sim_config.calculate_maps(&sun_config, reflection_coefficient, vegetation_maps); + sim_config.calculate_probabilities(vegetation_maps, to_be_generated.as_slice(), sun_config.daylight_hours, vegetation_collection); } +// TODO falla aquĆ­ - option none dice pub fn collect_values(w: &mut CheckBrowser, data: &mut VegetationData) { let nitems = w.nitems(); for i in 0..nitems { data.vegetationlist.clear(); - data.vegetationlist.insert(w.checked(i as i32), w.text(i as i32).unwrap()); + data.vegetationlist.insert(w.text(i as i32).unwrap(), w.checked(i as i32)); } } -//TODO init soil choice on main to keep track of state - pub fn base_choice_init(w: &mut impl MenuExt) { w.add_choice("Dirt"); w.add_choice("Loam"); diff --git a/src/ui.fl b/src/ui.fl index 375fa7b..d7e9ac0 100644 --- a/src/ui.fl +++ b/src/ui.fl @@ -8,7 +8,7 @@ class UserInterface {open } { Fl_Window main_window { label {OpenBattlesim Map Generator} open - xywh {926 357 870 579} type Single color 55 visible + xywh {51 237 870 579} type Single color 55 visible } { Fl_Menu_Bar menu_bar {open xywh {-1 0 870 30} color 55 @@ -115,7 +115,7 @@ class UserInterface {open } } Fl_Group hydrography_pane { - label Hydrography + label Hydrography open xywh {0 60 895 520} hide } { Fl_Group {} {open @@ -151,21 +151,15 @@ class UserInterface {open } } Fl_Group weather_pane { - label Weather - xywh {0 60 870 520} hide + label Weather open + xywh {0 60 870 520} } { Fl_Group {} {open xywh {0 60 870 520} box BORDER_BOX color 7 } { - Fl_Group weather_preview { - label {Grid Preview} - xywh {28 99 447 446} box BORDER_FRAME color 37 labelcolor 8 - } { - Fl_Box render_target { - label label - xywh {29 100 445 445} labeltype NO_LABEL - } - } + Fl_Group weather_preview {open selected + xywh {28 99 447 446} box BORDER_FRAME color 37 labelcolor 8 align 0 + } {} Fl_Group {} { xywh {500 60 370 520} box FLAT_BOX color 7 align 192 } { @@ -238,6 +232,14 @@ class UserInterface {open Fl_Button wind_mode { xywh {503 333 35 35} color 7 } + Fl_Button twod_vis { + label 2D + xywh {505 467 35 35} color 7 + } + Fl_Button threed_vis { + label 3D + xywh {505 511 35 35} color 7 + } Fl_Value_Slider day_vis_slider { label {Day visualization:} xywh {570 197 265 21} type Horizontal color 7 align 1 minimum 1 maximum 360 step 1 textsize 14 @@ -246,49 +248,53 @@ class UserInterface {open } Fl_Group soil_pane { label Soil open - xywh {0 60 870 520} color 7 + xywh {0 60 870 520} color 7 hide } { Fl_Group {} {open xywh {0 60 870 520} } { - Fl_Box soil_preview { - label {Soil map} - xywh {15 80 230 230} box BORDER_FRAME color 47 align 1 - } - Fl_Box veg_preview { - label {Vegetation previsualization} - xywh {15 335 230 230} box BORDER_FRAME color 47 align 1 - } Fl_Box {} { label Soil xywh {592 62 45 23} box FLAT_BOX color 55 selection_color 55 } - Fl_Button generate_all_button { - label {Generate all} - xywh {290 498 265 25} - } - Fl_Button view_selected_button { - label {View selected} - xywh {290 540 265 25} - } Fl_Button generate_selected_button { label {Generate selected} - xywh {290 458 265 25} + xywh {290 537 265 25} } Fl_Box {} { label {Note: Only 1 vegetation map can be displayed at a time.} - xywh {290 399 265 41} box FLAT_BOX align 128 + xywh {290 483 265 41} box FLAT_BOX align 128 } Fl_Box {} { label {Loaded vegetation definitions:} xywh {595 336 190 22} } - Fl_Box legend_box_soil {selected + Fl_Box legend_box_soil { xywh {290 81 145 229} } Fl_Check_Browser vegetation_list { xywh {595 360 265 205} } + Fl_Box veg_name { + label {Now displaying: []} + xywh {290 450 265 25} + } + Fl_Group {} { + label {Soil preview} open + xywh {15 85 235 475} + } { + Fl_Box soil_preview { + xywh {15 87 230 230} + } + } + Fl_Group {} { + label {Soil preview} open + xywh {12 337 235 230} + } { + Fl_Box veg_preview { + xywh {12 337 235 13} + } + } } Fl_Group soil_opts_group {open xywh {595 70 265 260} box BORDER_FRAME color 35 @@ -334,6 +340,10 @@ class UserInterface {open xywh {640 288 176 25} } } + Fl_Button next_veg { + label Next + xywh {355 415 130 25} + } } } } @@ -346,7 +356,7 @@ class UserInterface {open } { Fl_Window heightmap_dialog_win { label {Heightmap importer} open - xywh {1503 580 425 114} type Single color 55 visible + xywh {1487 580 425 114} type Single color 55 hide } { Fl_Button import_button { label Import diff --git a/src/weather_pane.rs b/src/weather_pane.rs index a20653e..04a839f 100644 --- a/src/weather_pane.rs +++ b/src/weather_pane.rs @@ -1,4 +1,13 @@ +use colorgrad::Color; +use fltk::enums::ColorDepth; +use fltk::frame::Frame; +use fltk::group::Group; +use fltk::image::{PngImage, RgbImage, SharedImage}; use fltk::prelude::{ButtonExt, InputExt, MenuExt, ValuatorExt, WidgetExt}; +use image_crate::{imageops}; +use image_crate::imageops::FilterType; +use image_newest::{ImageBuffer, Rgb}; +use ordered_float::OrderedFloat; use rand::{Rng, thread_rng}; use three_d::{ColorMaterial, Gm, Mesh}; use crate::{FileData, ViewState, WeatherVisualization}; @@ -12,123 +21,87 @@ latitude: 0, grid_size: 16, }; -pub fn vis_image(box: &mut Frame, hour: u32, grid_vector: &mut Vec, state: &ViewState) { - let mut i: ImageBuffer, Vec> = ImageBuffer::new(16, 16); - for component in grid_vector.as_slice() { - let p = &mut cube_vector[component.index.0 as usize + 16 *(component.index.1 as usize + 6 * component.index.2 as usize)]; - let range = match hour { - 0 => 0..24, - _ => (((24 * hour) - 24) as usize)..((24 * hour) as usize) - }; - match state.mode { - Init => {}, - WeatherVisualization::Wind => {}, - WeatherVisualization::Temperature => { - if !component.pressure.is_empty() { - let median = (component.temperature[range.clone()].iter().sum::>().0 as isize) / range.clone().len() as isize; - let color = match median { - -60..=-10 => Color::from_rgba8(30, 92, 179, 255), - -11..=-1 => Color::from_rgba8(4, 161, 230, 255), - 0..=5 => Color::from_rgba8(102, 204, 206, 255), - 6..=10 => Color::from_rgba8(192, 229, 136, 255), - 11..=15 => Color::from_rgba8(204, 230, 75, 255), - 16..=20 => Color::from_rgba8(243, 240, 29, 255), - 21..=25 => Color::from_rgba8(248, 157, 14, 255), - 26..=30 => Color::from_rgba8(219, 30, 38, 255), - 31..=90 => Color::from_rgba8(164, 38, 44, 255), - _ => Color::from_rgba8(255, 255, 255, 255) - }; - let color_rgba = color.to_linear_rgba_u8(); - - - match state.layer { - 0 => {opacity = 10}, - 1 => {if component.index.1 != 0 {opacity = 0}}, - 2 => {if component.index.1 != 1 {opacity = 0}}, - 3 => {if component.index.1 != 2 {opacity = 0}}, - 4 => {if component.index.1 != 3 {opacity = 0}}, - 5 => {if component.index.1 != 4 {opacity = 0}}, - 6 => {if component.index.1 != 5 {opacity = 0}}, - _ => { opacity = 10 } - } - if color.r == 1.0 && color.g == 1.0 && color.b == 1.0 { - opacity = 10; - } - i.put_pixel(component.index.x, component.index.z, Rgba[color.r, color.g, color.b, opacity]); - box.set_image_scaled(None::); - box.set_image_scaled(Some(SharedImage::from_image(i).unwrap())); - box.redraw(); - } - }, - WeatherVisualization::Pressure => { - if !component.pressure.is_empty() { - let median = (component.pressure[range.clone()].iter().sum::>().0 as usize) / range.clone().len(); - let color = match median { - 50..=950 => Color::from_rgba8(40, 40, 255, 255) , - 951..=990 => Color::from_rgba8(102, 102, 255, 255), - 991..=1000 => Color::from_rgba8(161, 161, 255, 255), - 1001..=1015 => Color::from_rgba8(203, 203, 255, 255), - 1016..=1030 => Color::from_rgba8(255, 138, 138, 255), - 1031..=1060 => Color::from_rgba8(255, 103, 103, 255), - 1061..=2000 => Color::from_rgba8(255, 41, 41, 255), - _ => Color::from_rgba8(255, 255, 255, 0) - }; - let color_rgba = color.to_linear_rgba_u8(); - let mut opacity = 10; - match state.layer { - 0 => {opacity = 10}, - 1 => {if component.index.1 != 0 {opacity = 0}}, - 2 => {if component.index.1 != 1 {opacity = 0}}, - 3 => {if component.index.1 != 2 {opacity = 0}}, - 4 => {if component.index.1 != 3 {opacity = 0}}, - 5 => {if component.index.1 != 4 {opacity = 0}}, - 6 => {if component.index.1 != 5 {opacity = 0}}, - _ => { opacity = 10 } - } - i.put_pixel(component.index.x, component.index.z, Rgba[color.r, color.g, color.b, opacity]); - box.set_image_scaled(None::); - box.set_image_scaled(Some(SharedImage::from_image(i).unwrap())); - box.redraw(); - } - }, - WeatherVisualization::Humidity => { - let median = (component.humidity[range.clone()].iter().sum::>().0 as usize) / range.clone().len(); - let color = match median { - 0..=10 => Color::from_rgba8(255, 255, 217, 255), - 11..=20 => Color::from_rgba8(237, 248, 177, 255), - 21..=30 => Color::from_rgba8(199, 233, 180, 255), - 31..=40 => Color::from_rgba8(127, 205, 187, 255), - 41..=50 => Color::from_rgba8(65, 182, 196, 255), - 51..=60 => Color::from_rgba8(29, 145, 192, 255), - 61..=70 => Color::from_rgba8(34, 94, 168, 255), - 71..=80 => Color::from_rgba8(37, 52, 148, 255), - 81..=90 => Color::from_rgba8(8, 29, 88, 255), - 91..=100 => Color::from_rgba8(3, 20, 70, 255), - _ => Color::from_rgba8(255, 255, 255, 0) +pub fn vis_image(r#box: &mut Group, hour: u32, grid_vector: &mut Vec, state: &ViewState) { + let mut i: ImageBuffer, Vec> = ImageBuffer::new(16, 16); + let layer = state.layer; + for component in grid_vector.clone().as_slice() { + if component.index.1 == layer as i32 { + let p = &mut grid_vector[component.index.0 as usize + 16 *(component.index.1 as usize + 6 * component.index.2 as usize)]; + let range = match hour { + 0 => 0..24, + _ => (((24 * hour) - 24) as usize)..((24 * hour) as usize) }; - let color_rgba = color.to_linear_rgba_u8(); - let mut opacity = 10; + match state.mode { + WeatherVisualization::Init => {}, + WeatherVisualization::Wind => {}, + WeatherVisualization::Temperature => { + if !p.temperature.is_empty() { + println!("{:?}", p.index); + let median = (p.temperature[range.clone()].iter().sum::>().0 as isize) / range.clone().len() as isize; + let color = match median { + -60..=-10 => [30, 92, 179], + -11..=-1 => [4, 161, 230], + 0..=5 => [102, 204, 206], + 6..=10 => [192, 229, 136], + 11..=15 => [204, 230, 75], + 16..=20 => [243, 240, 29], + 21..=25 => [248, 157, 14], + 26..=30 => [219, 30, 38], + 31..=90 => [164, 38, 44], + _ => [255, 255, 255] + }; + println!("COLOR: {:?}", color); - match state.layer { - 0 => {opacity = 10}, - 1 => {if component.index.1 != 0 {opacity = 0}}, - 2 => {if component.index.1 != 1 {opacity = 0}}, - 3 => {if component.index.1 != 2 {opacity = 0}}, - 4 => {if component.index.1 != 3 {opacity = 0}}, - 5 => {if component.index.1 != 4 {opacity = 0}}, - 6 => {if component.index.1 != 5 {opacity = 0}}, - _ => { opacity = 10 } - } - if color.r == 1.0 && color.g == 1.0 && color.b == 1.0 { - opacity = 0; - } - i.put_pixel(component.index.x, component.index.z, Rgba[color.r, color.g, color.b, opacity]); - box.set_image_scaled(None::); - box.set_image_scaled(Some(SharedImage::from_image(i).unwrap())); - box.redraw(); } + i.put_pixel(p.index.0 as u32, p.index.2 as u32, Rgb::from([color[0] as u8, color[1] as u8, color[2] as u8])); + + } + }, + WeatherVisualization::Pressure => { + if !p.pressure.is_empty() { + let median = (p.pressure[range.clone()].iter().sum::>().0 as usize) / range.clone().len(); + let color = match median { + 50..=950 => [40, 40, 255] , + 951..=990 => [102, 102, 255], + 991..=1000 => [161, 161, 255], + 1001..=1015 => [203, 203, 255], + 1016..=1030 => [255, 138, 138], + 1031..=1060 => [255, 103, 103], + 1061..=2000 => [255, 41, 41], + _ => [255, 255, 255] + }; + + i.put_pixel(p.index.0 as u32, p.index.2 as u32, Rgb::from([color[0] as u8, color[1] as u8, color[2] as u8])); + + } + }, + WeatherVisualization::Humidity => { + let median = (p.humidity[range.clone()].iter().sum::>().0 as usize) / range.clone().len(); + let color = match median { + 0..=10 => [255, 255, 217], + 11..=20 => [237, 248, 177], + 21..=30 => [199, 233, 180], + 31..=40 => [127, 205, 187], + 41..=50 => [65, 182, 196], + 51..=60 => [29, 145, 192], + 61..=70 => [34, 94, 168], + 71..=80 => [37, 52, 148], + 81..=90 => [8, 29, 88], + 91..=100 => [3, 20, 70], + _ => [255, 255, 255] + }; + i.put_pixel(p.index.0 as u32, p.index.2 as u32, Rgb::from([color[0] as u8, color[1] as u8, color[2] as u8])); + } + } + } } -box.show(); + i.save("test_16.png").unwrap(); + r#box.set_image_scaled(None::); + let a = image_newest::imageops::resize(&i, 1024, 1024, image_newest::imageops::FilterType::Nearest); + let s = RgbImage::new(a.as_raw().as_slice(), 1024, 1024, ColorDepth::Rgb8).unwrap(); + r#box.set_image_scaled(Some(SharedImage::from_image(s).unwrap())); + r#box.redraw(); + a.save("test.png").unwrap(); } pub fn set_hour(w: &mut impl ValuatorExt, state: &mut ViewState) { diff --git a/target/.rustc_info.json b/target/.rustc_info.json index 35cc7a4..b381998 100644 --- a/target/.rustc_info.json +++ b/target/.rustc_info.json @@ -1 +1 @@ -{"rustc_fingerprint":6129803241811068645,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.79.0-nightly (0bf471f33 2024-04-13)\nbinary: rustc\ncommit-hash: 0bf471f339837af930ec90ef5e1e9cb232e99f29\ncommit-date: 2024-04-13\nhost: x86_64-pc-windows-msvc\nrelease: 1.79.0-nightly\nLLVM version: 18.1.3\n","stderr":""},"15341137518005059754":{"success":true,"status":"","code":0,"stdout":"___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nC:\\Users\\xcc1006\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\npacked\n___\nclippy\ndebug_assertions\nfeature=\"cargo-clippy\"\noverflow_checks\npanic=\"unwind\"\nproc_macro\nrelocation_model=\"pic\"\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"cmpxchg16b\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"lahfsahf\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_has_atomic\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"128\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store\ntarget_has_atomic_load_store=\"128\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"pc\"\nub_checks\nwindows\n","stderr":""}},"successes":{}} \ No newline at end of file +{"rustc_fingerprint":17218152085934761169,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.79.0-nightly (0bf471f33 2024-04-13)\nbinary: rustc\ncommit-hash: 0bf471f339837af930ec90ef5e1e9cb232e99f29\ncommit-date: 2024-04-13\nhost: x86_64-pc-windows-msvc\nrelease: 1.79.0-nightly\nLLVM version: 18.1.3\n","stderr":""},"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nC:\\Users\\xcc1006\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\npacked\n___\ndebug_assertions\noverflow_checks\npanic=\"unwind\"\nproc_macro\nrelocation_model=\"pic\"\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"cmpxchg16b\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"lahfsahf\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_has_atomic\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"128\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store\ntarget_has_atomic_load_store=\"128\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"pc\"\nub_checks\nwindows\n","stderr":""}},"successes":{}} \ No newline at end of file diff --git a/test.png b/test.png new file mode 100644 index 0000000000000000000000000000000000000000..e3c911babdae8f708ee6a86260ed63776828da34 GIT binary patch literal 24461 zcmeHP4{Q_H8Gq*_B#>23VGwnj=FqOoN(rGw8;M#t!&rgQCTv40b4U$zEumo~A`4*@ z`^-iKbn1e{7CJ3pPn!hQaQ-w286@?28!OrZaTx3j8*l*>%zBVZFvrDb-`&3V&Veya zn>MLZOP^#Vc6|5l?&ZDj&+qs9zTL~q7C$uUGm{WP4=r7?=$i;-!rM%gV}oBKT<=+g z+$)wYTCieE^UZVZzkY6wt2H*~dieG?ezIo5g3sBWeq(U`j_I>s_~41hXHPqLdf}3n zr|x>AGW=ZIz@zIY{BBlo!wc=h_^sL3Xv2+l;D$qJtT5 z`Tdf-4^>U{HNiLb0VR8bXZsWsRFaP&mlUtl^~tD+8JLXP73P@X3l`Vf0$pA%(^>8D zw(xFS;Bn-#6&#uGj5^wstTNOo$c->`B%-LxP-mud89FXxU)M5@gu)Yjf~G$VL*skJ z*Mp0m(@-TB7V=BrPIwlEp3g?bVtlea5wY^+7es?swyn-vn1=n##+#D4W|$k&pc($pTq9*8uy#x5vVO@-UiUkPq6guss_ zMVGsPcpiawW7qXm?s9NL7feC3O~>A<%g`rb_xf!gd>Asih5Q_RSWuB)#NO(p?JT%E zmG25UbFfzoay;>H(*p3}s2NnU7UILI_2g9S6+2K@rn6742^QxO?<o~8A2z}B0Xgcbd2hqE}2F~=G5StrJE=0TNz8gcG^v39n(KSYQB{dh+z*3h)edU7{ zU5I0sxJzDNQ6Q)=onB7RZ*+4?={wuvvY|lc8i}}#U$OvQnnT$vP=jou0~o~>nYEau zbIfMK6D{VA&~NagUCDkP)e`hEP3B>8O=qT{W`Z%MsX7Nyoe*j*H zjAZifjl2n}4P~!I7Trzz(IHIp>`E&jnh=^n=$^Y+qVG+@=inb$BY^^s z-iI2{)9KXVl|h%y+K5NG#}R!37})1@OjveUW+4}c z?EDI5N79K^?OKod3(&@b6KPEXp>6p`F#Ab61ly3cZ^491I%{uUDRK~Ez73Bqg|Pb} z@g~dzy=6MfbYal#_rO>Tu-|;@lpE;b8gpbZ=8}ehSVQLmcF7pY9)p*14C}r7hrP>XeS0dpU2Y7ar3(ngQfH!It6qU z(2ejR+k((&E`OV4xy_y=XNrJBj#q;bu?$n`2(ZbUZco_^Dfa@A$Y@=n-jA^eP|-x@ zn!|2CV3%wymuNHwaa@Uk0}#w)^gF6-Xh9zR^gcwwKk>lU9B2s!1 zod~)ja1=nd2DK3+m8Qn>fAku{HZ;z&*#`*ER`}C@;n_0UKEH?6M^)mtmJ1mNteRip zp6kLCo3G&rt|4wsW8P4F<-?fC;C@n*T%Cr~tDp!Pqa$0^ks4=L8cugfc7mT@I#0@p z>CkjS=nA1*hT4$-%c!bv$;Npz?r+lHSG}VkLnE^Pj826V)?VnE&j}_26|#~jkLM#Y zzY*#M(2uP`*a$SJNQ2-|9#DdH5Fq@A<`WhGBS1C4;4Uj|Nj;2%f74~4!xg;w&mec%jPVHC z*12)sU^FP(NgIP;h3Sh1MGi}Vu?iT9vTz$6#?@^wtuO{Kiue`i3b8p*%>^gx883Bv z&8##G4&_;SAQ#T6x~OIMZq&irmgT?;@Fb%E>bi0Vjw$vn7d1T}D~I6~RP+U)InEE% zOOBCaN)oL5bo_Ej$sa<6SFuwP*ui>9bz>9_E06^>8&t+_p8(Zgk|2ZO-+^CM^a1F9 zfG#1ri3u4;t#6g zIHV7QKE}myQI(_!(46iI@Fm)e8H{94$Rykay;VA^bgj~D^-(icP^DKqKh{E;i47Uh zF*8z}y2?Xgi8*%44YED2*_1dBjXBL*b2;dMkXENa&o0z;!4Ew&+kHn;Mp3*2nq`s} zU!MvzCC@cN2QWwRO<=lXNqC#95>s zgjS$414TU7m)a1Fl;h3zRK_9lOpRHcLu$>>{Gf1u0^4nR^K|C1pnxtLbewKjwDuEk zZM64QBkpIpLx)+!-{}#*f4_{pFx8!~DhQ36<>r;rcT!e&XYdPRVy_5p!p)^r5Hsp( zK8VJ_^7hWLpc}W7cm*6KkMyVWB8Ie%oC4-Q{0ynyhOUw;uyx1!MI>8Q-a`IzV!`QP sAndI6&^e<^1CmU-ojz2nVQ`JFE<4kqZJG^j_R-R>l`U#nxcUeG0N@y$U;qFB literal 0 HcmV?d00001 diff --git a/test_16.png b/test_16.png new file mode 100644 index 0000000000000000000000000000000000000000..129edf420c4857ded270fadaa3f1ee813b397cdf GIT binary patch literal 478 zcmV<40U`d0P)_{e)L8Z54RI4;rw+B+e>-A-}P_!u@e+DlY zjs1J#u2Jq_hPX3Qes}>&8DpqqEJIdrRuNQqGBI}&RFDR*8v=BJ^@WyXNQl#sbh6%$ zPP2s~wz+GSh8d9luNW`s&oATAP(v*_wgzJ_CzL={W|{!X9n6HF-X2sSGbGAdr2)rL ztyDmlEfhgQ4dyZ{rOCtMStw12$Btf;^b9U#_jdW!+fM;?4F`C&_A99nv+*@#ngHd5 z#9ovGN@-l^;TF)5CdnV)Fw=1glplme2yEG_IPmntp~l{Usuv|hF9%6OuOg%)VdxA7 zaycYTEMM)s+UFF9i~Np&P2@!5#S9a*3mRB#`fG4