2D 다각형의 면적은 어떻게 계산합니까?


81

2D 공간에서 자체 교차하지 않는 일련의 점을 가정 할 때 결과 다각형의 면적을 결정하는 효율적인 방법은 무엇입니까?

참고로 이것은 숙제가 아니며 나는 코드를 찾고 있지 않습니다. 내 자신의 방법을 구현하는 데 사용할 수있는 설명을 찾고 있습니다. 점 목록에서 일련의 삼각형을 가져 오는 것에 대한 아이디어가 있지만 볼록 및 오목 다각형과 관련된 가장자리 사례가 많이 있다는 것을 알고 있습니다.


6
"표면적"이라는 용어는 약간 오해의 소지가 있습니다. 당신이 원하는 것은 (일반) 영역입니다. 3D에서 표면적은 외부 표면의 영역이므로이 개념의 자연스러운 2D 일반화는 다각형 둘레의 길이이며, 이는 분명히 찾고있는 것이 아닙니다.
batty

def area (polygon) : return abs (numpy.cross (polygon, numpy.roll (polygon, -1, 0)). sum () / 2)
iouvxz

답변:


110

다음은 표준 방법 인 AFAIK입니다. 기본적으로 각 정점 주변의 외적을 합산합니다. 삼각 측량보다 훨씬 간단합니다.

(x, y) 꼭지점 좌표의 목록으로 표시된 다각형이 주어진 Python 코드, 마지막 꼭지점에서 첫 번째 꼭짓점으로 암시 적으로 래핑됩니다.

def area(p):
    return 0.5 * abs(sum(x0*y1 - x1*y0
                         for ((x0, y0), (x1, y1)) in segments(p)))

def segments(p):
    return zip(p, p[1:] + [p[0]])

David Lehavi는 다음과 같이 설명합니다.이 알고리즘이 작동하는 이유를 언급 할 가치가 있습니다. 함수 −y 및 x에 대한 Green의 정리 를 적용한 것입니다 . 면적계가 작동 하는 방식과 정확히 일치 합니다. 더 구체적으로:

위의 공식 =
integral_over_perimeter(-y dx + x dy) =
integral_over_area((-(-dy)/dy+dx/dx) dy dx) =
2 Area


7
이 알고리즘이 작동하는 이유를 언급 할 가치가 있습니다. 함수 -y 및 x에 대한 Green의 정리를 적용한 것입니다. 면적계가 작동하는 방식과 정확히 일치합니다. 구체적으로는 - (- DY) / DY + DX / DX) = 2 영역 dydyx integral_permieter = (X + -y DX, DY) integral_area = ((상기 화학식
데이비드 Lehavi

6
게시물의 링크가 끊어졌습니다. 다른 사람이 있습니까?
Yakov 2011-07-11

1
compgeom-discuss@research.bell-labs.com 메일 링리스트에 대한 링크 된 토론은 나에게 유용하지 않습니다. Google 캐시에서 메시지를 복사했습니다 : gist.github.com/1200393
Andrew Андрей Листочкин 2011-09-07

2
@ perfectionm1ng 방향 전환은 합계에서 부호를 뒤집지 만 abs()로그 아웃을 제거합니다.
Darius Bacon

3
제한 사항 :이 방법은 오른쪽에 표시된 것처럼 한쪽이 다른 쪽과 교차하는 자체 교차 다각형에 대해 잘못된 답을 생성합니다. 그러나 삼각형, 일반 및 불규칙 다각형, 볼록 또는 오목 다각형에 대해서는 올바르게 작동합니다. ( mathopenref.com/coordpolygonarea.html )
월드

14

외적은 고전적입니다.

수행해야 할 이러한 계산이 무궁무진 한 경우 곱셈이 절반으로 줄어드는 다음 최적화 된 버전을 사용해보십시오.

area = 0;
for( i = 0; i < N; i += 2 )
   area += x[i+1]*(y[i+2]-y[i]) + y[i+1]*(x[i]-x[i+2]);
area /= 2;

명확성을 위해 배열 첨자를 사용합니다. 포인터를 사용하는 것이 더 효율적입니다. 좋은 컴파일러가 당신을 위해 그것을 할 것이지만.

다각형은 "닫힌"것으로 간주됩니다. 즉, 첫 번째 점을 아래 첨자 N이있는 점으로 복사합니다. 또한 다각형에 짝수의 점이 있다고 가정합니다. N이 짝수가 아니면 첫 번째 점의 추가 사본을 추가하십시오.

이 알고리즘은 고전적인 교차 곱 알고리즘의 두 번의 연속적인 반복을 풀고 결합하여 얻습니다.

두 알고리즘이 수치 정밀도와 관련하여 어떻게 비교되는지 잘 모르겠습니다. 내 인상은 곱셈이 뺄셈의 정밀도 손실을 복원하는 경향이 있기 때문에 위의 알고리즘이 고전적인 알고리즘보다 낫다는 것입니다. GPU와 마찬가지로 부동 소수점을 사용하도록 제한되면 상당한 차이를 만들 수 있습니다.

편집 : "삼각형 및 다각형 영역 2D 및 3D" 는 훨씬 더 효율적인 방법을 설명합니다.

// "close" polygon
x[N] = x[0];
x[N+1] = x[1];
y[N] = y[0];
y[N+1] = y[1];

// compute area
area = 0;
for( size_t i = 1; i <= N; ++i )
  area += x[i]*( y[i+1] - y[i-1] );
area /= 2;

1
두 번째 코드 조각이 작동 할 것이라고 상상할 수 없습니다. 폴리곤이 X 축에서 멀수록 면적이 더 커진다는 것은 매우 분명합니다.
Cygon

1
위에서 설명한 알고리즘의 올바른 수학적 재 배열로 일부 곱셈을 저장합니다. 당신 말이 맞지만 다른 꼭지점에 의해 정의 된 영역은 뺄 것입니다. 그러나 이것은 실제로 정밀도 저하로 이어질 수 있습니다.
chmike

2
당신이 간과 한 것은 덧셈에 y 뺄셈 때문에 항상 부정적인 항이 있다는 것입니다. 2D 다각형 모양을 고려하고 연속 된 꼭지점의 y 값을 비교합니다. 일부 빼기는 음수 값과 일부 양수 값을 생성합니다.
chmike

2
사실, 그 마지막 단락은 내 마음을 둘러 쌀 수 없었습니다! 나는 <= N으로 작동합니다. 양해 해 주셔서 감사합니다. 모든 것을 다시 가져옵니다. :)
Cygon

1
참고로, 알고리즘에 의해 반환 된 영역은 "부호"(점 순서에 따라 음수 또는 양수)이므로 항상 양수 영역을 원하면 절대 값을 사용하십시오.
NightElfik 2014

11

이 페이지 는 공식이

여기에 이미지 설명 입력

다음과 같이 단순화 할 수 있습니다.

여기에 이미지 설명 입력

몇 가지 용어를 작성하고의 공약수에 따라 그룹화 xi하면 평등을보기가 어렵지 않습니다.

최종 합산은 n대신 곱셈 만 필요하므로 더 효율적 입니다 2n.

def area(x, y):
    return abs(sum(x[i] * (y[i + 1] - y[i - 1]) for i in xrange(-1, len(x) - 1))) / 2.0

저는 여기 에서 Joe Kington으로부터이 단순화를 배웠습니다 .


NumPy가있는 경우이 버전이 더 빠릅니다 (매우 작은 어레이를 제외하고 모두) :

def area_np(x, y):        
    x = np.asanyarray(x)
    y = np.asanyarray(y)
    n = len(x)
    shift_up = np.arange(-n+1, 1)
    shift_down = np.arange(-1, n-1)    
    return (x * (y.take(shift_up) - y.take(shift_down))).sum() / 2.0

1
NumPy 버전에 감사드립니다.
physicsmichael


4

삼각형 영역을 확장하고 삼각형 영역을 합산하려면 볼록 다각형이 있거나 다각형과 교차하는 다른 모든 지점에 선을 생성하지 않는 지점을 선택하면 작동합니다.

일반적인 비교 차 다각형의 경우 a와 b가 서로 "다음"인 벡터 (기준점, 점 a), (기준점, 점 b)의 외적을 합산해야합니다.

순서대로 다각형을 정의하는 점 목록이 있다고 가정합니다 (순서는 점 i 및 i + 1이 다각형의 선을 형성 함).

합계 (외적 ((점 0, 점 i), (점 0, 점 i + 1)) for i = 1 to n-1.

그 외적의 크기를 취하면 표면적이 있습니다.

이것은 좋은 참조 점을 선택하는 것에 대해 걱정할 필요없이 오목한 다각형을 처리합니다. 다각형 내부에 있지 않은 삼각형을 생성하는 세 점은 다각형 내부에있는 삼각형의 반대 방향을 가리키는 외적을 가지므로 영역이 올바르게 합산됩니다.


3

다각형의 면적을 계산하려면

http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry1#polygon_area

int cross(vct a,vct b,vct c)
{
    vct ab,bc;
    ab=b-a;
    bc=c-b;
    return ab.x*bc.y-ab.y*bc.x;
}    
double area(vct p[],int n)
{ 
    int ar=0;
    for(i=1;i+1<n;i++)
    {
        vct a=p[i]-p[0];
        vct b=p[i+1]-p[0];
        area+=cross(a,b);
    }
    return abs(area/2.0);
}    

이 질문은 수락 된 답변에 34 개의 찬성표가있는 3 년 된 질문입니다. 귀하의 답변이 이미 게시 된 다른 답변보다 얼마나 나은지 알려주십시오.
Mark Taylor

3
이것은 파이썬이 아닌 c의 예입니다. 아니 더 나은하지만 좋은 다른 언어로 그것을 가지고
underdoeg

2

또는 윤곽 적분을 수행하십시오. Stokes의 정리를 사용하면 면적 적분을 등고선 적분으로 표현할 수 있습니다. 작은 가우스 구적법과 밥은 당신의 삼촌입니다.


2

언어 독립적 솔루션 :

GIVEN : 다각형은 항상 겹치지 않는 n-2 개의 삼각형으로 구성 될 수 있습니다 (n = 점 수 또는 변). 1 삼각형 = 3면 다각형 = 1 삼각형; 1 정사각형 = 4면 다각형 = 2 삼각형; 기타 광고 구역질 QED

따라서 삼각형을 "잘라내서"다각형을 줄일 수 있으며 총 면적은 이러한 삼각형의 면적의 합이됩니다. 종이와 가위로 시도해보십시오. 다음 단계를 따르기 전에 프로세스를 시각화하는 것이 가장 좋습니다.

다각형 경로에서 3 개의 연속 된 점을 가져 와서 이러한 점으로 삼각형을 만들면 다음 세 가지 시나리오 중 하나만 사용할 수 있습니다.

  1. 결과 삼각형은 완전히 원래 다각형 안에 있습니다.
  2. 결과 삼각형은 완전히 원래 다각형 밖에 있습니다.
  3. 결과 삼각형은 원래 다각형에 부분적으로 포함됩니다.

첫 번째 옵션 (완전히 포함됨)에 해당하는 경우에만 관심이 있습니다.

우리가 이들 중 하나를 찾을 때마다, 우리는 그것을 잘라 내고, 그것의 면적을 계산하고 (쉽게, 여기에서 공식을 설명하지 않을 것입니다) 한면이 적은 새로운 다각형을 만듭니다 (이 삼각형이 잘린 다각형과 동일). 삼각형이 하나만 남을 때까지.

이것을 프로그래밍 방식으로 구현하는 방법 :

다각형 주위의 경로를 나타내는 (연속적인) 점의 배열을 만듭니다. 점 0에서 시작합니다. 점 x, x + 1 및 x + 2에서 삼각형 (한 번에 하나씩)을 만드는 배열을 실행합니다. 각 삼각형을 모양에서 영역으로 변환하고 다각형에서 만든 영역과 교차합니다. 결과 교차점이 원래 삼각형과 동일하면 해당 삼각형이 다각형에 완전히 포함되어 잘릴 수 있습니다. 배열에서 x + 1을 제거하고 x = 0에서 다시 시작합니다. 그렇지 않으면 (삼각형이 [부분적으로 또는 완전히] 다각형 밖에있는 경우) 배열의 다음 점 x + 1로 이동합니다.

또한 매핑과 통합하려는 경우 지오 포인트에서 시작하는 경우 지오 포인트에서 스크린 포인트로 먼저 변환해야합니다. 이를 위해서는 지구 모양에 대한 모델링과 공식을 결정해야합니다 (우리는 지구를 구로 생각하는 경향이 있지만 실제로는 움푹 들어간 불규칙한 난형 (달걀 모양)입니다). 추가 정보 위키에 대한 많은 모델이 있습니다. 중요한 문제는 해당 영역을 평면인지 곡선인지 여부입니다. 일반적으로 지점이 최대 몇 km 떨어져있는 "작은"영역은 볼록이 아닌 평면을 고려하면 큰 오류를 생성하지 않습니다.



1
  1. 기준점 (가장 볼록한 점)을 설정합니다. 이것이 삼각형의 피벗 포인트가 될 것입니다.
  2. 기준점 이외의 가장 왼쪽 지점 (임의)을 계산합니다.
  3. 삼각형을 완성하기 위해 두 번째로 왼쪽 점을 계산하십시오.
  4. 이 삼각형 영역을 저장합니다.
  5. 반복 할 때마다 오른쪽으로 한 지점 위로 이동합니다.
  6. 삼각 측량 영역 합계

다음 점이 "뒤로"이동하는 경우 삼각형 영역을 부정해야합니다.
재귀 적

1

삼각형을 합하는 것보다 데카르트 공간에서 사다리꼴을 합하는 것이 좋습니다.

area = 0;
for (i = 0; i < n; i++) {
  i1 = (i + 1) % n;
  area += (vertex[i].y + vertex[i1].y) * (vertex[i1].x - vertex[i].x) / 2.0;
}

1

신발 끈 공식의 구현은 Numpy에서 할 수 있습니다. 다음 정점을 가정합니다.

import numpy as np
x = np.arange(0,1,0.001)
y = np.sqrt(1-x**2)

영역을 찾기 위해 다음 함수를 정의 할 수 있습니다.

def PolyArea(x,y):
    return 0.5*np.abs(np.dot(x,np.roll(y,1))-np.dot(y,np.roll(x,1)))

결과 얻기 :

print PolyArea(x,y)
# 0.26353377782163534

루프를 피하면이 함수가 PolygonArea다음 보다 50 배 더 빠릅니다 .

%timeit PolyArea(x,y)
# 10000 loops, best of 3: 42 µs per loop
%timeit PolygonArea(zip(x,y))
# 100 loops, best of 3: 2.09 ms per loop

참고 : 다른 질문에 대해이 답변을 작성했습니다 . 전체 솔루션 목록을 위해 여기에 언급했습니다.


0

내 경향은 단순히 삼각형을 자르기 시작하는 것입니다. 나는 다른 어떤 것이 끔찍한 털이 피할 수 있는지 보지 못했습니다.

다각형을 구성하는 세 개의 연속적인 점을 취하십시오. 각도가 180 미만인지 확인하십시오. 이제 계산에 문제가없는 새 삼각형이 있습니다. 다각형의 점 목록에서 중간 점을 삭제하십시오. 3 점만 남을 때까지 반복하십시오.


이것에 대한 털이 많은 부분은 세 개의 연속 된 점이 다각형 외부 또는 부분적으로 다각형 외부에 삼각형을 정의하면 문제가 있다는 것입니다.
Richard

@Richard : 그것이 자격이 약 180 도인 이유입니다. 다각형 외부의 삼각형을 잘라 내면 너무 많은 각도로 끝납니다.
Loren Pechtel 2012

각도를 찾는 방법을 더 잘 설명해야 할 수도 있습니다. 평면 기하학에서 삼각형의 일부로 3 개의 점을 갖고 180도를 초과하는 각도 또는 각도 조합을 가질 수있는 방법이 없습니다. 검사는 의미가 없어 보입니다.
Richard

@Richard : 다각형에는 모든 교차점의 각도가 있습니다. 관련 삼각형이 다각형 외부에있는 경우 두 세그먼트 사이의 각도는 180 도보 다 커집니다.
Loren Pechtel 2012

인접한 두 모서리 세그먼트의 내부 각도가 180 도보 다 크다는 것을 의미합니다.
Richard

0

C 방식 :

float areaForPoly(const int numVerts, const Point *verts)
{
    Point v2;
    float area = 0.0f;

    for (int i = 0; i<numVerts; i++){
        v2 = verts[(i + 1) % numVerts];
        area += verts[i].x*v2.y - verts[i].y*v2.x;
    }

    return area / 2.0f;
}

0

파이썬 코드

여기에 설명 된대로 : http://www.wikihow.com/Calculate-the-Area-of-a-Polygon

팬더와 함께

import pandas as pd

df = pd.DataFrame({'x': [10, 20, 20, 30, 20, 10, 0], 'y': [-10, -10, -10, 0, 10, 30, 20]})
df = df.append(df.loc[0])

first_product = (df['x'].shift(1) * df['y']).fillna(0).sum()
second_product = (df['y'].shift(1) * df['x']).fillna(0).sum()

(first_product - second_product) / 2
600

0

2D 폴리곤의 면적을 계산하기위한 몇 가지 간단한 함수를 제공하겠습니다. 이것은 볼록한 다각형과 오목한 다각형 모두에 적용됩니다. 우리는 단순히 다각형을 많은 하위 삼각형으로 나눕니다.

//don't forget to include cmath for abs function
struct Point{
  double x;
  double y;
}
// cross_product
double cp(Point a, Point b){ //returns cross product
  return a.x*b.y-a.y*b.x;
}

double area(Point * vertices, int n){  //n is number of sides
  double sum=0.0;
  for(i=0; i<n; i++){
    sum+=cp(vertices[i], vertices[(i+1)%n]); //%n is for last triangle
  }
  return abs(sum)/2.0;
}

cp두 개의 인수를 취하지 만 하나로 호출합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.