use crate::noise::NoiseProvider;
use std::default::Default;
use std::ops::{Add, Mul};
use std::cmp;
use std::sync::atomic::{AtomicUsize, Ordering};
pub use self::property::{Seed, Step, Size, Property};
mod property;
static NEXT_NM_ID: AtomicUsize = AtomicUsize::new(0);
pub fn next_id() -> u64 {
NEXT_NM_ID.fetch_add(1, Ordering::SeqCst) as u64
}
pub trait NoiseMapGeneratorBase {
fn generate_chunk(&self, x: i64, y: i64) -> Vec<Vec<f64>>;
fn generate_sized_chunk(&self, size: Size, x: i64, y: i64) -> Vec<Vec<f64>>;
fn id(&self) -> u64;
}
pub trait NoiseMapGenerator : NoiseMapGeneratorBase + Clone + Mul<i64, Output=ScaledNoiseMap<Self>> {
fn set<P: Property>(self, property: P) -> Self where Self: Sized;
fn set_size(self, size: Size) -> Self where Self: Sized;
fn set_seed(self, seed: Seed) -> Self where Self: Sized;
fn set_step(self, step: Step) -> Self where Self: Sized;
fn get_size(&self) -> Size where Self: Sized;
}
#[derive(Default, Debug, Clone, Copy)]
pub struct NoiseMap<T> {
seed: Seed,
step: Step,
size: Size,
noise: T,
id: u64
}
#[derive(Debug, Clone, Copy)]
pub struct ScaledNoiseMap<T> {
nm: T,
scale: i64,
id: u64
}
#[derive(Debug, Clone, Copy)]
pub struct NoiseMapCombination<T1, T2> {
nm1: T1,
nm2: T2,
outer: bool,
total_scale: i64,
id: u64
}
impl<T: NoiseProvider> NoiseMap<T> {
pub fn new(noise: T) -> NoiseMap<T> {
NoiseMap {
noise,
id: next_id(),
..Default::default()
}
}
}
impl<T: NoiseProvider> NoiseMapGeneratorBase for NoiseMap<T> {
fn generate_chunk(&self, x: i64, y: i64) -> Vec<Vec<f64>> {
let size = self.size;
self.generate_sized_chunk(size, x, y)
}
fn generate_sized_chunk(&self, size: Size, x: i64, y: i64) -> Vec<Vec<f64>> {
(y * size.h .. (y + 1) * size.h).map(|y| y as f64 * self.step.y)
.map(|y| (x * size.w .. (x + 1) * size.w).map(|x| x as f64 * self.step.x)
.map(|x| self.noise.generate(x, y, self.seed.value)).collect()
).collect()
}
fn id(&self) -> u64 {
self.id
}
}
impl<T: NoiseProvider> NoiseMapGenerator for NoiseMap<T> {
fn set<P: Property>(self, property: P) -> NoiseMap<T> {
property.set_to(self)
}
fn get_size(&self) -> Size {
self.size
}
fn set_seed(self, seed: Seed) -> NoiseMap<T> {
NoiseMap {
seed,
..self
}
}
fn set_step(self, step: Step) -> NoiseMap<T> {
NoiseMap {
step,
..self
}
}
fn set_size(self, size: Size) -> NoiseMap<T> {
NoiseMap {
size,
..self
}
}
}
impl<T: NoiseMapGenerator> NoiseMapGeneratorBase for ScaledNoiseMap<T> {
fn generate_chunk(&self, x: i64, y: i64) -> Vec<Vec<f64>> {
let size = self.nm.get_size();
self.generate_sized_chunk(size, x, y)
}
fn generate_sized_chunk(&self, size: Size, x: i64, y: i64) -> Vec<Vec<f64>> {
self.nm.generate_sized_chunk(size, x, y).iter().map(|row| row.iter().map(|value| value * self.scale as f64).collect()).collect()
}
fn id(&self) -> u64 {
self.id
}
}
impl<T: NoiseMapGenerator> NoiseMapGenerator for ScaledNoiseMap<T> {
fn set<P: Property>(self, property: P) -> ScaledNoiseMap<T> {
ScaledNoiseMap {
nm: self.nm.set(property),
..self
}
}
fn get_size(&self) -> Size {
self.nm.get_size()
}
fn set_seed(self, seed: Seed) -> ScaledNoiseMap<T> {
self.set(seed)
}
fn set_step(self, step: Step) -> ScaledNoiseMap<T> {
self.set(step)
}
fn set_size(self, size: Size) -> ScaledNoiseMap<T> {
self.set(size)
}
}
impl<T> ScaledNoiseMap<T> {
pub fn new(nm: T, scale: i64) -> ScaledNoiseMap<T> {
ScaledNoiseMap {
nm,
scale,
id: next_id()
}
}
pub fn scale(&self) -> i64 {
self.scale
}
}
impl<T1: NoiseMapGenerator, T2: NoiseMapGenerator> NoiseMapGeneratorBase for NoiseMapCombination<T1, T2> {
fn generate_chunk(&self, x: i64, y: i64) -> Vec<Vec<f64>> {
let size = self.get_size();
self.generate_sized_chunk(size, x, y)
}
fn generate_sized_chunk(&self, size: Size, x: i64, y: i64) -> Vec<Vec<f64>> {
if self.outer {
let nm1_map = self.nm1.generate_sized_chunk(size, x, y);
let nm2_map = self.nm2.generate_sized_chunk(size, x, y);
nm1_map.iter().zip(nm2_map.iter()).map(|(lr, rr)| lr.iter().zip(rr.iter()).map(|(lv, rv)| (lv + rv) / self.total_scale as f64).collect()).collect()
} else {
let nm1_map = self.nm1.generate_sized_chunk(size, x, y);
let nm2_map = self.nm2.generate_sized_chunk(size, x, y);
nm1_map.iter().zip(nm2_map.iter()).map(|(lr, rr)| lr.iter().zip(rr.iter()).map(|(lv, rv)| lv + rv).collect()).collect()
}
}
fn id(&self) -> u64 {
self.id
}
}
impl<T1: NoiseMapGenerator, T2: NoiseMapGenerator> NoiseMapGenerator for NoiseMapCombination<T1, T2> {
fn set<P: Property>(self, property: P) -> NoiseMapCombination<T1, T2> {
NoiseMapCombination {
nm1: self.nm1.set(property),
nm2: self.nm2.set(property),
..self
}
}
fn get_size(&self) -> Size {
self.nm1.get_size()
}
fn set_seed(self, seed: Seed) -> NoiseMapCombination<T1, T2> {
self.set(seed)
}
fn set_step(self, step: Step) -> NoiseMapCombination<T1, T2> {
self.set(step)
}
fn set_size(self, size: Size) -> NoiseMapCombination<T1, T2> {
self.set(size)
}
}
impl<T1, T2> NoiseMapCombination<T1, T2> {
fn inner(self) -> NoiseMapCombination<T1, T2> {
NoiseMapCombination {
outer: false,
..self
}
}
}
impl<T: NoiseProvider> Mul<i64> for NoiseMap<T> {
type Output = ScaledNoiseMap<NoiseMap<T>>;
fn mul(self, scale: i64) -> ScaledNoiseMap<NoiseMap<T>> {
ScaledNoiseMap::new(self, scale)
}
}
impl<T: NoiseMapGenerator> Mul<i64> for ScaledNoiseMap<T> {
type Output = ScaledNoiseMap<ScaledNoiseMap<T>>;
fn mul(self, scale: i64) -> ScaledNoiseMap<ScaledNoiseMap<T>> {
ScaledNoiseMap::new(self, scale)
}
}
impl<T1: NoiseMapGenerator, T2: NoiseMapGenerator> Mul<i64> for NoiseMapCombination<T1, T2> {
type Output = ScaledNoiseMap<NoiseMapCombination<T1, T2>>;
fn mul(self, scale: i64) -> ScaledNoiseMap<NoiseMapCombination<T1, T2>> {
ScaledNoiseMap::new(self, scale)
}
}
impl<T1: NoiseProvider, T2: NoiseProvider> Add<NoiseMap<T2>> for NoiseMap<T1> {
type Output = NoiseMapCombination<NoiseMap<T1>, NoiseMap<T2>>;
fn add(self, rhs: NoiseMap<T2>) -> Self::Output {
NoiseMapCombination {
nm1: self,
nm2: rhs,
outer: true,
total_scale: 2,
id: next_id(),
}.set(cmp::max(self.get_size(), rhs.get_size()))
}
}
impl<T1: NoiseProvider, T2: NoiseMapGenerator> Add<ScaledNoiseMap<T2>> for NoiseMap<T1> {
type Output = NoiseMapCombination<NoiseMap<T1>, ScaledNoiseMap<T2>>;
fn add(self, rhs: ScaledNoiseMap<T2>) -> Self::Output {
rhs + self
}
}
impl<T: NoiseProvider, T1: NoiseMapGenerator, T2: NoiseMapGenerator> Add<NoiseMapCombination<T1, T2>> for NoiseMap<T> {
type Output = NoiseMapCombination<NoiseMap<T>, NoiseMapCombination<T1, T2>>;
fn add(self, rhs: NoiseMapCombination<T1, T2>) -> Self::Output {
rhs + self
}
}
impl<T1: NoiseMapGenerator, T2: NoiseProvider> Add<NoiseMap<T2>> for ScaledNoiseMap<T1> {
type Output = NoiseMapCombination<NoiseMap<T2>, ScaledNoiseMap<T1>>;
fn add(self, rhs: NoiseMap<T2>) -> Self::Output {
let scale = self.scale;
let s1 = self.get_size();
let s2 = rhs.get_size();
NoiseMapCombination {
nm1: rhs,
nm2: self,
outer: true,
total_scale: scale + 1,
id: next_id(),
}.set(cmp::max(s1, s2))
}
}
impl<T1: NoiseMapGenerator, T2: NoiseMapGenerator> Add<ScaledNoiseMap<T2>> for ScaledNoiseMap<T1> {
type Output = NoiseMapCombination<ScaledNoiseMap<T1>, ScaledNoiseMap<T2>>;
fn add(self, rhs: ScaledNoiseMap<T2>) -> Self::Output {
let scale1 = self.scale;
let scale2 = rhs.scale;
let s1 = self.get_size();
let s2 = rhs.get_size();
NoiseMapCombination {
nm1: self,
nm2: rhs,
outer: true,
total_scale: scale1 + scale2,
id: next_id(),
}.set(cmp::max(s1, s2))
}
}
impl<T: NoiseMapGenerator, T1: NoiseMapGenerator, T2: NoiseMapGenerator> Add<NoiseMapCombination<T1, T2>> for ScaledNoiseMap<T> {
type Output = NoiseMapCombination<ScaledNoiseMap<T>, NoiseMapCombination<T1, T2>>;
fn add(self, rhs: NoiseMapCombination<T1, T2>) -> Self::Output {
rhs + self
}
}
impl<T: NoiseProvider, T1: NoiseMapGenerator, T2: NoiseMapGenerator> Add<NoiseMap<T>> for NoiseMapCombination<T1, T2> {
type Output = NoiseMapCombination<NoiseMap<T>, NoiseMapCombination<T1, T2>>;
fn add(self, rhs: NoiseMap<T>) -> Self::Output {
let scale = self.total_scale;
let s1 = self.get_size();
let s2 = rhs.get_size();
NoiseMapCombination {
nm1: rhs,
nm2: self.inner(),
outer: true,
total_scale: 1 + scale,
id: next_id(),
}.set(cmp::max(s1, s2))
}
}
impl<T: NoiseMapGenerator, T1: NoiseMapGenerator, T2: NoiseMapGenerator> Add<ScaledNoiseMap<T>> for NoiseMapCombination<T1, T2> {
type Output = NoiseMapCombination<ScaledNoiseMap<T>, NoiseMapCombination<T1, T2>>;
fn add(self, rhs: ScaledNoiseMap<T>) -> Self::Output {
let scale1 = rhs.scale();
let scale2 = self.total_scale;
let s1 = self.get_size();
let s2 = rhs.get_size();
let inner = self.inner();
NoiseMapCombination {
nm1: rhs,
nm2: inner,
outer: true,
total_scale: scale1 + scale2,
id: next_id(),
}.set(cmp::max(s1, s2))
}
}
impl<L1: NoiseMapGenerator, L2: NoiseMapGenerator, R1: NoiseMapGenerator, R2: NoiseMapGenerator> Add<NoiseMapCombination<R1, R2>> for NoiseMapCombination<L1, L2> {
type Output = NoiseMapCombination<NoiseMapCombination<L1, L2>, NoiseMapCombination<R1, R2>>;
fn add(self, rhs: NoiseMapCombination<R1, R2>) -> Self::Output {
let scale1 = rhs.total_scale;
let scale2 = self.total_scale;
let s1 = self.get_size();
let s2 = rhs.get_size();
let inner1 = self.inner();
let inner2 = rhs.inner();
NoiseMapCombination {
nm1: inner1,
nm2: inner2,
outer: true,
total_scale: scale1 + scale2,
id: next_id(),
}.set(cmp::max(s1, s2))
}
}