You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Plotly绘制贴合倾斜/旋转线条轴线的椭球

根因分析

你当前的调用代码中固定给ellipse函数传入了旋转角为π/2的轴向向量,没有匹配实际数据线条的倾斜方向,导致生成的椭圆和线条无法贴合。原ellipse函数本身的逻辑是正确的,只需要调整调用时的轴向参数,或者给函数增加自动适配点集轴向的能力即可。

修改方案

步骤1:新增计算点集主轴方向的函数

通过主成分分析(PCA)提取离散点序列的第一主成分方向,作为椭圆长轴的指向:

import numpy as np
from sklearn.decomposition import PCA
import plotly.graph_objects as go

# 原ellipse函数保持不变
def ellipse(x_center=0, y_center=0, ax1 = [1, 0],  ax2 = [0,1], a=1, b =1,  N=100):
    if np.linalg.norm(ax1) != 1 or np.linalg.norm(ax2) != 1:
        raise ValueError('ax1, ax2 must be unit vectors')
    if  abs(np.dot(ax1, ax2)) > 1e-06:
        raise ValueError('ax1, ax2 must be orthogonal vectors')
    t = np.linspace(0, 2*np.pi, N)
    xs = a * np.cos(t)
    ys = b * np.sin(t)
    R = np.array([ax1, ax2]).T
    xp, yp = np.dot(R, [xs, ys])
    x = xp + x_center 
    y = yp + y_center
    return x, y

# 新增:计算点集的主轴方向角
def get_axis_angle(points):
    # points为shape=(n,2)的数组,存储x、y坐标
    pca = PCA(n_components=2)
    pca.fit(points)
    # 第一主成分的方向向量
    main_axis = pca.components_[0]
    # 计算方向角
    theta = np.arctan2(main_axis[1], main_axis[0])
    return theta

步骤2:调整调用逻辑,使用点集实际方向角生成椭圆

# 读取数据(你原有的读取逻辑不变)
x22 = tw2_df['x']
z22 = tw2_df['z']
x5 = tw5_df['x']
z5 = tw5_df['z']

# 创建画布
fig = go.Figure()

# 绘制原始点
fig.add_trace(go.Scatter(x=x22, y=z22, name="line-2", mode="markers", marker_color='gray'))
fig.add_trace(go.Scatter(x=x5, y=z5, name="line-3", mode="markers", marker_color='gray'))

# 处理well-2椭圆
h2=540.05
k2=-54.75
a2=36.67
b2=577.62
# 计算well2点集的主轴方向角
theta2 = get_axis_angle(np.column_stack((x22, z22)))
# 用实际方向角生成轴向向量
ax1_2 = [np.cos(theta2), np.sin(theta2)]
ax2_2 = [-np.sin(theta2), np.cos(theta2)]
x_e2, y_e2 = ellipse(x_center=h2, y_center=k2, ax1=ax1_2, ax2=ax2_2, a=a2, b=b2)
fig.add_scatter(x=x_e2, y=y_e2, mode = 'lines', name='well-2椭圆')

# 处理well-5椭圆
h5=550.28
k5=-246.58
a5=43.17
b5=590.69
# 计算well5点集的主轴方向角
theta5 = get_axis_angle(np.column_stack((x5, z5)))
ax1_5 = [np.cos(theta5), np.sin(theta5)]
ax2_5 = [-np.sin(theta5), np.cos(theta5)]
x_e5, y_e5 = ellipse(x_center=h5, y_center=k5, ax1=ax1_5, ax2=ax2_5, a=a5, b=b5)
fig.add_scatter(x=x_e5, y=y_e5, mode = 'lines', name='well-5椭圆')

fig.update_layout(showlegend=True)
fig.show()
补充说明

如果你的数据点本身已经是沿直线分布的,也可以直接用首尾点计算方向角代替PCA,逻辑如下:

def get_axis_angle_by_endpoints(points):
    dx = points[-1,0] - points[0,0]
    dy = points[-1,1] - points[0,1]
    theta = np.arctan2(dy, dx)
    return theta

内容的提问来源于stack exchange,提问作者Ramy Abdallah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 01:18:01