计算几何-凸闭包(convex hull)

convex combination: 凸组合(系数和为1)

convex set: 凸集(点集) 任一子集的凸组合仍是子集

convex hull: 凸闭包[conv§] 凸集的所有子集的所有凸组合

CH§: the boundary of conv§

extreme points, EP

定义:存在一条线L穿过点P,凸集中其他所有点在L的同一侧

算法:查找凸集中所有extreme points

思路:为遍历判断,EP不在任一三角形内, O(n^4)

extreme edge, EE:

定义:CH§的所有边

算法:通过找EE找出所有的EP

思路:

(1)逐条边检查,所有点都在EE同一侧,O(n^3)

(2)借鉴插入排序,减而治之,从小点集出发逐个加点,加入时判断是否在CH§中,在则加入点集并更新其他点,否则跳过。判断是否在CH§的方法:toLeft(x, v, v.pre) + toLeft(x, v, v.next)。逐个加点O(n),判断O(n),复杂度O(n^2)

(3)借助选择排序,从lowest-then-leftmost EP开始,逐个加入满足minimal left-turn的EP(即加入next EE),判断mlt的方法是遍历点集每次找位于当前边右边的点。总共加h(EE数量)次,每次判断n个点,复杂度O(nh)

python实现:

class Point:
    def __init__(self, x, y, extreme=False) -> None:
        self.extreme = extreme
        self.x = x
        self.y = y

"""
    Algorithm of finding extreme points
"""
def extremePoints(S: list):
    """Compute extreme points of convex hull S
    
    Args
        S: set of points, len(S)>2 
    """
    for p in S:
        p.extreme = True
    n = len(S)
    for p in range(n):
        for q in range(p + 1, n):
            for r in range(q + 1, n):
                for s in range(r + 1, n):
                    if s == p or s == q or s == r or S[s].extreme == False:
                        continue
                    if inTriangle(S[p], S[q], S[r], S[s]):
                        S[s].extreme = False

def inTriangle(p: Point, q: Point, r:Point, s: Point) -> bool:
    """Judge weather s in triangle composed of (p, q, r)
    """
    pql = toLeft(p, q, s)
    qrl = toLeft(q, r, s)
    rpl = toLeft(r, p, s)
    return pql == qrl and qrl == rpl

def toLeft(a: Point, b: Point, s:Point) -> bool:
    """Judge weather s in the left of vector ab
    """
    return area2(a, b, s) > 0

def area2(a:Point, b:Point, s:Point) -> float:
    """Compute area * 2 of triangle composed of (a, b, s)
    """
    return b.x * s.y - b.y * s.x + \
        a.y * s.x - a.x * s.y + \
        a.x * b.y - a.y * b.x


"""
    Algorithm of finding extreme edges
"""

def ltl(points: list) -> Point:
    """Find lowest-then-leftmost point of set points
    """
    ans = points[0]
    for p in points:
        if p.y < ans.y or p.y == ans.y and p.x < ans.x:
            ans = p
    return ans

def extremePointsByEdges(points: list):
    """Find all extreme points by finding extreme edges, O(nh)
    """
    for p in points: p.extreme = False
    k = LTL = ltl(points)
    while True:
        k.extreme = True
        tmp = None
        for p in points:
            if p == k: continue
            if not tmp or not toLeft(k, tmp, p):
                tmp = p
        k.succ = tmp
        k = tmp
        if k == LTL:
            break
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值