{{ message }}
FIX: keep sub-pixel segments visible when snapping (#20243)#31981
Open
Zish19 wants to merge 2 commits into
Open
FIX: keep sub-pixel segments visible when snapping (#20243)#31981Zish19 wants to merge 2 commits into
Zish19 wants to merge 2 commits into
Conversation
343a057 to
0911d67
Compare
PathSnapper rounds each vertex to the nearest pixel. A line mark shorter than one pixel then has both endpoints rounded onto the same pixel, so it collapses to zero length and is not drawn at all. eventplot builds every event as its own two-point segment, so plotting many closely spaced events silently dropped most of them. When the opening LINETO of a subpath snaps onto its MOVETO even though the raw segment was non-degenerate, extend the endpoint by one pixel along the segment's dominant axis so a single pixel is still drawn. Limiting this to the first segment of a subpath leaves polygon outlines (bars, markers, grids) snapping exactly as before.
0911d67 to
eec0fee
Compare
Update PathSnapper to look ahead one vertex. This ensures that only isolated zero-length segments (like those generated by eventplot) are extended to 1 pixel. This fixes unintended rendering distortion in polygons from streamplot, hist_step_filled, etc.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

PR summary
Closes #20243
PathSnapper rounds every vertex to the nearest pixel. When a line segment is shorter than a pixel, both endpoints
round to the same pixel, so the segment collapses to zero length and the Agg renderer draws nothing. With eventplots
of many events, this silently dropped most of the data, see #20243.
This change tracks the previous raw/snapped vertex in PathSnapper. When a LINETO snaps onto the previous point even
though the raw segment had non-zero length, the snapped endpoint is nudged by one pixel along the segment's dominant
direction. The result is at least one full-color pixel rather than blurring the mark by disabling snapping (per the
discussion in #20243, this matches the preference for a full-color pixel over anti-aliased fuzz). Segments that
already span a pixel are untouched, so normal rendering (lines, bars, grids) is byte-for-byte unchanged.
Minimum self-contained example
import matplotlib.pyplot as plt
import numpy as np
data = [np.random.random(np.random.randint(10)) for _ in range(500)]
fig, ax = plt.subplots()
ax.eventplot(data, linelength=1)
plt.show()
Before: most rows are missing.
After: every event renders as at least one full pixel.
Verification: A regression test (test_eventplot_sub_pixel_events_not_dropped) renders 200 isolated sub-pixel event
marks and asserts they are all drawn. On the unpatched renderer 0/200 marks appear; with this change all of them do.
A separate check confirms the pixel buffers of ordinary line plots, bar charts, grids, and normal-scale eventplots
are identical before and after the change, so there is no visual regression on content that already covers a pixel.
PR checklist
(https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
(https://matplotlib.org/devdocs/devel/document.html#write-examples-and-tutorials)
(https://matplotlib.org/devdocs/devel/api_changes.html#announce-changes-deprecations-and-new-features)
docstring (https://matplotlib.org/devdocs/devel/document.html#write-docstrings) guidelines