use std::hash::{Hash, Hasher};
pub type Position = [f32; 2];
pub type Rgb = [f32; 3];
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Point {
pub position: Position,
pub color: Rgb,
pub weight: u32,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct RawPoint {
pub position: Position,
pub color: Rgb,
}
impl Point {
pub const DEFAULT_LINE_POINT_WEIGHT: u32 = 0;
pub fn new(position: Position, color: Rgb) -> Self {
Point::with_weight(position, color, Self::DEFAULT_LINE_POINT_WEIGHT)
}
pub fn with_weight(position: Position, color: Rgb, weight: u32) -> Self {
Point {
position,
color,
weight,
}
}
pub fn centered_blank() -> Self {
Point::new([0.0, 0.0], [0.0, 0.0, 0.0])
}
pub fn blanked(&self) -> Self {
let mut blanked = *self;
blanked.color = [0.0, 0.0, 0.0];
blanked
}
pub fn is_blank(&self) -> bool {
color_is_blank(self.color)
}
pub fn to_raw(&self) -> RawPoint {
RawPoint::new(self.position, self.color)
}
pub fn to_raw_weighted(&self) -> impl Iterator<Item = RawPoint> {
let Point {
position,
color,
weight,
} = *self;
(0..weight).map(move |_| RawPoint::new(position, color))
}
}
impl RawPoint {
pub fn new(position: Position, color: Rgb) -> Self {
RawPoint { position, color }
}
pub fn with_weight(&self, weight: u32) -> Point {
Point::with_weight(self.position, self.color, weight)
}
pub fn centered_blank() -> Self {
RawPoint::new([0.0, 0.0], [0.0, 0.0, 0.0])
}
pub fn blanked(&self) -> Self {
let mut blanked = *self;
blanked.color = [0.0, 0.0, 0.0];
blanked
}
pub fn is_blank(&self) -> bool {
color_is_blank(self.color)
}
}
impl lasy::Lerp for RawPoint {
type Scalar = f32;
fn lerp(&self, other: &Self, amt: f32) -> Self {
RawPoint::new(
self.position.lerp(&other.position, amt),
self.color.lerp(&other.color, amt),
)
}
}
impl lasy::IsBlank for Point {
fn is_blank(&self) -> bool {
color_is_blank(self.color)
}
}
impl lasy::Position for Point {
fn position(&self) -> [f32; 2] {
self.position
}
}
impl lasy::Weight for Point {
fn weight(&self) -> u32 {
self.weight
}
}
impl Hash for Point {
fn hash<H: Hasher>(&self, hasher: &mut H) {
#[derive(Eq, Hash, PartialEq)]
struct HashPoint {
pos: [i32; 2],
rgb: [u32; 3],
}
impl From<Point> for HashPoint {
fn from(p: Point) -> Self {
let [px, py] = p.position;
let [pr, pg, pb] = p.color;
let x = (px * std::i16::MAX as f32) as i32;
let y = (py * std::i16::MAX as f32) as i32;
let r = (pr * std::u16::MAX as f32) as u32;
let g = (pg * std::u16::MAX as f32) as u32;
let b = (pb * std::u16::MAX as f32) as u32;
let pos = [x, y];
let rgb = [r, g, b];
HashPoint { pos, rgb }
}
}
HashPoint::from(*self).hash(hasher);
}
}
impl lasy::Blanked for RawPoint {
fn blanked(&self) -> Self {
RawPoint::blanked(self)
}
}
impl From<Point> for RawPoint {
fn from(p: Point) -> Self {
p.to_raw()
}
}
pub fn color_is_blank([r, g, b]: Rgb) -> bool {
r == 0.0 && g == 0.0 && b == 0.0
}