实现雷达扫描图,主要难点在于扫面目标这块。
当前提供两种方法:1、弧度法;2、等比三角。
1、弧度法:会使用到atan、atan2、qAtan、qAtan2。其中atan和atan2、QAtan和QAtan2它们区别在于atan、qAtan它弧度的范围是[-PI/2,PI/2],atan2、qAtan2它的弧度范围是[-PI,PI];我们得到弧度后将它转换为角度,然后通过角度来进行比较。弧度转角度,只需要”*180/PI“就可以实现转换。
2、等比三角:就是两个三角形,A三角形它的边长为abc;B三角形它的边长为efg。且a/e = b/f = c/g,我们进行扫描时,目标位置会与扫描线构成一对等比三角形,所以凡是符合这个公式的就能判断目标位置在扫描线上。
qFloor 向下取整
qCeil 向上取整
qRound 四舍五入
代码示例:完整代码
void Widget::paintEvent(QPaintEvent *event)
{
#if 1
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QString pixpath = QApplication::applicationDirPath()+"/世界地图.jfif";
painter.drawPixmap(0,0,width(),height(),QPixmap(pixpath));
painter.setPen(Qt::white);
painter.drawLine(QPoint(width()/2,0),QPoint(width()/2,height()));
painter.drawLine(QPoint(0,height()/2),QPoint(width(),height()/2));
painter.translate(width()/2,height()/2);
painter.setPen(Qt::white);
painter.drawEllipse(QPoint(0,0),width()/2,height()/2);
painter.drawEllipse(QPoint(0,0),width()/4,height()/4);
painter.drawEllipse(QPoint(0,0),width()/8,height()/8);
painter.drawEllipse(QPoint(0,0),width()/16,height()/16);
painter.drawEllipse(QPoint(0,0),width()/32,height()/32);
//余晖扫描
// int len = m_drawArea.width();
double x = width()/2 * cos(m_pieRotate*PI/180);
double y = height()/2 * sin(m_pieRotate*PI/180);
painter.setPen(QPen(Qt::green));
painter.drawLine(QPoint( 0, 0 ),QPointF(x,y));
//扇形
QConicalGradient gradient;
gradient.setCenter(QPoint( 0, 0 ));
gradient.setAngle(-m_pieRotate + 180); //渐变与旋转方向恰好相反,以扇形相反的边作为渐变角度。
gradient.setColorAt(0.4,QColor(169,253,51,100)); //从渐变角度开始0.5 - 0.75为扇形区域,由于Int类型计算不精确,将范围扩大到0.4-0.8
gradient.setColorAt(0.8,QColor(169,253,51,0));
painter.setBrush(QBrush(gradient));
painter.setPen(Qt::NoPen);
painter.drawPie(-width()/2,-height()/2,width(),height(),-m_pieRotate*16,90*16);
//目标圆位置
QPointF p1(0,0); //扫描线起点坐标
QPointF p2(x,y); //扫描线终点坐标
for (int i = 0; i < m_desPoints.size(); ++i) {
QPointF Q = m_desPoints[i];
#if 1
scanRegion1(painter,Q,p1,p2,i);
#else
scanRegion2(painter,Q,p1,p2,i);
#endif
}
#endif
}
void Widget::scanRegion1(QPainter &painter,QPointF Q,QPointF p1,QPointF p2,int index)
{
double s1 = atan2(Q.y(),Q.x())*180/PI;
double s2 = atan2(p2.y(),p2.x())*180/PI;
painter.save();
painter.translate(Q);
painter.rotate(2*m_pieRotate);
//按照弧度来计算,此处求弧度的方法atan、atan2、qAtan、qAtan2。
//atan弧度范围[-PI/2,PI/2]、atan2弧度范围[-PI,PI]
if (s1 <= s2 && s1 >= s2 - ShowRange) //判断一个返回内出现的目标。
// if (s2 >= qFloor(s1) && s2 <= qCeil(s1)) //判断扫描线上出现的目标
{
painter.setPen(Qt::green);
painter.setBrush(QBrush(QColor(255,255,255,50)));
QPointF P = QPointF(0,0); //移到坐标原点,配合rotate实现自转。
painter.drawEllipse(P,maxSize,maxSize);
painter.drawRect(P.x()-(maxSize+4)/2,P.y()-(maxSize+4)/2,maxSize+4,maxSize+4);
painter.drawText(P.x()-(maxSize+4)/2,P.y()-(maxSize+4)/2,maxSize+4,maxSize+4,Qt::AlignCenter,QString::number(index));
}
else
{
painter.setPen(Qt::red);
painter.setBrush(QBrush(QColor(255,255,255,50)));
QPointF P = QPointF(0,0); //移到坐标原点,配合rotate实现自转。
painter.drawEllipse(P,NoalmalSize,NoalmalSize);
painter.drawRect(P.x()-(NoalmalSize+4)/2,P.y()-(NoalmalSize+4)/2,NoalmalSize+4,NoalmalSize+4);
}
painter.restore();
}
void Widget::scanRegion2(QPainter &painter,QPointF Q,QPointF p1,QPointF p2,int index)
{
painter.save();
painter.translate(Q);
painter.rotate(2*m_pieRotate);
// 叉积公式:(Q - P1) * (P2 - P1)= 0 判断Q点是否在点P1到P2的线段上
// (Q.x - P1.x) * (P2.y - P1.y) == (P2.x - P1.x) * (Q.y - P1.y)
// int val = (Q.x() - p1.x())*(p2.y() - p1.y()) - (p2.x() - p1.x())*(Q.y() - p1.y());
//等比 三角形A(边abc)和三角形B(边efg)是等比三角形,所以a/e = b/f = c/g.扫描线和出现在扫描线上的坐标点构成等比三角形。
double val = (Q.x() - p1.x())/(p2.x() - p1.x()) - (Q.y() - p1.y())/(p2.y() - p1.y());
// qDebug()<<val;
if ( val<= 0.1 && val >= -0.1
&& qMin(p1.x() , p2.x()) <= Q.x() && Q.x() <= qMax(p1.x() , p2.x())
&& qMin(p1.y() , p2.y()) <= Q.y() && Q.y() <= qMax(p1.y() , p2.y()))
{
painter.setPen(Qt::green);
painter.setBrush(QBrush(QColor(255,255,255,50)));
QPointF P = QPointF(0,0); //移到坐标原点,配合rotate实现自转。
painter.drawEllipse(P,maxSize,maxSize);
painter.drawRect(P.x()-(maxSize+4)/2,P.y()-(maxSize+4)/2,maxSize+4,maxSize+4);
painter.drawText(P.x()-(maxSize+4)/2,P.y()-(maxSize+4)/2,maxSize+4,maxSize+4,Qt::AlignCenter,QString::number(index));
}
else
{
painter.setPen(Qt::red);
painter.setBrush(QBrush(QColor(255,255,255,50)));
QPointF P = QPointF(0,0); //移到坐标原点,配合rotate实现自转。
painter.drawEllipse(P,NoalmalSize,NoalmalSize);
painter.drawRect(P.x()-(NoalmalSize+4)/2,P.y()-(NoalmalSize+4)/2,NoalmalSize+4,NoalmalSize+4);
}
painter.restore();
}