URL
https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk
Subversion Repositories riscv_vhdl
[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [gui_plugin/] [GnssWidgets/] [MapWidget.cpp] - Rev 4
Compare with Previous | Blame | View Log
#include "MapWidget.h" #include "moc_MapWidget.h" #include <math.h> namespace debugger { /** Start marker of GNSS raw measurements that receiver generates in JSON * format. */ const Reg64Type MAGIC_GNSS = {"{'Epoch"}; /** Test points that will shown even if no position availbale */ QPointF defaultPos[] = { {55.929967, 37.516868}, // MIPT, Dolgoprudniy (Moscow area) {37.871853, -122.258423}, // University of California, Berkely {59.336187, 18.068777} // Sweden, Gaisler (Leon3) office location }; MapWidget::MapWidget(IGui *igui, QWidget *parent) : QWidget(parent) { igui_ = igui; gnssIsParsing_ = false; bNewDataAvailable = true; pressed = false; invert = false; m_normalMap = new StreetMap(this, 17); m_miniMap = new StreetMap(this, 12); // This signal force redrawing when new data were downloaded connect(m_normalMap, SIGNAL(signalTilesUpdated(QRect)), this, SLOT(slotTilesUpdated(QRect))); connect(m_miniMap, SIGNAL(signalTilesUpdated(QRect)), this, SLOT(slotTilesUpdated(QRect))); connect(this, SIGNAL(signalRequestNetworkData()), m_normalMap, SLOT(slotRequestNetworkData())); connect(this, SIGNAL(signalRequestNetworkData()), m_miniMap, SLOT(slotRequestNetworkData())); setFocusPolicy(Qt::ClickFocus); contextMenu = new QMenu(this); contextMenu->addAction(tr("Clear"), this, SLOT(slotActionClear())); contextMenu->addAction(tr("Nightmode"), this, SLOT(slotActionNightMode())); setContextMenuPolicy(Qt::CustomContextMenu); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(slotRightClickMenu(const QPoint &))); connect(this, SIGNAL(signalUpdateGnssRaw()), SLOT(slotUpdateGnssRaw())); setWindowTitle(tr("Map")); posinfoSize = QSize(340, 200); posinfoPixmap = QPixmap(posinfoSize); const AttributeType *cfg = igui_->getpConfig(); const AttributeType &serial_name = (*cfg)["Serial"]; if (serial_name.is_string()) { uart_ = static_cast<ISerial *> (RISCV_get_service_iface(serial_name.to_string(), IFACE_SERIAL)); if (uart_) { uart_->registerRawListener(static_cast<IRawListener *>(this)); } } QDateTime sd = QDateTime::currentDateTime(); qsrand(sd.toTime_t()); int pos_init_idx = qrand() % static_cast<int>(sizeof(defaultPos)/sizeof(QPointF)); #if 0 pos_init_idx = 0; double lat = defaultPos[pos_init_idx].x() + (double)(rand() & 0x1f)/100000.0; double lon = defaultPos[pos_init_idx].y()+ (double)(rand() & 0x1f)/100000.0; for (int x = 0; x < 50; x++) { gpsLat_.put(lat); gpsLon_.put(lon); lat = defaultPos[pos_init_idx].x() + (double)(rand() & 0x1f)/100000.0; lon = defaultPos[pos_init_idx].y() + (double)(rand() & 0x1f)/100000.0; } #endif m_normalMap->setCenterCoord(defaultPos[pos_init_idx]); m_miniMap->setCenterCoord(defaultPos[pos_init_idx]); } MapWidget::~MapWidget() { if (uart_) { uart_->unregisterRawListener(static_cast<IRawListener *>(this)); } } void MapWidget::updateData(const char *buf, int buflen) { for (int i = 0; i < buflen; i++) { gnssMagicNumber_.buf[7] = buf[i]; gnssMagicNumber_.val >>= 8; if (!gnssIsParsing_) { if (gnssMagicNumber_.val == MAGIC_GNSS.val) { memcpy(gnssBuf_, MAGIC_GNSS.buf, 8); gnssBufCnt_ = 7; gnssBraceCnt_ = 1; gnssIsParsing_ = true; } continue; } gnssBuf_[gnssBufCnt_++] = buf[i]; gnssBuf_[gnssBufCnt_] = '\0'; if (buf[i] == '{') { gnssBraceCnt_++; continue; } if (buf[i] != '}') { continue; } if (--gnssBraceCnt_ == 0) { gnssIsParsing_ = false; gnssRawMeas_.from_config(gnssBuf_); emit signalUpdateGnssRaw(); } } } void MapWidget::slotUpdateGnssRaw() { if (!gnssRawMeas_.is_dict()) { return; } AttributeType &gps = gnssRawMeas_["GPS"]; if (!gps.is_dict()) { return; } AttributeType &lms = gps["LMS"]; if (!lms.is_list() || lms.size() < 8) { return; } if (lms[0u].to_int() == 0) { return; } double lat, lon; lat = static_cast<double>(lms[1].to_int()); lat += lms[2].to_float() / 60.0; if (lms[3].is_equal("S")) { lat = -lat; } lon = static_cast<double>(lms[4].to_int()); lon += lms[5].to_float() / 60.0; if (lms[6].is_equal("W")) { lon = -lon; } if (lat == 0 || lon == 0) { return; } gpsLat_.put(lat); gpsLon_.put(lon); if (!pressed) { QPointF coord(gpsLat_.get_avg(), gpsLon_.get_avg()); m_normalMap->setCenterCoord(coord); m_miniMap->setCenterCoord(coord); } emit signalRequestNetworkData(); } void MapWidget::slotTilesUpdated(QRect rect) { renderAll(); update(); } void MapWidget::slotActionClear() { //for (int i=0; i<DataTotal; i++) { //pPosTrack[i]->clear(); //} gpsLat_.clear(); gpsLon_.clear(); renderAll(); update(); } void MapWidget::slotActionNightMode() { invert = !invert; renderAll(); update(); } void MapWidget::slotRightClickMenu(const QPoint &p) { QPoint globalPos = mapToGlobal(p); //contextMenu->exec(globalPos); contextMenu->popup(globalPos); } void MapWidget::resizeEvent(QResizeEvent *ev) { if (ev->size().height() == 0 || ev->size().width() == 0) { // Warning: When window inactive the height=0 return; } mainmapSize = ev->size(); int w = mainmapSize.width(); int h = mainmapSize.height(); m_normalMap->resize(w, h); int square_sz = qMin((2*w)/5, (2*h)/5); minimapSize = QSize(square_sz, square_sz); m_miniMap->resize(square_sz, square_sz); renderAll(); update(); if (bNewDataAvailable) { bNewDataAvailable = false; emit signalRequestNetworkData(); } } void MapWidget::renderAll() { renderMinimap(); renderMainMap(); // Rendering of the mainMap will cause update signal } void MapWidget::renderMainMap() { // only set the dimension to the magnified portion if (mainmapPixmap.size() != mainmapSize) { mainmapPixmap = QPixmap(mainmapSize); mainmapPixmap.fill(Qt::lightGray); } QPainter p_map(&mainmapPixmap); m_normalMap->render(&p_map, QRect(QPoint(0,0), mainmapSize)); p_map.setPen(Qt::black); p_map.drawText(rect(), Qt::AlignBottom | Qt::TextWordWrap, tr("Map data CCBYSA 2017 OpenStreetMap.org contributors")); // Draw Position track: p_map.translate(20,20); fontPos.setPixelSize(16); p_map.setFont(fontPos); renderTrack(0, p_map); p_map.end(); } void MapWidget::renderTrack(int trkIdx, QPainter &p) { // Draw semi-transparent background for coordinates output: QColor trackLineColor(tr("#008F8F")); QColor trackPointColor(tr("#004848")); QColor trackTextColor; QPen pointPen(trackPointColor, 0, Qt::SolidLine, Qt::RoundCap); trackLineColor.setAlpha(0xa0); trackPointColor.setAlpha(0xa0); QPen linePen = QPen(trackLineColor, 0, Qt::SolidLine, Qt::RoundCap); p.setPen(pointPen); p.setRenderHint(QPainter::Antialiasing); QPoint xy; double lat = gpsLat_.getp()[0]; double lon = gpsLon_.getp()[0]; QPoint xy0 = m_normalMap->coordToPixpos(QPointF(lat, lon)); p.drawLine(xy0.x() - 2, xy0.y(), xy0.x() + 2, xy0.y()); p.drawLine(xy0.x(), xy0.y() + 2, xy0.x(), xy0.y() - 2); for (int i = 0; i < gpsLat_.size(); i++) { lat = gpsLat_.getp()[i]; lon = gpsLon_.getp()[i]; xy = m_normalMap->coordToPixpos(QPointF(lat, lon)); p.setPen(linePen); p.drawLine(xy0.x(), xy0.y(), xy.x(), xy.y()); xy0 = xy; p.setPen(pointPen); p.drawLine(xy0.x() - 2, xy0.y(), xy0.x() + 2, xy0.y()); p.drawLine(xy0.x(), xy0.y() + 2, xy0.x(), xy0.y() - 2); } QString strPosition; strPosition.sprintf("GPS LMS: Lat %.4f; Lon %.4f", lat, lon); int h = p.fontMetrics().size(Qt::TextSingleLine, strPosition).height(); QRect rect = QRect(QPoint(0, trkIdx * (h + 5)), QPoint(340, (trkIdx + 1) * (h + 5))); p.fillRect(rect, QBrush(QColor(128, 128, 128, 128))); // Draw axis line template: int marginy = trkIdx*(h + 5)/2; int startx = 5; int starty = marginy + (h + 5)/2; int endx = 30; int endy = marginy + (h + 5)/2; p.setPen(linePen); p.drawLine(startx, starty, endx, endy); p.setPen(pointPen); p.drawLine(startx - 2, starty, startx + 2, starty); p.drawLine(startx, starty + 2, startx, starty - 2); p.drawLine(endx - 2, endy, endx + 2, endy); p.drawLine(endx, endy + 2, endx, endy - 2); trackTextColor.setRgb(0xff, 0xff, 0xff, 0xc0); p.setPen(trackTextColor); p.drawText(endx + 6, h + trkIdx*(h + 5) + 1, strPosition); trackTextColor.setRgb(0x20, 0x20, 0x20, 0xff); p.setPen(trackTextColor); p.drawText(endx + 5, h + trkIdx*(h + 5), strPosition); } void MapWidget::renderPosInfo(QPainter &p) { QString info, strTmp; /*for (int i=0; i<POS_Total; i++) { if (PosTrack[i].ena == false) continue; strTmp.sprintf("%s: \n", PosTrack[i].name.c_str()); info += strTmp; }*/ QSize infoSize = p.fontMetrics().size(Qt::TextDontClip, info); QPoint infoPos = QPoint(10, 10); QRect infoRect = QRect(infoPos, infoSize); p.fillRect(infoRect, QBrush(QColor(0xff, 0xef, 0xd5, 0x80))); /* int sz = pPosTrack[type]->size(); QColor clr = getDataColor(type); p.setPen(QPen(clr, 2, Qt::SolidLine, Qt::RoundCap)); p.setRenderHint(QPainter::Antialiasing); */ } void MapWidget::renderMinimap() { if (minimapSize.width() == 0 || minimapSize.height() == 0) { // At the beging there occurs strange resizeEvent() return; } // 1/2 x 1/2 of the main screen width: int w = mainmapSize.width(); int h = mainmapSize.height(); if (w == 0 || h == 0) return; int square_sz = m_miniMap->getWidth(); // always square: height = width minimapRadius = square_sz/2; // minimapInnerRadius = minimapRadius - 15; minimapSize = QSize(square_sz, square_sz); minimapPosition = QPoint(w - square_sz, h - square_sz); minimapCenter = minimapPosition + QPoint(minimapRadius, minimapRadius); // reupdate our mask if (minimapPixmapMask.size() != minimapSize) { minimapPixmapMask = QPixmap(minimapSize); minimapPixmapMask.fill(Qt::transparent); QRadialGradient g; g.setCenter(minimapRadius, minimapRadius); g.setFocalPoint(minimapRadius, minimapRadius); g.setRadius(minimapRadius); g.setColorAt(1.0, QColor(255, 255, 255, 0)); g.setColorAt(0.5, QColor(128, 128, 128, 255)); QPainter mask(&minimapPixmapMask); mask.setRenderHint(QPainter::Antialiasing); mask.setCompositionMode(QPainter::CompositionMode_Source); mask.setBrush(g); mask.setPen(Qt::NoPen); mask.drawRect(minimapPixmapMask.rect()); mask.setBrush(QColor(Qt::transparent)); mask.drawEllipse(g.center(), minimapInnerRadius, minimapInnerRadius); mask.end(); } // only set the dimension to the magnified portion if (minimapPixmap.size() != minimapSize) { minimapPixmap = QPixmap(minimapSize); minimapPixmap.fill(Qt::lightGray); } QPainter p_map(&minimapPixmap); m_miniMap->render(&p_map, QRect(QPoint(0,0), minimapSize)); // Draw small view area: p_map.setPen(Qt::red); QRectF border = m_normalMap->getBorderCoord(); QRect view = m_miniMap->coordToPixpos(border); //view.translate(minimapPosition); p_map.drawLine(view.topLeft(), view.topRight()); p_map.drawLine(view.topRight(), view.bottomRight()); p_map.drawLine(view.bottomRight(), view.bottomLeft()); p_map.drawLine(view.bottomLeft(), view.topLeft()); p_map.end(); } void MapWidget::paintEvent(QPaintEvent *event) { QPainter p; p.begin(this); // Main Map: p.drawPixmap(QPoint(0,0), mainmapPixmap); // Painting minimap: p.setRenderHint(QPainter::Antialiasing); QPainterPath clipPath; clipPath.addEllipse(minimapCenter, minimapInnerRadius, minimapInnerRadius); p.setClipPath(clipPath); p.drawPixmap(minimapPosition, minimapPixmap); p.setClipping(false); p.drawPixmap(minimapPosition, minimapPixmapMask); //renderPosInfo(p); p.setPen(Qt::gray); p.drawPath(clipPath); if (invert) { p.setCompositionMode(QPainter::CompositionMode_Difference); p.fillRect(event->rect(), Qt::white); } p.end(); } void MapWidget::mousePressEvent(QMouseEvent *event) { setFocus(); if (event->buttons() != Qt::LeftButton) return; pressed = true; pressPos = event->pos(); } void MapWidget::mouseMoveEvent(QMouseEvent *event) { if (!event->buttons()) return; if (pressed) { QPoint delta = event->pos() - pressPos; pressPos = event->pos(); m_normalMap->pan(delta); m_miniMap->setCenterCoord(m_normalMap->getCenterCoord()); // Warning: // It will draw tiles that were already downloaded, others will be empty. // Network request will on button release renderAll(); update(); } } void MapWidget::mouseReleaseEvent(QMouseEvent *) { pressed = false; emit signalRequestNetworkData(); } void MapWidget::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Plus: if (m_normalMap->getZoom() < 19) { m_normalMap->setZoom(m_normalMap->getZoom()+1); m_normalMap->pan(QPoint()); emit signalRequestNetworkData(); } break; case Qt::Key_Minus: if (m_normalMap->getZoom() > 15) { m_normalMap->setZoom(m_normalMap->getZoom()-1); m_normalMap->pan(QPoint()); emit signalRequestNetworkData(); } break; default:; } } } // namespace debugger