#include "fm_360_position_view.h" #if (USE_360_POSITION_VIEW) #include #include #include #include #define POS_VIEW_SIZE 80 #define POS_VIEW_RIGHT_MARGIN 83 #define POS_VIEW_OFFSET 10 FM360PositionView::FM360PositionView(QWidget *parent) : QWidget(parent) { setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); //setFixedSize(POS_VIEW_SIZE,POS_VIEW_SIZE); _ax = 0.0; _ay = 0.0; } void FM360PositionView::setAngle(double ax,double ay) { //qInfo() << _ax << _ay << __FUNCTION__; _ax = ax; _ay = ay; update(); } void FM360PositionView::map_to_custom_angles(double x, double y, double *ax, double* ay) { // 0.0~1.0 => -1.0~1.0 로 변경 double X = (x-0.5) * 2.0; double Y = (y-0.5) * 2.0; const double M_PI = 3.14159265359f; // 2. Yaw (Z축 기준의 좌우 각도) 계산 // atan2(Y, X)를 사용하여 -PI ~ PI 라디안 값 획득 // 각도는 x축의 양의 방향(오른쪽)을 0∘ 로 하여 반시계 방향으로 0∘에서 360∘까지 측정됨 double yaw = atan2(-Y, X); // 라디안을 도로 변환하고, 0 ~ 360도 범위로 조정 yaw = yaw * 180.0 / M_PI; if (yaw < 0.0) { yaw += 360.0; } yaw = 90.0 - yaw; // 시계 방향 각도로 변환 (Y축(90도)을 0도로 기준 잡기 위해 90에서 뺌) if (yaw < 0.0) { yaw += 360.0; } *ax = yaw; // 3. Pitch = 거리 계산 double pitch_90_deg; double horizontal_dist = sqrt(X * X + Y * Y); if(horizontal_dist > 1.0) { horizontal_dist = 1.0; } pitch_90_deg = (horizontal_dist * 70.0) + 270.0; *ay = pitch_90_deg; } void FM360PositionView::mouseDoubleClickEvent(QMouseEvent *e) { QRect pr = _posRect(); // 마우스 클릭용으로 POS_VIEW_OFFSET 제거한 큰 영역 const int margin = 10; QRect containRect = pr.adjusted(-margin,-margin,margin,margin); if(containRect.contains(e->pos())) { e->accept(); return; } QWidget::mouseDoubleClickEvent(e); } void FM360PositionView::mouseReleaseEvent(QMouseEvent *e) { QRect pr = _posRect(); // 마우스 클릭용으로 POS_VIEW_OFFSET 제거한 큰 영역 const int margin = 10; QRect containRect = pr.adjusted(-margin,-margin,margin,margin); if(containRect.contains(e->pos())) { const double ex = (double)(e->pos().x() - pr.left()) / (double)pr.width(); const double ey = (double)(e->pos().y() - pr.top()) / (double)pr.height(); double yaw, pitch; //convert_2d_to_yaw_pitch(ex,ey,&yaw,&pitch); map_to_custom_angles(ex,ey,&yaw,&pitch); //qInfo() << "yaw.pitch:" << yaw << pitch << __FUNCTION__; //pitch = 340.0; setAngle(yaw,pitch); emit angleUpdated(yaw,pitch); } else { // 네비게이션 클릭시 하위에 클릭 이벤트 발생시키지 않는다.. QWidget::mouseReleaseEvent(e); } } QRect FM360PositionView::_posRect() { const int lx = size().width() - POS_VIEW_RIGHT_MARGIN; const int end = POS_VIEW_SIZE-(POS_VIEW_OFFSET*2); // 실제 영역 return QRect(lx+POS_VIEW_OFFSET, POS_VIEW_OFFSET, end, end); } void FM360PositionView::paintEvent(QPaintEvent *pe) { Q_UNUSED(pe) const int lx = size().width() - POS_VIEW_RIGHT_MARGIN; //const QColor color = QColor(0xCC, 0x99, 0x33, 0xCC); const QColor color = QColor(0xFF, 0xCC, 0x33, 0xCC); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); const int width = 3; QPen pen = QPen(color,width, Qt::SolidLine); //QPen pen = QPen(color,width, Qt::SolidLine); painter.setPen(pen); //const int offset = POS_VIEW_OFFSET; const int end = POS_VIEW_SIZE-(POS_VIEW_OFFSET*2); painter.drawEllipse(QRect(lx+POS_VIEW_OFFSET, POS_VIEW_OFFSET, end, end)); //painter.drawRect(QRect(lx+offset, offset, end, end)); painter.drawLine(lx+POS_VIEW_SIZE/2, POS_VIEW_OFFSET + width,lx+POS_VIEW_SIZE/2, POS_VIEW_SIZE-POS_VIEW_OFFSET-width); painter.drawLine(lx+POS_VIEW_OFFSET+width,POS_VIEW_SIZE/2,lx+POS_VIEW_SIZE-POS_VIEW_OFFSET-width,POS_VIEW_SIZE/2); const double DEG_PI = 3.14159265359f; double r = ((_ay- 200.0) / 140.0) - 0.5; // 340~200 => -0.5~0.5 double xoffset = 270; if(r < 0.0) { xoffset += 180; } double seta = ((_ax+xoffset) * DEG_PI / 180.0); r = abs(r) * 2.0; // 0.0~1.0 const double hsize = POS_VIEW_SIZE/2; const double x = (cos(seta) * r * (hsize*0.7)) + hsize; // -1.0~1.0 => 0~POS_VIEW_SIZE const double y = (sin(seta) * r * (hsize*0.7)) + hsize; // -1.0~1.0 => 0~POS_VIEW_SIZE const int csize = 9;//12; QColor white = QColor(0xFF, 0xFF, 0xFF); painter.setPen(Qt::NoPen); painter.setBrush(white); // QColor(0xCC, 0x99, 0x33, 0xA0) QRect rect = QRect(lx+x-csize,y-csize,(csize*2),(csize*2)); painter.drawEllipse(rect); //qInfo() << "XY:" << x << y << "RP:" << _ax << _ay << "R:" << r << __FUNCTION__; } FM360StaticPositionView::FM360StaticPositionView(QWidget *parent) : QWidget(parent) { setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); ptl = QPixmap(":/image/cam_01.png"); ptr = QPixmap(":/image/cam_02.png"); pbr = QPixmap(":/image/cam_04.png"); // 2025/10/15 표지 변경 -> 2026/01/08 다시 변경 pbl = QPixmap(":/image/cam_03.png"); // pc = QPixmap(":/image/cam_center.png"); } void FM360StaticPositionView::setMode(int mode) { _mode = mode; //qInfo() << _mode << __FUNCTION__; } void FM360StaticPositionView::paintEvent(QPaintEvent *pe) { Q_UNUSED(pe) if(_mode == 0) { return; } // //_mode : 1=4분할, 4=5분할 if(_mode == 1) { // 4분할 QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); const int width = 42; const int height = 42; const int xOffset = 10; const int yOffset = 10; const int hw = size().width() / 2; const int hh = size().height() / 2; QRect tl = QRect(hw-width-xOffset,hh - height - yOffset,width,height); painter.drawPixmap(tl, ptl); //QRect tr = QRect((hw*2)-width-xOffset,yOffset,width,height); QRect tr = QRect(hw+xOffset,hh - height - yOffset,width,height); painter.drawPixmap(tr, ptr); QRect bl = QRect(hw-width-xOffset,hh + yOffset,width,height); painter.drawPixmap(bl, pbl); //QRect br = QRect((hw*2)-width-xOffset,hh + yOffset,width,height); QRect br = QRect(hw+xOffset,hh + yOffset,width,height); painter.drawPixmap(br, pbr); painter.end(); } else if (_mode == 4) { // 5분할 QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); #if (MULTI_5CH_LR) const float leftArea = 0.5f; const int bwidth = (int)(((float)size().width()) * ((1.0f - leftArea) * 0.5f)); // 좌측영역 PX const int left = (int)(((float)size().width()) * leftArea); QRect cr = QRect(left-84-10,10,84,84); painter.drawPixmap(cr, pc); const int width = 42; const int height = 42; const int xOffset = 3; const int yOffset = 3; const int left2 = left + bwidth; const int hOffset = (int)((float)size().height() * (float)0.5f); //QRect tl = QRect(left+bwidth-width-xOffset,yOffset,width,height); QRect tl = QRect(left+bwidth-width-xOffset,hOffset - height - yOffset,width,height); painter.drawPixmap(tl, ptl); //QRect tr = QRect(left2+bwidth-width-xOffset,yOffset,width,height); QRect tr = QRect(left+bwidth+xOffset,hOffset - height - yOffset,width,height); painter.drawPixmap(tr, ptr); QRect bl = QRect(left+bwidth-width-xOffset,hOffset+yOffset,width,height); painter.drawPixmap(bl, pbl); //QRect br = QRect(left2+bwidth-width-xOffset,hOffset+yOffset,width,height); QRect br = QRect(left+bwidth+xOffset,hOffset+yOffset,width,height); painter.drawPixmap(br, pbr); #else // !MULTI_5CH_LR QRect cr = QRect(size().width()-84-10,10,84,84); painter.drawPixmap(cr, pc); const int width = 42; const int height = 42; const int xOffset = 3; const int yOffset = 3; const int qw = size().width() / 4; const int hOffset = (int)((float)size().height() * (float)0.75f); QRect tl = QRect((qw * 1)-width-xOffset,hOffset+yOffset,width,height); painter.drawPixmap(tl, ptl); QRect tr = QRect((qw * 2)-width-xOffset,hOffset+yOffset,width,height); painter.drawPixmap(tr, ptr); QRect bl = QRect((qw * 3)-width-xOffset,hOffset+yOffset,width,height); painter.drawPixmap(bl, pbl); QRect br = QRect((qw * 4)-width-xOffset,hOffset+yOffset,width,height); painter.drawPixmap(br, pbr); #endif // #else // !MULTI_5CH_LR painter.end(); } } #endif // #if (USE_360_POSITION_VIEW)