Skip to content

Commit

Permalink
[FEATURE] Add more airport congestion options - glow and size.
Browse files Browse the repository at this point in the history
This adds a new visualization ("glow") to airport traffic/congestion. It
can be enabled alone or together with the existing ("ring").

It adds the option to configure radius and color separately for a
minimum and a maximum congestion. For values in between the result is
interpolated and above it is clamped to the given values for maximum.

Planes with status "taxiing in" and "blocked" are now ignored for
the filtered (default for {traffic} label content) congestion numbers.

The configurable default "minimum movements" has been raised to 20 to
account for the higher traffic levels.
  • Loading branch information
jonaseberle committed Jun 14, 2023
1 parent 04fbd00 commit 9fa116f
Show file tree
Hide file tree
Showing 15 changed files with 855 additions and 256 deletions.
1 change: 0 additions & 1 deletion README.md
Expand Up @@ -20,7 +20,6 @@ QuteScoop is a status indicator for the online flight simulation community VATSI

![Plot routes](docs/images/plotRoute.jpg)


[More screenshots](https://github.com/qutescoop/qutescoop/tree/master/docs/images)

Its unique "Time Warp" feature lets you see booked controllers and the traffic
Expand Down
10 changes: 5 additions & 5 deletions src/Airport.cpp
Expand Up @@ -137,8 +137,8 @@ void Airport::resetWhazzupStatus() {
arrivals.clear();
departures.clear();

numFilteredArrivals = 0;
numFilteredDepartures = 0;
nMaybeFilteredArrivals = 0;
nMaybeFilteredDepartures = 0;
}

void Airport::addArrival(Pilot* client) {
Expand All @@ -152,7 +152,7 @@ void Airport::addDeparture(Pilot* client) {
}

uint Airport::congestion() const {
return numFilteredArrivals + numFilteredDepartures;
return nMaybeFilteredArrivals + nMaybeFilteredDepartures;
}

void Airport::addController(Controller* c) {
Expand Down Expand Up @@ -315,8 +315,8 @@ const QString Airport::trafficFilteredString() const {
}

return QString("%1/%2").arg(
numFilteredArrivals? QString::number(numFilteredArrivals): "-",
numFilteredDepartures? QString::number(numFilteredDepartures): "-"
nMaybeFilteredArrivals > 0? QString::number(nMaybeFilteredArrivals): "-",
nMaybeFilteredDepartures > 0? QString::number(nMaybeFilteredDepartures): "-"
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Airport.h
Expand Up @@ -64,7 +64,7 @@ class Airport

void addArrival(Pilot* client);
void addDeparture(Pilot* client);
uint numFilteredArrivals, numFilteredDepartures;
uint nMaybeFilteredArrivals, nMaybeFilteredDepartures;

uint congestion() const;

Expand Down
1 change: 1 addition & 0 deletions src/Controller.h
Expand Up @@ -44,6 +44,7 @@ class Controller

QString facilityString() const;
QString typeString() const;

bool isCtrFss() const;
bool isAppDep() const;
bool isTwr() const;
Expand Down
108 changes: 87 additions & 21 deletions src/GLWidget.cpp
Expand Up @@ -298,7 +298,8 @@ void GLWidget::createPilotsList() {

QList<DoublePair> points; // these are the points that really get drawn

if (p->showDepLine() && !qFuzzyIsNull(Settings::depLineStrength())) { // Dep -> plane
// Dep -> plane
if (p->showDepLine() && !qFuzzyIsNull(Settings::depLineStrength()) && !Settings::onlyShowImmediateRoutePart()) {
for (int i = 0; i < next; i++) {
if (!m_usedWaypointMapObjects.contains(waypoints[i])) {
m_usedWaypointMapObjects.append(waypoints[i]);
Expand All @@ -324,7 +325,8 @@ void GLWidget::createPilotsList() {

points.append(DoublePair(p->lat, p->lon));

if (p->showDestLine() && next < waypoints.size()) { // plane -> Dest
// plane -> Dest
if (p->showDestLine() && next < waypoints.size()) {
// immediate
auto destImmediateNm = p->groundspeed * (Settings::destImmediateDurationMin() / 60.);

Expand Down Expand Up @@ -525,32 +527,95 @@ void GLWidget::createAirportsList() {
}
glNewList(_congestionsList, GL_COMPILE);
if (Settings::showAirportCongestion()) {
qglColor(Settings::airportCongestionBorderLineColor());
glLineWidth(Settings::airportCongestionBorderLineStrength());
for (int i = 0; i < airportList.size(); i++) {
if (airportList[i] == 0) {
glPushAttrib(GL_ENABLE_BIT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_1D);
glBindTexture(GL_TEXTURE_1D, _immediateRouteTex);
foreach (const Airport* a, airportList) {
Q_ASSERT(a != 0);
if (!a->active) {
continue;
}
if (!airportList[i]->active) {
int congestion = a->congestion();
if (congestion < Settings::airportCongestionMovementsMin()) {
continue;
}
int congestion = airportList[i]->congestion();
if (congestion < Settings::airportCongestionMinimum()) {
const GLdouble circle_distort = qCos(a->lat * Pi180);
if (qFuzzyIsNull(circle_distort)) {
continue;
}
GLdouble circle_distort = qCos(airportList[i]->lat * Pi180);

const float fraction = qMin<float>(
1.,
Helpers::fraction(
Settings::airportCongestionMovementsMin(),
Settings::airportCongestionMovementsMax(),
a->congestion()
)
);
const GLfloat distanceNm = Helpers::lerp(
Settings::airportCongestionRadiusMin(),
Settings::airportCongestionRadiusMax(),
fraction
);
QList<QPair<double, double> > points;
for (int h = 0; h <= 360; h += 6) {
double x = airportList[i]->lat + Nm2Deg(congestion * 5) * circle_distort * qCos(h * Pi180);
double y = airportList[i]->lon + Nm2Deg(congestion * 5) * qSin(h * Pi180);
double x = a->lat + Nm2Deg(distanceNm) * qCos(h * Pi180);
double y = a->lon + Nm2Deg(distanceNm) / circle_distort * qSin(h * Pi180);
points.append(QPair<double, double>(x, y));
}
glBegin(GL_LINE_LOOP);
for (int h = 0; h < points.size(); h++) {
VERTEX(points[h].first, points[h].second);
qglColor(
Helpers::mixColor(
Settings::airportCongestionColorMin(),
Settings::airportCongestionColorMax(),
fraction
)
);
if (Settings::showAirportCongestionGlow()) {
glBegin(GL_TRIANGLE_FAN);
glTexCoord1f(0.);
VERTEX(a->lat, a->lon);
for (int h = 0; h < points.size(); h++) {
glTexCoord1f(1.);
VERTEX(points[h].first, points[h].second);
}
glEnd();
}
if (Settings::showAirportCongestionRing()) {
glLineWidth(
Helpers::lerp(
Settings::airportCongestionBorderLineStrengthMin(),
Settings::airportCongestionBorderLineStrengthMax(),
fraction
)
);
glBegin(GL_LINE_LOOP);
for (int h = 0; h < points.size(); h++) {
glTexCoord1f(0.);
VERTEX(points[h].first, points[h].second);
}
glEnd();

// or as a Torus:
if (false) {
glBegin(GL_TRIANGLE_STRIP);
for (int h = 0; h <= 360; h += 6) {
glTexCoord1f(-1.);
VERTEX(
a->lat + Nm2Deg(distanceNm) * qCos(h * Pi180),
a->lon + Nm2Deg(distanceNm) / circle_distort * qSin(h * Pi180)
);
glTexCoord1f(1.);
VERTEX(
a->lat + Nm2Deg(distanceNm * 2) * qCos(h * Pi180),
a->lon + Nm2Deg(distanceNm * 2) / circle_distort * qSin(h * Pi180)
);
}
glEnd();
}
}
glEnd();
}
glPopAttrib();
}
glEndList();
qDebug() << "-- finished";
Expand Down Expand Up @@ -695,7 +760,7 @@ void GLWidget::createStaticLists() {
if (_immediateRouteTex == 0) {
glGenTextures(1, &_immediateRouteTex);
glBindTexture(GL_TEXTURE_1D, _immediateRouteTex);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
const char components = 4;
Expand Down Expand Up @@ -1125,6 +1190,11 @@ void GLWidget::paintGL() {
glCallList(_coastlinesList);
glCallList(_countriesList);
glCallList(_gridlinesList);

if (Settings::showAirportCongestion()) {
glCallList(_congestionsList);
}

if (Settings::showUsedWaypoints() && _zoom < _usedWaypointsLabelZoomThreshold * .1) {
glCallList(_usedWaypointsList);
}
Expand Down Expand Up @@ -1178,10 +1248,6 @@ void GLWidget::paintGL() {
}
}


if (Settings::showAirportCongestion()) {
glCallList(_congestionsList);
}
glCallList(_activeAirportsList);
if (Settings::showInactiveAirports() && (_zoom < _inactiveAirportLabelZoomTreshold * .7)) {
glCallList(_inactiveAirportsList);
Expand Down
22 changes: 13 additions & 9 deletions src/NavData.cpp
Expand Up @@ -228,29 +228,33 @@ void NavData::updateData(const WhazzupData& whazzupData) {
if (dep != 0) {
dep->addDeparture(p);
newActiveAirportsSet.insert(dep);
if (Settings::filterTraffic()) { // Airport traffic filtered
if (p->distanceFromDeparture() < Settings::filterDistance()) {
dep->numFilteredDepartures++;
}
if (
!Settings::filterTraffic()
|| (p->distanceFromDeparture() < Settings::filterDistance())
) {
dep->nMaybeFilteredDepartures++;
}
} else if (p->flightStatus() == Pilot::BUSH) { // no flightplan yet?
Airport* a = airportAt(p->lat, p->lon, 3.);
if (a != 0) {
a->addDeparture(p);
a->numFilteredDepartures++;
a->nMaybeFilteredDepartures++;
newActiveAirportsSet.insert(a);
}
}
Airport* dest = airports.value(p->planDest, 0);
if (dest != 0) {
dest->addArrival(p);
newActiveAirportsSet.insert(dest);
if (Settings::filterTraffic()) { // Airport traffic filtered
if (
if (
!Settings::filterTraffic()
|| (
(p->distanceToDestination() < Settings::filterDistance())
|| (p->eet().hour() + p->eet().minute() / 60. < Settings::filterArriving())
) {
dest->numFilteredArrivals++;
)
) {
if (p->flightStatus() != Pilot::FlightStatus::BLOCKED && p->flightStatus() != Pilot::FlightStatus::GROUND_ARR) {
dest->nMaybeFilteredArrivals++;
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/Sector.cpp
Expand Up @@ -8,7 +8,8 @@ Sector::Sector() {}

Sector::Sector(const QStringList &fields, const int debugControllerLineNumber, const int debugSectorLineNumber)
: _debugControllerLineNumber(debugControllerLineNumber),
_debugSectorLineNumber(debugSectorLineNumber) {
_debugSectorLineNumber(debugSectorLineNumber),
_polygon(0), _borderline(0), _polygonHighlighted(0), _borderlineHighlighted(0) {
// LSAZ:Zurich::::189[:CTR]
if (fields.size() != 6 && fields.size() != 7) {
QMessageLogger("firlist.dat", debugControllerLineNumber, QT_MESSAGELOG_FUNC).critical()
Expand Down Expand Up @@ -162,6 +163,7 @@ GLuint Sector::glBorderLine() {
}

GLuint Sector::glPolygonHighlighted() {
// we have crashes exactly at that NEXT line. - added a constructor initialization
if (_polygonHighlighted == 0) {
_polygonHighlighted = glGenLists(1);
glNewList(_polygonHighlighted, GL_COMPILE);
Expand Down

0 comments on commit 9fa116f

Please sign in to comment.