@@ -738,37 +738,32 @@ d3.geo.clip = function() {
738738 o = { source : origin , target : null } ,
739739 n = d . length ,
740740 i = - 1 ,
741- j ,
742741 path ,
743742 clipped = [ ] ,
744743 p = null ,
745- q = null ;
744+ q = null ,
745+ distance ,
746+ oldDistance ;
746747 while ( ++ i < n ) {
747748 o . target = d [ i ] ;
748749 distance = d3_geo_clipGreatCircle . distance ( o ) ;
749750 if ( distance < r ) {
750- if ( q ) {
751- path = d3_geo_clipGreatCircle ( { source : q , target : o . target } ) ;
752- j = d3_geo_clipClosest ( path , o , r ) ;
753- if ( path . length ) clipped . push ( path [ j ] ) ;
754- }
751+ if ( q ) clipped . push ( d3_geo_clipIntersect ( q , o . target , ( oldDistance - r ) / ( oldDistance - distance ) ) ) ;
755752 clipped . push ( d [ i ] ) ;
756753 p = q = null ;
757754 } else {
758755 q = o . target ;
759756 if ( ! p && clipped . length ) {
760- path = d3_geo_clipGreatCircle ( { source : clipped [ clipped . length - 1 ] , target : o . target } ) ;
761- j = d3_geo_clipClosest ( path , o , r ) ;
762- if ( path . length ) clipped . push ( path [ j ] ) ;
763- p = o . target ;
757+ clipped . push ( d3_geo_clipIntersect ( clipped [ clipped . length - 1 ] , q , ( r - oldDistance ) / ( distance - oldDistance ) ) ) ;
758+ p = q ;
764759 }
765760 }
761+ oldDistance = distance ;
766762 }
767763 if ( q && clipped . length ) {
768764 o . target = clipped [ 0 ] ;
769- path = d3_geo_clipGreatCircle ( { source : q , target : o . target } ) ;
770- j = d3_geo_clipClosest ( path , o , r ) ;
771- if ( path . length ) clipped . push ( path [ j ] ) ;
765+ distance = d3_geo_clipGreatCircle . distance ( o ) ;
766+ clipped . push ( d3_geo_clipIntersect ( q , o . target , ( oldDistance - r ) / ( oldDistance - distance ) ) ) ;
772767 }
773768 return clipped ;
774769 }
@@ -799,20 +794,27 @@ var d3_geo_clipGreatCircle = d3.geo.greatCircle().coordinates(function(d) {
799794 return [ d . source , d . target ] ;
800795} ) ;
801796
802- function d3_geo_clipClosest ( path , o , r ) {
803- var i = - 1 ,
804- n = path . length ,
805- index = 0 ,
806- best = Infinity ;
807- while ( ++ i < n ) {
808- o . target = path [ i ] ;
809- var d = Math . abs ( d3_geo_clipGreatCircle . distance ( o ) - r ) ;
810- if ( d < best ) {
811- best = d ;
812- index = i ;
813- }
814- }
815- o . target = path [ index ] ;
816- return index ;
797+ function d3_geo_clipIntersect ( from , to , f ) {
798+ var x0 = from [ 0 ] * d3_radians ,
799+ y0 = from [ 1 ] * d3_radians ,
800+ x1 = to [ 0 ] * d3_radians ,
801+ y1 = to [ 1 ] * d3_radians ,
802+ cx0 = Math . cos ( x0 ) , sx0 = Math . sin ( x0 ) ,
803+ cy0 = Math . cos ( y0 ) , sy0 = Math . sin ( y0 ) ,
804+ cx1 = Math . cos ( x1 ) , sx1 = Math . sin ( x1 ) ,
805+ cy1 = Math . cos ( y1 ) , sy1 = Math . sin ( y1 ) ,
806+ d = Math . acos ( Math . max ( - 1 , Math . min ( 1 , sy0 * sy1 + cy0 * cy1 * Math . cos ( x1 - x0 ) ) ) ) ,
807+ e = f * d ,
808+ sd = Math . sin ( d ) ,
809+ A = Math . sin ( d - e ) / sd ,
810+ B = Math . sin ( e ) / sd ,
811+ x = A * cy0 * cx0 + B * cy1 * cx1 ,
812+ y = A * cy0 * sx0 + B * cy1 * sx1 ,
813+ z = A * sy0 + B * sy1 ;
814+
815+ return [
816+ Math . atan2 ( y , x ) / d3_radians ,
817+ Math . atan2 ( z , Math . sqrt ( x * x + y * y ) ) / d3_radians
818+ ] ;
817819}
818820} ) ( ) ;
0 commit comments