BUG: Refresh 3D axis projection before tightbbox to fix constrained layout overlap (GH#31277)#31548
Conversation
4c805f7 to
b8ee493
Compare
|
The testing failures are real and require the baseline images to be regenerated, but I think this is a pretty clean fix that solves things correctly. A note: your PR description and follow-on comment appear AI-generated. Please do not do this, except for direct translation if English is not your first language. There are things in it which do not match the code ( |
b8ee493 to
5959833
Compare
|
Thanks — that's fair feedback. You're right that the description and follow-up comment were not precise and contained a leftover reference to I've also narrowed the fix:
|
|
Does it make more sense to put all this new logic inside the constrained layout check? We should be avoiding code that can have side effects, what was the issue with Also, please comment on the extent of AI usage to write your comments here. |
5959833 to
b55e1e1
Compare
|
In the fix the "if" block is now in the constrained layout check as you pointed out, it makes more sense as it is needed only for draw() call. test_axes3d_primary_views issue is failing locally in my virtual environment even without my code so it is not regression from my code.
_tightbbox_initialized flag ensures that block runs only once per axis, so draw() is not called on every get_tightbbox() call. AI (Copilot) was also used for my comments. I have read and understood the problem that it solves. |
…ayout overlap (GH#31277) Axis3D.get_tightbbox() read stale tick-label (x, y) positions that were last set during the previous draw() call. When constrained_layout queries the bounding boxes before any draw has occurred, the positions are uninitialised, causing the 3D subplot's reported bbox to be too small. Adjacent subplots then overlap the 3D tick labels. Fix: at the start of Axis3D.get_tightbbox(), if constrained_layout is active and this is the first tightbbox call for this axis, compute the projection matrix (M / invM) and call self.draw() inside renderer._draw_disabled() to update the tick-label positions without producing any visible output. A per-axis flag (_tightbbox_initialized) ensures the dry-run happens only once per layout pass. Two regression tests are added: - test_axis_get_tightbbox_before_draw_includes_ticklabels: the bboxes returned before any draw() must be non-degenerate for all three axes. - test_constrained_layout_3d_no_overlap_with_subplot_title: with a 3D subplot above a 2D subplot in constrained_layout, the 3D tight bbox bottom must not overlap the 2D subplot title. Baseline image update (stem3d.png): test_stem3d uses constrained_layout=True with a 2x3 grid of 3D subplots, which puts it directly on the fixed code path. Before this fix the layout engine received degenerate bboxes for all six 3D axes, so it did not reserve space for the tick labels; several labels were clipped at the subplot edges. After the fix the layout engine reserves the correct space, the subplots are slightly smaller, and all tick labels are fully visible. The baseline image has been regenerated to reflect the corrected layout.
b55e1e1 to
3cb927a
Compare
|
I just wanted to comment those 3 CI failings are not coused by this PR. Thank you for your review and if there are any issues that should be addressed, I am happy to re-evaluate and fix them. |
Closes #31277
constrained_layoutcallsAxis3D.get_tightbbox()before anydraw(), so tick-label 2D positions are not initialized yet and the returned bbox is too small. That leads to overlap between the 3D axis tick labels and the title of the subplot below.The fix adds a one-time no-output
draw()insideget_tightbbox(), guarded by_tightbbox_initialized, and only whenconstrained_layoutis active. If needed,axes.M/axes.invMare initialized first.This keeps behavior unchanged for non-constrained layouts.
Before / After:
Minimal reproducer:
test_stem3dbaseline is updated because it usesconstrained_layout=True, so this fix changes the rendered output (tick labels are no longer clipped).I used GitHub Copilot to help explore the code path; all changes were reviewed and tested manually.