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

Python实现Newton多边形:如何提取Scipy凸包的下边界?

解决Scipy ConvexHull获取Newton多边形下边界的思路

核心逻辑

Scipy的ConvexHull返回的顶点是逆时针顺序排列的,Newton多边形需要的是从最左点到最右点的下凸包部分,可通过以下步骤精准分离:

  • 定位凸包顶点中的最左点(x坐标最小)和最右点(x坐标最大)
  • 基于这两个端点,提取凸包的两条候选路径(逆时针方向的两个分支)
  • 通过斜率变化判断哪条路径是下凸包(下凸包的相邻点斜率单调非递减)

具体实现代码

import numpy as np
from scipy.spatial import ConvexHull

# 示例点集(模拟Newton多边形的输入点)
points = np.array([[0, 5], [1, 3], [2, 2], [3, 4], [4, 1], [5, 6]])
hull = ConvexHull(points)
hull_vertices = points[hull.vertices]

# 找到最左、最右点在凸包顶点中的索引
left_idx = np.argmin(hull_vertices[:, 0])
right_idx = np.argmax(hull_vertices[:, 0])

# 生成两条从左到右的候选路径
# 路径1:顺着逆时针顺序从左到右
if left_idx < right_idx:
    path1 = hull_vertices[left_idx:right_idx+1]
else:
    path1 = np.vstack([hull_vertices[left_idx:], hull_vertices[:right_idx+1]])

# 路径2:逆着逆时针顺序从左到右(即另一条分支)
if right_idx < left_idx:
    path2 = hull_vertices[right_idx:left_idx+1]
else:
    path2 = np.vstack([hull_vertices[right_idx:], hull_vertices[:left_idx+1]])
path2 = path2[::-1]  # 反转后变成从左到右的顺序

# 判断下凸包:下凸包的相邻点斜率单调非递减(允许浮点误差)
def is_lower_hull(path):
    x_diffs = np.diff(path[:, 0])
    y_diffs = np.diff(path[:, 1])
    slopes = y_diffs / x_diffs
    # 检查斜率的差分是否非负(下凸的特征)
    return np.all(np.diff(slopes) >= -1e-9)

# 确定最终的下凸包
lower_hull = path1 if is_lower_hull(path1) else path2

print("Newton多边形下边界点集:")
print(lower_hull)

原方法失效原因

直接截取到最右侧点前的条目不可靠,因为ConvexHull的顶点是逆时针排列的:当最左点不在顶点列表起始位置时,截取的路径可能是上凸包分支,而非需要的下凸包。必须通过定位左右端点+路径判断的方式,才能准确分离出下边界。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:02:03