X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FGUI%2FBaseDiagram.cxx;h=fa593f8b7cdcc5353bdfea0d233173b5914ece1a;hb=4befe0e6ea6b5f21119364f1175a0b6c8e97395c;hp=0db4a88c1f63918be42b5f3dfe12ef57a76ac202;hpb=5fd350cb3d410c2873fa88d867c8d991f5a3254d;p=flightgear.git diff --git a/src/GUI/BaseDiagram.cxx b/src/GUI/BaseDiagram.cxx index 0db4a88c1..fa593f8b7 100644 --- a/src/GUI/BaseDiagram.cxx +++ b/src/GUI/BaseDiagram.cxx @@ -30,11 +30,16 @@ #include #include #include +#include + +#include "QtLauncher_fwd.hxx" /* equatorial and polar earth radius */ const float rec = 6378137; // earth radius, equator (?) const float rpol = 6356752.314f; // earth radius, polar (?) +const double MINIMUM_SCALE = 0.002; + //Returns Earth radius at a given latitude (Ellipsoide equation with two equal axis) static float earth_radius_lat( float lat ) { @@ -110,6 +115,8 @@ void BaseDiagram::paintEvent(QPaintEvent* pe) QTransform t(transform()); p.setTransform(t); + paintPolygonData(&p); + paintNavaids(&p); paintContents(&p); @@ -130,33 +137,139 @@ void BaseDiagram::paintAirplaneIcon(QPainter* painter, const SGGeod& geod, int h painter->drawPixmap(airplaneIconRect, pix); } +void BaseDiagram::paintPolygonData(QPainter* painter) +{ + QTransform xf = painter->transform(); + QTransform invT = xf.inverted(); + + SGGeod topLeft = unproject(invT.map(rect().topLeft()), m_projectionCenter); + SGGeod viewCenter = unproject(invT.map(rect().center()), m_projectionCenter); + SGGeod bottomRight = unproject(invT.map(rect().bottomRight()), m_projectionCenter); + + double drawRangeNm = std::max(SGGeodesy::distanceNm(viewCenter, topLeft), + SGGeodesy::distanceNm(viewCenter, bottomRight)); + + flightgear::PolyLineList lines(flightgear::PolyLine::linesNearPos(viewCenter, drawRangeNm, + flightgear::PolyLine::COASTLINE)); + + QPen waterPen(QColor(64, 64, 255), 1); + waterPen.setCosmetic(true); + painter->setPen(waterPen); + flightgear::PolyLineList::const_iterator it; + for (it=lines.begin(); it != lines.end(); ++it) { + paintGeodVec(painter, (*it)->points()); + } + + lines = flightgear::PolyLine::linesNearPos(viewCenter, drawRangeNm, + flightgear::PolyLine::URBAN); + for (it=lines.begin(); it != lines.end(); ++it) { + fillClosedGeodVec(painter, QColor(192, 192, 96), (*it)->points()); + } + + lines = flightgear::PolyLine::linesNearPos(viewCenter, drawRangeNm, + flightgear::PolyLine::RIVER); + + painter->setPen(waterPen); + for (it=lines.begin(); it != lines.end(); ++it) { + paintGeodVec(painter, (*it)->points()); + } + + + lines = flightgear::PolyLine::linesNearPos(viewCenter, drawRangeNm, + flightgear::PolyLine::LAKE); + + for (it=lines.begin(); it != lines.end(); ++it) { + fillClosedGeodVec(painter, QColor(128, 128, 255), + (*it)->points()); + } + + +} + +void BaseDiagram::paintGeodVec(QPainter* painter, const flightgear::SGGeodVec& vec) +{ + QVector projected; + projected.reserve(vec.size()); + flightgear::SGGeodVec::const_iterator it; + for (it=vec.begin(); it != vec.end(); ++it) { + projected.append(project(*it)); + } + + painter->drawPolyline(projected.data(), projected.size()); +} + +void BaseDiagram::fillClosedGeodVec(QPainter* painter, const QColor& color, const flightgear::SGGeodVec& vec) +{ + QVector projected; + projected.reserve(vec.size()); + flightgear::SGGeodVec::const_iterator it; + for (it=vec.begin(); it != vec.end(); ++it) { + projected.append(project(*it)); + } + + painter->setPen(Qt::NoPen); + painter->setBrush(color); + painter->drawPolygon(projected.data(), projected.size()); +} + class MapFilter : public FGPositioned::TypeFilter { public: - MapFilter() + + MapFilter(LauncherAircraftType aircraft) { // addType(FGPositioned::FIX); - addType(FGPositioned::AIRPORT); - addType(FGPositioned::HELIPORT); - addType(FGPositioned::SEAPORT); addType(FGPositioned::NDB); addType(FGPositioned::VOR); + + if (aircraft == Helicopter) { + addType(FGPositioned::HELIPAD); + } + + if (aircraft == Seaplane) { + addType(FGPositioned::SEAPORT); + } else { + addType(FGPositioned::AIRPORT); + } } virtual bool pass(FGPositioned* aPos) const { bool ok = TypeFilter::pass(aPos); + // fix-filtering code disabled since fixed are entirely disabled +#if 0 if (ok && (aPos->type() == FGPositioned::FIX)) { // ignore fixes which end in digits if (aPos->ident().length() > 4 && isdigit(aPos->ident()[3]) && isdigit(aPos->ident()[4])) { return false; } } - +#endif return ok; } }; +void BaseDiagram::splitItems(const FGPositionedList& in, FGPositionedList& navaids, + FGPositionedList& ports) +{ + FGPositionedList::const_iterator it = in.begin(); + for (; it != in.end(); ++it) { + if (FGAirport::isAirportType(it->ptr())) { + ports.push_back(*it); + } else { + navaids.push_back(*it); + } + } +} + +bool orderAirportsByRunwayLength(const FGPositionedRef& a, + const FGPositionedRef& b) +{ + FGAirport* aptA = static_cast(a.ptr()); + FGAirport* aptB = static_cast(b.ptr()); + + return aptA->longestRunway()->lengthFt() > aptB->longestRunway()->lengthFt(); +} void BaseDiagram::paintNavaids(QPainter* painter) { @@ -169,85 +282,118 @@ void BaseDiagram::paintNavaids(QPainter* painter) SGGeod viewCenter = unproject(invT.map(rect().center()), m_projectionCenter); SGGeod bottomRight = unproject(invT.map(rect().bottomRight()), m_projectionCenter); - double minRunwayLengthFt = (16 / m_scale) * SG_METER_TO_FEET; - double drawRangeNm = std::max(SGGeodesy::distanceNm(viewCenter, topLeft), SGGeodesy::distanceNm(viewCenter, bottomRight)); - MapFilter f; + MapFilter f(m_aircraftType); FGPositionedList items = FGPositioned::findWithinRange(viewCenter, drawRangeNm, &f); + FGPositionedList navaids, ports; + splitItems(items, navaids, ports); + + if (ports.size() >= 40) { + FGPositionedList::iterator middle = ports.begin() + 40; + std::partial_sort(ports.begin(), middle, ports.end(), + orderAirportsByRunwayLength); + ports.resize(40); + } + m_labelRects.clear(); m_labelRects.reserve(items.size()); FGPositionedList::const_iterator it; - for (it = items.begin(); it != items.end(); ++it) { - FGPositionedRef pos(*it); - bool drawAsIcon = true; - if (isNavaidIgnored(pos)) - continue; - - FGPositioned::Type ty(pos->type()); - if (ty == FGPositioned::AIRPORT) { - FGAirport* apt = static_cast(pos.ptr()); - if (apt->hasHardRunwayOfLengthFt(minRunwayLengthFt)) { - - drawAsIcon = false; - painter->setTransform(xf); - QVector lines = projectAirportRuwaysWithCenter(apt, m_projectionCenter); - - QPen pen(QColor(0x03, 0x83, 0xbf), 8); - pen.setCosmetic(true); - painter->setPen(pen); - painter->drawLines(lines); - - QPen linePen(Qt::white, 2); - linePen.setCosmetic(true); - painter->setPen(linePen); - painter->drawLines(lines); - - painter->resetTransform(); - } - } + for (it = ports.begin(); it != ports.end(); ++it) { + paintNavaid(painter, xf, *it); + } - if (drawAsIcon) { - QPixmap pm = iconForPositioned(pos); - QPointF loc = xf.map(project(pos->geod())); - QRect iconRect = pm.rect(); - iconRect.moveCenter(loc.toPoint()); - painter->drawPixmap(iconRect, pm); - bool isNDB = (ty == FGPositioned::NDB); - - // compute label text so we can measure it - QString label; - if (FGAirport::isAirportType(pos.ptr())) { - label = QString::fromStdString((*it)->name()); - } else { - label = QString::fromStdString((*it)->ident()); - } + for (it = navaids.begin(); it != navaids.end(); ++it) { + paintNavaid(painter, xf, *it); + } - if (ty == FGPositioned::NDB) { - FGNavRecord* nav = static_cast(pos.ptr()); - label.append("\n").append(QString::number(nav->get_freq() / 100)); - } else if (ty == FGPositioned::VOR) { - FGNavRecord* nav = static_cast(pos.ptr()); - label.append("\n").append(QString::number(nav->get_freq() / 100.0, 'f', 1)); - } - QRect textBounds = painter->boundingRect(QRect(0, 0, 100, 100), - Qt::TextWordWrap, label); - int textFlags; - textBounds = rectAndFlagsForLabel(pos->guid(), iconRect, - textBounds.size(), - textFlags); + // restore transform + painter->setTransform(xf); +} - painter->setPen(isNDB ? QColor(0x9b, 0x5d, 0xa2) : QColor(0x03, 0x83, 0xbf)); - painter->drawText(textBounds, textFlags, label); +QRect boundsOfLines(const QVector& lines) +{ + QRect r; + Q_FOREACH(const QLineF& l, lines) { + r = r.united(QRectF(l.p1(), l.p2()).toRect()); + } + + return r; +} + +void BaseDiagram::paintNavaid(QPainter* painter, const QTransform& t, const FGPositionedRef &pos) +{ + if (isNavaidIgnored(pos)) + return; + + bool drawAsIcon = true; + const double minRunwayLengthFt = (16 / m_scale) * SG_METER_TO_FEET; + const FGPositioned::Type ty(pos->type()); + const bool isNDB = (ty == FGPositioned::NDB); + QRect iconRect; + + if (ty == FGPositioned::AIRPORT) { + FGAirport* apt = static_cast(pos.ptr()); + if (apt->hasHardRunwayOfLengthFt(minRunwayLengthFt)) { + + drawAsIcon = false; + painter->setTransform(t); + QVector lines = projectAirportRuwaysWithCenter(apt, m_projectionCenter); + + QPen pen(QColor(0x03, 0x83, 0xbf), 8); + pen.setCosmetic(true); + painter->setPen(pen); + painter->drawLines(lines); + + QPen linePen(Qt::white, 2); + linePen.setCosmetic(true); + painter->setPen(linePen); + painter->drawLines(lines); + + painter->resetTransform(); + + iconRect = t.mapRect(boundsOfLines(lines)); } } - // restore transform - painter->setTransform(xf); + if (drawAsIcon) { + QPixmap pm = iconForPositioned(pos); + QPointF loc = t.map(project(pos->geod())); + iconRect = pm.rect(); + iconRect.moveCenter(loc.toPoint()); + painter->drawPixmap(iconRect, pm); + } + + // compute label text so we can measure it + QString label; + if (FGAirport::isAirportType(pos.ptr())) { + label = QString::fromStdString(pos->name()); + label = fixNavaidName(label); + } else { + label = QString::fromStdString(pos->ident()); + } + + if (ty == FGPositioned::NDB) { + FGNavRecord* nav = static_cast(pos.ptr()); + label.append("\n").append(QString::number(nav->get_freq() / 100)); + } else if (ty == FGPositioned::VOR) { + FGNavRecord* nav = static_cast(pos.ptr()); + label.append("\n").append(QString::number(nav->get_freq() / 100.0, 'f', 1)); + } + + QRect textBounds = painter->boundingRect(QRect(0, 0, 100, 100), + Qt::TextWordWrap, label); + int textFlags; + textBounds = rectAndFlagsForLabel(pos->guid(), iconRect, + textBounds.size(), + textFlags); + + painter->setPen(isNDB ? QColor(0x9b, 0x5d, 0xa2) : QColor(0x03, 0x83, 0xbf)); + painter->drawText(textBounds, textFlags, label); } bool BaseDiagram::isNavaidIgnored(const FGPositionedRef &pos) const @@ -403,12 +549,16 @@ void BaseDiagram::wheelEvent(QWheelEvent *we) m_wheelAngleDeltaAccumulator += delta; if (m_wheelAngleDeltaAccumulator > 120) { m_wheelAngleDeltaAccumulator = 0; - m_scale *= 2.0; + + m_scale *= 1.5; + } else if (m_wheelAngleDeltaAccumulator < -120) { m_wheelAngleDeltaAccumulator = 0; - m_scale *= 0.5; + + m_scale *= 0.75; } + SG_CLAMP_RANGE(m_scale, MINIMUM_SCALE, 1.0); update(); } @@ -626,6 +776,12 @@ QVector BaseDiagram::projectAirportRuwaysWithCenter(FGAirportRef apt, co return r; } +void BaseDiagram::setAircraftType(LauncherAircraftType type) +{ + m_aircraftType = type; + update(); +} + QVector BaseDiagram::projectAirportRuwaysIntoRect(FGAirportRef apt, const QRectF &bounds) { QVector r = projectAirportRuwaysWithCenter(apt, apt->geod());