499 let φ = self.side_cap_crossing(side, cap, z); |
499 let φ = self.side_cap_crossing(side, cap, z); |
500 let capedge = CapPoint{ angle : φ, r }; |
500 let capedge = CapPoint{ angle : φ, r }; |
501 let sideedge = SidePoint{ angle : φ, z }; |
501 let sideedge = SidePoint{ angle : φ, z }; |
502 let t1 = cap.log(&capedge); |
502 let t1 = cap.log(&capedge); |
503 let t2 = sideedge.log(r, side); |
503 let t2 = sideedge.log(r, side); |
504 // Either option should give the same result, but the first one avoids division. |
504 // Either option should give the same result. |
505 t1 + capedge.tangent_from_side(top, t2) |
505 // The first one avoids division, but seems numerically more unstable due to |
506 // let n = t1.norm(L2); |
506 // sines and cosines. |
507 // (t1/n)*(n + t2.norm(L2)) |
507 //t1 + capedge.tangent_from_side(top, t2) |
|
508 let n = t1.norm(L2); |
|
509 if n < f64::EPSILON { |
|
510 capedge.tangent_from_side(top, t2) |
|
511 } else { |
|
512 (t1/n)*(n + t2.norm(L2)) |
|
513 } |
508 } |
514 } |
509 } |
515 } |
510 |
516 |
511 fn side_cap_log( |
517 fn side_cap_log( |
512 &self, |
518 &self, |
526 let φ = self.side_cap_crossing(side, cap, z); |
532 let φ = self.side_cap_crossing(side, cap, z); |
527 let capedge = CapPoint{ angle : φ, r }; |
533 let capedge = CapPoint{ angle : φ, r }; |
528 let sideedge = SidePoint{ angle : φ, z }; |
534 let sideedge = SidePoint{ angle : φ, z }; |
529 let t1 = side.log(r, &sideedge); |
535 let t1 = side.log(r, &sideedge); |
530 let t2 = capedge.log(cap); |
536 let t2 = capedge.log(cap); |
531 // Either option should give the same result, but the first one avoids division. |
537 // Either option should give the same result. |
532 t1 + capedge.tangent_to_side(top, t2) |
538 // The first one avoids division, but seems numerically more unstable due to |
533 // let n = t1.norm(L2); |
539 // sines and cosines. |
534 // (t1/n)*(n + t2.norm(L2)) |
540 // t1 + capedge.tangent_to_side(top, t2) |
|
541 let n = t1.norm(L2); |
|
542 if n < f64::EPSILON { |
|
543 capedge.tangent_to_side(top, t2) |
|
544 } else { |
|
545 (t1/n)*(n + t2.norm(L2)) |
|
546 } |
535 } |
547 } |
536 } |
548 } |
537 |
549 |
538 fn side_cap_side_log( |
550 fn side_cap_side_log( |
539 &self, |
551 &self, |
561 let capedge2 = CapPoint{ angle : φ2, r }; |
573 let capedge2 = CapPoint{ angle : φ2, r }; |
562 let sideedge2 = SidePoint{ angle : φ2, z }; |
574 let sideedge2 = SidePoint{ angle : φ2, z }; |
563 let t1 = side1.log(r, &sideedge1); |
575 let t1 = side1.log(r, &sideedge1); |
564 let t2 = capedge1.log(&capedge2); |
576 let t2 = capedge1.log(&capedge2); |
565 let t3 = sideedge2.log(r, &side2); |
577 let t3 = sideedge2.log(r, &side2); |
566 // Any option should give the same result, but the first one avoids division. |
578 // Either option should give the same result. |
|
579 // The first one avoids division, but seems numerically more unstable due to |
|
580 // sines and cosines. |
|
581 // |
567 // t1 + capedge1.tangent_to_side(top, t2 + capedge2.tangent_from_side(top, t3)) |
582 // t1 + capedge1.tangent_to_side(top, t2 + capedge2.tangent_from_side(top, t3)) |
568 // |
|
569 // let n = t2.norm(L2); |
|
570 // t1 + capedge1.tangent_to_side(top, (t2/n)*(n + t3.norm(L2))) |
|
571 // |
|
572 let n = t1.norm(L2); |
583 let n = t1.norm(L2); |
573 (t1/n)*(n + t2.norm(L2) + t3.norm(L2)) |
584 if n < f64::EPSILON { |
574 // |
585 let n2 = t2.norm(L2); |
575 // let n = t1.norm(L2); |
586 capedge1.tangent_to_side(top, |
576 // let t23 = t2 + capedge2.tangent_from_side(top, t3); |
587 if n2 < f64::EPSILON { |
577 // (t1/n)*(n + t23.norm(L2)) |
588 capedge2.tangent_from_side(top, t3) |
|
589 } else { |
|
590 (t2/n2)*(n2 + t3.norm(L2)) |
|
591 } |
|
592 ) |
|
593 } else { |
|
594 (t1/n)*(n + t2.norm(L2) + t3.norm(L2)) |
|
595 } |
578 } |
596 } |
579 } |
597 } |
580 |
598 |
581 fn cap_side_cap_log( |
599 fn cap_side_cap_log( |
582 &self, |
600 &self, |
604 let sideedge2 = SidePoint{ angle : φ2, z : z2}; |
622 let sideedge2 = SidePoint{ angle : φ2, z : z2}; |
605 let capedge2 = CapPoint{ angle : φ2, r }; |
623 let capedge2 = CapPoint{ angle : φ2, r }; |
606 let t1 = cap1.log(&capedge1); |
624 let t1 = cap1.log(&capedge1); |
607 let t2 = sideedge1.log(r, &sideedge2); |
625 let t2 = sideedge1.log(r, &sideedge2); |
608 let t3 = capedge2.log(cap2); |
626 let t3 = capedge2.log(cap2); |
609 // Either option should give the same result, but the first one avoids division. |
627 // Either option should give the same result. |
610 t1 + capedge1.tangent_from_side(top1, t2 + capedge2.tangent_to_side(top2, t3)) |
628 // The first one avoids division, but seems numerically more unstable due to |
611 //let n = t1.norm(L2); |
629 // sines and cosines. |
612 //(t1/n)*(n + t2.norm(L2) + t3.norm(L2)) |
630 // t1 + capedge1.tangent_from_side(top1, t2 + capedge2.tangent_to_side(top2, t3)) |
|
631 let n = t1.norm(L2); |
|
632 if n < f64::EPSILON { |
|
633 let n2 = t2.norm(L2); |
|
634 capedge1.tangent_from_side(top1, |
|
635 if n2 < f64::EPSILON { |
|
636 capedge2.tangent_to_side(top2, t3) |
|
637 } else { |
|
638 (t2/n2)*(n2 + t3.norm(L2)) |
|
639 } |
|
640 ) |
|
641 } else { |
|
642 (t1/n)*(n + t2.norm(L2) + t3.norm(L2)) |
|
643 } |
613 } |
644 } |
614 } |
645 } |
615 |
646 |
616 /// Calculates both the logarithmic map and distance to another point |
647 /// Calculates both the logarithmic map and distance to another point |
617 fn log_dist(&self, source : &Point, destination : &Point) -> (Tangent, f64) { |
648 fn log_dist(&self, source : &Point, destination : &Point) -> (Tangent, f64) { |