use alloc::{
slice::{Iter, IterMut},
vec::{IntoIter, Vec},
};
use core::ops::{Index, IndexMut};
#[cfg(feature = "images")]
use std::path::Path;
const RASTER_MAX_WIDTH: u16 = 32_767;
const RASTER_MAX_HEIGHT: u16 = 32_767;
pub struct NoiseMap {
size: (usize, usize),
border_value: f64,
map: Vec<f64>,
}
impl NoiseMap {
pub fn new(width: usize, height: usize) -> Self {
Self::initialize().set_size(width, height)
}
pub fn iter(&self) -> Iter<'_, f64> {
self.map.iter()
}
pub fn iter_mut(&mut self) -> IterMut<'_, f64> {
self.map.iter_mut()
}
pub fn set_size(self, width: usize, height: usize) -> Self {
assert!(width < RASTER_MAX_WIDTH as usize);
assert!(height < RASTER_MAX_HEIGHT as usize);
if width == 0 || height == 0 {
Self::initialize()
} else {
let map_size = width * height;
if self.map.capacity() < map_size {
Self {
map: vec![0.0; map_size],
size: (width, height),
..self
}
} else {
Self {
size: (width, height),
..self
}
}
}
}
pub fn size(&self) -> (usize, usize) {
self.size
}
pub fn set_border_value(self, border_value: f64) -> Self {
Self {
border_value,
..self
}
}
pub fn border_value(&self) -> f64 {
self.border_value
}
pub fn set_value(&mut self, x: usize, y: usize, value: f64) {
let (width, height) = self.size;
if x < width && y < height {
self.map[x + y * width] = value;
} else {
}
}
pub fn get_value(&self, x: usize, y: usize) -> f64 {
let (width, height) = self.size;
if x < width && y < height {
self.map[x + y * width]
} else {
self.border_value
}
}
#[cfg(feature = "images")]
pub fn write_to_file(&self, filename: &Path) {
let (width, height) = self.size;
let mut pixels: Vec<u8> = Vec::with_capacity(width * height);
for i in &self.map {
pixels.push(((i * 0.5 + 0.5).clamp(0.0, 1.0) * 255.0) as u8);
}
let _ = image::save_buffer(
filename,
&pixels,
self.size.0 as u32,
self.size.1 as u32,
image::ColorType::L8,
);
println!("\nFinished generating {}", filename.to_string_lossy());
}
fn initialize() -> Self {
Self {
size: (0, 0),
border_value: 0.0,
map: Vec::new(),
}
}
}
impl Default for NoiseMap {
fn default() -> Self {
Self::initialize()
}
}
impl Index<(usize, usize)> for NoiseMap {
type Output = f64;
fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
let (width, height) = self.size;
if x < width && y < height {
&self.map[x + y * width]
} else {
&self.border_value
}
}
}
impl IndexMut<(usize, usize)> for NoiseMap {
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
let (width, height) = self.size;
if x < width && y < height {
&mut self.map[x + y * width]
} else {
panic!(
"index ({}, {}) out of bounds for NoiseMap of size ({}, {})",
x, y, width, height
)
}
}
}
impl IntoIterator for NoiseMap {
type Item = f64;
type IntoIter = IntoIter<f64>;
fn into_iter(self) -> Self::IntoIter {
self.map.into_iter()
}
}
impl<'a> IntoIterator for &'a NoiseMap {
type Item = &'a f64;
type IntoIter = Iter<'a, f64>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut NoiseMap {
type Item = &'a mut f64;
type IntoIter = IterMut<'a, f64>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}