From: Ian Jackson Date: Sun, 27 Sep 2020 15:11:21 +0000 (+0100) Subject: make Pos a struct X-Git-Tag: otter-0.2.0~852 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=5590722004c646f3fe41de68fc752700fd44b0b2;p=otter.git make Pos a struct Signed-off-by: Ian Jackson --- diff --git a/src/bin/otter.rs b/src/bin/otter.rs index 109c4be6..913d45b9 100644 --- a/src/bin/otter.rs +++ b/src/bin/otter.rs @@ -741,10 +741,10 @@ mod library_add { } Good([a, b]) => { // todo: take account of the space used by the markers themselves - let lhs = min(a[0], b[0]); - let rhs = max(a[0], b[0]); - let top = min(a[1], b[1]); - let bot = max(a[1], b[1]); + let lhs = min(a.0[0], b.0[0]); + let rhs = max(a.0[0], b.0[0]); + let top = min(a.0[1], b.0[1]); + let bot = max(a.0[1], b.0[1]); Placement { lhs, rhs, top, bot, cline_upto: lhs, diff --git a/src/cmdlistener.rs b/src/cmdlistener.rs index 0387093d..99e59c62 100644 --- a/src/cmdlistener.rs +++ b/src/cmdlistener.rs @@ -28,8 +28,8 @@ from_instance_lock_error!{MgmtError} const USERLIST : &str = "/etc/userlist"; const CREATE_PIECES_MAX : u32 = 300; -const DEFAULT_POS_START : Pos = [20,20]; -const DEFAULT_POS_DELTA : Pos = [5,5]; +const DEFAULT_POS_START : Pos = PosC([20,20]); +const DEFAULT_POS_DELTA : Pos = PosC([5,5]); pub struct CommandListener { listener : UnixListener, @@ -152,7 +152,7 @@ fn execute_game_insn(cs: &CommandStream, (U{ pcs: vec![], log: vec![ LogEntry { html: Html(format!("The table was resized to {}x{}", - size[0], size[1])), + size.0[0], size.0[1])), }], raw: Some(vec![ PreparedUpdateEntry::SetTableSize(size) ]) }, Fine) @@ -281,8 +281,7 @@ fn execute_game_insn(cs: &CommandStream, let piece = gs.pieces.as_mut(modperm).insert(pc); ig.pieces.as_mut(modperm).insert(piece, p); updates.push((piece, PieceUpdateOp::Insert(()))); - pos[0] += posd[0]; - pos[1] += posd[1]; + pos += posd; } (U{ pcs: updates, diff --git a/src/gamestate.rs b/src/gamestate.rs index 77f98525..db2f00e2 100644 --- a/src/gamestate.rs +++ b/src/gamestate.rs @@ -29,7 +29,7 @@ pub struct ZCoord(pub f64); #[serde(transparent)] pub struct Html (pub String); -pub const DEFAULT_TABLE_SIZE : Pos = [ 400, 200 ]; +pub const DEFAULT_TABLE_SIZE : Pos = PosC([ 400, 200 ]); // ---------- general data types ---------- @@ -171,12 +171,12 @@ impl ClampTable for Pos { fn clamped(self, range: Pos) -> (Pos, bool) { let mut output = ArrayVec::new(); let mut did = false; - for (npos, tdid) in self.iter().zip(range.iter()) + for (npos, tdid) in self.0.iter().zip(range.0.iter()) .map(|(&pos, &rng)| pos.clamped(rng)) { output.push(npos); did |= tdid; } - (output.into_inner().unwrap(), did) + (PosC(output.into_inner().unwrap()), did) } } diff --git a/src/pieces.rs b/src/pieces.rs index 95076f4a..f30e5361 100644 --- a/src/pieces.rs +++ b/src/pieces.rs @@ -100,7 +100,7 @@ pub fn svg_circle_path(diam: f64) -> Html { } #[throws(SE)] -pub fn svg_rectangle_path([x, y] : [f64;2]) -> Html { +pub fn svg_rectangle_path(PosC([x,y]) : PosC) -> Html { Html(format!("M {} {} h {} v {} h {} z", -x*0.5, -y*0.5, x, y, -x)) } @@ -179,13 +179,13 @@ impl PieceSpec for piece_specs::Disc { impl PieceSpec for piece_specs::Square { #[throws(SpecError)] fn load(&self) -> Box { - let (x, y) = match *self.size.as_slice() { - [s,] => (s,s), - [x, y] => (x,y), + let xy = match *self.size.as_slice() { + [s,] => PosC([s,s]), + [x,y] => PosC([x,y]), _ => throw!(SpecError::ImproperSizeSpec), }; - let outline = Box::new(shapelib::Square { xy: [x as f64, y as f64] }); - let path = svg_rectangle_path([x as f64, y as f64])?; + let outline = Box::new(shapelib::Square { xy: xy.map(|v| v as f64) }); + let path = svg_rectangle_path(xy.promote())?; let itemname = self.itemname.clone() .unwrap_or_else(||"simple-square".to_string()); SimpleShape::new_from_path(Html::lit("square"), path, diff --git a/src/shapelib.rs b/src/shapelib.rs index 8fa730fd..bd46f014 100644 --- a/src/shapelib.rs +++ b/src/shapelib.rs @@ -451,7 +451,7 @@ impl Outline for Circle { } fn bbox_approx(&self) -> [Pos;2] { let d = (self.diam * 0.5).ceil() as Coord; - [[-d,-d], [d, d]] + [PosC([-d,-d]), PosC([d, d])] } } @@ -479,31 +479,27 @@ impl CircleDefn { } #[derive(Serialize,Deserialize,Debug)] -pub struct Square { pub xy: [f64;2] } +pub struct Square { pub xy: PosC } #[typetag::serde(name="Square")] impl Outline for Square { #[throws(IE)] fn surround_path(&self, _pri : &PieceRenderInstructions) -> Html { - let size : ArrayVec<_> = - self.xy.iter().map(|s| s * SELECT_SCALE) - .collect(); - svg_rectangle_path(size.into_inner().unwrap())? + let size = self.xy * SELECT_SCALE; + svg_rectangle_path(size)? } #[throws(IE)] fn thresh_dragraise(&self, _pri : &PieceRenderInstructions) -> Option { - let smallest : f64 = self.xy.iter().cloned() + let smallest : f64 = self.xy.0.iter().cloned() .map(OrderedFloat::from).min().unwrap().into(); Some((smallest * 0.5) as Coord) } fn bbox_approx(&self) -> [Pos;2] { - let pos : Pos = self.xy.iter().map( + let pos : Pos = (self.xy * 0.5).map( |v| ((v * 0.5).ceil()) as Coord - ).collect::>().into_inner().unwrap(); - let neg : Pos = pos.iter().map( - |v| -v - ).collect::>().into_inner().unwrap(); + ); + let neg = -pos; [ neg, pos ] } } @@ -523,12 +519,14 @@ impl OutlineDefn for SquareDefn { impl SquareDefn { #[throws(LibraryLoadError)] fn get(group: &GroupData) -> Square { - match group.d.size.as_slice() { - &[s] => Square { xy: [s,s] }, - s if s.len() == 2 => Square { xy: s.try_into().unwrap() }, - size => throw!(LLE::WrongNumberOfSizeDimensions - { got: size.len(), expected : [1,2]}), - } + Square { xy: PosC( + match group.d.size.as_slice() { + &[s] => [s,s], + s if s.len() == 2 => s.try_into().unwrap(), + size => throw!(LLE::WrongNumberOfSizeDimensions + { got: size.len(), expected : [1,2]}), + } + )} } } diff --git a/src/spec.rs b/src/spec.rs index 6e217ff9..64512b39 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -17,7 +17,11 @@ use crate::error::display_as_debug; pub type Coord = isize; -pub type Pos = [Coord; 2]; +#[derive(Clone,Copy,Debug,Serialize,Deserialize,Hash)] +#[derive(Eq,PartialEq,Ord,PartialOrd)] +#[serde(transparent)] +pub struct PosC (pub [T; 2]); +pub type Pos = PosC; #[derive(Clone,Eq,PartialEq,Ord,PartialOrd,Hash,Serialize,Deserialize)] #[serde(transparent)] @@ -105,6 +109,84 @@ pub mod piece_specs { } +//---------- Pos ---------- + +pub mod pos_traits { + use std::ops::{Add,Sub,Mul,Neg,AddAssign,SubAssign}; + use crate::imports::*; + + impl+Copy+Clone+Debug> Add> for PosC { + type Output = PosC; + fn add(self, rhs: PosC) -> PosC { + PosC( + itertools::zip_eq( + self.0.iter().cloned(), + rhs .0.iter().cloned(), + ).map(|(a,b)| a + b) + .collect::>().into_inner().unwrap() + ) + } + } + + impl+Copy+Clone+Debug> Sub> for PosC { + type Output = PosC; + fn sub(self, rhs: PosC) -> PosC { + PosC( + itertools::zip_eq( + self.0.iter().cloned(), + rhs .0.iter().cloned(), + ).map(|(a,b)| a - b) + .collect::>().into_inner().unwrap() + ) + } + } + + impl+Copy+Clone+Debug> AddAssign> for PosC { + fn add_assign(&mut self, rhs: PosC) { + *self = *self + rhs; + } + } + + impl+Copy+Clone+Debug> SubAssign> for PosC { + fn sub_assign(&mut self, rhs: PosC) { + *self = *self - rhs; + } + } + + impl+Copy+Clone+Debug> Mul for PosC { + type Output = PosC; + fn mul(self, rhs: T) -> PosC { + PosC( + self.0.iter().cloned().map(|a| a * rhs) + .collect::>().into_inner().unwrap() + ) + } + } + + impl+Copy+Clone+Debug> Neg for PosC { + type Output = Self; + fn neg(self) -> Self { + PosC( + self.0.iter().cloned().map(|a| -a) + .collect::>().into_inner().unwrap() + ) + } + } + + impl PosC { + pub fn map U>(self, f: F) -> PosC { + PosC( + self.0.iter().cloned().map(f) + .collect::>().into_inner().unwrap() + ) + } + } + + impl PosC { + pub fn promote(&self) -> PosC { self.map(|v| v as f64) } + } +} + //---------- Implementation ---------- pub mod implementation {