| 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) { |