@@ -1957,6 +1957,130 @@ def plot(self, xs, ys, *args, zdir='z', **kwargs):
19571957
19581958    plot3D  =  plot 
19591959
1960+     def  fill_between (self , x1 , y1 , z1 , x2 , y2 , z2 , * ,
1961+                      where = None , mode = 'auto' , facecolors = None , shade = None ,
1962+                      ** kwargs ):
1963+         """ 
1964+         Fill the area between two 3D curves. 
1965+ 
1966+         The curves are defined by the points (*x1*, *y1*, *z1*) and 
1967+         (*x2*, *y2*, *z2*). This creates one or multiple quadrangle 
1968+         polygons that are filled. All points must be the same length N, or a 
1969+         single value to be used for all points. 
1970+ 
1971+         Parameters 
1972+         ---------- 
1973+         x1, y1, z1 : float or 1D array-like 
1974+             x, y, and z  coordinates of vertices for 1st line. 
1975+ 
1976+         x2, y2, z2 : float or 1D array-like 
1977+             x, y, and z coordinates of vertices for 2nd line. 
1978+ 
1979+         where : array of bool (length N), optional 
1980+             Define *where* to exclude some regions from being filled. The 
1981+             filled regions are defined by the coordinates ``pts[where]``, 
1982+             for all x, y, and z pts. More precisely, fill between ``pts[i]`` 
1983+             and ``pts[i+1]`` if ``where[i] and where[i+1]``. Note that this 
1984+             definition implies that an isolated *True* value between two 
1985+             *False* values in *where* will not result in filling. Both sides of 
1986+             the *True* position remain unfilled due to the adjacent *False* 
1987+             values. 
1988+ 
1989+         mode : {'quad', 'polygon', 'auto'}, default: 'auto' 
1990+             The fill mode. One of: 
1991+ 
1992+             - 'quad':  A separate quadrilateral polygon is created for each 
1993+               pair of subsequent points in the two lines. 
1994+             - 'polygon': The two lines are connected to form a single polygon. 
1995+               This is faster and can render more cleanly for simple shapes 
1996+               (e.g. for filling between two lines that lie within a plane). 
1997+             - 'auto': If the points all lie on the same 3D plane, 'polygon' is 
1998+               used. Otherwise, 'quad' is used. 
1999+ 
2000+         facecolors : list of :mpltype:`color`, default: None 
2001+             Colors of each individual patch, or a single color to be used for 
2002+             all patches. 
2003+ 
2004+         shade : bool, default: None 
2005+             Whether to shade the facecolors. If *None*, then defaults to *True* 
2006+             for 'quad' mode and *False* for 'polygon' mode. 
2007+ 
2008+         **kwargs 
2009+             All other keyword arguments are passed on to `.Poly3DCollection`. 
2010+ 
2011+         Returns 
2012+         ------- 
2013+         `.Poly3DCollection` 
2014+             A `.Poly3DCollection` containing the plotted polygons. 
2015+ 
2016+         """ 
2017+         _api .check_in_list (['auto' , 'quad' , 'polygon' ], mode = mode )
2018+ 
2019+         had_data  =  self .has_data ()
2020+         x1 , y1 , z1 , x2 , y2 , z2  =  cbook ._broadcast_with_masks (x1 , y1 , z1 , x2 , y2 , z2 )
2021+ 
2022+         if  facecolors  is  None :
2023+             facecolors  =  [self ._get_patches_for_fill .get_next_color ()]
2024+         facecolors  =  list (mcolors .to_rgba_array (facecolors ))
2025+ 
2026+         if  where  is  None :
2027+             where  =  True 
2028+         else :
2029+             where  =  np .asarray (where , dtype = bool )
2030+             if  where .size  !=  x1 .size :
2031+                 raise  ValueError (f"where size ({ where .size }  ) does not match " 
2032+                                  f"size ({ x1 .size }  )" )
2033+         where  =  where  &  ~ np .isnan (x1 )  # NaNs were broadcast in _broadcast_with_masks 
2034+ 
2035+         if  mode  ==  'auto' :
2036+             if  art3d ._all_points_on_plane (np .concatenate ((x1 [where ], x2 [where ])),
2037+                                           np .concatenate ((y1 [where ], y2 [where ])),
2038+                                           np .concatenate ((z1 [where ], z2 [where ])),
2039+                                           atol = 1e-12 ):
2040+                 mode  =  'polygon' 
2041+             else :
2042+                 mode  =  'quad' 
2043+ 
2044+         if  shade  is  None :
2045+             if  mode  ==  'quad' :
2046+                 shade  =  True 
2047+             else :
2048+                 shade  =  False 
2049+ 
2050+         polys  =  []
2051+         for  idx0 , idx1  in  cbook .contiguous_regions (where ):
2052+             x1i  =  x1 [idx0 :idx1 ]
2053+             y1i  =  y1 [idx0 :idx1 ]
2054+             z1i  =  z1 [idx0 :idx1 ]
2055+             x2i  =  x2 [idx0 :idx1 ]
2056+             y2i  =  y2 [idx0 :idx1 ]
2057+             z2i  =  z2 [idx0 :idx1 ]
2058+ 
2059+             if  not  len (x1i ):
2060+                 continue 
2061+ 
2062+             if  mode  ==  'quad' :
2063+                 # Preallocate the array for the region's vertices, and fill it in 
2064+                 n_polys_i  =  len (x1i ) -  1 
2065+                 polys_i  =  np .empty ((n_polys_i , 4 , 3 ))
2066+                 polys_i [:, 0 , :] =  np .column_stack ((x1i [:- 1 ], y1i [:- 1 ], z1i [:- 1 ]))
2067+                 polys_i [:, 1 , :] =  np .column_stack ((x1i [1 :], y1i [1 :], z1i [1 :]))
2068+                 polys_i [:, 2 , :] =  np .column_stack ((x2i [1 :], y2i [1 :], z2i [1 :]))
2069+                 polys_i [:, 3 , :] =  np .column_stack ((x2i [:- 1 ], y2i [:- 1 ], z2i [:- 1 ]))
2070+                 polys  =  polys  +  [* polys_i ]
2071+             elif  mode  ==  'polygon' :
2072+                 line1  =  np .column_stack ((x1i , y1i , z1i ))
2073+                 line2  =  np .column_stack ((x2i [::- 1 ], y2i [::- 1 ], z2i [::- 1 ]))
2074+                 poly  =  np .concatenate ((line1 , line2 ), axis = 0 )
2075+                 polys .append (poly )
2076+ 
2077+         polyc  =  art3d .Poly3DCollection (polys , facecolors = facecolors , shade = shade ,
2078+                                        ** kwargs )
2079+         self .add_collection (polyc )
2080+ 
2081+         self .auto_scale_xyz ([x1 , x2 ], [y1 , y2 ], [z1 , z2 ], had_data )
2082+         return  polyc 
2083+ 
19602084    def  plot_surface (self , X , Y , Z , * , norm = None , vmin = None ,
19612085                     vmax = None , lightsource = None , ** kwargs ):
19622086        """ 
0 commit comments