旋转平移杆端轨迹填充及覆盖区域概率可视化实现求助
解决方案与代码优化
一、轨迹区域正确填充的实现
Plotly的fill参数依赖连续闭合路径才能生成预期填充效果,离散轨迹点直接填充会出现交叉或不完整问题。核心思路是提取轨迹的上下包络线,再填充两条包络线之间的区域:
- 收集所有杆端坐标,按X轴排序后,提取每个X值对应的最大Y(上边界)和最小Y(下边界)
- 绘制上下边界曲线,通过
fill='tonexty'实现区域填充 - 叠加原始杆端轨迹点或路径,保留细节展示
二、覆盖率可视化(类高斯分布)
要实现中心100%、Y正向覆盖率略低于负向的效果,可通过带权重的核密度估计(KDE) 实现:
- 给Y负向轨迹点赋予更高权重,让负向区域密度更高
- 将密度值归一化为百分比,中心峰值设为100%
- 用热力图或等高线图展示覆盖率分布
三、完整代码示例
import numpy as np import plotly.graph_objects as go from scipy.stats import gaussian_kde # 1. 生成旋转平移杆端轨迹数据 t = np.linspace(0, 10, 500) rod_length = 2 x_base = 0.5 * t # 底座X方向匀速平移 theta = np.pi * t * 0.3 # 旋转角度 # 杆自由端坐标(添加微小噪声模拟真实轨迹) x_b = x_base + rod_length * np.cos(theta) y_b = rod_length * np.sin(theta) + 0.2 * np.random.randn(len(t)) # 2. 提取轨迹上下包络线 all_points = np.column_stack((x_b, y_b)) sorted_idx = np.argsort(all_points[:, 0]) sorted_x, sorted_y = all_points[sorted_idx, 0], all_points[sorted_idx, 1] # 去重X并提取对应Y的极值 unique_x, idx = np.unique(sorted_x, return_index=True) upper_y, lower_y = [], [] for i in range(len(unique_x)-1): y_segment = sorted_y[idx[i]:idx[i+1]] upper_y.append(np.max(y_segment)) lower_y.append(np.min(y_segment)) upper_y.append(np.max(sorted_y[idx[-1]:])) lower_y.append(np.min(sorted_y[idx[-1]:])) upper_y, lower_y = np.array(upper_y), np.array(lower_y) # 3. 计算带权重的覆盖率分布(Y负向权重更高) weights = np.exp(0.5 * y_b) # Y值越小,权重越大 kde = gaussian_kde([x_b, y_b], weights=weights) # 生成可视化网格并计算密度 x_grid = np.linspace(np.min(x_b), np.max(x_b), 100) y_grid = np.linspace(np.min(y_b), np.max(y_b), 100) X, Y = np.meshgrid(x_grid, y_grid) density = kde(np.vstack([X.ravel(), Y.ravel()])).reshape(X.shape) density_norm = (density / np.max(density)) * 100 # 归一化为百分比 # 4. Plotly可视化 fig = go.Figure() # 添加覆盖率热力图(底层) fig.add_trace(go.Heatmap( x=x_grid, y=y_grid, z=density_norm, colorscale='Blues_r', opacity=0.5, colorbar=dict(title='覆盖率(%)'), name='覆盖率' )) # 填充轨迹区域 fig.add_trace(go.Scatter( x=unique_x, y=upper_y, mode='lines', line=dict(color='rgba(30,144,255,0.3)'), name='上边界' )) fig.add_trace(go.Scatter( x=unique_x, y=lower_y, mode='lines', line=dict(color='rgba(30,144,255,0.3)'), fill='tonexty', fillcolor='rgba(30,144,255,0.15)', name='轨迹区域' )) # 叠加原始轨迹点 fig.add_trace(go.Scatter( x=x_b, y=y_b, mode='markers', marker=dict(color='darkblue', size=3), name='杆端轨迹' )) # 布局调整 fig.update_layout( title='旋转平移杆端轨迹与覆盖率可视化', xaxis_title='X坐标', yaxis_title='Y坐标', template='plotly_white', showlegend=True ) fig.show()
四、代码优化建议
- 效率优化:若时间步数量极大,用
np.histogram2d分箱统计X-Y极值,替代逐段遍历,提升包络线提取速度 - 填充精度优化:若轨迹存在交叉,用
shapely库将离散点转换为多边形后填充,避免异常填充区域 - 覆盖率调优:通过KDE的
bw_method参数控制分布宽窄,或直接自定义二维高斯函数生成符合要求的分布(更高效) - 动态可视化:添加时间滑块展示杆的旋转平移过程,结合轨迹生成动画,提升直观性
内容的提问来源于stack exchange,提问作者pinq-
相关产品推荐
相关产品推荐

