질문: 2차원 평면 좌표계에서 모든 다각형에 대해 각 꼭지점의 좌표를 알고 다각형의 면적을 계산합니다.
"좌표"와 "영역"이라는 단어를 보았을 때 가장 먼저 생각한 것은 방금 작성한 지난 블로그의 내용인 벡터의 외적입니다. 그런 다음 면적 계산 문제에 답할 수 있는지 확인하기 위해 벡터의 외적에서 시작하려고 합니다.
벡터 외적의 정의:
벡터가 두 개인 경우
그렇다면 =
계산 및 도출을 용이하게 하기 위해 다음과 같이 외부 제품의 정의 공식을 더욱 발전시킵니다.
=
=
=
2차원 평면으로의 차원 축소, 우리는 다음을 얻습니다.
=
=
,
각각 x축, y축 및 z축의 단위 벡터를 나타냅니다.
세 번째 열에서 첫 번째 행을 제외한 다른 모든 행은 0이므로 행렬식의 세 번째 열에 따라 확장하고
=
=
=
, 대수적 공동 인자를
나타냅니다 .
따라서 2차원 평면에서 두 벡터의 외적을 계산할 때 두 벡터의 정렬된 좌표 배열의 행렬식을 계산하여 평가할 수 있습니다. 이전 블로그에서 두 벡터의 외적 절대값이 원점 과 세 점
으로 둘러싸인 삼각형 면적의 2배 와 같다는 것을 확인했습니다.
이 토대를 마련하고 다시 질문으로 돌아가 봅시다.
문제는 다각형을 설명합니다. 아래 그림과 같이 가장 간단한 다각형인 삼각형부터 시작하겠습니다.
위 그림에서 삼각형의 넓이 는
우리는 위 공식에서 각 삼각형의 면적을 가져오기 위해 벡터 외적을 사용합니다.
=
참고: 벡터를 교차 곱하면 결과는 양수 또는 음수가 되고 양수 및 음수는 오른손 규칙을 만족하는 방향을 나타냅니다.
삼각형을 계산한 후 사각형으로 이동합니다.
사변형은 소위 볼록하고 오목한 변이 있기 때문에 조금 더 복잡해집니다.두 시나리오가 동일한 계산 아이디어를 가질 수 있는지, 즉 요철이 없는지 확인해 봅시다. 먼저 두 그래픽을 별도로 계산합니다.
볼록한 모양:
=
=
오목형:
=
=
상하 결과의 공식, 즉 사변형의 볼록면과 오목면이 통일되어 있음을 알 수 있으며 벡터 외적을 면적 계산에 사용할 때 계산식이 일관되고 요철감이 없음을 알 수 있습니다. .
이제 우리는 삼각형에서 사변형으로의 문제 해결 방법을 확인했습니다.
각 정점과 다각형의 원점으로 구성된 벡터를 시계 반대 방향(또는 시계 방향으로도 사용 가능)으로 구성하고 전후 두 벡터를 교차 곱하여 외적을 구하고 꼬리 벡터와 머리 벡터를 구합니다. 또한 교차 곱합니다(즉, 그래프의 각 가장자리로 연결된 두 끝점은 머리에서 꼬리까지 교차 곱해야 함 ). 모든 외부 제품은 다각형의 영역입니다. 지금 바로
=
이 계산 방법을 모든 폴리곤에 적용할 수 있습니까? 수학적 귀납법으로 증명해 보자.
n개의 변이 있을 때 =가
참이라고 가정하고 이때 이를 기준으로 한 점을 더하면
n+1개의 변이 된다.
위의 그림과 같이 두 개의 모서리(그림의 노란색 부분)를 추가하고
이 모서리(그림의 빨간색 점선)를 제거 해야 합니다 .
= +
= +
(참고: 이는 두 면을 추가하고 한 면을 제거하는 것에 해당합니다.)
=
최종 결과는 위에서 요약한 계산 규칙을 만족합니다. 지금까지 이론적으로 다각형 영역의 해를 구했습니다.
다음에는 이 계산 방법을 컴퓨터에 이식하고 컴퓨터가 계산을 수행하도록 해야 하므로 계산 공식을 컴퓨터가 계산하기 편리한 형태로 계속 발전시켜야 합니다.
=
=
=
=
그 중 당시 ,
즉
마지막으로, 우리는 유명한 Shoelace Theorem 신발 끈 정리 인 위의 공식을 얻었습니다 .
그 특징은 무엇입니까? 다음과 같이 인터넷에서 사진을 빌리자.
이 공식은 신발끈과 같이 작용하기 때문에 신발끈 정리라고 합니다.
신발 끈 정리를 사용하면 쉽게 코드로 이식할 수 있습니다.
struct Point2d
{
double x;
double y;
Point2d(double xx, double yy): x(xx), y(yy){}
};
//计算任意多边形的面积,顶点按照顺时针或者逆时针方向排列
double ComputePolygonArea(const vector<Point2d> &points)
{
int point_num = points.size();
if(point_num < 3)return 0.0;
double s = 0;
for(int i = 0; i < point_num; ++i)
s += points[i].x * points[(i+1)%point_num].y - points[i].y * points[(i+1)%point_num].x;
return fabs(s/2.0);
}