Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3200e54

Browse files
First pass at exact 3d plot limits
1 parente7fd79f commit3200e54

File tree

8 files changed

+178
-78
lines changed

8 files changed

+178
-78
lines changed

‎lib/matplotlib/axis.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -829,13 +829,14 @@ def _get_autoscale_on(self):
829829
def_set_autoscale_on(self,b):
830830
"""
831831
Set whether this Axis is autoscaled when drawing or by
832-
`.Axes.autoscale_view`.
832+
`.Axes.autoscale_view`. If b is None, then the value is not changed.
833833
834834
Parameters
835835
----------
836836
b : bool
837837
"""
838-
self._autoscale_on=b
838+
ifbisnotNone:
839+
self._autoscale_on=b
839840

840841
defget_children(self):
841842
return [self.label,self.offsetText,
@@ -1219,8 +1220,7 @@ def _set_lim(self, v0, v1, *, emit=True, auto):
12191220
# Mark viewlims as no longer stale without triggering an autoscale.
12201221
foraxinself._get_shared_axes():
12211222
ax._stale_viewlims[name]=False
1222-
ifautoisnotNone:
1223-
self._set_autoscale_on(bool(auto))
1223+
self._set_autoscale_on(auto)
12241224

12251225
ifemit:
12261226
self.axes.callbacks.process(f"{name}lim_changed",self.axes)

‎lib/matplotlib/mpl-data/matplotlibrc‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,9 @@
425425
#axes.autolimit_mode: data # If "data", use axes.xmargin and axes.ymargin as is.
426426
# If "round_numbers", after application of margins, axis
427427
# limits are further expanded to the nearest "round" number.
428-
#polaraxes.grid: True # display grid on polar axes
429-
#axes3d.grid: True # display grid on 3D axes
428+
#polaraxes.grid: True # display grid on polar axes
429+
#axes3d.grid: True # display grid on 3D axes
430+
#axes3d.automargin: False # automatically add margin when manually setting 3D axis limits
430431

431432
#axes3d.xaxis.panecolor: (0.95, 0.95, 0.95, 0.5) # background pane on 3D axes
432433
#axes3d.yaxis.panecolor: (0.90, 0.90, 0.90, 0.5) # background pane on 3D axes

‎lib/matplotlib/mpl-data/stylelib/classic.mplstyle‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ axes.spines.left : True
223223
axes.spines.right : True
224224
axes.spines.top : True
225225
polaraxes.grid : True # display grid on polar axes
226-
axes3d.grid : True # display grid on 3d axes
226+
axes3d.grid : True # display grid on 3D axes
227+
axes3d.automargin : False # automatically add margin when manually setting 3D axis limits
227228

228229
date.autoformatter.year : %Y
229230
date.autoformatter.month : %b %Y

‎lib/matplotlib/rcsetup.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,8 +1016,10 @@ def _convert_validator_spec(key, conv):
10161016
"axes.ymargin":_range_validators["0 <= x <= 1"],# margin added to yaxis
10171017
'axes.zmargin':_range_validators["0 <= x <= 1"],# margin added to zaxis
10181018

1019-
"polaraxes.grid":validate_bool,# display polar grid or not
1020-
"axes3d.grid":validate_bool,# display 3d grid
1019+
"polaraxes.grid":validate_bool,# display polar grid or not
1020+
"axes3d.grid":validate_bool,# display 3d grid
1021+
"axes3d.automargin":validate_bool,# automatically add margin when
1022+
# manually setting 3D axis limits
10211023

10221024
"axes3d.xaxis.panecolor":validate_color,# 3d background pane
10231025
"axes3d.yaxis.panecolor":validate_color,# 3d background pane

‎lib/matplotlib/ticker.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,6 +2076,8 @@ def _raw_ticks(self, vmin, vmax):
20762076
steps=steps[igood]
20772077

20782078
raw_step= ((_vmax-_vmin)/nbins)
2079+
ifhasattr(self.axis,"axes")andself.axis.axes.name=='3d':
2080+
raw_step=raw_step*24/25# needed to match mpl3.7 appearance
20792081
large_steps=steps>=raw_step
20802082
ifmpl.rcParams['axes.autolimit_mode']=='round_numbers':
20812083
# Classic round_numbers mode may require a larger step.

‎lib/mpl_toolkits/mplot3d/axes3d.py‎

Lines changed: 137 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ def __init__(
129129

130130
self.xy_viewLim=Bbox.unit()
131131
self.zz_viewLim=Bbox.unit()
132-
self.xy_dataLim=Bbox.unit()
132+
xymargin=0.05*10/11# match mpl3.7 appearance
133+
self.xy_dataLim=Bbox([[xymargin,xymargin],
134+
[1-xymargin,1-xymargin]])
133135
# z-limits are encoded in the x-component of the Bbox, y is un-used
134136
self.zz_dataLim=Bbox.unit()
135137

@@ -157,6 +159,9 @@ def __init__(
157159
self.set_axis_on()
158160
self.M=None
159161

162+
self._view_margin=1/48# default value to match mpl3.7
163+
self.autoscale_view()
164+
160165
# func used to format z -- fall back on major formatters
161166
self.fmt_zdata=None
162167

@@ -336,7 +341,8 @@ def set_aspect(self, aspect, adjustable=None, anchor=None, share=False):
336341
self.set_ylim3d,
337342
self.set_zlim3d)):
338343
ifiinax_indices:
339-
set_lim(mean[i]-deltas[i]/2.,mean[i]+deltas[i]/2.)
344+
set_lim(mean[i]-deltas[i]/2.,mean[i]+deltas[i]/2.,
345+
auto=None,view_margin=self._view_margin)
340346
else:# 'box'
341347
# Change the box aspect such that the ratio of the length of
342348
# the unmodified axis to the length of the diagonal
@@ -404,8 +410,8 @@ def set_box_aspect(self, aspect, *, zoom=1):
404410
else:
405411
aspect=np.asarray(aspect,dtype=float)
406412
_api.check_shape((3,),aspect=aspect)
407-
# default scale tuned to match thempl32 appearance.
408-
aspect*=1.8294640721620434*zoom/np.linalg.norm(aspect)
413+
# default scale tuned to match thempl3.2 appearance.
414+
aspect*=1.8294640721620434*25/24*zoom/np.linalg.norm(aspect)
409415

410416
self._box_aspect=aspect
411417
self.stale=True
@@ -575,17 +581,17 @@ def autoscale(self, enable=True, axis='both', tight=None):
575581
scalez=True
576582
else:
577583
ifaxisin ['x','both']:
578-
self.set_autoscalex_on(bool(enable))
584+
self.set_autoscalex_on(enable)
579585
scalex=self.get_autoscalex_on()
580586
else:
581587
scalex=False
582588
ifaxisin ['y','both']:
583-
self.set_autoscaley_on(bool(enable))
589+
self.set_autoscaley_on(enable)
584590
scaley=self.get_autoscaley_on()
585591
else:
586592
scaley=False
587593
ifaxisin ['z','both']:
588-
self.set_autoscalez_on(bool(enable))
594+
self.set_autoscalez_on(enable)
589595
scalez=self.get_autoscalez_on()
590596
else:
591597
scalez=False
@@ -610,8 +616,8 @@ def auto_scale_xyz(self, X, Y, Z=None, had_data=None):
610616
# Let autoscale_view figure out how to use this data.
611617
self.autoscale_view()
612618

613-
defautoscale_view(self,tight=None,scalex=True,scaley=True,
614-
scalez=True):
619+
defautoscale_view(self,tight=None,
620+
scalex=True,scaley=True,scalez=True):
615621
"""
616622
Autoscale the view limits using the data limits.
617623
@@ -643,7 +649,7 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True,
643649
x1+=delta
644650
ifnot_tight:
645651
x0,x1=xlocator.view_limits(x0,x1)
646-
self.set_xbound(x0,x1)
652+
self.set_xbound(x0,x1,self._view_margin)
647653

648654
ifscaleyandself.get_autoscaley_on():
649655
y0,y1=self.xy_dataLim.intervaly
@@ -655,7 +661,7 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True,
655661
y1+=delta
656662
ifnot_tight:
657663
y0,y1=ylocator.view_limits(y0,y1)
658-
self.set_ybound(y0,y1)
664+
self.set_ybound(y0,y1,self._view_margin)
659665

660666
ifscalezandself.get_autoscalez_on():
661667
z0,z1=self.zz_dataLim.intervalx
@@ -667,7 +673,7 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True,
667673
z1+=delta
668674
ifnot_tight:
669675
z0,z1=zlocator.view_limits(z0,z1)
670-
self.set_zbound(z0,z1)
676+
self.set_zbound(z0,z1,self._view_margin)
671677

672678
defget_w_lims(self):
673679
"""Get 3D world limits."""
@@ -676,28 +682,116 @@ def get_w_lims(self):
676682
minz,maxz=self.get_zlim3d()
677683
returnminx,maxx,miny,maxy,minz,maxz
678684

679-
# set_xlim, set_ylim are directly inherited from base Axes.
685+
def_set_bound3d(self,get_bound,set_lim,axis_inverted,
686+
lower=None,upper=None,view_margin=None):
687+
"""
688+
Set 3D axis bounds.
689+
"""
690+
ifupperisNoneandnp.iterable(lower):
691+
lower,upper=lower
692+
693+
old_lower,old_upper=get_bound()
694+
iflowerisNone:
695+
lower=old_lower
696+
ifupperisNone:
697+
upper=old_upper
698+
699+
set_lim(sorted((lower,upper),reverse=bool(axis_inverted())),
700+
auto=None,view_margin=view_margin)
701+
702+
defset_xbound(self,lower=None,upper=None,view_margin=None):
703+
# docstring inherited
704+
self._set_bound3d(self.get_xbound,self.set_xlim,self.xaxis_inverted,
705+
upper,lower,view_margin)
706+
707+
defset_ybound(self,lower=None,upper=None,view_margin=None):
708+
# docstring inherited
709+
self._set_bound3d(self.get_ybound,self.set_ylim,self.yaxis_inverted,
710+
upper,lower,view_margin)
711+
712+
defset_zbound(self,lower=None,upper=None,view_margin=None):
713+
"""
714+
Set the lower and upper numerical bounds of the z-axis.
715+
This method will honor axis inversion regardless of parameter order.
716+
It will not change the autoscaling setting (`.get_autoscaley_on()`).
717+
Parameters
718+
----------
719+
lower, upper : float or None
720+
The lower and upper bounds. If *None*, the respective axis bound
721+
is not modified.
722+
view_margin : float or None
723+
The margin to apply to the bounds. If *None*, the margin is handled
724+
by set_zlim.
725+
See Also
726+
--------
727+
get_zbound
728+
get_zlim, set_zlim
729+
invert_zaxis, zaxis_inverted
730+
"""
731+
self._set_bound3d(self.get_zbound,self.set_zlim,self.zaxis_inverted,
732+
upper,lower,view_margin)
733+
734+
def_set_lim3d(self,axis,lower=None,upper=None,*,emit=True,
735+
auto=False,view_margin=None,axmin=None,axmax=None):
736+
"""
737+
Set 3D axis limits.
738+
See `.Axes.set_ylim` for full documentation
739+
"""
740+
ifupperisNone:
741+
ifnp.iterable(lower):
742+
lower,upper=lower
743+
else:
744+
raiseValueError("Must provide an upper bound.")
745+
iflowerisNone:
746+
raiseValueError("Must provide a lower bound.")
747+
ifaxminisnotNone:
748+
iflowerisnotNone:
749+
raiseTypeError("Cannot pass both 'lower' and 'min'")
750+
lower=axmin
751+
ifaxmaxisnotNone:
752+
ifupperisnotNone:
753+
raiseTypeError("Cannot pass both 'upper' and 'max'")
754+
upper=axmax
755+
ifview_marginisNone:
756+
ifmpl.rcParams['axes3d.automargin']:
757+
view_margin=self._view_margin
758+
else:
759+
view_margin=0
760+
delta= (upper-lower)*view_margin
761+
lower-=delta
762+
upper+=delta
763+
returnaxis._set_lim(lower,upper,emit=emit,auto=auto)
764+
765+
defset_xlim(self,left=None,right=None,*,emit=True,auto=False,
766+
view_margin=None,xmin=None,xmax=None):
767+
"""
768+
Set 3D x limits.
769+
See `.Axes.set_xlim` for full documentation
770+
"""
771+
returnself._set_lim3d(self.xaxis,left,right,emit=emit,auto=auto,
772+
view_margin=view_margin,axmin=xmin,axmax=xmax)
773+
774+
defset_ylim(self,bottom=None,top=None,*,emit=True,auto=False,
775+
view_margin=None,ymin=None,ymax=None):
776+
"""
777+
Set 3D y limits.
778+
See `.Axes.set_ylim` for full documentation
779+
"""
780+
returnself._set_lim3d(self.yaxis,bottom,top,emit=emit,auto=auto,
781+
view_margin=view_margin,axmin=ymin,axmax=ymax)
782+
680783
defset_zlim(self,bottom=None,top=None,*,emit=True,auto=False,
681-
zmin=None,zmax=None):
784+
view_margin=None,zmin=None,zmax=None):
682785
"""
683786
Set 3D z limits.
684787
685788
See `.Axes.set_ylim` for full documentation
686789
"""
687-
iftopisNoneandnp.iterable(bottom):
688-
bottom,top=bottom
689-
ifzminisnotNone:
690-
ifbottomisnotNone:
691-
raiseTypeError("Cannot pass both 'bottom' and 'zmin'")
692-
bottom=zmin
693-
ifzmaxisnotNone:
694-
iftopisnotNone:
695-
raiseTypeError("Cannot pass both 'top' and 'zmax'")
696-
top=zmax
697-
returnself.zaxis._set_lim(bottom,top,emit=emit,auto=auto)
698-
699-
set_xlim3d=maxes.Axes.set_xlim
700-
set_ylim3d=maxes.Axes.set_ylim
790+
returnself._set_lim3d(self.zaxis,bottom,top,emit=emit,auto=auto,
791+
view_margin=view_margin,axmin=zmin,axmax=zmax)
792+
793+
set_xlim3d=set_xlim
794+
set_ylim3d=set_ylim
701795
set_zlim3d=set_zlim
702796

703797
defget_xlim(self):
@@ -982,6 +1076,15 @@ def clear(self):
9821076
self._zmargin=mpl.rcParams['axes.zmargin']
9831077
else:
9841078
self._zmargin=0.
1079+
1080+
xymargin=0.05*10/11# match mpl3.7 appearance
1081+
self.xy_dataLim=Bbox([[xymargin,xymargin],
1082+
[1-xymargin,1-xymargin]])
1083+
# z-limits are encoded in the x-component of the Bbox, y is un-used
1084+
self.zz_dataLim=Bbox.unit()
1085+
self._view_margin=1/48# default value to match mpl3.7
1086+
self.autoscale_view()
1087+
9851088
self.grid(mpl.rcParams['axes3d.grid'])
9861089

9871090
def_button_press(self,event):
@@ -1162,9 +1265,9 @@ def drag_pan(self, button, key, x, y):
11621265
dz= (maxz-minz)*duvw_projected[2]
11631266

11641267
# Set the new axis limits
1165-
self.set_xlim3d(minx+dx,maxx+dx)
1166-
self.set_ylim3d(miny+dy,maxy+dy)
1167-
self.set_zlim3d(minz+dz,maxz+dz)
1268+
self.set_xlim3d(minx+dx,maxx+dx,auto=None)
1269+
self.set_ylim3d(miny+dy,maxy+dy,auto=None)
1270+
self.set_zlim3d(minz+dz,maxz+dz,auto=None)
11681271

11691272
def_calc_view_axes(self,eye):
11701273
"""
@@ -1301,9 +1404,9 @@ def _scale_axis_limits(self, scale_x, scale_y, scale_z):
13011404
dz= (maxz-minz)*scale_z
13021405

13031406
# Set the scaled axis limits
1304-
self.set_xlim3d(cx-dx/2,cx+dx/2)
1305-
self.set_ylim3d(cy-dy/2,cy+dy/2)
1306-
self.set_zlim3d(cz-dz/2,cz+dz/2)
1407+
self.set_xlim3d(cx-dx/2,cx+dx/2,auto=None)
1408+
self.set_ylim3d(cy-dy/2,cy+dy/2,auto=None)
1409+
self.set_zlim3d(cz-dz/2,cz+dz/2,auto=None)
13071410

13081411
defset_zlabel(self,zlabel,fontdict=None,labelpad=None,**kwargs):
13091412
"""
@@ -1392,26 +1495,6 @@ def get_zbound(self):
13921495
else:
13931496
returntop,bottom
13941497

1395-
defset_zbound(self,lower=None,upper=None):
1396-
"""
1397-
Set the lower and upper numerical bounds of the z-axis.
1398-
1399-
This method will honor axes inversion regardless of parameter order.
1400-
It will not change the autoscaling setting (`.get_autoscalez_on()`).
1401-
"""
1402-
ifupperisNoneandnp.iterable(lower):
1403-
lower,upper=lower
1404-
1405-
old_lower,old_upper=self.get_zbound()
1406-
iflowerisNone:
1407-
lower=old_lower
1408-
ifupperisNone:
1409-
upper=old_upper
1410-
1411-
self.set_zlim(sorted((lower,upper),
1412-
reverse=bool(self.zaxis_inverted())),
1413-
auto=None)
1414-
14151498
deftext(self,x,y,z,s,zdir=None,**kwargs):
14161499
"""
14171500
Add text to the plot.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp