@@ -2616,15 +2616,16 @@ d3 = function() {
26162616 function d3_true ( ) {
26172617 return true ;
26182618 }
2619- function d3_geo_clipPolygon ( segments , compare , clipStartInside , pointInPolygon , interpolate , listener ) {
2620- var subject = [ ] , clip = [ ] , rings = [ ] , n = segments . length ;
2621- for ( var i = 0 ; i < n ; ++ i ) {
2622- var segment = segments [ i ] ;
2623- if ( ( m = segment . length - 1 ) <= 0 ) continue ;
2624- var m , p0 = segment [ 0 ] , p1 = segment [ m ] ;
2619+ function d3_geo_clipPolygon ( segments , compare , clipStartInside , interpolate , listener ) {
2620+ var subject = [ ] , clip = [ ] ;
2621+ segments . forEach ( function ( segment ) {
2622+ if ( ( n = segment . length - 1 ) <= 0 ) return ;
2623+ var n , p0 = segment [ 0 ] , p1 = segment [ n ] ;
26252624 if ( d3_geo_sphericalEqual ( p0 , p1 ) ) {
2626- rings . push ( segment ) ;
2627- continue ;
2625+ listener . lineStart ( ) ;
2626+ for ( var i = 0 ; i < n ; ++ i ) listener . point ( ( p0 = segment [ i ] ) [ 0 ] , p0 [ 1 ] ) ;
2627+ listener . lineEnd ( ) ;
2628+ return ;
26282629 }
26292630 var a = new d3_geo_clipPolygonIntersection ( p0 , segment , null , true ) , b = new d3_geo_clipPolygonIntersection ( p0 , null , a , false ) ;
26302631 a . o = b ;
@@ -2635,86 +2636,45 @@ d3 = function() {
26352636 a . o = b ;
26362637 subject . push ( a ) ;
26372638 clip . push ( b ) ;
2638- }
2639- if ( subject . length ) {
2640- clip . sort ( compare ) ;
2641- d3_geo_clipPolygonLinkCircular ( subject ) ;
2642- d3_geo_clipPolygonLinkCircular ( clip ) ;
2643- for ( var i = 0 , entry = clipStartInside , n = clip . length ; i < n ; ++ i ) {
2644- clip [ i ] . e = entry = ! entry ;
2645- }
2646- var start = subject [ 0 ] , listener_ = listener , point ;
2647- if ( rings . length ) listener = d3_geo_clipBufferListener ( ) ;
2648- while ( 1 ) {
2649- var current = start , isSubject = true ;
2650- while ( current . v ) if ( ( current = current . n ) === start ) break ;
2651- if ( current . v ) break ;
2652- listener . polygonStart ( ) ;
2653- listener . lineStart ( ) ;
2654- do {
2655- current . v = current . o . v = true ;
2656- if ( current . e ) {
2657- if ( isSubject ) {
2658- for ( var i = 0 , points = current . z , n = points . length ; i < n ; ++ i ) {
2659- listener . point ( ( point = points [ i ] ) [ 0 ] , point [ 1 ] ) ;
2660- }
2661- } else {
2662- interpolate ( current . x , current . n . x , 1 , listener ) ;
2663- }
2664- current = current . n ;
2639+ } ) ;
2640+ clip . sort ( compare ) ;
2641+ d3_geo_clipPolygonLinkCircular ( subject ) ;
2642+ d3_geo_clipPolygonLinkCircular ( clip ) ;
2643+ if ( ! subject . length ) return ;
2644+ for ( var i = 0 , entry = clipStartInside , n = clip . length ; i < n ; ++ i ) {
2645+ clip [ i ] . e = entry = ! entry ;
2646+ }
2647+ var start = subject [ 0 ] , points , point ;
2648+ while ( 1 ) {
2649+ var current = start , isSubject = true ;
2650+ while ( current . v ) if ( ( current = current . n ) === start ) return ;
2651+ points = current . z ;
2652+ listener . lineStart ( ) ;
2653+ do {
2654+ current . v = current . o . v = true ;
2655+ if ( current . e ) {
2656+ if ( isSubject ) {
2657+ for ( var i = 0 , n = points . length ; i < n ; ++ i ) listener . point ( ( point = points [ i ] ) [ 0 ] , point [ 1 ] ) ;
26652658 } else {
2666- if ( isSubject ) {
2667- for ( var points = current . z , i = points . length ; -- i >= 0 ; ) {
2668- listener . point ( ( point = points [ i ] ) [ 0 ] , point [ 1 ] ) ;
2669- }
2670- } else {
2671- interpolate ( current . x , current . p . x , - 1 , listener ) ;
2672- }
2673- current = current . p ;
2659+ interpolate ( current . x , current . n . x , 1 , listener ) ;
26742660 }
2675- current = current . o ;
2676- isSubject = ! isSubject ;
2677- } while ( ! current . v ) ;
2678- listener . lineEnd ( ) ;
2679- listener . polygonEnd ( ) ;
2680- }
2681- if ( n = rings . length ) {
2682- var exteriors = listener . buffer ( ) , exteriorPolygon = [ null ] ;
2683- listener = listener_ ;
2684- for ( var j = 0 , m = exteriors . length ; j < m ; ++ j ) {
2685- var exterior = exteriorPolygon [ 0 ] = exteriors [ j ] ;
2686- listener . polygonStart ( ) ;
2687- d3_geo_clipPolygonStreamRing ( exterior , listener ) ;
2688- for ( var i = 0 ; i < n ; ++ i ) {
2689- var ring = rings [ i ] ;
2690- if ( ring && pointInPolygon ( ring [ 0 ] , exteriorPolygon ) ) {
2691- d3_geo_clipPolygonStreamRing ( ring , listener ) ;
2692- rings [ i ] = null ;
2693- }
2661+ current = current . n ;
2662+ } else {
2663+ if ( isSubject ) {
2664+ points = current . p . z ;
2665+ for ( var i = points . length - 1 ; i >= 0 ; -- i ) listener . point ( ( point = points [ i ] ) [ 0 ] , point [ 1 ] ) ;
2666+ } else {
2667+ interpolate ( current . x , current . p . x , - 1 , listener ) ;
26942668 }
2695- listener . polygonEnd ( ) ;
2669+ current = current . p ;
26962670 }
2697- }
2698- } else if ( ( n = rings . length ) || clipStartInside ) {
2699- listener . polygonStart ( ) ;
2700- if ( clipStartInside ) {
2701- listener . lineStart ( ) ;
2702- interpolate ( null , null , 1 , listener ) ;
2703- listener . lineEnd ( ) ;
2704- }
2705- for ( var i = 0 ; i < n ; ++ i ) {
2706- d3_geo_clipPolygonStreamRing ( rings [ i ] , listener ) ;
2707- }
2708- listener . polygonEnd ( ) ;
2671+ current = current . o ;
2672+ points = current . z ;
2673+ isSubject = ! isSubject ;
2674+ } while ( ! current . v ) ;
2675+ listener . lineEnd ( ) ;
27092676 }
27102677 }
2711- function d3_geo_clipPolygonStreamRing ( ring , listener ) {
2712- listener . lineStart ( ) ;
2713- for ( var i = 0 , n = ring . length - 1 , p ; i < n ; ++ i ) {
2714- listener . point ( ( p = ring [ i ] ) [ 0 ] , p [ 1 ] ) ;
2715- }
2716- listener . lineEnd ( ) ;
2717- }
27182678 function d3_geo_clipPolygonLinkCircular ( array ) {
27192679 if ( ! ( n = array . length ) ) return ;
27202680 var n , i = 0 , a = array [ 0 ] , b ;
@@ -2747,12 +2707,22 @@ d3 = function() {
27472707 clip . lineEnd = ringEnd ;
27482708 segments = [ ] ;
27492709 polygon = [ ] ;
2710+ listener . polygonStart ( ) ;
27502711 } ,
27512712 polygonEnd : function ( ) {
27522713 clip . point = point ;
27532714 clip . lineStart = lineStart ;
27542715 clip . lineEnd = lineEnd ;
2755- d3_geo_clipPolygon ( d3 . merge ( segments ) , d3_geo_clipSort , d3_geo_pointInPolygon ( rotatedClipStart , polygon ) , d3_geo_pointInPolygon , interpolate , listener ) ;
2716+ segments = d3 . merge ( segments ) ;
2717+ var clipStartInside = d3_geo_pointInPolygon ( rotatedClipStart , polygon ) ;
2718+ if ( segments . length ) {
2719+ d3_geo_clipPolygon ( segments , d3_geo_clipSort , clipStartInside , interpolate , listener ) ;
2720+ } else if ( clipStartInside ) {
2721+ listener . lineStart ( ) ;
2722+ interpolate ( null , null , 1 , listener ) ;
2723+ listener . lineEnd ( ) ;
2724+ }
2725+ listener . polygonEnd ( ) ;
27562726 segments = polygon = null ;
27572727 } ,
27582728 sphere : function ( ) {
@@ -2793,11 +2763,19 @@ d3 = function() {
27932763 function ringEnd ( ) {
27942764 pointRing ( ring [ 0 ] [ 0 ] , ring [ 0 ] [ 1 ] ) ;
27952765 ringListener . lineEnd ( ) ;
2796- var clean = ringListener . clean ( ) , ringSegments = buffer . buffer ( ) , n = ringSegments . length ;
2766+ var clean = ringListener . clean ( ) , ringSegments = buffer . buffer ( ) , segment , n = ringSegments . length ;
27972767 ring . pop ( ) ;
27982768 polygon . push ( ring ) ;
27992769 ring = null ;
28002770 if ( ! n ) return ;
2771+ if ( clean & 1 ) {
2772+ segment = ringSegments [ 0 ] ;
2773+ var n = segment . length - 1 , i = - 1 , point ;
2774+ listener . lineStart ( ) ;
2775+ while ( ++ i < n ) listener . point ( ( point = segment [ i ] ) [ 0 ] , point [ 1 ] ) ;
2776+ listener . lineEnd ( ) ;
2777+ return ;
2778+ }
28012779 if ( n > 1 && clean & 2 ) ringSegments . push ( ringSegments . pop ( ) . concat ( ringSegments . shift ( ) ) ) ;
28022780 segments . push ( ringSegments . filter ( d3_geo_clipSegmentLength1 ) ) ;
28032781 }
@@ -2817,8 +2795,6 @@ d3 = function() {
28172795 line . push ( [ λ , φ ] ) ;
28182796 } ,
28192797 lineEnd : d3_noop ,
2820- polygonStart : d3_noop ,
2821- polygonEnd : d3_noop ,
28222798 buffer : function ( ) {
28232799 var buffer = lines ;
28242800 lines = [ ] ;
@@ -3111,11 +3087,25 @@ d3 = function() {
31113087 clean = true ;
31123088 } ,
31133089 polygonEnd : function ( ) {
3114- d3_geo_clipPolygon ( d3 . merge ( segments ) , compare , pointInPolygon ( [ x0 , y1 ] , polygon ) , pointInPolygon , interpolate , listener = listener_ ) ;
3090+ listener = listener_ ;
3091+ segments = d3 . merge ( segments ) ;
3092+ var clipStartInside = insidePolygon ( [ x0 , y1 ] ) , inside = clean && clipStartInside , visible = segments . length ;
3093+ if ( inside || visible ) {
3094+ listener . polygonStart ( ) ;
3095+ if ( inside ) {
3096+ listener . lineStart ( ) ;
3097+ interpolate ( null , null , 1 , listener ) ;
3098+ listener . lineEnd ( ) ;
3099+ }
3100+ if ( visible ) {
3101+ d3_geo_clipPolygon ( segments , compare , clipStartInside , interpolate , listener ) ;
3102+ }
3103+ listener . polygonEnd ( ) ;
3104+ }
31153105 segments = polygon = ring = null ;
31163106 }
31173107 } ;
3118- function pointInPolygon ( p , polygon ) {
3108+ function insidePolygon ( p ) {
31193109 var wn = 0 , n = polygon . length , y = p [ 1 ] ;
31203110 for ( var i = 0 ; i < n ; ++ i ) {
31213111 for ( var j = 1 , v = polygon [ i ] , m = v . length , a = v [ 0 ] , b ; j < m ; ++ j ) {
0 commit comments