src/cube.rs

changeset 14
d0f20c6cb49c
parent 13
f67949050a32
child 15
2f4af30af476
equal deleted inserted replaced
13:f67949050a32 14:d0f20c6cb49c
185 } 185 }
186 186
187 /// Indicates whether an unfolded point `p` is on this face, i.e., 187 /// Indicates whether an unfolded point `p` is on this face, i.e.,
188 /// has coordinates in [0,1]². 188 /// has coordinates in [0,1]².
189 pub fn is_in_face(&self, p: &Point) -> bool { 189 pub fn is_in_face(&self, p: &Point) -> bool {
190 p.iter().map(|t| t.abs()).all(|t| 0.0 <= t && t <= 1.0) 190 p.iter().all(|t| 0.0 <= *t && *t <= 1.0)
191 } 191 }
192 192
193 /// Given an unfolded point `p`, possibly outside this face, finds 193 /// Given an unfolded point `p` and a destination point `d` in unfolded coordinates,
194 /// the edge, presented by an adjacent face, in whose direction it is. 194 /// but possibly outside this face, find the crossing point of the line between
195 /// `p` and `d` on an edge of (`self`). Return the point and the edge presented
196 /// by an adjacent face.
195 /// 197 ///
196 /// **TODO:** this does not correctly handle corners, i.e., when the point is not in 198 /// Crossing at corners is decided arbitrarily.
197 /// the direction of an adjacent face. 199 pub fn find_crossing(&self, p :& Point, d : &Point) -> (Face, Point) {
198 pub fn find_crossing(&self, p : &Point) -> Face { 200 //assert!(self.is_in_face(p));
201
202 if self.is_in_face(d) {
203 return (*self, *p)
204 }
205
206 use std::cmp::Ordering::*;
207
199 let &Loc([x, y]) = p; 208 let &Loc([x, y]) = p;
200 use std::cmp::Ordering::*; 209 let &Loc([xd, yd]) = d;
201 let crossing = |t| match (0.0 <= t, t<=1.0) { 210 let tx = xd - x;
211 let ty = yd - y;
212
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].
215 let sx = match tx.partial_cmp(&0.0) {
216 Some(Less) => 1.0f64.min(-x/tx),
217 Some(Greater) => 1.0f64.min((1.0-x)/tx),
218 _ => 1.0,
219 };
220 let sy = match ty.partial_cmp(&0.0) {
221 Some(Less) => 1.0f64.min(-y/ty),
222 Some(Greater) => 1.0f64.min((1.0-y)/ty),
223 _ => 1.0,
224 };
225 // We use the point where one coordinate comes within the range to decide on
226 // the edge.
227 let s = sx.max(sy);
228 // But move such that both coordinates are within the range.
229 let c = sx.min(sy);
230 let (cx, cy) = (x + c*tx, y + c*ty);
231
232 let crossing = |t| match (0.0 <= t, t <= 1.0) {
202 (false, _) => Less, 233 (false, _) => Less,
203 (_, false) => Greater, 234 (_, false) => Greater,
204 _ => Equal, 235 _ => Equal,
205 }; 236 };
206 237
207 // TODO: how to properly handle corners? Just throw an error? 238 // TODO: how to properly handle corners? Just throw an error?
208 match (crossing(x), crossing(y)) { 239 let crossing = match (crossing(x + s*tx), crossing(y + s*ty)) {
209 (Equal, Equal) => *self, 240 (Equal, Equal) => *self,
210 (Less, _) => self.adjacent_faces()[0], 241 (Less, _) => self.adjacent_faces()[0],
211 (Greater, _) => self.adjacent_faces()[1], 242 (Greater, _) => self.adjacent_faces()[1],
212 (Equal, Less) => self.adjacent_faces()[2], 243 (Equal, Less) => self.adjacent_faces()[2],
213 (Equal, Greater) => self.adjacent_faces()[3], 244 (Equal, Greater) => self.adjacent_faces()[3],
214 } 245 };
246 (crossing, Loc([cx, cy]))
215 } 247 }
216 248
217 /// Get embedded 3D coordinates 249 /// Get embedded 3D coordinates
218 pub fn embedded_coords(&self, p : &Point) -> Loc<f64, 3> { 250 pub fn embedded_coords(&self, p : &Point) -> Loc<f64, 3> {
219 let &Loc([x, y]) = p; 251 let &Loc([x, y]) = p;
276 impl ManifoldPoint for OnCube { 308 impl ManifoldPoint for OnCube {
277 type Tangent = Point; 309 type Tangent = Point;
278 310
279 fn exp(self, tangent : &Self::Tangent) -> Self { 311 fn exp(self, tangent : &Self::Tangent) -> Self {
280 let mut face = self.face; 312 let mut face = self.face;
281 let mut point = self.point + tangent; 313 let mut point = self.point;
314 let mut dest = self.point + tangent;
282 loop { 315 loop {
283 let next_face = face.find_crossing(&point); 316 let (next_face, cross) = face.find_crossing(&point, &dest);
284 if next_face == face { 317 if next_face == face {
285 break 318 break
286 } 319 }
287 point = next_face.convert_adjacent(face, &point).unwrap(); 320 point = next_face.convert_adjacent(face, &cross).unwrap();
321 dest = next_face.convert_adjacent(face, &dest).unwrap();
288 face = next_face; 322 face = next_face;
289 } 323 }
290 OnCube { face, point } 324 OnCube { face, point : dest }
291 } 325 }
292 326
293 fn log(&self, other : &Self) -> Self::Tangent { 327 fn log(&self, other : &Self) -> Self::Tangent {
294 self.log_dist(other).0 328 self.log_dist(other).0
295 } 329 }
309 343
310 #[test] 344 #[test]
311 fn convert_adjacent() { 345 fn convert_adjacent() {
312 let point = Loc([0.4, 0.6]); 346 let point = Loc([0.4, 0.6]);
313 347
314 for f1 in [F1, F2, F3, F4, F5, F6] { 348 for f1 in Face::all() {
315 for f2 in [F1, F2, F3, F4, F5, F6] { 349 for f2 in Face::all() {
316 println!("{:?}-{:?}", f1, f2); 350 println!("{:?}-{:?}", f1, f2);
317 match f1.convert_adjacent(f2, &point) { 351 match f1.convert_adjacent(f2, &point) {
318 None => assert_eq!(f2.opposing_face(), f1), 352 None => assert_eq!(f2.opposing_face(), f1),
319 Some(q) => { 353 Some(q) => {
320 match f2.convert_adjacent(f1, &q) { 354 match f2.convert_adjacent(f1, &q) {
331 // that a point outside the face will be returned to its point of origin. 365 // that a point outside the face will be returned to its point of origin.
332 // #[test] 366 // #[test]
333 // fn convert_paths() { 367 // fn convert_paths() {
334 // let point = Loc([0.4, 0.6]); 368 // let point = Loc([0.4, 0.6]);
335 369
336 // for f1 in [F1, F2, F3, F4, F5, F6] { 370 // for f1 in Face::all() {
337 // for f2 in [F1, F2, F3, F4, F5, F6] { 371 // for f2 in Face::all() {
338 // for p1 in f2.paths(f1) { 372 // for p1 in f2.paths(f1) {
339 // for p2 in f1.paths(f2) { 373 // for p2 in f1.paths(f2) {
340 // println!("{:?}-{:?}; {:?} {:?}", f1, f2, p1, p2); 374 // println!("{:?}-{:?}; {:?} {:?}", f1, f2, p1, p2);
341 // let v = &f2.convert(&p1, &point); 375 // let v = &f2.convert(&p1, &point);
342 // let q = f1.convert(&p2, v); 376 // let q = f1.convert(&p2, v);

mercurial