【问题标题】:Counting lattice points inside a triangle计算三角形内的格点
【发布时间】:2015-02-12 21:59:56
【问题描述】:

我有一个大三角形的点,我们称之为 a、b、c。 (a = (x, y) 等等)。

现在我想计算这个三角形包围的区域内的积分点数,所以我首先看了一下Pick定理。我考虑的第二种方法是生成一个以三角形的最大值、最小值为界的点列表,然后检查每个点是否位于三角形内。

我使用重心坐标方法来执行此操作。它可以工作,但是我的三角形非常大,我的程序基本上是跨点的蛮力。我该如何改进这个算法?

我的代码可以在这里找到:https://bpaste.net/show/58433b6e389c

【问题讨论】:

  • 皮克定理出了什么问题?
  • @DavidEisenstat 好吧,一方面,Pick 的定理只适用于整数三角形,所以如果一个坐标是有理/无理点,它就会崩溃......当然,OP 没有指定什么他/她正在处理的那种三角形,但说尝试过 Pick 定理,所以我想它被假定为一个积分三角形?

标签: algorithm collision-detection counting


【解决方案1】:

这个问题可以而且应该使用Pick's theorem 来解决。阅读文章以全面了解它的工作原理,并且它适用于您能想到的任何多边形。所以,“Pick 说”如果你想计算多边形的面积,你有公式area = noOfInsidePoints + noOfBoundaryPoints /2 - 1。要计算任何多边形的面积,您可以使用以下代码,其中pc 是表示多边形顶点的结构数组。

float computeArea()
{
    float area = 0;
    for(int i=1;i<=n;++i) // n is the total number of vertices
        area += (pc[i].x*pc[i+1].y - pc[i+1].x*pc[i].y );
    if(area < 0)
        area *= (-1);
}

计算面积后,我们必须计算所有多边形边缘的点数。这可以使用以下方法完成:

int getBoundaryPoints()
{
    long left=0, right=0;
    int noPoints = 0;
    for(int i=1;i<=n;++i)
    {
        st = abst( pc[i].x - pc[i+1].x );
        right = abs( pc[i].y - pc[i+1].y );
        if(right == 0)
            right = left;
        if(left == 0)
            left = right;
        noPoints += gcd(left, right) +1;
    }
}

也计算了这个,我们可以找到里面的点数

noPointsInside = (computeArea() - (getBoundaryPoints() - n)) / 2 + 1;

最终时间复杂度:O(N) 最终内存复杂度:O(N)

【讨论】:

    【解决方案2】:

    三角形内的格点数:Pick 定理

    from operator import abs
    def renj(pts):
        X=[]
        Y=[]
        for i in range(len(pts)):
            if i in [0,2,4]:                    #(0-x1, 1-y1) (2-x2,3-y2) (4-x3,5-y3)
                X.append(pts[i])
            else:   
                Y.append(pts[i])
        return [min(X), max(X), min(Y), max(Y)]             # returns the range for triangle.
    
    def m(a,b):
        from math import e
        if b[0]-a[0]:
            return (b[1]-a[1])/(b[0]-a[0])
        return e
    
    def test(a,b,z):                                        # creating function to check if z lies on line(ab)
        if m(a,b)==m(a,z):
            return 1
        return 0    
    
    n=int(input())      
    for i in range(n):
        points = list(map(int, input().split()))
        count = 0
        A=[points[0], points[1]]
        B=[points[2], points[3]]
        C=[points[4], points[5]]
        r = renj(points)
        for u in range(r[0], r[1]+1):
            for v in range(r[2], r[3]+1):
                Z=[u, v]
                if test(A,B,Z) or test(A,C,Z) or test(B, C, Z):
                    count += 1
        aa=abs((A[0]*(B[1]-C[1])+B[0]*(C[1]-A[1])+C[0]*(A[1]-B[1]))/2)
        #print("are",aa)
        bb=count
        #print("b",bb)
        ii=(aa+1)-bb/2
        print(int(ii))
    

    解决方案基于:Pick 定理

    A + 1 = i + b/2

    • A:三角形的面积

    • i:内部点

    • b:包含顶点的边界点

    • 注意:对整数点有效。 建议来自社区。​​p>

    • sn-p 代码

      输入保持整数输入。

      1                      # Number of trianlges
      2 4 8 2 10 6           # x1 y1 x2 y2 x3 y3
      

      输出

      12        #As, In triangle there are 12 Points
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      • 2014-11-07
      • 2011-10-03
      相关资源
      最近更新 更多