绕数
绕数(winding number)是闭合曲线围绕一个未被曲线经过的指定点转过的有向圈数。逆时针取正、顺时针取负;重复绕行会累加。曲线的几何图像相同,参数化的绕行次数仍可能不同。
在复平面中,它既可以用连续辐角的总变化定义,也可以用复积分计算。下面先算一条重复绕行的圆,再说明整数性及自交曲线各区域的差异。
同一圆周上的两次绕行
令 ,,指定点为原点。曲线图像是单位圆,但辐角的连续提升为 ,总变化为 ,所以绕数为二。
若只走 ,绕数为一;沿反向 走一周,绕数为负一。改变速度而保留方向和总绕行次数,不改变绕数。指定点若改为 ,它在圆外,绕数则为零。
积分定义与整数性
设 为闭合、分段 曲线,,且 。定义 曲线可以自交,也可以重复经过同一点,积分按给定的参数化累计。
沿参数区间可以连续选择 连续辐角可逐段拼接:将紧参数区间细分,使每段的单位方向落在一个不覆盖整圆的短弧中,在该弧选择辐角,并在相邻段加上适当的 整数倍使端点相接。分段光滑时, 积分后,闭合性使 ,于是 又因两端单位方向相同,,辐角差必为 的整数倍。这证明了积分定义确实给出整数。
主例也可直接代入: 绕数与辐角变化的关系,是辐角原理将复函数的零点、极点计数联系起来的基础。[1]
区域、拼接与自交
绕数对闭曲线的拼接相加,反向遍历则变号。这可以直接从积分的可加性与参数反向换元得到。
对固定曲线,绕数作为 的函数,在曲线补集的每个连通分量上常值:当 在不碰曲线的小邻域内移动时,分母与零保持正距离,积分连续;连续且取整数值的函数在连通分量上只能常值。在无界分量中, 时积分绝对值趋于零,故该分量绕数为零。这也给出了主例外部点绕数为零的理由。
自交曲线可能围出多个绕数不同的区域。例如按次序连接 并回到起点,得到一条交叉折线。右侧小环顺时针,左侧小环逆时针,因此 原点正好在交叉处,绕数在该指定点没有定义。
有理坐标折线的计算
对有理坐标多边形,可数一条从指定点向右发出的水平射线与有向边的交叉:向上穿过计一,向下穿过计负一。边的端点采用半开规则,避免射线恰过顶点时重复计数。下面用 Fraction 精确判断所给有理数数据的方向与共线性;返回整数绕数,不改写输入。
from fractions import Fraction
def winding_number(vertices, query):
polygon = [(Fraction(x), Fraction(y)) for x, y in vertices]
ax, ay = map(Fraction, query)
if len(polygon) < 3:
raise ValueError("require at least three vertices")
if polygon[0] != polygon[-1]:
polygon.append(polygon[0])
winding = 0
for (px, py), (qx, qy) in zip(polygon, polygon[1:]):
px, py, qx, qy = px - ax, py - ay, qx - ax, qy - ay
cross = px * qy - qx * py
if cross == 0 and min(px, qx) <= 0 <= max(px, qx) \
and min(py, qy) <= 0 <= max(py, qy):
raise ValueError("query lies on the curve")
if py <= 0 < qy and cross > 0:
winding += 1
elif qy <= 0 < py and cross < 0:
winding -= 1
return winding
bow = [(-2, -1), (2, 1), (2, -1), (-2, 1)]
print(winding_number(bow, (-1, 0))) # 1
print(winding_number(bow, (1, 0))) # -1
print(winding_number(bow, (3, 0))) # 0
assert winding_number(list(reversed(bow)), (-1, 0)) == -1
计数的理由。 沿每条不经过指定点的边连续跟踪辐角。只有越过所选射线时,选在 内的分支需要增加或减去一个 来保持连续。向上穿过正向射线需要增加,向下需要减少;叉积符号判断交点是否在正向射线上。半开端点规则把穿越顶点的贡献恰计一次。因此累计数等于连续辐角总变化除以 。
对 条边,算法进行 次有理数运算与比较,点列规范化占 空间;实际位运算代价还随整数位数变化。浮点输入会被转换为其实际二进制数值的精确分数,若原始数据代表精确十进制,宜传十进制字符串或已构造的分数。
连续变形只要保持闭合并始终避开指定点,绕数就保持不变;指定点穿过曲线时则可能跳变。对于开曲线,可以计算辐角变化,但没有闭合性便没有这里的整数结论。
参考文献
- ↑ Jeremy Orloff,MIT 18.04,Topic 11: Argument Principle,关于index、绕行方向与总辐角变化的部分。