@@ -41,21 +41,25 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
4141
4242    // BUILD LINES AND FILLS 
4343    var  prevpath  =  '' , 
44-         tozero ,  tonext ,  nexttonext ; 
44+         ownFillEl3 ,   ownFillDir ,  tonext ,  nexttonext ; 
4545
4646    scattertraces . each ( function ( d )  { 
4747        var  trace  =  d [ 0 ] . trace , 
4848            line  =  trace . line , 
4949            tr  =  d3 . select ( this ) ; 
5050        if ( trace . visible  !==  true )  return ; 
5151
52+         ownFillDir  =  trace . fill . charAt ( trace . fill . length  -  1 ) ; 
53+         if ( ownFillDir  !==  'x'  &&  ownFillDir  !==  'y' )  ownFillDir  =  '' ; 
54+ 
5255        d [ 0 ] . node3  =  tr ;  // store node for tweaking by selectPoints 
5356
5457        arraysToCalcdata ( d ) ; 
5558
5659        if ( ! subTypes . hasLines ( trace )  &&  trace . fill  ===  'none' )  return ; 
5760
5861        var  thispath , 
62+             thisrevpath , 
5963            // fullpath is all paths for this curve, joined together straight 
6064            // across gaps, for filling 
6165            fullpath  =  '' , 
@@ -67,12 +71,12 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
6771        // make the fill-to-zero path now, so it shows behind the line 
6872        // fill to next puts the fill associated with one trace 
6973        // grouped with the previous 
70-         if ( trace . fill . substr ( 0 ,  6 )  ===  'tozero'  || 
74+         if ( trace . fill . substr ( 0 ,  6 )  ===  'tozero'  ||   trace . fill   ===   'toself'   || 
7175                ( trace . fill . substr ( 0 ,  2 )  ===  'to'  &&  ! prevpath ) )  { 
72-             tozero  =  tr . append ( 'path' ) 
76+             ownFillEl3  =  tr . append ( 'path' ) 
7377                . classed ( 'js-fill' ,  true ) ; 
7478        } 
75-         else  tozero  =  null ; 
79+         else  ownFillEl3  =  null ; 
7680
7781        // make the fill-to-next path now for the NEXT trace, so it shows 
7882        // behind both lines. 
@@ -102,7 +106,7 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
102106
103107        revpathfn  =  function ( pts )  { 
104108            // note: this is destructive (reverses pts in place) so can't use pts after this 
105-             return  'L'   +   revpathbase ( pts . reverse ( ) ) . substr ( 1 ) ; 
109+             return  revpathbase ( pts . reverse ( ) ) ; 
106110        } ; 
107111
108112        var  segments  =  linePoints ( d ,  { 
@@ -121,27 +125,58 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
121125            for ( var  i  =  0 ;  i  <  segments . length ;  i ++ )  { 
122126                var  pts  =  segments [ i ] ; 
123127                thispath  =  pathfn ( pts ) ; 
124-                 fullpath  +=  fullpath  ? ( 'L'  +  thispath . substr ( 1 ) )  : thispath ; 
125-                 revpath  =  revpathfn ( pts )  +  revpath ; 
128+                 thisrevpath  =  revpathfn ( pts ) ; 
129+                 if ( ! fullpath )  { 
130+                     fullpath  =  thispath ; 
131+                     revpath  =  thisrevpath ; 
132+                 } 
133+                 else  if ( ownFillDir )  { 
134+                     fullpath  +=  'L'  +  thispath . substr ( 1 ) ; 
135+                     revpath  =  thisrevpath  +  ( 'L'  +  revpath . substr ( 1 ) ) ; 
136+                 } 
137+                 else  { 
138+                     fullpath  +=  'Z'  +  thispath ; 
139+                     revpath  =  thisrevpath  +  'Z'  +  revpath ; 
140+                 } 
126141                if ( subTypes . hasLines ( trace )  &&  pts . length  >  1 )  { 
127142                    tr . append ( 'path' ) . classed ( 'js-line' ,  true ) . attr ( 'd' ,  thispath ) ; 
128143                } 
129144            } 
130-             if ( tozero )  { 
145+             if ( ownFillEl3 )  { 
131146                if ( pt0  &&  pt1 )  { 
132-                     if ( trace . fill . charAt ( trace . fill . length  -  1 )  ===  'y' )  { 
133-                         pt0 [ 1 ]  =  pt1 [ 1 ]  =  ya . c2p ( 0 ,  true ) ; 
147+                     if ( ownFillDir )  { 
148+                         if ( ownFillDir  ===  'y' )  { 
149+                             pt0 [ 1 ]  =  pt1 [ 1 ]  =  ya . c2p ( 0 ,  true ) ; 
150+                         } 
151+                         else  if ( ownFillDir  ===  'x' )  { 
152+                             pt0 [ 0 ]  =  pt1 [ 0 ]  =  xa . c2p ( 0 ,  true ) ; 
153+                         } 
154+ 
155+                         // fill to zero: full trace path, plus extension of 
156+                         // the endpoints to the appropriate axis 
157+                         ownFillEl3 . attr ( 'd' ,  fullpath  +  'L'  +  pt1  +  'L'  +  pt0  +  'Z' ) ; 
134158                    } 
135-                     else  pt0 [ 0 ]  =  pt1 [ 0 ]  =  xa . c2p ( 0 ,  true ) ; 
136- 
137-                     // fill to zero: full trace path, plus extension of 
138-                     // the endpoints to the appropriate axis 
139-                     tozero . attr ( 'd' ,  fullpath  +  'L'  +  pt1  +  'L'  +  pt0  +  'Z' ) ; 
159+                     // fill to self: just join the path to itself 
160+                     else  ownFillEl3 . attr ( 'd' ,  fullpath  +  'Z' ) ; 
140161                } 
141162            } 
142163            else  if ( trace . fill . substr ( 0 ,  6 )  ===  'tonext'  &&  fullpath  &&  prevpath )  { 
143164                // fill to next: full trace path, plus the previous path reversed 
144-                 tonext . attr ( 'd' ,  fullpath  +  prevpath  +  'Z' ) ; 
165+                 if ( trace . fill  ===  'tonext' )  { 
166+                     // tonext: for use by concentric shapes, like manually constructed 
167+                     // contours, we just add the two paths closed on themselves. 
168+                     // This makes strange results if one path is *not* entirely 
169+                     // inside the other, but then that is a strange usage. 
170+                     tonext . attr ( 'd' ,  fullpath  +  'Z'  +  prevpath  +  'Z' ) ; 
171+                 } 
172+                 else  { 
173+                     // tonextx/y: for now just connect endpoints with lines. This is 
174+                     // the correct behavior if the endpoints are at the same value of 
175+                     // y/x, but if they *aren't*, we should ideally do more complicated 
176+                     // things depending on whether the new endpoint projects onto the 
177+                     // existing curve or off the end of it 
178+                     tonext . attr ( 'd' ,  fullpath  +  'L'  +  prevpath . substr ( 1 )  +  'Z' ) ; 
179+                 } 
145180            } 
146181            prevpath  =  revpath ; 
147182        } 
0 commit comments