#include <algorithm> // for std::sort
#include <plib/puAux.h>
+#include <simgear/sg_inlines.h>
#include <simgear/route/waypoint.hxx>
#include <simgear/sg_inlines.h>
#include <simgear/misc/strutils.hxx>
///////////////////////////////////////////////////////////////////////////
-const int MAX_ZOOM = 16;
+const int MAX_ZOOM = 12;
const int SHOW_DETAIL_ZOOM = 8;
const int CURSOR_PAN_STEP = 32;
_route = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
_gps = fgGetNode("/instrumentation/gps");
- _zoom = 6;
_width = maxX - x;
_height = maxY - y;
+ _hasPanned = false;
MapData::setFont(legendFont);
MapData::setPalette(colour);
MapWidget::~MapWidget()
{
delete _magVar;
+ clearData();
}
void MapWidget::setProperty(SGPropertyNode_ptr prop)
{
_root = prop;
+ int zoom = _root->getIntValue("zoom", -1);
+ if (zoom < 0) {
+ _root->setIntValue("zoom", 6); // default zoom
+ }
+
+// expose MAX_ZOOM to the UI
+ _root->setIntValue("max-zoom", MAX_ZOOM);
_root->setBoolValue("centre-on-aircraft", true);
_root->setBoolValue("draw-data", false);
_root->setBoolValue("magnetic-headings", true);
void MapWidget::pan(const SGVec2d& delta)
{
+ _hasPanned = true;
_projectionCenter = unproject(-delta);
}
+int MapWidget::zoom() const
+{
+ int z = _root->getIntValue("zoom");
+ SG_CLAMP_RANGE(z, 0, MAX_ZOOM);
+ return z;
+}
+
void MapWidget::zoomIn()
{
- if (_zoom <= 0) {
+ if (zoom() >= MAX_ZOOM) {
return;
}
- --_zoom;
- SG_LOG(SG_GENERAL, SG_INFO, "zoom is now:" << _zoom);
+ _root->setIntValue("zoom", zoom() + 1);
}
void MapWidget::zoomOut()
{
- if (_zoom >= MAX_ZOOM) {
+ if (zoom() <= 0) {
return;
}
- ++_zoom;
- SG_LOG(SG_GENERAL, SG_INFO, "zoom is now:" << _zoom);
+ _root->setIntValue("zoom", zoom() - 1);
}
void MapWidget::draw(int dx, int dy)
{
_aircraft = SGGeod::fromDeg(fgGetDouble("/position/longitude-deg"),
fgGetDouble("/position/latitude-deg"));
- _magneticHeadings = _root->getBoolValue("magnetic-headings");
-
- if (_root->getBoolValue("centre-on-aircraft")) {
+
+ bool mag = _root->getBoolValue("magnetic-headings");
+ if (mag != _magneticHeadings) {
+ clearData(); // flush cached data text, since it often includes heading
+ _magneticHeadings = mag;
+ }
+
+ if (_hasPanned) {
+ _root->setBoolValue("centre-on-aircraft", false);
+ _hasPanned = false;
+ }
+ else if (_root->getBoolValue("centre-on-aircraft")) {
_projectionCenter = _aircraft;
}
_upHeading = 0.0;
}
+ _cachedZoom = MAX_ZOOM - zoom();
SGGeod topLeft = unproject(SGVec2d(_width/2, _height/2));
// compute draw range, including a fudge factor for ILSs and other 'long'
// symbols
double dist, az, az2;
SGGeodesy::inverse(_aircraft, _clickGeod, az, az2, dist);
- if (_magneticHeadings) {
- az -= _magVar->get_magvar();
- SG_NORMALIZE_RANGE(az, 0.0, 360.0);
- }
-
char buffer[1024];
::snprintf(buffer, 1024, "%03d/%.1fnm",
- SGMiscd::roundToInt(az), dist * SG_METER_TO_NM);
+ displayHeading(az), dist * SG_METER_TO_NM);
MapData* d = getOrCreateDataForKey((void*) RULER_LEGEND_KEY);
d->setLabel(buffer);
virtual bool pass(FGPositioned* aPos) const {
if (_fixes && (aPos->type() == FGPositioned::FIX)) {
// ignore fixes which end in digits - expirmental
- if (isdigit(aPos->ident()[3]) && isdigit(aPos->ident()[4])) {
+ if (aPos->ident().length() > 4 && isdigit(aPos->ident()[3]) && isdigit(aPos->ident()[4])) {
return false;
}
}
glColor3f(0.0, 0.0, 0.0);
circleAt(pos, 3, 6);
- if (_zoom > SHOW_DETAIL_ZOOM) {
+ if (_cachedZoom > SHOW_DETAIL_ZOOM) {
return; // hide fix labels beyond a certain zoom level
}
// draw tower location
SGVec2d towerPos = project(apt->getTowerLocation());
- if (_zoom <= SHOW_DETAIL_ZOOM) {
+ if (_cachedZoom <= SHOW_DETAIL_ZOOM) {
glColor3f(1.0, 1.0, 1.0);
glLineWidth(1.0);
d->setAnchor(towerPos);
}
- if (_zoom > SHOW_DETAIL_ZOOM) {
+ if (_cachedZoom > SHOW_DETAIL_ZOOM) {
return;
}
setAnchorForKey(rwy, (p1 + p2) * 0.5);
return;
}
-
+
char buffer[1024];
- ::snprintf(buffer, 1024, "%s/%s\n%3.0f/%3.0f\n%.0f'",
+ ::snprintf(buffer, 1024, "%s/%s\n%03d/%03d\n%.0f'",
rwy->ident().c_str(),
rwy->reciprocalRunway()->ident().c_str(),
- rwy->headingDeg(),
- rwy->reciprocalRunway()->headingDeg(),
+ displayHeading(rwy->headingDeg()),
+ displayHeading(rwy->reciprocalRunway()->headingDeg()),
rwy->lengthFt());
MapData* d = createDataForKey(rwy);
}
char buffer[1024];
- ::snprintf(buffer, 1024, "%s\n%s\n%3.2fMHz",
- loc->name().c_str(), loc->ident().c_str(),loc->get_freq()/100.0);
+ ::snprintf(buffer, 1024, "%s\n%s\n%03d - %3.2fMHz",
+ loc->ident().c_str(), loc->name().c_str(),
+ displayHeading(radial),
+ loc->get_freq()/100.0);
MapData* d = createDataForKey(loc);
d->setPriority(40);
return;
}
- if (_zoom > SHOW_DETAIL_ZOOM) {
+ if (_cachedZoom > SHOW_DETAIL_ZOOM) {
return;
}
drawLine(p, project(advance));
}
- if (validDataForKey((void*) model)) {
- setAnchorForKey((void*) model, p);
- return;
- }
// draw callsign / altitude / speed
-
-
char buffer[1024];
::snprintf(buffer, 1024, "%s\n%d'\n%dkts",
model->getStringValue("callsign", "<>"),
static_cast<int>(pos.getElevationFt() / 50.0) * 50,
speedKts);
- MapData* d = createDataForKey((void*) model);
+ MapData* d = getOrCreateDataForKey((void*) model);
d->setText(buffer);
d->setLabel(model->getStringValue("callsign", "<>"));
d->setPriority(speedKts > 5 ? 60 : 10); // low priority for parked aircraft
drawLine(p, project(advance));
}
- if (validDataForKey((void*) model)) {
- setAnchorForKey((void*) model, p);
- return;
- }
-
// draw callsign / speed
char buffer[1024];
::snprintf(buffer, 1024, "%s\n%dkts",
model->getStringValue("name", "<>"),
speedKts);
- MapData* d = createDataForKey((void*) model);
+ MapData* d = getOrCreateDataForKey((void*) model);
d->setText(buffer);
d->setLabel(model->getStringValue("name", "<>"));
d->setPriority(speedKts > 2 ? 30 : 10); // low priority for slow moving ships
double MapWidget::currentScale() const
{
- return 1.0 / pow(2.0, _zoom);
+ return 1.0 / pow(2.0, _cachedZoom);
}
void MapWidget::circleAt(const SGVec2d& center, int nSides, double r)
d->resetAge();
return d;
}
+
+void MapWidget::clearData()
+{
+ KeyDataMap::iterator it = _mapData.begin();
+ for (; it != _mapData.end(); ++it) {
+ delete it->second;
+ }
+
+ _mapData.clear();
+}
+
+int MapWidget::displayHeading(double h) const
+{
+ if (_magneticHeadings) {
+ h -= _magVar->get_magvar() * SG_RADIANS_TO_DEGREES;
+ }
+
+ SG_NORMALIZE_RANGE(h, 0.0, 360.0);
+ return SGMiscd::roundToInt(h);
+}