use num_traits::FloatConst;
use geo::CoordFloat;
use geo_types::Coord;
use crate::clip::clipper::Connectable as ConnectableClip;
use crate::clip::rectangle::Rectangle;
use crate::path::bounds::Bounds;
use crate::path::Result;
use crate::projection::builder::template::PCNC;
use crate::projection::projector_common::Projector;
use crate::projection::Build;
use crate::projection::ClipExtentGet;
use crate::projection::ScaleSet;
use crate::projection::TranslateSet;
use crate::stream::Connectable;
use crate::stream::Stream;
use crate::stream::Streamable;
use crate::stream::Unconnected;
use crate::Transform;
use super::projector_common::Source;
use super::ClipExtentAdjust;
use super::Projector as ProjectorTrait;
use super::TranslateGet;
pub(super) fn fit_reclip<B, CLIPC, CLIPU, FB, PR, RC, RU, T>(
builder: &B,
mut fit_bounds: FB,
object: &impl Streamable<T = T>,
) -> B
where
B: Build<
Projector = Projector<
CLIPU,
Bounds<T>,
Rectangle<Unconnected, T>,
PR,
RU,
Source<CLIPC, T>,
T,
>,
> + Clone
+ ClipExtentGet<T = T>
+ ClipExtentAdjust<T = T>
+ ScaleSet<T = T>
+ TranslateSet<T = T>,
CLIPC: Clone + Stream<EP = Bounds<T>, T = T>,
CLIPU: Clone + ConnectableClip<Output = CLIPC, SC = RC>,
FB: FnMut([Coord<T>; 2], &B) -> B,
PR: Transform<T = T>,
RU: Clone + Connectable<Output<PCNC<Bounds<T>, T>> = RC>,
T: 'static + CoordFloat + FloatConst,
{
let mut b = builder.clone();
b.scale_set(T::from(150_f64).unwrap());
b.translate_set(&Coord {
x: T::zero(),
y: T::zero(),
});
let mut projector = b.build();
let bounds_stream = Bounds::default();
let mut stream_in = projector.stream(&bounds_stream);
object.to_stream(&mut stream_in);
let bounds = stream_in.endpoint().result();
fit_bounds(bounds, &mut b)
}
pub(super) fn fit_extent_reclip<B, CLIPC, CLIPU, PR, RC, RU, T>(
builder: &B,
extent: [Coord<T>; 2],
object: &impl Streamable<T = T>,
) -> B
where
B: Build<
Projector = Projector<
CLIPU,
Bounds<T>,
Rectangle<Unconnected, T>,
PR,
RU,
Source<CLIPC, T>,
T,
>,
> + Clone
+ ClipExtentGet<T = T>
+ ClipExtentAdjust<T = T>
+ ScaleSet<T = T>
+ TranslateGet<T = T>
+ TranslateSet<T = T>,
CLIPC: Clone + Stream<EP = Bounds<T>, T = T>,
CLIPU: Clone + ConnectableClip<Output = CLIPC, SC = RC>,
PR: Transform<T = T>,
RU: Clone + Connectable<Output<PCNC<Bounds<T>, T>> = RC>,
T: 'static + CoordFloat + FloatConst,
{
let two = T::from(2.0_f64).unwrap();
let one_five_zero = T::from(150_f64).unwrap();
fit_reclip(
builder,
|b: [Coord<T>; 2], builder: &B| -> B {
let w = extent[1].x - extent[0].x;
let h = extent[1].y - extent[0].y;
let k = T::min(w / (b[1].x - b[0].x), h / (b[1].y - b[0].y));
let x = extent[0].x + (w - k * (b[1].x + b[0].x)) / two;
let y = extent[0].y + (h - k * (b[1].y + b[0].y)) / two;
let mut out: B = builder.clone();
out.scale_set(one_five_zero * k);
out.translate_set(&Coord { x, y });
out
},
object,
)
}
pub(super) fn fit_size_reclip<B, CLIPC, CLIPU, PR, RC, RU, T>(
builder: &B,
size: Coord<T>,
object: &impl Streamable<T = T>,
) -> B
where
B: Build<
Projector = Projector<
CLIPU,
Bounds<T>,
Rectangle<Unconnected, T>,
PR,
RU,
Source<CLIPC, T>,
T,
>,
> + ClipExtentAdjust<T = T>
+ ClipExtentGet<T = T>
+ Clone
+ ScaleSet<T = T>
+ TranslateGet<T = T>
+ TranslateSet<T = T>,
CLIPC: Clone + Stream<EP = Bounds<T>, T = T>,
CLIPU: Clone + ConnectableClip<Output = CLIPC, SC = RC>,
PR: Transform<T = T>,
RU: Clone + Connectable<Output<PCNC<Bounds<T>, T>> = RC>,
T: 'static + CoordFloat + FloatConst,
{
fit_extent_reclip(
builder,
[
Coord {
x: T::zero(),
y: T::zero(),
},
size,
],
object,
)
}
pub(super) fn fit_width_reclip<B, CLIPC, CLIPU, PR, RC, RU, T>(
builder: &B,
width: T,
object: &impl Streamable<T = T>,
) -> B
where
B: Build<
Projector = Projector<
CLIPU,
Bounds<T>,
Rectangle<Unconnected, T>,
PR,
RU,
Source<CLIPC, T>,
T,
>,
> + Clone
+ ClipExtentGet<T = T>
+ ClipExtentAdjust<T = T>
+ ScaleSet<T = T>
+ TranslateSet<T = T>,
CLIPC: Clone + Stream<EP = Bounds<T>, T = T>,
CLIPU: Clone + ConnectableClip<Output = CLIPC, SC = RC>,
PR: Transform<T = T>,
RU: Clone + Connectable<Output<PCNC<Bounds<T>, T>> = RC>,
T: 'static + CoordFloat + FloatConst,
{
let two = T::from(2.0_f64).unwrap();
let one_five_zero = T::from(150_f64).unwrap();
fit_reclip(
builder,
|b: [Coord<T>; 2], builder: &B| -> B {
let w = width;
let k = w / (b[1].x - b[0].x);
let x = (w - k * (b[1].x + b[0].x)) / two;
let y = -k * b[0].y;
let mut out = builder.clone();
out.scale_set(one_five_zero * k);
out.translate_set(&Coord { x, y });
out
},
object,
)
}
pub(super) fn fit_height_reclip<B, CLIPC, CLIPU, PR, RC, RU, T>(
builder: &B,
height: T,
object: &impl Streamable<T = T>,
) -> B
where
PR: Clone + Transform<T = T>,
B: Build<
Projector = Projector<
CLIPU,
Bounds<T>,
Rectangle<Unconnected, T>,
PR,
RU,
Source<CLIPC, T>,
T,
>,
> + Clone
+ ClipExtentGet<T = T>
+ ClipExtentAdjust<T = T>
+ ScaleSet<T = T>
+ TranslateSet<T = T>,
CLIPC: Clone + Stream<EP = Bounds<T>, T = T>,
CLIPU: Clone + ConnectableClip<Output = CLIPC, SC = RC>,
RU: Clone + Connectable<Output<PCNC<Bounds<T>, T>> = RC>,
T: 'static + CoordFloat + FloatConst,
{
let two = T::from(2.0_f64).unwrap();
let one_five_zero = T::from(150_f64).unwrap();
fit_reclip(
builder,
|b: [Coord<T>; 2], builder: &B| -> B {
let h = height;
let k = h / (b[1].y - b[0].y);
let x = -k * b[0].x;
let y = (h - k * (b[1].y + b[0].y)) / two;
let mut out = builder.clone();
out.scale_set(one_five_zero * k);
out.translate_set(&Coord { x, y });
out
},
object,
)
}