编程之美 4.4点是否在三角形内

问题:如果一个二维坐标系中,已知三角形三个点的坐标,那么对于任意一点,如何判断其在三角形内呢?(点在三角形边上也算在三角形内)

解法一:面积法

S=Area(ABC)、S1=Area(ABP)、S2=Area(BCP)、S3=Area(CAP)

若P点在三角形内,S=S1+S2+S3

若P在三角形外,S1+S2+S3>S

计算三角形的面积可以使用海伦公式

heron1

而公式里的p为半周长(周长的一半):

heron2

但注意了我们可以利用向量积的几何意义以两个向量为邻边的平行四边形的面积(即三角形面积的2倍)

若 |AB×BP| + |BC×CP| + |CA×AP| = |AB×BC|,则得点 P 在 △ABC 内。

解法二:叉乘法

沿 △ABC 各有向边按一定方向走(顺时针或逆时针),判断点 P 是否在该边的某侧(右侧或左侧),若点 P 在三条边的同侧,则点 P 在 △ABC 内。

分别计算向量 AB、BC、CA 与向量 AP、BP、CP 的向量积(叉乘),若三个结果均同号(正或负,为零表示 P 在边上),则可得点 P 在 △ABC 内。

其中AB = B - A,AB×AP = AB.x*AP.y - AB.y*AP.x即 x1y2-y1x2。

其实不止三角形对于凸多边形也是可以通过叉乘法来判断的。

补充知识:

所谓凸多边形,就是把一个多边形任意一边向两方无限延长成为一条直线,如果多边形的其他各边均在此直线的同旁,那么这个多边形就叫做凸多边形。

下面是示例代码:注意面积法对输入的点序没要求,叉乘法就要按逆时针的顺序。

#include <iostream>
#include <cmath>
using namespace std;

struct point
{
    double x,y;
    point(double _x=0,double _y=0)
    {
        x=_x;
        y=_y;
    }
};

inline double VecProduct(point A,point B,point P)
{
    return (B.x-A.x)*(P.y-A.y)-(B.y-A.y)*(P.x-A.x);
}

double TriArea(point A,point B,point P)
{
    return abs((B.x-A.x)*(P.y-B.y)-(B.y-A.y)*(P.x-B.x));
}

//method:Area
bool isInTriangle1(point A,point B,point C,point P)
{
    double sABP,sBCP,sCAP,sABC;
    sABP=TriArea(A,B,P);
    sBCP=TriArea(B,C,P);
    sCAP=TriArea(C,A,P);
    sABC=TriArea(A,B,C);
    if (sABC==sABP+sBCP+sCAP)
    {
        return true;
    }
    return false;
}
//method:Vector Product,ABC anticlockwise
bool isInTriangle2(point A,point B,point C,point P)
{
    if (VecProduct(A,B,P)>=0 && VecProduct(B,C,P)>=0 && VecProduct(C,A,P)>=0)
    {
        return true;
    }
    return false;
}

void main()
{
    point A(0,2);
    point B(0,0);
    point C(2,0);

    point P1(1,1);//in the Triangle
    point P2(4,4);//outside the Triangle 
    point P3(2,0);//on the edge of the Triangle

    cout<<boolalpha<<isInTriangle1(A,B,C,P1)<<endl;
    cout<<boolalpha<<isInTriangle1(A,B,C,P2)<<endl;
    cout<<boolalpha<<isInTriangle1(A,B,C,P3)<<endl;

    cout<<boolalpha<<isInTriangle2(A,B,C,P1)<<endl;
    cout<<boolalpha<<isInTriangle2(A,B,C,P2)<<endl;
    cout<<boolalpha<<isInTriangle2(A,B,C,P3)<<endl;
}

转载于:https://www.cnblogs.com/Linkabox/p/3357768.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园的建设目标是通过数据整合、全面共享,实现校园内教学、科研、管理、服务流程的数字化、信息化、智能化和多媒体化,以提高资源利用率和管理效率,确保校园安全。 智慧校园的建设思路包括构建统一支撑平台、建立完善管理体系、大数据辅助决策和建设校园智慧环境。通过云架构的数据心与智慧的学习、办公环境,实现日常教学活动、资源建设情况、学业水平情况的全面统计和分析,为决策提供辅助。此外,智慧校园还涵盖了多媒体教学、智慧录播、电子图书馆、VR教室等多种教学模式,以及校园网络、智慧班牌、校园广播等教务管理功能,旨在提升教学品质和管理水平。 智慧校园的详细方案设计进一步细化了教学、教务、安防和运维等多个方面的应用。例如,在智慧教学领域,通过多媒体教学、智慧录播、电子图书馆等技术,实现教学资源的共享和教学模式的创新。在智慧教务方面,校园网络、考场监控、智慧班牌等系统为校园管理提供了便捷和高效。智慧安防系统包括视频监控、一键报警、阳光厨房等,确保校园安全。智慧运维则通过综合管理平台、设备管理、能效管理和资产管理,实现校园设施的智能化管理。 智慧校园的优势和价值体现在个性化互动的智慧教学、协同高效的校园管理、无处不在的校园学习、全面感知的校园环境和轻松便捷的校园生活等方面。通过智慧校园的建设,可以促进教育资源的均衡化,提高教育质量和管理效率,同时保障校园安全和提升师生的学习体验。 总之,智慧校园解决方案通过整合现代信息技术,如云计算、大数据、物联网和人工智能,为教育行业带来了革命性的变革。它不仅提高了教育的质量和效率,还为师生创造了一个更加安全、便捷和富有智慧的学习与生活环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值