第三章课后习题(判断是否为多边形图形,求多边形面积)——程序设计艺术与方法实验三 计算几何

第三章课后习题(判断是否为多边形图形,求多边形面积)——程序设计艺术与方法实验三 计算几何

分析:
判断能否构成多边形,即判断是否存在两直线相交:两直线互相跨立;或一条线段的一个端点在另一条线段上
在这里插入图片描述

求多边形面积:取一顶点与其它顶点相连,相邻的边做向量积再除以2;也就是求每个三角形的面积。

代码:

#include<bits/stdc++.h>
using namespace std;
struct Point{//构造一个点的结构
    double x, y;
    Point() {}
    Point(double _x, double _y){//构造函数
        x = _x;
        y = _y;
    }
    Point operator -(const Point& b) const {
        return Point(x - b.x, y - b.y);
    }
};
double crossProduct(Point p, Point p1, Point p2){//用来求叉积  p.p1叉乘p.p2
    Point a = p1 - p;
    Point b = p2 - p;//两个向量
    return a.x * b.y - b.x * a.y;
}
bool isIntersect(Point a1, Point a2, Point b1, Point b2){//该函数用来判断线段a1.a2  与 线段 b1.b2是否相交
    //这个if是快速排斥实验的条件
    if (min(a1.x, a2.x) <= max(b1.x, b2.x) && min(b1.x, b2.x) <= max(a1.x, a2.x) &&
        min(a1.y, a2.y) <= max(b1.y, b2.y) && min(b1.y, b2.y) <= max(a1.y, a2.y)){
        //在满足快速排斥实验的基础上我们再进行跨立实验
        double c1 = crossProduct(a1, b1, a2);//a1b 叉乘 a1a2
        double c2 = crossProduct(a1, b2, a2);//a1b2 叉乘 a1a2
        double c3 = crossProduct(b1, a1, b2);//b1a1 叉乘 b1b2
        double c4 = crossProduct(b1, a2, b2);//b1a2 叉乘 b1b2
        if (c1 * c2 <= 0 && c3 * c4 <= 0) return true;  //两条直线相互跨立则返回true
    }
    return false;
}
bool isPolygon(vector<Point> points){//判断是否是合格的多边形
    for (int i = 2; i < points.size() - 1; i++){//从第2条边开始判断第i条边与从第0条边开始不相邻的边是否相交  (说明:我们的边和点都是从0开始计数)
        for (int j = 0; j < i - 1; j++){
            if (isIntersect(points[i], points[i + 1], points[j], points[j + 1]))
                return false;
        }
    }
    //因为最后一条边的终点与起点相连 所以单独来一个for循环讨论
    for (int j = 1; j < points.size() - 2; j++){
        if (isIntersect(points[points.size() - 1], points[0], points[j], points[j + 1]))
            return false;
    }
    return true;
}
double getArea(vector<Point> points){//叉积求面积
    Point p0 = points.front();
    double S = 0;
    for (int i = 1; i < points.size() - 1; i++){
        S += crossProduct(p0, points[i], points[i + 1]);
    }
    return fabs(S / 2.0);
}
int main(){
    vector<Point> points;
    int n = 0;
    int i = 1;
    double x, y;
    while (cin >> n && n){
        if (n < 3) cout << "Figure " << i << ": " << "Impossible !" << endl; // 点的个数小于3 则直接pass
        else {
            for (int j = 0; j < n; j++){
                cin >> x >> y;
                points.push_back(Point(x, y));//把点压入容器中
            }
            if (isPolygon(points)){//如果可以构成多边形则计算面积
                double S = getArea(points);
                cout << "Area";
                cout << "Figure " << i << ": " << S << endl;
            }
            else{
                cout << "Figure " << i << ": " << "Impossible !" << endl;
            }
        }
        points.clear();//每回计算完毕清空容器进行下一次计算
        i++;
    }
    return 0;
}

运行结果:

在这里插入图片描述
思考:
若一条线段端点在另一线段(除端点)上,则无法构成多边形;
若一条线段端点与另一线段的端点重合,则可能构成多边形。但若三条线段端点重合则无法形成多边形。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值