src/cube.rs

changeset 15
2f4af30af476
parent 14
d0f20c6cb49c
child 28
334fd47c482e
child 29
76f9ec073a83
equal deleted inserted replaced
14:d0f20c6cb49c 15:2f4af30af476
209 let &Loc([xd, yd]) = d; 209 let &Loc([xd, yd]) = d;
210 let tx = xd - x; 210 let tx = xd - x;
211 let ty = yd - y; 211 let ty = yd - y;
212 212
213 // Move towards tangent as (x + s tx, y + s ty) for the largest s<=1.0 for which 213 // Move towards tangent as (x + s tx, y + s ty) for the largest s<=1.0 for which
214 // both coordinates is within [0, 1]. 214 // both coordinates is within [0, 1]. Also gives the direction of move along
215 let sx = match tx.partial_cmp(&0.0) { 215 // each coordinate.
216 Some(Less) => 1.0f64.min(-x/tx), 216 let (sx, dirx) = match tx.partial_cmp(&0.0) {
217 Some(Greater) => 1.0f64.min((1.0-x)/tx), 217 Some(Less) => (1.0f64.min(-x/tx), Less),
218 _ => 1.0, 218 Some(Greater) => (1.0f64.min((1.0-x)/tx), Greater),
219 _ => (1.0, Equal)
219 }; 220 };
220 let sy = match ty.partial_cmp(&0.0) { 221 let (sy, diry) = match ty.partial_cmp(&0.0) {
221 Some(Less) => 1.0f64.min(-y/ty), 222 Some(Less) => (1.0f64.min(-y/ty), Less),
222 Some(Greater) => 1.0f64.min((1.0-y)/ty), 223 Some(Greater) => (1.0f64.min((1.0-y)/ty), Greater),
223 _ => 1.0, 224 _ => (1.0, Equal),
224 }; 225 };
225 // We use the point where one coordinate comes within the range to decide on 226
226 // the edge. 227 // TODO: how to properly handle corners? Just throw an error?
227 let s = sx.max(sy); 228 let (crossing, c) = match (sx < sy, dirx, diry) {
228 // But move such that both coordinates are within the range. 229 // x move is less than y move, so crossing is either on left or right edge
229 let c = sx.min(sy); 230 (true, Less, _) => (self.adjacent_faces()[0], sx),
230 let (cx, cy) = (x + c*tx, y + c*ty); 231 (true, Greater, _) => (self.adjacent_faces()[1], sx),
231 232 (true, Equal, _) => (*self, sx),
232 let crossing = |t| match (0.0 <= t, t <= 1.0) { 233 // y move is less than x move, so crossing is either on bottom or top edge
233 (false, _) => Less, 234 (false, _, Less) => (self.adjacent_faces()[2], sy),
234 (_, false) => Greater, 235 (false, _, Greater) => (self.adjacent_faces()[3], sy),
235 _ => Equal, 236 (false, _, Equal) => (*self, sy),
236 }; 237 };
237 238 (crossing, Loc([x + c*tx, y + c*ty]))
238 // TODO: how to properly handle corners? Just throw an error?
239 let crossing = match (crossing(x + s*tx), crossing(y + s*ty)) {
240 (Equal, Equal) => *self,
241 (Less, _) => self.adjacent_faces()[0],
242 (Greater, _) => self.adjacent_faces()[1],
243 (Equal, Less) => self.adjacent_faces()[2],
244 (Equal, Greater) => self.adjacent_faces()[3],
245 };
246 (crossing, Loc([cx, cy]))
247 } 239 }
248 240
249 /// Get embedded 3D coordinates 241 /// Get embedded 3D coordinates
250 pub fn embedded_coords(&self, p : &Point) -> Loc<f64, 3> { 242 pub fn embedded_coords(&self, p : &Point) -> Loc<f64, 3> {
251 let &Loc([x, y]) = p; 243 let &Loc([x, y]) = p;

mercurial