别再死记公式了用Python的NumPy和Matplotlib搞定坐标转换附象限处理完整代码坐标转换是数据处理中的常见需求但很多初学者往往陷入死记硬背数学公式的误区忽略了实际编程中的各种边界情况。今天我们就用Python的科学计算库NumPy和数据可视化库Matplotlib带你从零开始掌握坐标转换的实战技巧特别是如何处理不同象限下的角度计算问题。1. 为什么直接套用atan2(y/x)会出问题很多教程会告诉你笛卡尔坐标转极坐标时角度θ可以通过atan2(y/x)计算得到。但在实际编程中这种简单套用往往会带来意想不到的错误。让我们看一个典型例子import numpy as np # 四个象限的测试点 points np.array([(1, 1), (-1, 1), (-1, -1), (1, -1)]) # 错误的角度计算方式 wrong_angles np.arctan(points[:,1] / points[:,0]) print(错误的角度计算结果(弧度):, wrong_angles)运行这段代码你会发现输出的角度值存在明显问题。原因在于除零错误当x坐标为0时直接除法会导致程序崩溃象限丢失arctan函数无法区分第二和第三象限的点角度范围结果被限制在[-π/2, π/2]之间丢失了完整圆周信息提示在Python中math.atan2(y, x)函数已经解决了这些问题但对于数组计算我们更推荐使用NumPy的np.arctan2(y, x)。2. 使用NumPy进行批量坐标转换的正确姿势NumPy提供了完整的坐标转换工具链让我们看看如何正确处理批量转换def cartesian_to_polar(x, y): 将笛卡尔坐标(x,y)转换为极坐标(r,θ) 返回(半径, 角度(弧度)) r np.sqrt(x**2 y**2) theta np.arctan2(y, x) return r, theta # 批量转换示例 x_coords np.array([1, -1, -1, 1, 0, 2]) y_coords np.array([1, 1, -1, -1, 1, 0]) radii, angles cartesian_to_polar(x_coords, y_coords) # 打印结果 for i in range(len(x_coords)): print(f点({x_coords[i]}, {y_coords[i]}) - 半径:{radii[i]:.2f}, 角度:{np.degrees(angles[i]):.2f}°)这个实现解决了以下关键问题自动处理零值np.arctan2能正确处理x或y为零的情况完整角度范围返回的角度值在[-π, π]之间覆盖所有象限向量化计算一次处理整个数组效率远高于循环3. 不同象限的角度处理陷阱与解决方案虽然np.arctan2已经帮我们解决了大部分问题但在实际应用中我们还需要注意以下特殊情况3.1 角度标准化不同应用可能需要不同范围的角度表示角度范围适用场景转换方法[-π, π]默认输出np.arctan2直接结果[0, 2π]工程应用theta % (2 * np.pi)[0°, 360°]地理坐标(np.degrees(theta) 360) % 360def normalize_angle(theta, moderadians): 角度标准化 mode: radians返回[0,2π], degrees返回[0°,360°] if mode radians: return theta % (2 * np.pi) elif mode degrees: return (np.degrees(theta) 360) % 360 else: raise ValueError(mode必须是radians或degrees)3.2 特殊点处理某些边界情况需要特别注意(0,0)原点半径为零角度无定义极小值当x或y接近零时数值稳定性问题NaN处理输入包含NaN时的健壮性处理改进版的坐标转换函数def robust_cartesian_to_polar(x, y): 健壮的笛卡尔坐标转极坐标实现 x np.asarray(x) y np.asarray(y) r np.sqrt(x**2 y**2) theta np.arctan2(y, x) # 处理原点 origin_mask (x 0) (y 0) theta[origin_mask] np.nan return r, theta4. 用Matplotlib实现坐标转换可视化理解坐标转换最好的方式就是可视化。下面我们创建一个动态演示展示点在不同坐标系下的表示import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # 创建图形和坐标轴 fig, (ax1, ax2) plt.subplots(1, 2, figsize(12, 6)) # 初始化数据 theta np.linspace(0, 2*np.pi, 100) r 1 0.5 * np.sin(5 * theta) # 花瓣形状 x, y r * np.cos(theta), r * np.sin(theta) # 笛卡尔坐标系设置 ax1.set_xlim(-2, 2) ax1.set_ylim(-2, 2) ax1.grid(True) ax1.set_title(笛卡尔坐标系) cartesian_line, ax1.plot([], [], b-) cartesian_point, ax1.plot([], [], ro) # 极坐标系设置 ax2 plt.subplot(122, polarTrue) ax2.set_rmax(2) ax2.grid(True) ax2.set_title(极坐标系) polar_line, ax2.plot([], [], b-) polar_point, ax2.plot([], [], ro) def update(frame): # 更新当前点 current_x, current_y x[frame], y[frame] # 更新笛卡尔坐标系 cartesian_line.set_data(x[:frame1], y[:frame1]) cartesian_point.set_data([current_x], [current_y]) # 更新极坐标系 polar_line.set_data(theta[:frame1], r[:frame1]) polar_point.set_data([theta[frame]], [r[frame]]) return cartesian_line, cartesian_point, polar_line, polar_point ani FuncAnimation(fig, update, frameslen(theta), interval50, blitTrue) plt.tight_layout() plt.show()这段代码会生成一个动态图左侧显示笛卡尔坐标系中的点右侧显示对应的极坐标表示。通过动画你可以直观地看到笛卡尔坐标(x,y)与极坐标(r,θ)的对应关系角度θ如何随着点在平面中的位置变化半径r与点到原点距离的关系5. 实际应用案例信号处理中的坐标转换在信号处理中我们经常需要在直角坐标系和极坐标系之间转换。例如分析信号的幅度和相位# 生成一个复合信号 t np.linspace(0, 1, 1000) signal1 0.5 * np.sin(2 * np.pi * 5 * t) # 5Hz信号 signal2 0.3 * np.sin(2 * np.pi * 12 * t np.pi/4) # 12Hz信号相位偏移 combined_signal signal1 signal2 # 希尔伯特变换获取解析信号 from scipy.signal import hilbert analytic_signal hilbert(combined_signal) # 转换为极坐标表示 amplitude np.abs(analytic_signal) phase np.angle(analytic_signal) # 绘制结果 plt.figure(figsize(12, 6)) plt.subplot(211) plt.plot(t, combined_signal, label原始信号) plt.plot(t, amplitude, r, label瞬时幅度) plt.legend() plt.subplot(212) plt.plot(t, phase, g, label瞬时相位) plt.legend() plt.show()这个例子展示了如何将时域信号转换为解析信号提取信号的瞬时幅度极坐标中的半径提取信号的瞬时相位极坐标中的角度可视化信号的这些特征6. 性能优化技巧当处理大规模数据时坐标转换的性能变得重要。以下是几个优化建议6.1 使用NumPy的向量化操作避免使用Python循环始终使用NumPy的向量化函数# 不推荐的方式 def slow_convert(x_list, y_list): radii [] angles [] for x, y in zip(x_list, y_list): r np.sqrt(x**2 y**2) theta np.arctan2(y, x) radii.append(r) angles.append(theta) return np.array(radii), np.array(angles) # 推荐的方式 def fast_convert(x_arr, y_arr): x_arr np.asarray(x_arr) y_arr np.asarray(y_arr) radii np.sqrt(x_arr**2 y_arr**2) angles np.arctan2(y_arr, x_arr) return radii, angles6.2 预分配内存对于需要多次转换的场景预分配输出数组可以避免重复内存分配def batch_convert(coords): coords: (N,2)形状的数组每行是一个(x,y)点 返回: (N,)半径数组和(N,)角度数组 coords np.asarray(coords) output_r np.empty(coords.shape[0]) output_theta np.empty(coords.shape[0]) np.sqrt(coords[:,0]**2 coords[:,1]**2, outoutput_r) np.arctan2(coords[:,1], coords[:,0], outoutput_theta) return output_r, output_theta6.3 使用Numba加速对于特别大的数据集可以使用Numba进行即时编译加速from numba import njit njit def numba_convert(x, y): r np.sqrt(x**2 y**2) theta np.arctan2(y, x) return r, theta # 首次调用会有编译开销后续调用极快 large_x np.random.randn(1000000) large_y np.random.randn(1000000) r, theta numba_convert(large_x, large_y)7. 常见问题与调试技巧在实际项目中你可能会遇到以下问题7.1 角度跳跃问题当角度从π跳转到-π时可能会导致可视化或后续处理出现问题。解决方案是使用角度展开def unwrap_angle(theta): 处理角度跳变使角度连续变化 diff np.diff(theta) jumps np.abs(diff) np.pi offsets np.cumsum(-2 * np.pi * np.sign(diff) * jumps) return np.concatenate(([theta[0]], theta[1:] offsets))7.2 极坐标转笛卡尔坐标反向转换同样重要这里是一个完整的实现def polar_to_cartesian(r, theta): 将极坐标(r,θ)转换为笛卡尔坐标(x,y) x r * np.cos(theta) y r * np.sin(theta) return x, y # 示例圆形轨迹 theta np.linspace(0, 2*np.pi, 100) r np.ones_like(theta) # 单位圆 x, y polar_to_cartesian(r, theta) plt.plot(x, y) plt.axis(equal) plt.show()7.3 处理非有限数值在实际数据中可能会遇到无穷大或NaN值def safe_convert(x, y): 安全转换处理非有限数值 x np.asarray(x) y np.asarray(y) # 创建有效点掩码 valid np.isfinite(x) np.isfinite(y) # 初始化输出为NaN r np.full_like(x, np.nan) theta np.full_like(x, np.nan) # 只对有效点计算 r[valid] np.sqrt(x[valid]**2 y[valid]**2) theta[valid] np.arctan2(y[valid], x[valid]) return r, theta8. 扩展应用三维坐标转换虽然本文主要讨论二维坐标转换但NumPy同样支持三维空间的转换def cartesian_to_spherical(x, y, z): 三维笛卡尔坐标转球坐标(r,θ,φ) θ: 方位角(与x轴的夹角在xy平面内) φ: 极角(与z轴的夹角) r np.sqrt(x**2 y**2 z**2) theta np.arctan2(y, x) # 方位角 phi np.arccos(z / r) # 极角 return r, theta, phi def spherical_to_cartesian(r, theta, phi): 球坐标转笛卡尔坐标 x r * np.sin(phi) * np.cos(theta) y r * np.sin(phi) * np.sin(theta) z r * np.cos(phi) return x, y, z # 示例球面点 r 1 theta np.pi/4 # 45度 phi np.pi/3 # 60度 x, y, z spherical_to_cartesian(r, theta, phi) print(f球坐标({r}, {theta:.2f}, {phi:.2f}) - 笛卡尔坐标({x:.2f}, {y:.2f}, {z:.2f}))这个三维扩展展示了如何将三维点转换为半径、方位角和极角处理三维空间中的角度计算实现反向转换9. 完整代码示例最后我们提供一个完整的坐标转换工具类集成了本文讨论的所有功能import numpy as np class CoordinateConverter: 坐标转换工具类 staticmethod def cartesian_to_polar(x, y, angle_moderadians): 笛卡尔坐标转极坐标 angle_mode: radians返回弧度, degrees返回角度 x np.asarray(x) y np.asarray(y) r np.sqrt(x**2 y**2) theta np.arctan2(y, x) if angle_mode degrees: theta np.degrees(theta) # 处理原点 origin_mask (x 0) (y 0) theta[origin_mask] np.nan return r, theta staticmethod def polar_to_cartesian(r, theta, angle_moderadians): 极坐标转笛卡尔坐标 angle_mode: radians输入为弧度, degrees输入为角度 r np.asarray(r) theta np.asarray(theta) if angle_mode degrees: theta np.radians(theta) x r * np.cos(theta) y r * np.sin(theta) return x, y staticmethod def normalize_angle(theta, angle_moderadians, range0_to_2pi): 角度标准化 angle_mode: radians或degrees range: 0_to_2pi或-pi_to_pi theta np.asarray(theta) if angle_mode degrees: if range 0_to_2pi: return (theta 360) % 360 else: # -pi_to_pi return (theta 180) % 360 - 180 else: # radians if range 0_to_2pi: return theta % (2 * np.pi) else: # -pi_to_pi return (theta np.pi) % (2 * np.pi) - np.pi staticmethod def angle_between(v1, v2, angle_moderadians): 计算两个向量之间的夹角 v1, v2: 二维向量 v1 np.asarray(v1) v2 np.asarray(v2) dot v1[0]*v2[0] v1[1]*v2[1] det v1[0]*v2[1] - v1[1]*v2[0] angle np.arctan2(det, dot) if angle_mode degrees: return np.degrees(angle) return angle # 使用示例 x [1, 0, -1, 0] y [0, 1, 0, -1] r, theta CoordinateConverter.cartesian_to_polar(x, y, angle_modedegrees) print(半径:, r) print(角度:, theta)这个工具类提供了笛卡尔坐标与极坐标的双向转换角度标准化功能向量间角度计算支持弧度与角度两种模式完善的边界条件处理
别再死记公式了!用Python的NumPy和Matplotlib搞定坐标转换(附象限处理完整代码)
别再死记公式了用Python的NumPy和Matplotlib搞定坐标转换附象限处理完整代码坐标转换是数据处理中的常见需求但很多初学者往往陷入死记硬背数学公式的误区忽略了实际编程中的各种边界情况。今天我们就用Python的科学计算库NumPy和数据可视化库Matplotlib带你从零开始掌握坐标转换的实战技巧特别是如何处理不同象限下的角度计算问题。1. 为什么直接套用atan2(y/x)会出问题很多教程会告诉你笛卡尔坐标转极坐标时角度θ可以通过atan2(y/x)计算得到。但在实际编程中这种简单套用往往会带来意想不到的错误。让我们看一个典型例子import numpy as np # 四个象限的测试点 points np.array([(1, 1), (-1, 1), (-1, -1), (1, -1)]) # 错误的角度计算方式 wrong_angles np.arctan(points[:,1] / points[:,0]) print(错误的角度计算结果(弧度):, wrong_angles)运行这段代码你会发现输出的角度值存在明显问题。原因在于除零错误当x坐标为0时直接除法会导致程序崩溃象限丢失arctan函数无法区分第二和第三象限的点角度范围结果被限制在[-π/2, π/2]之间丢失了完整圆周信息提示在Python中math.atan2(y, x)函数已经解决了这些问题但对于数组计算我们更推荐使用NumPy的np.arctan2(y, x)。2. 使用NumPy进行批量坐标转换的正确姿势NumPy提供了完整的坐标转换工具链让我们看看如何正确处理批量转换def cartesian_to_polar(x, y): 将笛卡尔坐标(x,y)转换为极坐标(r,θ) 返回(半径, 角度(弧度)) r np.sqrt(x**2 y**2) theta np.arctan2(y, x) return r, theta # 批量转换示例 x_coords np.array([1, -1, -1, 1, 0, 2]) y_coords np.array([1, 1, -1, -1, 1, 0]) radii, angles cartesian_to_polar(x_coords, y_coords) # 打印结果 for i in range(len(x_coords)): print(f点({x_coords[i]}, {y_coords[i]}) - 半径:{radii[i]:.2f}, 角度:{np.degrees(angles[i]):.2f}°)这个实现解决了以下关键问题自动处理零值np.arctan2能正确处理x或y为零的情况完整角度范围返回的角度值在[-π, π]之间覆盖所有象限向量化计算一次处理整个数组效率远高于循环3. 不同象限的角度处理陷阱与解决方案虽然np.arctan2已经帮我们解决了大部分问题但在实际应用中我们还需要注意以下特殊情况3.1 角度标准化不同应用可能需要不同范围的角度表示角度范围适用场景转换方法[-π, π]默认输出np.arctan2直接结果[0, 2π]工程应用theta % (2 * np.pi)[0°, 360°]地理坐标(np.degrees(theta) 360) % 360def normalize_angle(theta, moderadians): 角度标准化 mode: radians返回[0,2π], degrees返回[0°,360°] if mode radians: return theta % (2 * np.pi) elif mode degrees: return (np.degrees(theta) 360) % 360 else: raise ValueError(mode必须是radians或degrees)3.2 特殊点处理某些边界情况需要特别注意(0,0)原点半径为零角度无定义极小值当x或y接近零时数值稳定性问题NaN处理输入包含NaN时的健壮性处理改进版的坐标转换函数def robust_cartesian_to_polar(x, y): 健壮的笛卡尔坐标转极坐标实现 x np.asarray(x) y np.asarray(y) r np.sqrt(x**2 y**2) theta np.arctan2(y, x) # 处理原点 origin_mask (x 0) (y 0) theta[origin_mask] np.nan return r, theta4. 用Matplotlib实现坐标转换可视化理解坐标转换最好的方式就是可视化。下面我们创建一个动态演示展示点在不同坐标系下的表示import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # 创建图形和坐标轴 fig, (ax1, ax2) plt.subplots(1, 2, figsize(12, 6)) # 初始化数据 theta np.linspace(0, 2*np.pi, 100) r 1 0.5 * np.sin(5 * theta) # 花瓣形状 x, y r * np.cos(theta), r * np.sin(theta) # 笛卡尔坐标系设置 ax1.set_xlim(-2, 2) ax1.set_ylim(-2, 2) ax1.grid(True) ax1.set_title(笛卡尔坐标系) cartesian_line, ax1.plot([], [], b-) cartesian_point, ax1.plot([], [], ro) # 极坐标系设置 ax2 plt.subplot(122, polarTrue) ax2.set_rmax(2) ax2.grid(True) ax2.set_title(极坐标系) polar_line, ax2.plot([], [], b-) polar_point, ax2.plot([], [], ro) def update(frame): # 更新当前点 current_x, current_y x[frame], y[frame] # 更新笛卡尔坐标系 cartesian_line.set_data(x[:frame1], y[:frame1]) cartesian_point.set_data([current_x], [current_y]) # 更新极坐标系 polar_line.set_data(theta[:frame1], r[:frame1]) polar_point.set_data([theta[frame]], [r[frame]]) return cartesian_line, cartesian_point, polar_line, polar_point ani FuncAnimation(fig, update, frameslen(theta), interval50, blitTrue) plt.tight_layout() plt.show()这段代码会生成一个动态图左侧显示笛卡尔坐标系中的点右侧显示对应的极坐标表示。通过动画你可以直观地看到笛卡尔坐标(x,y)与极坐标(r,θ)的对应关系角度θ如何随着点在平面中的位置变化半径r与点到原点距离的关系5. 实际应用案例信号处理中的坐标转换在信号处理中我们经常需要在直角坐标系和极坐标系之间转换。例如分析信号的幅度和相位# 生成一个复合信号 t np.linspace(0, 1, 1000) signal1 0.5 * np.sin(2 * np.pi * 5 * t) # 5Hz信号 signal2 0.3 * np.sin(2 * np.pi * 12 * t np.pi/4) # 12Hz信号相位偏移 combined_signal signal1 signal2 # 希尔伯特变换获取解析信号 from scipy.signal import hilbert analytic_signal hilbert(combined_signal) # 转换为极坐标表示 amplitude np.abs(analytic_signal) phase np.angle(analytic_signal) # 绘制结果 plt.figure(figsize(12, 6)) plt.subplot(211) plt.plot(t, combined_signal, label原始信号) plt.plot(t, amplitude, r, label瞬时幅度) plt.legend() plt.subplot(212) plt.plot(t, phase, g, label瞬时相位) plt.legend() plt.show()这个例子展示了如何将时域信号转换为解析信号提取信号的瞬时幅度极坐标中的半径提取信号的瞬时相位极坐标中的角度可视化信号的这些特征6. 性能优化技巧当处理大规模数据时坐标转换的性能变得重要。以下是几个优化建议6.1 使用NumPy的向量化操作避免使用Python循环始终使用NumPy的向量化函数# 不推荐的方式 def slow_convert(x_list, y_list): radii [] angles [] for x, y in zip(x_list, y_list): r np.sqrt(x**2 y**2) theta np.arctan2(y, x) radii.append(r) angles.append(theta) return np.array(radii), np.array(angles) # 推荐的方式 def fast_convert(x_arr, y_arr): x_arr np.asarray(x_arr) y_arr np.asarray(y_arr) radii np.sqrt(x_arr**2 y_arr**2) angles np.arctan2(y_arr, x_arr) return radii, angles6.2 预分配内存对于需要多次转换的场景预分配输出数组可以避免重复内存分配def batch_convert(coords): coords: (N,2)形状的数组每行是一个(x,y)点 返回: (N,)半径数组和(N,)角度数组 coords np.asarray(coords) output_r np.empty(coords.shape[0]) output_theta np.empty(coords.shape[0]) np.sqrt(coords[:,0]**2 coords[:,1]**2, outoutput_r) np.arctan2(coords[:,1], coords[:,0], outoutput_theta) return output_r, output_theta6.3 使用Numba加速对于特别大的数据集可以使用Numba进行即时编译加速from numba import njit njit def numba_convert(x, y): r np.sqrt(x**2 y**2) theta np.arctan2(y, x) return r, theta # 首次调用会有编译开销后续调用极快 large_x np.random.randn(1000000) large_y np.random.randn(1000000) r, theta numba_convert(large_x, large_y)7. 常见问题与调试技巧在实际项目中你可能会遇到以下问题7.1 角度跳跃问题当角度从π跳转到-π时可能会导致可视化或后续处理出现问题。解决方案是使用角度展开def unwrap_angle(theta): 处理角度跳变使角度连续变化 diff np.diff(theta) jumps np.abs(diff) np.pi offsets np.cumsum(-2 * np.pi * np.sign(diff) * jumps) return np.concatenate(([theta[0]], theta[1:] offsets))7.2 极坐标转笛卡尔坐标反向转换同样重要这里是一个完整的实现def polar_to_cartesian(r, theta): 将极坐标(r,θ)转换为笛卡尔坐标(x,y) x r * np.cos(theta) y r * np.sin(theta) return x, y # 示例圆形轨迹 theta np.linspace(0, 2*np.pi, 100) r np.ones_like(theta) # 单位圆 x, y polar_to_cartesian(r, theta) plt.plot(x, y) plt.axis(equal) plt.show()7.3 处理非有限数值在实际数据中可能会遇到无穷大或NaN值def safe_convert(x, y): 安全转换处理非有限数值 x np.asarray(x) y np.asarray(y) # 创建有效点掩码 valid np.isfinite(x) np.isfinite(y) # 初始化输出为NaN r np.full_like(x, np.nan) theta np.full_like(x, np.nan) # 只对有效点计算 r[valid] np.sqrt(x[valid]**2 y[valid]**2) theta[valid] np.arctan2(y[valid], x[valid]) return r, theta8. 扩展应用三维坐标转换虽然本文主要讨论二维坐标转换但NumPy同样支持三维空间的转换def cartesian_to_spherical(x, y, z): 三维笛卡尔坐标转球坐标(r,θ,φ) θ: 方位角(与x轴的夹角在xy平面内) φ: 极角(与z轴的夹角) r np.sqrt(x**2 y**2 z**2) theta np.arctan2(y, x) # 方位角 phi np.arccos(z / r) # 极角 return r, theta, phi def spherical_to_cartesian(r, theta, phi): 球坐标转笛卡尔坐标 x r * np.sin(phi) * np.cos(theta) y r * np.sin(phi) * np.sin(theta) z r * np.cos(phi) return x, y, z # 示例球面点 r 1 theta np.pi/4 # 45度 phi np.pi/3 # 60度 x, y, z spherical_to_cartesian(r, theta, phi) print(f球坐标({r}, {theta:.2f}, {phi:.2f}) - 笛卡尔坐标({x:.2f}, {y:.2f}, {z:.2f}))这个三维扩展展示了如何将三维点转换为半径、方位角和极角处理三维空间中的角度计算实现反向转换9. 完整代码示例最后我们提供一个完整的坐标转换工具类集成了本文讨论的所有功能import numpy as np class CoordinateConverter: 坐标转换工具类 staticmethod def cartesian_to_polar(x, y, angle_moderadians): 笛卡尔坐标转极坐标 angle_mode: radians返回弧度, degrees返回角度 x np.asarray(x) y np.asarray(y) r np.sqrt(x**2 y**2) theta np.arctan2(y, x) if angle_mode degrees: theta np.degrees(theta) # 处理原点 origin_mask (x 0) (y 0) theta[origin_mask] np.nan return r, theta staticmethod def polar_to_cartesian(r, theta, angle_moderadians): 极坐标转笛卡尔坐标 angle_mode: radians输入为弧度, degrees输入为角度 r np.asarray(r) theta np.asarray(theta) if angle_mode degrees: theta np.radians(theta) x r * np.cos(theta) y r * np.sin(theta) return x, y staticmethod def normalize_angle(theta, angle_moderadians, range0_to_2pi): 角度标准化 angle_mode: radians或degrees range: 0_to_2pi或-pi_to_pi theta np.asarray(theta) if angle_mode degrees: if range 0_to_2pi: return (theta 360) % 360 else: # -pi_to_pi return (theta 180) % 360 - 180 else: # radians if range 0_to_2pi: return theta % (2 * np.pi) else: # -pi_to_pi return (theta np.pi) % (2 * np.pi) - np.pi staticmethod def angle_between(v1, v2, angle_moderadians): 计算两个向量之间的夹角 v1, v2: 二维向量 v1 np.asarray(v1) v2 np.asarray(v2) dot v1[0]*v2[0] v1[1]*v2[1] det v1[0]*v2[1] - v1[1]*v2[0] angle np.arctan2(det, dot) if angle_mode degrees: return np.degrees(angle) return angle # 使用示例 x [1, 0, -1, 0] y [0, 1, 0, -1] r, theta CoordinateConverter.cartesian_to_polar(x, y, angle_modedegrees) print(半径:, r) print(角度:, theta)这个工具类提供了笛卡尔坐标与极坐标的双向转换角度标准化功能向量间角度计算支持弧度与角度两种模式完善的边界条件处理