多边形面积计算

多边形面积计算

    由于多边形可以分解为多个三角形来计算,因此首先讨论三角形面积问题。

    假设三角形三个顶点坐标为 (x1, y1), (x2, y2), (x3, y3)

    则三角形的面积可以由以下的行列式计算

   | x1, y1, 1 |
   | x2, y2, 1 |       该行列式的值取绝对值再除2就是三角形的面积
   | x3, y3, 1 |

    这个行列式也可以排成它的转置形式,即x排成一行,y排成一行,1 排成一行(行列式与它的转置行列式相等)

    行列式性质一:任意调换行列式的两行(列),行列式的值变换符号

    这是个很重要的性质,我们就是利用这一点来计算有向三角形的面积。假设三角形的三个顶点按逆时针方向,按上面的行列式计算出的值为正,若为顺时针方向计算出的面积为负。三角形方向变换时,实际上是调换了上面这个行列式的两行。利用这个性质还可以判断指定点在有向线段的哪一侧或是否在线段确定的直线上。

    现在我们回到多边形面积的问题上。我们可以将多边形的每一条边看作首尾相连的环形有向线段,然后在多边形所在平面上任取一点,该点与多边形的每一条边构成一个有向三角形,所有有向三角形的面积之和的绝对值就是多边形的面积。

    参考示图


    对于点在多边形内部时,这个是显然的。当点在多边形外部时我们直观的感觉是计算出的面积会变大。但由于我们计算的是有向三角形的面积,当点在多边形外面时必然有部分三角形与其它三角形相反,正好抵消多出来的面积。且对凹多边形也同样适用。

    特殊地,当点在多形的一条边上或与某个顶点重合时也不影响

(行列式性质二:任意两行(列)完全相同或成比例时,行列式的值为零)。

根据前面的分析,下面用 C 语言给出计算函数

// 点结构
typedef struct 
{
    double x;
    double y;
} POINT;


// 多边形
typedef struct 
{
    // 顶点数
    int count;
    // 指向含有count+1个顶点的数组
    // 多保存一个顶点是为了方便处理环形向量
    // 最后一个点与第一个点重合
    POINT *acmes;
} POLY;


// 主功能:计算有向 △p1p2p3 的面积(绝对值为一般三角形面积)
// 辅功能:判断点 p3 在有向线段 p1p2 的哪一侧)
//             返回值  >0 左侧、=0 在直线上、<0 右侧
// 行列式如下:
//            | x1, y1, 1 |
//            | x2, y2, 1 | / 2
//            | x3, y3, 1 |

double TriangleArea(POINT p1, POINT p2, POINT p3)
{
    double area = (p1.x * p2.y + p2.x * p3.y + p3.x * p1.y)
        - (p1.x * p3.y + p2.x * p1.y + p3.x * p2.y);
   
    return area / 2;
}

// 计算多边形面积(给定的顶点序列必须能组成多边形)

double PolyArea(POLY *poly)
{
    POINT p0 = { 0.0, 0.0 };
   
    double area = 0.0;
    for(int i=0; i<poly->count; ++i)
        area += TriangleArea(p0, poly->acmes[i], poly->acmes[i+1]);
   
    return area > 0.0 ? area : -area;
}

测试:
我们将多边形的顶点放在一个文件 poly.txt 中,格式如下
首先用一行给出顶点数 n(顶点数为零时结束)
接着的n行每行两个数,代表一个顶点的 x, y 坐标
我测试的文件内容如下:(一个凸多边形、一个凹多边形)
5
0 0
10 0
10 10
5 20
0 10
5
0 0
10 0
10 10
5 4
0 10
0

测试代码(VC6):

#include <stdio.h>
#include <stdlib.h>

void main(int argc, char *argv[])
{
    int i;
    POLY poly;
    double area = 0.0;

    FILE * fp = fopen("Poly.txt", "r");

    while(1) {
        // 读顶点数
        fscanf(fp, "%d", &poly.count);

        if(poly.count <= 0)
            break;
       
        // 分配 count+1 个顶点的空间
        poly.acmes = (POINT*)malloc(sizeof(POINT) * (poly.count+1));
       
        // 顶点坐标
        for(i=0; i<poly.count; ++i)
            fscanf(fp, "%lf %lf", &poly.acmes[i].x, &poly.acmes[i].y);

        // 最后一个顶点与第一个顶点重合
        poly.acmes[i].x = poly.acmes[0].x;
        poly.acmes[i].y = poly.acmes[0].y;

        area = PolyArea(&poly);
        printf("%lf/n", area);

        // 释放空间
        free(poly.acmes);
    }
   
    fclose(fp);
}

输出结果如下:

150.000000
70.000000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值