2D 다각형의 다음은 어떻게 계산합니까?
2D 공간에서 자체 교차하지 않는 것이 점을 가정 할 때 결과 다각형의 존재를 결정하는 방법은 무엇입니까?
내가 코드를 찾고 있지 않습니다. 내 자신의 방법을 구현하는 데 사용할 수있는 설명을 찾고 있습니다. 모든 것이 많은 것이 알고 있습니다.
다음은 표준 방법 인 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
외적은 고전적입니다.
수행해야 할 계산이 무궁무진 한 경우 곱셈이 감소한 경우 다음 최적화 된 버전을 수행해야합니다.
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;
이 페이지 는 공식이
다음과 같이 단순화 할 수 있습니다.
몇 가지 용어를 작성하고의 공약수에 따라 그룹화 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
다른 제약 조건이없는 점 집합이 반드시 다각형을 고유하게 정의합니다.
따라서 먼저이 지점에서 어떤 다각형을 만들지 결정해야합니다. 볼록 껍질일까요? http://en.wikipedia.org/wiki/Convex_hull
그런 다음 수준을 삼각 측량하고 계산합니다. http://www.mathopenref.com/polygonirregulararea.html
다각형 영역을 확장하고 삼각형 영역을 확장하고 삼각형 영역을 합산 다각형 다각형 다각형으로 선과 교차하는 다른 모든 지점을 선택합니다.
일반적인 비교 차 다각형의 경우 a와 b가 서로 "다음"인 벡터 (기준점, 점 a), (기준점, 점 b)의 외적을 산해야합니다.
순서대로 다각형을 정의하는 점 목록이 가정합니다 (순서는 점 i 및 i + 1이 다각형의 선을 형성 함).
(외적 ((점 0, 점 i), (점 0, 점 i + 1)) for i = 1 to n-1.
그 외적의 크기를 취하면 표면적이 있습니다.
이는 걱정할 필요없이 오목한 다각형을 처리합니다. 다각형 내부에 있지 않은 삼각형을 생성하는 세 점은 다각형 내부에있는 삼각형의 반대 방향을 포함하는 외적을 가지 영역이 있습니다.
다각형의 가능한을 계산 비용
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);
}
또는 윤곽 적분을 수행하십시오. Stokes의 정리를 사용하면 적분을 등고선 적분으로 표현할 수 있습니다. 작은 가우스 구적법과 밥은 당신의 삼촌입니다.
수행하는 한이를 가지 방법 은 다각형을 삼각형 으로 분해하고 삼각형 의 면적을 계산 한 다음 합계를 다각형의 면적으로 취하는을 구석으로입니다.
- 기준점 (가장 볼록한 점)을 설정합니다. 이것이 삼각형의 피벗 포인트가 될 것입니다.
- 기준점이 아닌 가장 왼쪽에있는 지점 (임의)을 계산합니다.
- 삼각형을 완성하기 위해 두 번째로 왼쪽 점을 계산하십시오.
- 이 삼각형 영역을 저장합니다.
- 반복 할 때마다 오른쪽으로 한 지점 위로 이동합니다.
- 삼각 측량 영역
삼각형을 합하는 것보다 데카르트 공간에서 사다리꼴을 합하는 것이 좋습니다.
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;
}
언어 독립 솔루션 :
주어진 : 다각형은 항상 겹치지 않는 n-2 개의 삼각형으로 구성 될 수 있습니다 (n = 점 수 또는 변). 1 삼각형 = 3면 다각형 = 1 삼각형; 1 정사각형 = 4면 다각형 = 2 삼각형; 기타 광고 구역질 QED
따라서 삼각형을 "잘라내서"다각형을 줄일 수 있으며 총 면적은이 삼각형의 면적의 합이됩니다. 종이와 가위로 시도해보십시오. 다음 단계를 따르기 전에 프로세스를 시각화하는 것이 가장 좋습니다.
다각형 경로에서 3 개의 연속 된 점을 가져 와서 이러한 점으로 삼각형을 만들면 다음 세 가지 시나리오 중 하나만 사용할 수 있습니다.
- 결과 삼각형은 완전히 원래 다각형 안에 있습니다
- 결과 삼각형은 완전히 원래 다각형 밖에 있습니다.
- 결과 삼각형은 원래 다각형에 부분적으로 포함됩니다.
우리는 첫 번째 옵션 (완전히 포함)에 해당하는 경우에만 관심이 있습니다.
우리가이 중 하나를 찾을 때마다, 우리는 그것을 잘라 내고, 그 면적을 계산하고 (쉽게, 여기에서 공식을 설명하지 않을 것입니다) 한면이 적은 새로운 다각형을 만듭니다 (이 삼각형이 잘린 다각형과 동일). 삼각형이 하나만 남을 때까지.
이것을 프로그래밍 방식으로 구현하는 방법 :
다각형 주위의 경로를 나타내는 (연속적인) 점의 배열을 만듭니다. 점 0에서 시작합니다. 점 x, x + 1 및 x + 2에서 삼각형 (한 번에 하나씩)을 만드는 배열을 실행합니다. 각 삼각형을 모양에서 영역으로 변환하고 다각형에서 만든 영역과 교차합니다. 결과 교차점이 원래 삼각형과 동일하면 해당 삼각형은 완전히 다각형에 포함되어 잘릴 수 있습니다. 배열에서 x + 1을 제거하고 x = 0에서 다시 시작합니다. 그렇지 않으면 (삼각형이 [부분적으로 또는 완전히] 다각형 밖에있는 경우) 배열의 다음 점 x + 1로 이동합니다.
또한 매핑과 통합하려는 경우 지오 포인트에서 시작하는 경우 지오 포인트에서 스크린 포인트로 먼저 변환해야합니다. 이를 위해서는 지구 모양에 대한 모델링과 공식을 결정해야합니다 (우리는 지구를 구로 생각하는 경향이 있지만 실제로는 움푹 들어간 불규칙한 난형 (달걀 모양)). 추가 정보 위키에 대한 많은 모델이 있습니다. 중요한 문제는 해당 영역을 평면으로 간주할지 곡선으로 간주할지 여부입니다. 일반적으로 점이 최대 몇 km 떨어져있는 "작은"영역은 볼록이 아닌 평면을 고려하면 큰 오류를 생성하지 않습니다.
신발 끈 공식의 구현은 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
참고 : 다른 질문에 대해이 답변을 작성했습니다 . 전체 솔루션 목록을 위해 여기에 언급했습니다.
내 경향은 단순히 삼각형을 자르기 시작하는 것입니다. 나는 다른 어떤 것이 끔찍한 털이 피할 수 있는지 보지 못했습니다.
다각형을 구성하는 세 개의 연속적인 점을 취하십시오. 각도가 180 미만인지 확인하십시오. 이제 계산에 문제가없는 새 삼각형이 있습니다. 다각형의 점 목록에서 중간 점을 삭제하십시오. 3 점만 남을 때까지 반복하십시오.
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;
}
파이썬 코드
여기에 설명 된대로 : 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
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;
}
참고 URL : https://stackoverflow.com/questions/451426/how-do-i-calculate-the-area-of-a-2d-polygon
'ProgramingTip' 카테고리의 다른 글
매개 변수로 생성자 모의 (0) | 2020.10.21 |
---|---|
프로그래밍 방식으로 (법적으로) 거리 주소의 경도와 위도를 얻는 방법 (0) | 2020.10.21 |
(400) HTTP 잘못된 요청으로 인해 큰 WCF 웹 서비스 요청 실패 함 (0) | 2020.10.21 |
git : "branchname"과 "refs / head / branchname"의 차이점 (0) | 2020.10.21 |
ID 또는 클래스가없는 요소를 찾기위한 XPath (0) | 2020.10.21 |