use std::ops::Range;
use geo_types::CoordNum;
use num_traits::cast;
use rand::Rng;
use crate::{Dummy, Fake, Faker};
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::Coord<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
geo_types::Coord::<T> {
x: Faker.fake_with_rng(rng),
y: Faker.fake_with_rng(rng),
}
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::Line<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
geo_types::Line::<T> {
start: Faker.fake_with_rng(rng),
end: Faker.fake_with_rng(rng),
}
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::LineString<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
geo_types::LineString::<T>::new(Faker.fake_with_rng(rng))
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::MultiLineString<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
geo_types::MultiLineString::<T>::new(Faker.fake_with_rng(rng))
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::Point<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
geo_types::Point::<T>::new(Faker.fake_with_rng(rng), Faker.fake_with_rng(rng))
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::MultiPoint<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
geo_types::MultiPoint::<T>::new(Faker.fake_with_rng(rng))
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::Polygon<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
geo_types::Polygon::<T>::new(Faker.fake_with_rng(rng), Faker.fake_with_rng(rng))
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::MultiPolygon<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
geo_types::MultiPolygon::<T>::new(Faker.fake_with_rng(rng))
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::Rect<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
let nums: Vec<T> = crate::unique::<T, _>(rng, 4);
let coord_1 = geo_types::Coord::<T> {
x: nums[0],
y: nums[1],
};
let coord_2 = geo_types::Coord::<T> {
x: nums[2],
y: nums[3],
};
geo_types::Rect::new::<geo_types::Coord<T>>(coord_1, coord_2)
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::Triangle<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
fn abs_slope<T>(a: geo_types::Coord<T>, b: geo_types::Coord<T>) -> f64
where
T: CoordNum,
{
let (min_x, max_x) = if a.x > b.x { (b.x, a.x) } else { (a.x, b.x) };
let (min_y, max_y) = if a.y > b.y { (b.y, a.y) } else { (a.y, b.y) };
let delta_x: f64 = cast(max_x - min_x).unwrap();
let delta_y: f64 = cast(max_y - min_y).unwrap();
delta_y / delta_x
}
let nums: Vec<T> = crate::unique::<T, _>(rng, 6);
let coord_1 = geo_types::Coord::<T> {
x: nums[0],
y: nums[1],
};
let coord_2 = geo_types::Coord::<T> {
x: nums[2],
y: nums[3],
};
let slope_1 = abs_slope(coord_1, coord_2);
let mut coord_3 = geo_types::Coord::<T> {
x: nums[4],
y: nums[5],
};
let slope_2 = abs_slope(coord_2, coord_3);
if slope_1 == slope_2 {
coord_3 = geo_types::Coord::<T> {
x: nums[5],
y: nums[4],
};
}
geo_types::Triangle::<T>::new(coord_1, coord_2, coord_3)
}
}
const GEOMETRY_UNION_MEMBERS_IGNORE_RECURSIVE: usize = 7;
const GEOMETRY_UNION_MEMBERS: Range<usize> = 0..9;
struct NonRecursiveGeometry<T: CoordNum = f64>(geo_types::Geometry<T>);
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for NonRecursiveGeometry<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
let union_index: usize = GEOMETRY_UNION_MEMBERS.fake_with_rng(rng);
match union_index {
0 => NonRecursiveGeometry(geo_types::geometry::Geometry::Point::<T>(
Faker.fake_with_rng(rng),
)),
1 => NonRecursiveGeometry(geo_types::geometry::Geometry::Line::<T>(
Faker.fake_with_rng(rng),
)),
2 => NonRecursiveGeometry(geo_types::geometry::Geometry::LineString::<T>(
Faker.fake_with_rng(rng),
)),
3 => NonRecursiveGeometry(geo_types::geometry::Geometry::Polygon::<T>(
Faker.fake_with_rng(rng),
)),
4 => NonRecursiveGeometry(geo_types::geometry::Geometry::MultiPoint::<T>(
Faker.fake_with_rng(rng),
)),
5 => NonRecursiveGeometry(geo_types::geometry::Geometry::MultiLineString::<T>(
Faker.fake_with_rng(rng),
)),
6 => NonRecursiveGeometry(geo_types::geometry::Geometry::MultiPolygon::<T>(
Faker.fake_with_rng(rng),
)),
GEOMETRY_UNION_MEMBERS_IGNORE_RECURSIVE => NonRecursiveGeometry(
geo_types::geometry::Geometry::Point::<T>(Faker.fake_with_rng(rng)),
),
8 => NonRecursiveGeometry(geo_types::geometry::Geometry::Rect::<T>(
Faker.fake_with_rng(rng),
)),
9 => NonRecursiveGeometry(geo_types::geometry::Geometry::Triangle::<T>(
Faker.fake_with_rng(rng),
)),
_ => panic!(),
}
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::Geometry<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
let union_index: usize = GEOMETRY_UNION_MEMBERS.fake_with_rng(rng);
match union_index {
0 => geo_types::geometry::Geometry::Point::<T>(Faker.fake_with_rng(rng)),
1 => geo_types::geometry::Geometry::Line::<T>(Faker.fake_with_rng(rng)),
2 => geo_types::geometry::Geometry::LineString::<T>(Faker.fake_with_rng(rng)),
3 => geo_types::geometry::Geometry::Polygon::<T>(Faker.fake_with_rng(rng)),
4 => geo_types::geometry::Geometry::MultiPoint::<T>(Faker.fake_with_rng(rng)),
5 => geo_types::geometry::Geometry::MultiLineString::<T>(Faker.fake_with_rng(rng)),
6 => geo_types::geometry::Geometry::MultiPolygon::<T>(Faker.fake_with_rng(rng)),
7 => geo_types::geometry::Geometry::GeometryCollection::<T>(Faker.fake_with_rng(rng)),
8 => geo_types::geometry::Geometry::Rect::<T>(Faker.fake_with_rng(rng)),
9 => geo_types::geometry::Geometry::Triangle::<T>(Faker.fake_with_rng(rng)),
_ => panic!(),
}
}
}
impl<T: CoordNum + Dummy<Faker>> Dummy<Faker> for geo_types::GeometryCollection<T> {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
geo_types::GeometryCollection::<T>::new_from(
Faker
.fake_with_rng::<Vec<NonRecursiveGeometry<T>>, _>(rng)
.iter()
.map(|x| (x.0.to_owned()))
.collect::<Vec<geo_types::Geometry<T>>>(),
)
}
}