chiark / gitweb /
geometry: Massive overhaul of types and fields
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 25 Mar 2021 12:00:03 +0000 (12:00 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 25 Mar 2021 12:26:59 +0000 (12:26 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
17 files changed:
apitest/at-otter.rs
base/geometry.rs
daemon/cmdlistener.rs
src/bin/otter.rs
src/bin/otterlib.rs
src/clock.rs
src/commands.rs
src/deck.rs
src/gamestate.rs
src/hand.rs
src/hidden.rs
src/pieces.rs
src/shapelib.rs
wasm/wasm.rs
wdriver/wdriver.rs
wdriver/wdt-hand.rs
wdriver/wdt-simple.rs

index ae5eae4596929d94e37c113cd08dd2597a83dbbc..b30d231703bd592afc0535e15292f9be2e328dad 100644 (file)
@@ -375,10 +375,9 @@ pub fn update_update_pieces<PI:Idx>(
   let (op, d) = v["op"].as_object().unwrap().iter().next().unwrap();
 
   fn coord(j: &JsV) -> Pos {
-    PosC(
+    PosC::from_iter_2(
       j.as_array().unwrap().iter()
         .map(|n| n.as_i64().unwrap().try_into().unwrap())
-        .collect::<ArrayVec<_>>().into_inner().unwrap()
     )
   }
 
@@ -411,7 +410,7 @@ impl PieceOp for PieceOpData {
   fn api(&self) -> Option<PieceOpData> { Some((self.0, self.1.clone())) }
 }
 impl PieceOp for Pos {
-  fn api(&self) -> Option<PieceOpData> { Some(("m", json![self.0])) }
+  fn api(&self) -> Option<PieceOpData> { Some(("m", json![self.coords])) }
   fn update(&self, pi: &mut PieceInfo<JsV>) { pi.pos = *self }
 }
 impl PieceOp for () {
@@ -501,7 +500,7 @@ impl Ctx {
     let llm: [_;2] = llm.into_inner().unwrap();
     dbgc!(&llm);
 
-    for (llm, &pos) in izip!(&llm, [PosC([5,5]), PosC([50,25])].iter())
+    for (llm, &pos) in izip!(&llm, [PosC::new(5,5), PosC::new(50,25)].iter())
     {
       session.api_piece(GH::With, &llm.id, pos)?;
     }
@@ -559,7 +558,7 @@ impl Ctx {
         .collect::<ArrayVec<[_;2]>>()
         .into_inner().unwrap();
 
-      pawns.sort_by_key(|&p| -pieces[p].pos.0[0]);
+      pawns.sort_by_key(|&p| -pieces[p].pos.x());
       dbgc!(pawns)
     }
 
@@ -572,7 +571,7 @@ impl Ctx {
     // ----- alice: move pawns into alice's hand -----
 
     for (&pawn, &xoffset) in izip!(&a_pawns, [10,20].iter()) {
-      let pos = (a_pieces[hand].pos + PosC([xoffset, 0]))?;
+      let pos = (a_pieces[hand].pos + PosC::new(xoffset, 0))?;
       alice.api_piece(GH::With, (&mut a_pieces, pawn), pos)?;
     }
 
@@ -589,7 +588,7 @@ impl Ctx {
 
     {
       let p = a_pawns[0];
-      let alice_move_to = (a_pieces[p].pos + PosC([5, 5]))?;
+      let alice_move_to = (a_pieces[p].pos + PosC::new(5,5))?;
       let mut a_p = (&mut a_pieces, p);
 
       alice.api_piece(GH::Grab, PuSynch(&mut a_p), ())?;
@@ -619,7 +618,7 @@ impl Ctx {
 
     alice.api_piece(GH::With,
                     (&mut a_pieces, a_pawns[0]),
-                    PosC([ 15, 20 ]))?;
+                    PosC::new( 15, 20 ))?;
 
     alice.synchu(&mut a_pieces)?;
     bob.synchu(&mut b_pieces)?;
index 9a126888d2b942d4bfd34bcf601927651db11442..b0b9318f85715c64979c20e589d9ed206e4769fa 100644 (file)
@@ -12,16 +12,16 @@ use num_traits::NumCast;
 
 pub type Coord = i32;
 
-#[derive(Clone,Copy,Debug,Serialize,Deserialize,Hash)]
+#[derive(Clone,Copy,Serialize,Deserialize,Hash)]
 #[derive(Eq,PartialEq,Ord,PartialOrd)]
 #[serde(transparent)]
-pub struct PosC<T>(pub [T; 2]);
+pub struct PosC<T>{ pub coords: [T; 2] }
 pub type Pos = PosC<Coord>;
 
-#[derive(Clone,Copy,Debug,Serialize,Deserialize,Hash)]
-#[derive(Eq,PartialEq)]
+#[derive(Clone,Copy,Serialize,Deserialize,Hash)]
+#[derive(Eq,PartialEq,Ord,PartialOrd)]
 #[serde(transparent)]
-pub struct RectC<T>(pub [PosC<T>; 2]);
+pub struct RectC<T>{ pub corners: [PosC<T>; 2] }
 pub type Rect = RectC<Coord>;
 
 // ---------- CheckedArith ----------
@@ -95,14 +95,42 @@ impl PosC<Coord> {
 pub struct PosCFromIteratorError;
 display_as_debug!{PosCFromIteratorError}
 
+impl<T> PosC<T> {
+  pub const fn new(x: T, y: T) -> Self { PosC{ coords: [x,y] } }
+  pub fn both(v: T) -> Self where T: Copy { PosC::new(v,v) }
+  pub fn zero() -> Self where T: num_traits::Zero + Copy {
+    PosC::both(<T as num_traits::Zero>::zero())
+  }
+}
+impl<T> PosC<T> where T: Copy {
+  pub fn x(self) -> T { self.coords[0] }
+  pub fn y(self) -> T { self.coords[1] }
+}
+
 impl<T> PosC<T> {
   #[throws(PosCFromIteratorError)]
-  pub fn from_iter<I: Iterator<Item=T>>(i: I) -> Self { PosC(
+  pub fn from_iter<I: Iterator<Item=T>>(i: I) -> Self { PosC{ coords:
     i
       .collect::<ArrayVec<_>>()
       .into_inner()
       .map_err(|_| PosCFromIteratorError)?
-  )}
+  }}
+}
+
+impl<T> PosC<T> where T: Debug {
+  pub fn from_iter_2<I: Iterator<Item=T>>(i: I) -> Self { PosC{ coords:
+    i
+      .collect::<ArrayVec<_>>()
+      .into_inner()
+      .unwrap()
+  }}
+}
+
+impl<T> Debug for PosC<T> where T: Debug + Copy {
+  #[throws(fmt::Error)]
+  fn fmt(&self, f: &mut Formatter) {
+    write!(f, "[{:?},{:?}]", self.x(), self.y())?;
+  }
 }
 
 impl<T:Debug> PosC<T> {
@@ -111,11 +139,11 @@ impl<T:Debug> PosC<T> {
   pub fn try_from_iter_2<
     E: Debug,
     I: Iterator<Item=Result<T,E>>
-  >(i: I) -> Self { PosC(
+  >(i: I) -> Self { PosC{ coords:
     i
       .collect::<Result<ArrayVec<_>,E>>()?
       .into_inner().unwrap()
-  )}
+  }}
 }
 
 impl<T:CheckedArith> Add<PosC<T>> for PosC<T> {
@@ -124,8 +152,8 @@ impl<T:CheckedArith> Add<PosC<T>> for PosC<T> {
   fn add(self, rhs: PosC<T>) -> PosC<T> {
     PosC::try_from_iter_2(
       itertools::zip_eq(
-        self.0.iter().cloned(),
-        rhs .0.iter().cloned(),
+        self.coords.iter().cloned(),
+        rhs .coords.iter().cloned(),
       ).map(
         |(a,b)| a.checked_add(b)
       )
@@ -139,8 +167,8 @@ impl<T:CheckedArith> Sub<PosC<T>> for PosC<T> {
   fn sub(self, rhs: PosC<T>) -> PosC<T> {
     PosC::try_from_iter_2(
       itertools::zip_eq(
-        self.0.iter().cloned(),
-        rhs .0.iter().cloned(),
+        self.coords.iter().cloned(),
+        rhs .coords.iter().cloned(),
       ).map(|(a,b)| a.checked_sub(b))
     )?
   }
@@ -151,7 +179,7 @@ impl<S:Copy+Debug+Clone+'static,T:CheckedArithMul<S>> Mul<S> for PosC<T> {
   #[throws(CoordinateOverflow)]
   fn mul(self, rhs: S) -> PosC<T> {
     PosC::try_from_iter_2(
-      self.0.iter().cloned().map(
+      self.coords.iter().cloned().map(
         |a| a.checked_mul(rhs)
       )
     )?
@@ -163,7 +191,7 @@ impl<T:CheckedArith> Neg for PosC<T> {
   #[throws(CoordinateOverflow)]
   fn neg(self) -> Self {
     PosC::try_from_iter_2(
-      self.0.iter().cloned().map(|a| a.checked_neg())
+      self.coords.iter().cloned().map(|a| a.checked_neg())
     )?
   }
 }
@@ -171,7 +199,7 @@ impl<T:CheckedArith> Neg for PosC<T> {
 impl<T:Copy+Clone+Debug> PosC<T> {
   pub fn map<U:Copy+Clone+Debug, F: FnMut(T) -> U>(self, f: F) -> PosC<U> {
     PosC::from_iter(
-      self.0.iter().cloned().map(f)
+      self.coords.iter().cloned().map(f)
     ).unwrap()
   }
 }
@@ -181,51 +209,61 @@ impl<T:Copy+Clone+Debug> PosC<T> {
     (self, f: F) -> Result<PosC<U>,E>
   {
     PosC::try_from_iter_2(
-      self.0.iter().cloned().map(f)
+      self.coords.iter().cloned().map(f)
     )
   }
 }
 
 impl<T> Mean for PosC<T> where T: Mean + Debug {
   fn mean(&self, other: &Self) -> Self where T: Mean {
-    PosC::try_from_iter_2(
-      izip!(&self.0, &other.0)
-        .map(|(a,b)| Ok::<_,Void>(a.mean(b)))
-    ).unwrap_or_else(|v| match v { })
+    PosC::from_iter_2(
+      izip!(&self.coords, &other.coords)
+        .map(|(a,b)| a.mean(b))
+    )
   }
 }
 
 // ---------- Rect ----------
 
+impl<T> RectC<T> where T: Copy {
+  pub fn tl(&self) -> PosC<T> { self.corners[0] }
+  pub fn br(&self) -> PosC<T> { self.corners[1] }
+}
+
+impl<T> Debug for RectC<T> where T: Debug + Copy {
+  #[throws(fmt::Error)]
+  fn fmt(&self, f: &mut Formatter) {
+    write!(f, "Rect[{:?},{:?}]", self.tl(), self.br())?;
+  }
+}
+
 impl<T> RectC<T> {
-  pub fn contains(&self, p: PosC<T>) -> bool where T: PartialOrd {
+  pub fn contains(&self, p: PosC<T>) -> bool where T: PartialOrd + Copy {
     (0..2).all(|i| {
-      p.0[i] >= self.0[0].0[i] &&
-      p.0[i] <= self.0[1].0[i]
+      p.coords[i] >= self.tl().coords[i] &&
+      p.coords[i] <= self.br().coords[i]
     })
   }
 
-  pub fn overlaps(&self, other: &RectC<T>) -> bool where T: PartialOrd {
+  pub fn overlaps(&self, other: &RectC<T>) -> bool where T: PartialOrd + Copy {
     ! (0..2).any(|i| (
-      other.0[1].0[i] < self .0[0].0[i] ||
-      self .0[1].0[i] < other.0[0].0[i]
+      other.br().coords[i] < self .tl().coords[i] ||
+      self .br().coords[i] < other.tl().coords[i]
     ))
   }
 
-  pub fn empty() -> Self where T: Copy + num_traits::Zero + num_traits::One {
-    let zero = <T as num_traits::Zero>::zero();
-    let one = <T as num_traits::One>::one();
-    RectC([
-      PosC([ one,  one  ]),
-      PosC([ zero, zero ]),
-    ])
+  pub fn empty() -> Self where T: num_traits::Zero + num_traits::One + Copy {
+    RectC{ corners: [
+      PosC::both( <T as num_traits::One >::one()  ),
+      PosC::both( <T as num_traits::Zero>::zero() ),
+    ]}
   }
 }
 
-impl<T> RectC<T> where T: Mean + Debug {
+impl<T> RectC<T> where T: Mean + Debug + Copy {
   pub fn middle(&self) -> PosC<T> {
-    Mean::mean(&self.0[0],
-               &self.0[1])
+    Mean::mean(&self.tl(),
+               &self.br())
   }
 }
 
@@ -233,19 +271,20 @@ impl<T> RectC<T> where T: Mean + Debug {
 fn empty_area() {
   let empty = Rect::empty();
   for x in -3..3 { for y in -3..3 {
-    assert!(! empty.contains(PosC([x,y])));
+    dbg!(empty,x,y);
+    assert!(! empty.contains(PosC::new(x,y)));
   } }
 }
 
 // ---------- Region ----------
 
 #[derive(Clone,Debug,Serialize,Deserialize)]
-pub enum RegionC<T> {
+pub enum RegionC<T:Copy> {
   Rectangle(RectC<T>),
 }
 pub type Region = RegionC<Coord>;
 
-impl<T> RegionC<T> {
+impl<T:Copy> RegionC<T> {
   pub fn contains(&self, pos: PosC<T>) -> bool where T: PartialOrd {
     use RegionC::*;
     match &self {
index 4d1cc87b2aa5e0f6f3245d0b1c397d208900e53d..a41d1eedda3c6d9b18c3306e852f9e08e241e3dd 100644 (file)
@@ -28,8 +28,8 @@ const USERLIST: &str = "/etc/userlist";
 const CREATE_PIECES_MAX: u32 = 300;
 const OVERALL_PIECES_MAX: usize = 100_000; // don't make not fit in i32
 
-const DEFAULT_POS_START: Pos = PosC([20,20]);
-const DEFAULT_POS_DELTA: Pos = PosC([5,5]);
+const DEFAULT_POS_START: Pos = PosC::new(20,20);
+const DEFAULT_POS_DELTA: Pos = PosC::new(5,5);
 
 pub struct CommandListener {
   listener: UnixListener,
@@ -322,7 +322,7 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>(
       (U{ pcs: vec![],
           log: vec![ LogEntry {
             html: Html(format!("{} resized the table to {}x{}",
-                               &who.0, size.0[0], size.0[1])),
+                               &who.0, size.x(), size.y())),
           }],
           raw: Some(vec![ PreparedUpdateEntry::SetTableSize(size) ]) },
        Fine, None, ig)
index 708b90d99ce03114c5ae5e671aecd3c97b613dec..a6da62739f23589662de13e69ceb1b076ca75522 100644 (file)
@@ -1121,10 +1121,10 @@ mod library_add {
       }
       Good([a, b]) => {
         // todo: take account of the space used by the markers themselves
-        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]);
+        let lhs = min(a.x(), b.x());
+        let rhs = max(a.x(), b.x());
+        let top = min(a.y(), b.y());
+        let bot = max(a.y(), b.y());
         Placement {
           lhs, rhs, top, bot,
           clhs: lhs, cbot: top,
@@ -1136,10 +1136,10 @@ mod library_add {
     impl Placement {
       /// If returns None, has already maybe tried to take some space
       #[throws(AE)]
-      fn place(&mut self, bbox: &[Pos;2],
+      fn place(&mut self, bbox: &Rect,
                pieces: &Vec<MgmtGamePieceInfo>, ma: &MainOpts)
                -> Option<Pos> {
-        let PosC([w,h]) = (bbox[1] - bbox[0])?;
+        let PosC{ coords: [w,h] } = (bbox.br() - bbox.tl())?;
 
         let mut did_newline = false;
         let (ncbot, tlhs) = 'search: loop {
@@ -1155,12 +1155,12 @@ mod library_add {
             if let Some((nclhs, clash_bot)) = pieces.iter()
               .filter_map(|p| (|| if_chain! {
                 if let Some(pv) = p.visible.as_ref();
-                let tl = (pv.pos + pv.bbox[0])?;
-                let br = (pv.pos + pv.bbox[1])?;
-                if !(tl.0[0] >= self.clhs
-                    || tl.0[1] >= ncbot
-                    || br.0[0] <= tlhs
-                    || br.0[1] <= self.top);
+                let tl = (pv.pos + pv.bbox.tl())?;
+                let br = (pv.pos + pv.bbox.br())?;
+                if !(tl.x() >= self.clhs
+                    || tl.y() >= ncbot
+                    || br.x() <= tlhs
+                    || br.y() <= self.top);
                 then {
                   if ma.verbose > 2 {
                     eprintln!(
@@ -1168,7 +1168,7 @@ mod library_add {
                       &self, tlhs, ncbot, &p.itemname, &tl, &br
                     )
                   }
-                  Ok::<_,AE>(Some((br.0[0], br.0[1])))
+                  Ok::<_,AE>(Some((br.x(), br.y())))
                 } else {
                   Ok::<_,AE>(None)
                 }
@@ -1197,8 +1197,8 @@ mod library_add {
           // if we are simply too wide, we'll just loop until off the bottom
         };
         self.cbot = ncbot;
-        let ttopleft = PosC([tlhs, self.top]);
-        let tnominal = (ttopleft - bbox[0])?;
+        let ttopleft = PosC::new(tlhs, self.top);
+        let tnominal = (ttopleft - bbox.tl())?;
 
         if ma.verbose > 3 { dbgc!(&self, &tnominal); }
         Some(tnominal)
index b99c08745e9a5cc0b551583cee0b0bdfadeb8f78..5617bc708393e045d5ef008385f3571f0173a508 100644 (file)
@@ -101,9 +101,9 @@ fn preview(items: Vec<ItemForOutput>) {
 
       let bbox = p
         .bbox_approx()?;
-      let mut bbox = bbox
-        .iter()
-        .map(|PosC(xy)| xy.iter().map(|&p| p as f64).collect::<Vec<_>>())
+      let mut bbox = bbox.corners.iter()
+        .map(|PosC{coords}| coords.iter().map(|&p| p as f64)
+             .collect::<Vec<_>>())
         .collect::<Vec<_>>();
       for xy in &mut bbox[0] { *xy -= BORDER }
       for xy in &mut bbox[1] { *xy += BORDER }
index 6be531663a8cff03ca39a6f457fdb754d43d199a..174f9133363b2216ce6a8b29480bc924e5fb8a96 100644 (file)
@@ -388,7 +388,7 @@ impl ThreadState {
 
 const W: Coord = 40;
 const H: Coord = 14;
-const OUTLINE: Rectangle = Rectangle { xy: PosC([W as f64, H as f64]) };
+const OUTLINE: Rectangle = Rectangle { xy: PosC::new(W as f64, H as f64) };
 
 
 // ==================== piece management, loading, etc. ====================
@@ -426,7 +426,7 @@ impl OutlineTrait for Clock {
     to OUTLINE {
       fn outline_path(&self, scale: f64) -> Result<Html, IE>;
       fn thresh_dragraise(&self) -> Result<Option<Coord>, IE>;
-      fn bbox_approx(&self) -> Result<[Pos;2], IE>;
+      fn bbox_approx(&self) -> Result<Rect, IE>;
     }
   }
 }
index 2ba0c286110067b74cd6654f80e7df6623234344..158d6e9c9556e7725f17d5ae7dd0c763ac4c9b7e 100644 (file)
@@ -157,7 +157,7 @@ pub struct MgmtGamePieceVisibleInfo {
   pub pos: Pos,
   pub face: FaceId,
   pub desc_html: Html,
-  pub bbox: [Pos;2],
+  pub bbox: Rect,
 }
 
 #[derive(Debug,Copy,Clone,Serialize,Deserialize)]
index 7f1fc945179ed4e270703c7c567c8ce8dd6525fa..5d6e32945fd2f674429924f645b1a038ac9be435 100644 (file)
@@ -29,7 +29,7 @@ impl OutlineTrait for Deck {
     to self.shape {
       fn outline_path(&self, scale: f64) -> Result<Html,IE>;
       fn thresh_dragraise(&self) -> Result<Option<Coord>,IE>;
-      fn bbox_approx(&self) -> Result<[Pos;2], IE>;
+      fn bbox_approx(&self) -> Result<Rect, IE>;
     }
   }
 }
index 7b086ba9417b97aeaeae86b1b45d56ec35c6550c..efaef512ac15e3e40297fb704fe8a200676629ec 100644 (file)
@@ -27,7 +27,7 @@ pub struct Html(pub String);
 #[serde(transparent)]
 pub struct Timestamp(pub u64); /* time_t */
 
-pub const DEFAULT_TABLE_SIZE: Pos = PosC([ 400, 200 ]);
+pub const DEFAULT_TABLE_SIZE: Pos = PosC::new( 400, 200 );
 
 // ---------- general data types ----------
 
@@ -105,7 +105,7 @@ pub trait OutlineTrait: Debug + Sync + Send + 'static {
     self.outline_path(SELECT_SCALE)
   }
   fn thresh_dragraise(&self) -> Result<Option<Coord>, IE>;
-  fn bbox_approx(&self) -> Result<[Pos;2], IE>;
+  fn bbox_approx(&self) -> Result<Rect, IE>;
 }
 
 #[derive(Debug,Copy,Clone,Serialize,Deserialize)]
@@ -271,13 +271,13 @@ impl ClampTable for Pos {
   fn clamped(self, range: Pos) -> Result<Pos, Pos> {
     let mut output = ArrayVec::new();
     let mut ok = true;
-    for (&pos, &rng) in izip!(self.0.iter(), range.0.iter()) {
+    for (&pos, &rng) in izip!(self.coords.iter(), range.coords.iter()) {
       output.push(match pos.clamped(rng) {
         Ok(pos) => pos,
         Err(pos) => { ok = false; pos },
       })
     }
-    let output = PosC(output.into_inner().unwrap());
+    let output = PosC{ coords: output.into_inner().unwrap() };
     if ok { Ok(output) } else { Err(output) }
   }
 }
@@ -332,7 +332,7 @@ impl GPiece {
   pub fn dummy() -> Self {
     let gen_dummy = Generation(1);
     GPiece {
-      pos: PosC([0,0]),
+      pos: PosC::zero(),
       face: default(),
       held: None,
       zlevel: ZLevel { z: default(), zg: gen_dummy },
@@ -413,7 +413,7 @@ fn xdata_get_mut_inner<
 impl GameState {
   pub fn dummy() -> Self { GameState {
     table_colour: Html::lit("green"),
-    table_size: PosC([300,200]),
+    table_size: PosC::new(300,200),
     pieces: default(),
     gen: Generation(0),
     log: default(),
index 934ba895b868976f855c57e7893997ce8e51468b..ea74fe871b16aa3d93d6373efb63e0a0b01bd974 100644 (file)
@@ -42,7 +42,7 @@ impl OutlineTrait for Hand {
     to self.shape {
       fn outline_path(&self, scale: f64) -> Result<Html,IE>;
       fn thresh_dragraise(&self) -> Result<Option<Coord>,IE>;
-      fn bbox_approx(&self) -> Result<[Pos;2], IE>;
+      fn bbox_approx(&self) -> Result<Rect, IE>;
     }
   }
 }
index 09355461edc287d2d04d30e41657da5bc8d979e5..aef082e16f5104efd309da87ddf8a9f6beb215eb 100644 (file)
@@ -287,34 +287,34 @@ impl OccDisplacement {
       OD::Stack{pos} => *pos,
       OD::Rect{rect} => (|| Some({
         let notch: Coord = notch.try_into().ok()?;
-        let mut spare = ((rect.0[1] - rect.0[0]).ok()?
+        let mut spare = ((rect.br() - rect.tl()).ok()?
                          - ppiece_use_size).ok()?;
-        for s in &mut spare.0 { *s = max(*s,1) }
+        for s in &mut spare.coords { *s = max(*s,1) }
         let fi = 0;
         let gi = 1;
-        let f_stride = max(ppiece_use_size.0[fi] / 4, 1);
-        let g_stride = max(ppiece_use_size.0[gi] / 3, 1);
-        let f_count = max(spare.0[fi] / f_stride, 1);
-        let g_count = max(spare.0[gi] / g_stride, 1);
+        let f_stride = max(ppiece_use_size.coords[fi] / 4, 1);
+        let g_stride = max(ppiece_use_size.coords[gi] / 3, 1);
+        let f_count = max(spare.coords[fi] / f_stride, 1);
+        let g_count = max(spare.coords[gi] / g_stride, 1);
         let mut f_num = notch % f_count;
         let     g_num = notch / f_count;
         if g_num % 2 != 0 { f_num = f_count - 1 - f_num }
-        let f_coord = rect.0[1].0[fi] - ppiece_use_size.0[fi] / 2 -
+        let f_coord = rect.br().coords[fi] - ppiece_use_size.coords[fi] / 2 -
             f_stride * f_num;
-        let g_coord = rect.0[0].0[gi] + ppiece_use_size.0[gi] / 2 +
+        let g_coord = rect.tl().coords[gi] + ppiece_use_size.coords[gi] / 2 +
           if g_num < g_count {
             g_stride * g_num
-          } else if g_num < spare.0[gi] {
+          } else if g_num < spare.coords[gi] {
             g_num
           } else {
-            spare.0[gi] - 1
+            spare.coords[gi] - 1
           };
         trace_dbg!("placement", spare,
                    f_stride, f_count, f_num, f_coord,
                    g_stride, g_count, g_num, g_coord);
-        let mut pos = PosC([0,0]);
-        pos.0[fi] = f_coord;
-        pos.0[gi] = g_coord;
+        let mut pos = PosC::zero();
+        pos.coords[fi] = f_coord;
+        pos.coords[gi] = g_coord;
         pos
       }))().unwrap_or_else(||{
         rect.middle()
@@ -634,7 +634,7 @@ fn recalculate_occultation_general<
         let ilk = ilk.borrow();
         if let Some(ilk) = ioccults.ilks.get(ilk);         // expected, really
         if let Ok::<_,IE>(bbox) = ilk.p_occ.bbox_approx(); // expected, really
-        if let Ok(size) = bbox[1] - bbox[0];               // expected, really
+        if let Ok(size) = bbox.br() - bbox.tl();           // expected, really
         then { occ.ppiece_use_size = size; }
       };
       let notch = occ.notches
@@ -872,7 +872,7 @@ pub fn create_occultation(
     region,
     occulter,
     views,
-    ppiece_use_size: PosC([0,0]),
+    ppiece_use_size: PosC::zero(),
     notches: default(),
   };
   debug!("creating occultation {:?}", &occultation);
index febc131daecad7c6cb8c2fd81e3c881698a2ed5c..fed4679efce97e5e43f6b5bd4d9796841697523a 100644 (file)
@@ -106,7 +106,7 @@ pub fn svg_circle_path(diam: f64) -> Html {
 }
 
 #[throws(SvgE)]
-pub fn svg_rectangle_path(PosC([x,y]): PosC<f64>) -> Html {
+pub fn svg_rectangle_path(PosC{coords: [x,y]}: PosC<f64>) -> Html {
   Html(format!("M {} {} h {} v {} h {} z",
                -x*0.5, -y*0.5, x, y, -x))
 }
@@ -120,7 +120,7 @@ impl<Desc, Outl:'static> OutlineTrait for GenericSimpleShape<Desc, Outl>
     to self.outline {
       fn outline_path(&self, scale: f64) -> Result<Html,IE>;
       fn thresh_dragraise(&self) -> Result<Option<Coord>,IE>;
-      fn bbox_approx(&self) -> Result<[Pos;2], IE>;
+      fn bbox_approx(&self) -> Result<Rect, IE>;
     }
   }
 }
@@ -161,15 +161,15 @@ impl piece_specs::PieceLabel {
       else { "black" }
     };
     let fontsz = 4.;
-    let PosC([x,y]) = {
+    let PosC{ coords: [x,y] } = {
       use piece_specs::PieceLabelPlace::*;
       let inout = match self.place {
         BottomLeft        | TopLeft        =>  1.,
         BottomLeftOutside | TopLeftOutside => -1.,
       };
-      let eff_size = (outline.xy - PosC([2., inout * 2.]))?;
+      let eff_size = (outline.xy - PosC::new(2., inout * 2.))?;
       let mut pos = (eff_size * -0.5)?;
-      let y = &mut pos.0[1];
+      let y = &mut pos.coords[1];
       *y += 0.5 * fontsz * inout;
       match self.place {
         BottomLeft | BottomLeftOutside => { *y *= -1. },
@@ -304,8 +304,8 @@ impl piece_specs::Square {
   #[throws(SpecError)]
   fn xy(&self) -> Pos {
     match *self.size.as_slice() {
-      [s,]  => PosC([s,s]),
-      [x,y] => PosC([x,y]),
+      [s,]  => PosC::new(s,s),
+      [x,y] => PosC::new(x,y),
       _ => throw!(SpecError::ImproperSizeSpec),
     }
   }
index 40a412524d7ec9696c21b56e09f89088898b0454..34242520ae067be5dc1aaf4e428e8af4ba345c20 100644 (file)
@@ -175,7 +175,7 @@ struct ItemOccultable {
 impl OutlineTrait for ItemOccultable { delegate! { to self.outline {
   fn outline_path(&self, scale: f64) -> Result<Html, IE>;
   fn thresh_dragraise(&self) -> Result<Option<Coord>, IE>;
-  fn bbox_approx(&self) -> Result<[Pos; 2], IE>;
+  fn bbox_approx(&self) -> Result<Rect, IE>;
 }}}
 #[typetag::serde(name="Lib")]
 impl OccultedPieceTrait for ItemOccultable {
@@ -191,7 +191,7 @@ impl OccultedPieceTrait for ItemOccultable {
 pub struct ItemEnquiryData {
   pub itemname: String,
   pub f0desc: Html,
-  pub f0bbox: [Pos; 2],
+  pub f0bbox: Rect,
 }
 
 impl ItemEnquiryData {
@@ -204,7 +204,7 @@ impl ItemEnquiryData {
 impl OutlineTrait for Item { delegate! { to self.outline {
   fn outline_path(&self, scale: f64) -> Result<Html, IE>;
   fn thresh_dragraise(&self) -> Result<Option<Coord>, IE>;
-  fn bbox_approx(&self) -> Result<[Pos; 2], IE>;
+  fn bbox_approx(&self) -> Result<Rect, IE>;
 }}}
 
 impl FaceTransform {
@@ -748,9 +748,9 @@ impl OutlineTrait for Circle {
     Some((self.diam * 0.5) as Coord)
   }
   #[throws(IE)]
-  fn bbox_approx(&self) -> [Pos;2] {
+  fn bbox_approx(&self) -> Rect {
     let d = (self.diam * 0.5).ceil() as Coord;
-    [PosC([-d,-d]), PosC([d, d])]
+    Rect{ corners: [PosC::new(-d,-d), PosC::new(d, d)]}
   }
 }
 
@@ -787,13 +787,13 @@ impl Rectangle {
     let offset = offset.try_map(
       |c| c.floor().to_i32().ok_or(CoordinateOverflow)
     )?;
-    let rect = RectC(
+    let rect = RectC{ corners:
       [-1,1].iter().map(|&signum| Ok::<_,CoordinateOverflow>({
         (centre + (offset * signum)?)?
       }))
         .collect::<Result<ArrayVec<_>,_>>()?
         .into_inner().unwrap()
-    );
+    };
     rect
   }
 
@@ -812,17 +812,17 @@ impl OutlineTrait for Rectangle {
   }
   #[throws(IE)]
   fn thresh_dragraise(&self) -> Option<Coord> {
-    let smallest: f64 = self.xy.0.iter().cloned()
+    let smallest: f64 = self.xy.coords.iter().cloned()
       .map(OrderedFloat::from).min().unwrap().into();
     Some((smallest * 0.5) as Coord)
   }
   #[throws(IE)]
-  fn bbox_approx(&self) -> [Pos;2] {
+  fn bbox_approx(&self) -> Rect {
     let pos: Pos = self.xy.map(
       |v| ((v * 0.5).ceil()) as Coord
     );
     let neg = (-pos)?;
-    [ neg, pos ]
+    Rect{ corners: [ neg, pos ] }
   }
 }
 
@@ -841,14 +841,14 @@ impl OutlineDefn for SquareDefn {
 impl SquareDefn {
   #[throws(LibraryLoadError)]
   fn get(group: &GroupData) -> Rectangle {
-    Rectangle { xy: PosC(
+    Rectangle { xy: PosC{ coords:
       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]}),
       }
-    )}
+    }}
   }
 }
 
index d92a50a12ade781531f20beee40abe49d518cabb..00f9c3794028855cb36599214780a70bda2948fb 100644 (file)
@@ -175,7 +175,7 @@ impl RegionList {
     self.0
       .values()
       .any(
-        |r| r.contains(PosC([x,y]))
+        |r| r.contains(PosC::new(x,y))
       )
   }
 }
index 088b9846af69369d1b81c01989347cd13e6f118e..bec022fc108c92fcc90e4bce8573ca31c054e22d 100644 (file)
@@ -272,7 +272,7 @@ impl<'g> WindowGuard<'g> {
     })?;
     (||{
       let vec: ndarray::Array1<f64> =
-        posg.0.iter()
+        posg.coords.iter()
         .cloned()
         .map(|v| v as f64)
         .chain(iter::once(1.))
@@ -340,7 +340,7 @@ impl<'g> PieceElement<'g> {
       );
       let x = a("x")?;
       let y = a("y")?;
-      Ok::<_,AE>(PosC([x,y]))
+      Ok::<_,AE>(PosC::new(x,y))
     })()
       .with_context(|| self.pieceid.to_owned())
       .context("read position of piece out of x,y attributes")?
index 7d6ed30573c5ea1fa352ac770429367cb4933fbe..1abb761fceee1ea37d2df77ce78edeb6d163f45a 100644 (file)
@@ -87,7 +87,7 @@ impl Ctx {
       w.action_chain()
         .move_pos(&pawn)?
         .click_and_hold()
-        .move_w(&w, (hand_posg + PosC([20,0]))?)?
+        .move_w(&w, (hand_posg + PosC::new(20,0))?)?
         .release()
         .perform()?;
       w.synch()?;
index 88b9e281931a5b4ea191e44bcb1c2e46bc9b268f..8e9a51d9fdc838fcc4ebaaf3ea1408dbb0fd989e 100644 (file)
@@ -103,7 +103,7 @@ impl Ctx {
       let mut w = su.w(&self.alice)?;
       let p = w.find_piece(pc)?;
       let start = p.posg()?;
-      let end = |d| { let mut e = start; e.0[1] = table_size.0[1] + d; e };
+      let end = |d| { let mut e = start; e.coords[1] = table_size.y() + d; e };
       let try_end = end(10);
       let exp_end = end(0);
       w.action_chain()
@@ -142,7 +142,7 @@ impl Ctx {
     {
       let mut w = su.w(&self.alice)?;
       w.action_chain()
-        .move_w(&w, PosC([10,10]))?
+        .move_w(&w, PosC::new(10,10))?
         .click()
         .release()
         .perform()
@@ -183,7 +183,7 @@ impl Ctx {
       let mut w = su.w(window)?;
       let p = w.find_piece(pc)?;
       let start = p.posg()?;
-      let try_end = (start + PosC([dx, 0]))?;
+      let try_end = (start + PosC::new(dx, 0))?;
 
       let (sx,sy) = w.posg2posw(start)?;
       w.action_chain()