机场跑道入侵检测(C++、Qt)

2023-10-08 17:48

本文主要是介绍机场跑道入侵检测(C++、Qt),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

机场跑道入侵检测

    • 实现原理:
    • 效果
    • 关键代码(只提供思路和部分代码,并非完整代码。)

实现原理:

1、读取并解析机场跑道、车道数据,显示和存储。
2、根据本机的经纬度坐标,确定本机所在跑道,并计算出一个多边形区域。
3、实时获取它机、车辆坐标数据,判断是否位于本机起飞跑道的多边形范围内。
4、如果它机、车辆坐标位于本机跑道,则预警。

通过面积法,判断点P是否在四边形(A,B,C,D)内。如果在四边形内,则四边形的面积=面积(P,A,B)+面积(P,B,C)+面积(P,C,D)+面积(P,D,A),反之不在四边形内。

如下图:
在这里插入图片描述

效果

视频地址:https://www.bilibili.com/video/BV1bK4y147R1/

关键代码(只提供思路和部分代码,并非完整代码。)

	//judge quadrangle is contain point pbool isInQuadrangle(QVector<QPointF> &pointfs, QPointF p);//calculate triangle areadouble getTriangleArea(QPointF p1, QPointF p2, QPointF p3);//get Vertex of Quadrangle void getQuadrangleVertex(QPointF m1, QPointF m2, float direction, double len, QVector<QPointF> &pointfs);//polygon vertexes can be sorted clockwisevoid clockwiseSort(QVector<QPointF> & vPoints);bool PointCmp(const QPointF &a, const QPointF &b, const QPointF &center);double getAngle(const QPointF &oldPos, const QPointF &newPos) const;
//跑道入侵检测
void runwayIncursionCheck(std::vector<OtherAircraftInfo> &aircraftInfo)
{for (std::vector<OtherAircraftInfo>::iterator itr = aircraftInfo.begin(); itr != aircraftInfo.end(); itr++){if (mCurrentRunWay.count() == 4){if (mCalculate.isInQuadrangle(mCurrentRunWay, QPointF(itr->lon, itr->lat))){itr->incursion = true;qWarning() << "Runway Incursion: " << itr->ID;}else{itr->incursion = false;}}		}
}
计算本机所在的跑道
void whichRunWay(const AircraftInfo & aircraftInfo)
{//foreach runWaymCurrentRunWay.clear();for (int runwayIndex = 0; runwayIndex < mRunWays.count() ; runwayIndex++){		QVector<QPointF> runWay(4);double angle = mCalculate.getAngle(mRunWays[runwayIndex].at(0), mRunWays[runwayIndex].at(1));  //calculate runway anglemCalculate.getQuadrangleVertex(mRunWays[runwayIndex].at(0), mRunWays[runwayIndex].at(1), angle , 60/1852.0, runWay);if (mCalculate.isInQuadrangle(runWay, QPointF(aircraftInfo.lon, aircraftInfo.lat))){mCurrentRunWay = runWay;}}
}
//通过一个已知坐标点、方位角、和距离,计算另一个点的经纬度坐标
void CalculatePositionByAngle(double & DestLat, double & DestLon, double orgLat, double orgLon, double distNM, double angle)
{double rad_lati = ToRadian(orgLat);double rad_longi = ToRadian(orgLon);double Ec = PolarRadiusMeter + (EquatorRadiusMeter - PolarRadiusMeter)*(90.0 - orgLat) / 90.0;double Ed = EquatorRadiusMeter * cos(rad_lati);double difx = distNM * 1852.0 * cos(ToRadian(90 - angle));double dify = distNM * 1852.0 * sin(ToRadian(90 - angle));DestLat = ToAngle(1.0*dify / Ec + rad_lati);DestLon = ToAngle(1.0*difx / Ed + rad_longi);if (DestLon > 180){DestLon = DestLon - 360;}if (DestLat > 180){DestLat = DestLat - 360;}
}
const qreal pi = 3.141592653589793238462643383;
//判断坐标点,是否在一个四边形区域内
bool isInQuadrangle(QVector<QPointF> &pointfs, QPointF p)
{double dTriangle = getTriangleArea(pointfs.at(0), pointfs.at(1), p) + getTriangleArea(pointfs.at(1), pointfs.at(2), p) + getTriangleArea(pointfs.at(2), pointfs.at(3), p) + getTriangleArea(pointfs.at(3), pointfs.at(0), p);double dQuadrangle = getTriangleArea(pointfs.at(0), pointfs.at(1), pointfs.at(2)) + getTriangleArea(pointfs.at(2), pointfs.at(3), pointfs.at(0));if ((dTriangle >0) && (dQuadrangle > 0) && (qAbs(dTriangle - dQuadrangle) < 0.00001)){qDebug() << "isInQuadrangle: " << qAbs(dTriangle - dQuadrangle);return true;}elsereturn false;//return dTriangle == dQuadrangle;
}
//计算一个三角形的面积
double getTriangleArea(QPointF p1, QPointF p2, QPointF p3)
{return qAbs((p1.x()*p2.y() + p2.x()*p3.y() + p3.x()*p1.y() - p2.x()*p1.y() - p3.x()*p2.y() - p1.x()*p3.y()) / 2.0);
}//根据四边形两条对边的中线,方位、宽度,计算出四个顶点坐标
void getQuadrangleVertex(QPointF m1, QPointF m2, float direction, double len, QVector<QPointF> &pointfs)
{float angle1 = 0.0;float angle2 = 0.0;angle1 = (direction + 90.0) > 360.0 ? direction + 90.0 - 360.0 : direction + 90.0;angle2 = (direction + 270.0) > 360.0 ? direction + 270.0 - 360.0 : direction + 270.0;Conversions cver;cver.CalculatePositionByAngle(pointfs[0].ry(), pointfs[0].rx(), m1.y(), m1.x(), len / 2, angle1);cver.CalculatePositionByAngle(pointfs[1].ry(), pointfs[1].rx(), m1.y(), m1.x(), len / 2, angle2);cver.CalculatePositionByAngle(pointfs[2].ry(), pointfs[2].rx(), m2.y(), m2.x(), len / 2, angle1);cver.CalculatePositionByAngle(pointfs[3].ry(), pointfs[3].rx(), m2.y(), m2.x(), len / 2, angle2);clockwiseSort(pointfs);
}//四边形四个顶点 按照顺时针排序
void clockwiseSort(QVector<QPointF>& vPoints)
{//calculate centre pointQPointF center;double x = 0, y = 0;for (int i = 0; i < vPoints.size(); i++){x += vPoints[i].x();y += vPoints[i].y();}center.rx() = (int)x / vPoints.size();center.ry() = (int)y / vPoints.size();//sort pointfor (int i = 0; i < vPoints.size(); i++){for (int j = 0; j < vPoints.size() - i - 1; j++){if (PointCmp(vPoints[j], vPoints[j + 1], center)){QPointF tmp = vPoints[j];vPoints[j] = vPoints[j + 1];vPoints[j + 1] = tmp;}}}
}bool PointCmp(const QPointF &a, const QPointF &b, const QPointF &center)
{if (a.x() >= 0 && b.x() < 0)return true;/*if (a.x() == 0 && b.x() == 0)return a.y() > b.y();*///向量OA和向量OB的叉积int det = (a.x() - center.x()) * (b.y() - center.y()) - (b.x() - center.x()) * (a.y() - center.y());if (det < 0)return true;if (det > 0)return false;//向量OA和向量OB共线,以距离判断大小int d1 = (a.x() - center.x()) * (a.x() - center.x()) + (a.y() - center.y()) * (a.y() - center.y());int d2 = (b.x() - center.x()) * (b.x() - center.y()) + (b.y() - center.y()) * (b.y() - center.y());return d1 > d2;
}
//根据两个点,计算方位
double getAngle(const QPointF &oldPos, const QPointF &newPos) const
{//根据两个点的经纬度,以一个点(old)为坐标中心,y轴正方向为正北方向(即为 0°),求出另一个点(new)关于正北方向的角度(0° ~ 360°)double a = newPos.x() - oldPos.x();  //经度差double b = newPos.y() - oldPos.y();    //纬度差double c = hypot(fabs(a), fabs(b));double cosy = 0.0;double angle = 0;if (a > 0 && b > 0)         // 判断road点在user点的东北位置{cosy = b / c;angle = 0;}else if ((a == 0) && (b > 0))  //在正北位置{angle = -90;}else if ((a > 0) && (b < 0))   // 判断road点在user点的东南位置{cosy = a / c;angle = 90;}else if ((a > 0) && (b == 0))  //在正东位置{angle = 90;}else if ((a < 0) && (b < 0))    // 判断road点在user点的西南位置{cosy = fabs(b) / c;angle = 180;}else if ((a == 0) && (b < 0))   //在正南位置{angle = 90;}else if ((a < 0) && (b > 0))    // 判断road点在user点的西北位置{cosy = fabs(a) / c;angle = 270;}else if ((a < 0) && (b == 0))   //在正西位置{angle = 180;}double m = acos(cosy);//n 即以正北为 0 的总角度double n = (m / pi) * 180 + angle;return n;
}

这篇关于机场跑道入侵检测(C++、Qt)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/166965

相关文章

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

C/C++ chrono简单使用场景示例详解

《C/C++chrono简单使用场景示例详解》:本文主要介绍C/C++chrono简单使用场景示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录chrono使用场景举例1 输出格式化字符串chrono使用场景China编程举例1 输出格式化字符串示

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一