极坐标下fill_between绘图畸变及变宽螺旋异常点的排查与解决
Hey there! Let's tackle those weird artifacts in your spiral plot and solve the polar coordinate fill_between distortion together.
1. The Random "Spots" on Your Spiral Edges
What's Causing Them
The odd points you're seeing (marked by red arrows) come from how you're generating your r_bot and r_top values:
- You're using
np.random.uniform(0.1, 0.5, len(r))to create independent random offsets for every single anglet. This means adjacent points can have huge jumps in radius (e.g., one point has a +0.5 offset, the next has +0.1). - When
fill_betweenconnects these disjointed radius points in polar coordinates, the sudden jumps create sharp, unnatural kinks or "spots" in the otherwise smooth spiral edges.
How to Fix It
Instead of independent random values, generate smoothly varying random offsets so the radius changes gradually between adjacent angles. Here are two easy ways:
Option 1: Random Walk (Smooth Random Fluctuations)
Create offsets that build on the previous value to avoid sudden jumps:
# Generate small random steps, then accumulate them for smooth variation step_size = 0.05 offset_top = np.cumsum(np.random.uniform(-step_size, step_size, len(r))) # Normalize to keep offsets within your original 0.1-0.5 range offset_top = 0.1 + (0.4 * (offset_top - offset_top.min()) / (offset_top.max() - offset_top.min())) offset_bot = np.cumsum(np.random.uniform(-step_size, step_size, len(r))) offset_bot = 0.1 + (0.4 * (offset_bot - offset_bot.min()) / (offset_bot.max() - offset_bot.min())) r_bot = r - offset_bot r_top = r + offset_top
Option 2: Gaussian Smoothing
Take your original random offsets and apply a Gaussian filter to smooth out sharp jumps:
from scipy.ndimage import gaussian_filter # Generate original random offsets raw_offset_top = np.random.uniform(0.1, 0.5, len(r)) # Smooth with a Gaussian kernel (adjust sigma for more/less smoothness) offset_top = gaussian_filter(raw_offset_top, sigma=5) raw_offset_bot = np.random.uniform(0.1, 0.5, len(r)) offset_bot = gaussian_filter(raw_offset_bot, sigma=5) r_bot = r - offset_bot r_top = r + offset_top
2. Distortion in Polar Coordinate fill_between
What's Causing It
The distortion happens because of how Matplotlib handles fill_between in polar coordinates:
- Matplotlib converts polar coordinates (
t,r) to Cartesian (x,y) under the hood before drawing the filled area. - If your angle step (
0.1in your code) is too large, or if radius changes are abrupt, the converted Cartesian points can form self-intersecting polygons or misaligned edges. This leads to weird "folded" or distorted regions in the filled spiral.
How to Fix It
You can address this with two key adjustments:
- Reduce the angle step size: A smaller step (e.g.,
0.01instead of0.1) gives more dense sampling, making the Cartesian conversion smoother and avoiding misaligned edges. - Use smooth radius offsets: As we fixed in the first issue, smooth radius changes prevent sudden jumps that cause distortion.
Full Modified Code
Here's the complete code that fixes both issues:
import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt from scipy.ndimage import gaussian_filter mpl.use('Agg') plt.ioff() MY_DPI = 300 BKGD_COLOUR = 'w' FILL_COLOUR= 'k' a = 0 b = 0.5 maxRadius = 100 maxTheta = (maxRadius - a) / b # Smaller step size for smoother sampling t = np.arange(0, maxTheta, 0.01) r = a + b * t fig = plt.figure(figsize=(10,10), dpi=MY_DPI) ax = fig.add_axes([0,0,1,1], polar=True) ax.set_rlim(0, maxRadius) ax.axis('off') # Generate smooth random offsets using Gaussian filtering raw_offset_top = np.random.uniform(0.1, 0.5, len(r)) offset_top = gaussian_filter(raw_offset_top, sigma=5) raw_offset_bot = np.random.uniform(0.1, 0.5, len(r)) offset_bot = gaussian_filter(raw_offset_bot, sigma=5) r_bot = r - offset_bot r_top = r + offset_top # Fill between with smooth edges ax.fill_between(t, r_bot, r_top, color=FILL_COLOUR, lw=0) plt.savefig('spiraliser.jpg', facecolor=BKGD_COLOUR, bbox_inches='tight', dpi=MY_DPI) plt.close()
Quick Notes
- Adjust the
sigmavalue ingaussian_filterto control how smooth your spiral edges are (higher = smoother, lower = more variation but still no sharp jumps). - If you don't want to use
scipy, the random walk method works great without extra dependencies.
内容的提问来源于stack exchange,提问作者PangolinKing

