在曲面的交叉点上采样随机点

时间:2017-05-08 16:09:25

标签: python performance random

在python中,从复杂的曲面交集中均匀地采样随机二维数字的最有效方法是什么?

例如,考虑许多磁盘的交叉或许多磁盘联合的补充。

我知道我可以简单地从包含二维感兴趣区域的框中绘制点,然后检查是否满足所需的条件,但我想知道是否有一个非常有效的解决方案来直接从中抽取均匀的随机点划界的表面!

由于

1 个答案:

答案 0 :(得分:0)

如果有任意圈子,则无法避免进入或退出

加快此类检查的好方法是构建Quadtree,其中每个节点都有固定的(一个或零是最好的)指针,以便进行检查。

树搜索(线性变换)将通过一次循环检查(在此接受或拒绝)或不进行循环检查(无条件接受)进入节点。

更新

一些简单的实现。但您可能会阅读有关QuadTrees,R-trees和类似树的更多信息以进行空间数据搜索(请参阅QuadTree页面底部的链接), 因为这个想法的变化可能会帮助你建立更好的算法

一些示例代码,键入UNTESTED,递归地构建给定磁盘列表的四叉树,然后在到达点处递归地遍历树并对点进行分类。 树行走是O(log2(N))复杂度,最后是一个磁盘检查

def squared(x):
    return x*x

class Disk(object):
    def __init__(self, x, y, r):
        self._x = x
        self._y = y
        self._r = r

    def check(self, x, y):
        return squared(x-self._x) + squared(y-self._y) <= squared(self._r)

class Node(object):
    def __init__(self, llx, lly, urx, ury):
        # nodes, in CCW
        self._NE = None
        self._NW = None
        self._SW = None
        self._SE = None
        # corners
        self._llx = llx
        self._lly = lly
        self._urx = urx
        self._ury = ury

        # dividers
        self._dx = 0.5*(llx + urx)
        self._dy = 0.5*(lly + ury)

        # disk to check
        self._disk = None

    def is_leaf_node(self):
        """
        True if node  has no children
        """
        if self._NE is None:
            if self._NW is None:
                if self._SW is None:
                    if self._SE is None:
                        return True
        return False

    def check_point(self, x, y):
        """
        True if not covered by circle
        """
        if self._disk is None: 
            return True
        return not self._disk.check(x, y)

def check_node(node, disks):
    """
    return sublist of disks which affects the node
    """

    rc = []
    for disk in disks:
        if disk.check(node._llx, node._lly):
            rc.append(disk)
        elif disk.check(node._llx, node._ury):
            rc.append(disk)
        elif disk.check(node._urx, node._lly):
            rc.append(disk)
        elif disk.check(node._urx, node._ury):
            rc.append(disk)

    if len(rc) == 0:
        return None

    return rc

def build(node, disks):
     subdisks = check_node(node, disks)
     if subdisks is None: # empty type of leaf node
         node._disk = None
         return node
     if len(subdisks) == 1: # simple circle leaf node
         node._disk = subdisks
         return node

     node._NE = build(Node(self._dx, self._dy, self._urx, self._ury), disks)
     node._NW = build(Node(self._llx, self._dy, self._dx, self._ury), disks)
     node._SW = build(Node(self._llx, self._lly, self._dx, self._dy), disks)
     node._SE = build(Node(self._dx, self._lly, self._urx, self._dy), disks)

     return node

def check_point(node, x, y):
    if node.is_leaf_node():
        return node.check_point(x, y)        

    if x > node._dx: # SE of NE nodes
        y > node._dy: # NE
            return check_point(node._NE, x, y)

        return check_point(node._SE, x, y)

    # SW or NW
    y > node._dy: # NW
        return check_point(node._NW, x, y)

    return check_point(node._SW, x, y)

# main 
# in the (0,0):(1,1) square
root = build( Node(0.0, 0.0, 1.0, 1.0), disks )

rc = check_point(root, x, y)