📄 maps.cpp
字号:
actMapList.remove(delmap);
maps.remove(delmap);
}
MapImage::MapImage(QString & mapInfo, const QString &subdir) : MapBase(mapInfo, subdir)
{
pixmap = NULL;
}
MapImage::MapImage():MapBase()
{
pixmap = NULL;
}
MapImage::~MapImage()
{
if(pixmap != NULL)
unload();
}
void MapImage::setLimits()
{
Position limit;
calcPos(limit, 0, 0);
limitNorthWest.lat = limit.lat;
limitNorthWest.lon = limit.lon;
calcPos(limit, mapSizeX, mapSizeY);
limitSouthEast.lat = limit.lat;
limitSouthEast.lon = limit.lon;
}
bool MapImage::load()
{
if (pixmap != NULL && !pixmap->isNull())
return true; // already loaded
QString filename = mapSelector->mapPathStr();
filename.append("/");
filename.append(name());
pixmap = new QPixmap(filename);
if (pixmap->isNull()) // error reading map
{
unload();
return false;
}
else
return true;
}
void MapImage::unload()
{
if (pixmap != NULL)
delete pixmap;
pixmap = NULL;
}
void MapImage::draw(QPixmap *viewer, const Position & pos)
{
double xc, yc;
// load the image
if (!mapSelector->loadMapImage(this))
// load failed
return;
calcxy(&xc, &yc, pos);
int dx, dy, sx, sy, sw, sh;
sw = viewer->width();
if (sw/2 > (int) xc) {
sx = 0;
dx = sw/2 - (int)xc;
sw = sw - dx;
}
else {
dx = 0;
sx = (int)xc - sw/2;
}
if (sx+sw > pixmap->width())
sw = pixmap->width() - sx;
sh = viewer->height();
if (sh/2 > (int) yc) {
sy = 0;
dy = sh/2 - (int)yc;
sh = sh - dy;
}
else {
dy = 0;
sy = (int)yc - sh/2;
}
if (sy+sh > pixmap->height())
sh = pixmap->height() - sy;
bitBlt(viewer, dx, dy, pixmap, sx, sy, sw, sh);
}
void MapImage::addTrack(Track *track, QColor &, int)
{
// draw the track in the current map
QPainter painter;
if (pixmap && !pixmap->isNull())
{
painter.begin(pixmap);
track->drawTrack(&painter,this,0,0,
pixmap->width(), pixmap->height());
painter.end();
}
}
MapLin::MapLin(QString & mapInfo, const QString &subdir) : MapImage(mapInfo, subdir)
{
// read additional map info
QTextIStream mapIStream(&mapInfo);
mapIStream >> mapName >> scale >> mapSizeX >> mapSizeY;
mapIStream >> pos1.lon >> pos1.lat >> x1 >> y1
>> pos2.lon >> pos2.lat >> x2 >> y2;
projection = "LINEAR";
// FIXME: why check only longitude?
checkLg(deg2rad(pos1.lon));
checkLg(deg2rad(pos2.lon));
setLimits();
}
bool MapLin::calcxy(double * x, double * y, const Position & pos)
{
*x = x1 + (checkLg(deg2rad(pos.lon - pos1.lon)) * (x2 - x1)
/ checkLg(deg2rad(pos2.lon - pos1.lon)));
*y = y1 + ((deg2rad(pos.lat - pos1.lat)) * (y2 - y1)
/ deg2rad(pos2.lat - pos1.lat));
if ( (*x < 0) || (*x >= mapSizeX) || (*y < 0) || (*y >= mapSizeY) ) {
return false;
} else {
return true;
}
}
bool MapLin::calcPos(Position & pos, double x, double y)
{
double latr = deg2rad(pos1.lat)
+ ((y - y1) * (deg2rad(pos2.lat - pos1.lat)) / (y2 - y1));
double lonr = checkLg(deg2rad(pos1.lon) + ((x - x1)
* checkLg(deg2rad(pos2.lon - pos1.lon)) / (x2 - x1)));
pos.lat = rad2deg(latr);
pos.lon = rad2deg(lonr);
// FIXME: all calcPos methods always return true?
return true;
}
QString MapLin::getInfo()
{
QString info;
info = tr("Linear Projection, SCALE 1:%1,\nLat: %2 to %3, Lon: %4 to %5")
.arg(scale)
.arg(pos1.lat).arg(pos2.lat)
.arg(pos1.lon).arg(pos2.lon);
return info;
}
QString MapLin::getParameterStr()
{
QString param;
/* param = tr("%1 %2 %3 %4 %5 %6 %7 %8 %9")
.arg(projection).arg(name).arg(scale).arg(mapSizeX).arg(mapSizeY)
.arg(longitude1*rad2deg).arg(latitude1*rad2deg).arg(x1).arg(y1);
param.append(tr(" %1 %2 %3 %4")
.arg(longitude2*rad2deg).arg(latitude2*rad2deg).arg(x2).arg(y2));
*/
QTextOStream os(¶m);
os.precision(10);
os << projection << " " << name() << " " << scale << " " << mapSizeX
<< " " << mapSizeY << " " << pos1.lon << " " << pos1.lat << " " <<
x1 << " " << y1 << " " << pos2.lon << " " << pos2.lat << " " <<
x2 << " " << y2;
return param;
}
MapCEA::MapCEA(QString & mapInfo, const QString &subdir) : MapImage(mapInfo, subdir)
{
// read additional map info
QTextIStream mapIStream(&mapInfo);
mapIStream >> mapName >> scale >> mapSizeX >> mapSizeY;
Position pos1, pos2;
mapIStream >> pos1.lon >> pos1.lat >> x1 >> y1
>> pos2.lon >> pos2.lat >> x2 >> y2;
projection = "CEA";
// precalc
xlon1 = checkLg(deg2rad(pos1.lon));
ylat1 = sin(deg2rad(pos1.lat));
xlon2 = checkLg(deg2rad(pos2.lon));
ylat2 = sin(deg2rad(pos2.lat));
setLimits();
}
bool MapCEA::calcxy(double * x, double * y, const Position & pos)
{
double xt = deg2rad(pos.lon);
double yt = sin(deg2rad(pos.lat));
*x = x1 + (checkLg(xt - xlon1) * (x2 - x1) / checkLg(xlon2 - xlon1));
*y = y1 + ((yt - ylat1) * (y2 - y1) / (ylat2 - ylat1));
if ( (*x < 0) || (*x >= mapSizeX) || (*y < 0) || (*y >= mapSizeY) ) {
return false;
} else {
return true;
}
}
bool MapCEA::calcPos(Position & pos, double x, double y)
{
double xt = xlon1 + ((x - x1) * checkLg(xlon2 - xlon1) / (x2 - x1));
double yt = ylat1 + ((y - y1) * (ylat2 - ylat1) / (y2 - y1));
pos.lat = rad2deg(asin(yt));
pos.lon = rad2deg(checkLg(xt));
return true;
}
QString MapCEA::getInfo()
{
QString info;
Position pos1, pos2;
calcPos(pos1, x1, y1);
calcPos(pos1, x1, y1);
info = tr("Cylindrical Equal Area Projection, SCALE 1:%1,\n"
"Lat: %2 to %3, Lon: %4 to %5")
.arg(scale)
.arg(pos1.lat).arg(pos2.lat)
.arg(pos1.lon).arg(pos2.lon);
return info;
}
QString MapCEA::getParameterStr()
{
QString param;
Position pos1, pos2;
calcPos(pos1, x1, y1);
calcPos(pos1, x1, y1);
/*
param = tr("%1 %2 %3 %4 %5 %6 %7 %8 %9")
.arg(projection).arg(name).arg(scale).arg(mapSizeX).arg(mapSizeY)
.arg(longitude1*rad2deg).arg(latitude1*rad2deg).arg(x1).arg(y1);
param.append(tr(" %1 %2 %3 %4")
.arg(longitude2*rad2deg).arg(latitude2*rad2deg).arg(x2).arg(y2));
*/
QTextOStream os(¶m);
os.precision(10);
os << projection << " " << name() << " " << scale << " " << mapSizeX
<< " " << mapSizeY << " " << pos1.lon << " " << pos1.lat << " " <<
x1 << " " << y1 << " " << pos2.lon << " " << pos2.lat << " " <<
x2 << " " << y2;
return param;
}
MapUTM::MapUTM(QString & mapInfo, bool utmCoord, const QString &subdir) : MapImage(mapInfo, subdir)
{
// read additional map info
Position pos1, pos2;
QTextIStream mapIStream(&mapInfo);
mapIStream >> mapName >> scale >> mapSizeX >> mapSizeY;
if ( utmCoord ) {
universal = true;
mapIStream >> utmZone >> utmNorthing1 >> utmEasting1 >> x1 >> y1
>> utmNorthing2 >> utmEasting2 >> x2 >> y2;
UTMtoLL(utmNorthing1, utmEasting1, utmZone, pos1, stdLon );
UTMtoLL(utmNorthing2, utmEasting2, utmZone, pos2, stdLon );
projection = "UTM";
} else {
universal = false;
mapIStream >> pos1.lon >> pos1.lat >> x1 >> y1
>> pos2.lon >> pos2.lat >> x2 >> y2 >> stdLon;
projection = "TM";
}
stdLon = deg2rad(stdLon);
// precalc
xlon1 = 0.5 * atanh(cos(deg2rad(pos1.lat))
* sin(checkLg(deg2rad(pos1.lon) - stdLon)));
ylat1 = atan(tan(deg2rad(pos1.lat))
/ cos(checkLg(deg2rad(pos1.lon) - stdLon)));
xlon2 = 0.5 * atanh(cos(deg2rad(pos2.lat))
* sin(checkLg(deg2rad(pos2.lon) - stdLon)));
ylat2 = atan(tan(deg2rad(pos2.lat))
/ cos(checkLg(deg2rad(pos2.lon) - stdLon)));
setLimits();
}
MapUTM::MapUTM(bool utmCoord) : MapImage()
{
if ( utmCoord ) {
universal = true;
projection = "UTM";
} else {
universal = false;
projection = "TM";
}
setLimits();
}
bool MapUTM::calcxy(double * x, double * y, const Position & pos)
{
double xt = 0.5 * atanh(cos(deg2rad(pos.lat))
* sin(checkLg(deg2rad(pos.lon) - stdLon)));
double yt = atan(tan(deg2rad(pos.lat))
/ cos(checkLg(deg2rad(pos.lon) - stdLon)));
*x = x1 + (checkLg(xt - xlon1) * (x2 - x1) / checkLg(xlon2 - xlon1));
*y = y1 + ((yt - ylat1) * (y2 - y1) / (ylat2 - ylat1));
if ( (*x < 0) || (*x >= mapSizeX) || (*y < 0) || (*y >= mapSizeY) ) {
return false;
} else {
return true;
}
}
bool MapUTM::calcPos(Position & pos, double x, double y)
{
double xt = xlon1 + ((x - x1) * checkLg(xlon2 - xlon1) / (x2 - x1));
double yt = ylat1 + ((y - y1) * (ylat2 - ylat1) / (y2 - y1));
pos.lat = rad2deg(asin(sin(yt) / cosh(xt)));
pos.lon = rad2deg(checkLg(stdLon + atan(sinh(xt) / cos(yt))));
return true;
}
void MapUTM::UTMtoLL(double UTMNorthing, double UTMEasting, QString UTMZone,
Position & pos, double & stdLon )
{
//converts UTM coords to lat/long. Equations from USGS Bulletin 1532
//East Longitudes are positive, West longitudes are negative.
//North latitudes are positive, South latitudes are negative
//pos is in decimal degrees.
//Written by Chuck Gantz- chuck.gantz@globalstar.com
static const double k0 = 0.9996;
static const double a = 6378137;
static const double eccSquared = 0.00669438;
double e1 = (1 - sqrt(1 - eccSquared)) / (1 + sqrt(1 - eccSquared));
int NorthernHemisphere; //1 for northern hemispher, 0 for southern
double x = UTMEasting - 500000.0; //remove 500,000 meter offset for longitude
double y = UTMNorthing;
char * ZoneLetter;
int ZoneNumber = strtoul(UTMZone.latin1(), &ZoneLetter, 10);
if ( (*ZoneLetter - 'N') >= 0 ) {
NorthernHemisphere = 1;//point is in northern hemisphere
} else {
NorthernHemisphere = 0;//point is in southern hemisphere
y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere
}
double eccPrimeSquared = eccSquared / (1 - eccSquared);
double M = y / k0;
double mu = M / (a * (1 - eccSquared/4 - 3 * square(eccSquared) / 64
- 5 * std::pow(eccSquared, 3) / 256));
// FIXME: double check the following two lines
double phi1Rad = mu + (3 * e1 / 2 - 27 * std::pow(e1, 3) / 32) * sin(2 * mu)
+ (21 * square(e1) / 16 - 55 * std::pow(e1, 4) / 32) * sin(4 * mu)
+ (151 * std::pow(e1, 3) / 96) * sin(6 * mu);
// double phi1 = deg2rad(phi1Rad);
double N1 = a / sqrt(1 - eccSquared * square(sin(phi1Rad)));
double T1 = square(tan(phi1Rad));
double C1 = eccPrimeSquared * square(cos(phi1Rad));
double R1 = a * (1 - eccSquared)
/ std::pow(1 - eccSquared * square(sin(phi1Rad)), 1.5);
double D = x / (N1 * k0);
pos.lat = rad2deg(phi1Rad - (N1 * tan(phi1Rad) / R1) * (square(D) / 2
- (5 + 3 * T1 + 10 * C1 - 4 * square(C1) - 9 * eccPrimeSquared)
* std::pow(D, 4) / 24 + (61 + 90 * T1 + 298 * C1 + 45 * square(T1)
- 252 * eccPrimeSquared - 3 * square(C1)) * std::pow(D, 6)
/ 720));
// default value
double LonOrigin = (ZoneNumber - 1) * 6 - 180 + 3; //+3 puts origin in middle of zone
// check for need of special value
switch ( ZoneNumber ) {
case 31:
if ( pos.lat >= 72.0 && pos.lat < 84.0 ) {
LonOrigin = 4.5; // special case Svalbard
} else if ( pos.lat >= 56.0 && pos.lat < 64.0 ) {
LonOrigin = 1.5; // special case southwest Norway
}
break;
case 32:
if ( pos.lat >= 56.0 && pos.lat < 64.0 ) {
LonOrigin = 7.5; // special case southwest Norway
}
break;
case 33:
if ( pos.lat >= 72.0 && pos.lat < 84.0 ) {
LonOrigin = 15; // special case Svalbard
}
break;
case 35:
if ( pos.lat >= 72.0 && pos.lat < 84.0 ) {
LonOrigin = 27; // special case Svalbard
}
break;
case 37:
if ( pos.lat >= 72.0 && pos.lat < 84.0 ) {
LonOrigin = 37.5; // special case Svalbard
}
break;
}
stdLon = LonOrigin;
pos.lon = LonOrigin + rad2deg((D -(1 + 2 * T1 + C1) * std::pow(D, 3) / 6
+ (5 - 2 * C1 + 28 * T1 - 3 * square(C1) + 8 * eccPrimeSquared
+ 24 * square(T1)) * std::pow(D, 5) / 120) / cos(phi1Rad));
}
QString MapUTM::getInfo()
{
QString info;
Position pos1, pos2;
calcPos(pos1, x1, y1);
calcPos(pos1, x1, y1);
if ( universal ) {
info = tr("Universal Transverse Mercator Projection, "
"SCALE 1:%1,\nLat: %2 to %3, Lon: %4 to %5\n"
"std.Longitude: %6")
.arg(scale)
.arg(pos1.lat).arg(pos2.lat)
.arg(pos1.lon).arg(pos2.lon)
.arg(rad2deg(stdLon));
} else {
info = tr("Transverse Mercator Projection, "
"SCALE 1:%1,\nLat: %2 to %3, Lon: %4 to %5\n"
"std.Longitude: %6")
.arg(scale)
.arg(pos1.lat).arg(pos2.lat)
.arg(pos1.lon).arg(pos2.lon)
.arg(rad2deg(stdLon));
}
return info;
}
QString MapUTM::getParameterStr()
{
QString param;
if ( universal ) {
/* param = tr("%1 %2 %3 %4 %5 %6 %7 %8 %9")
.arg(projection).arg(name).arg(scale).arg(mapSizeX).arg(mapSizeY)
.arg(utmZone).arg(utmNorthing1).arg(utmEasting1).arg(x1);
param.append(tr(" %1 %2 %3 %4 %5")
.arg(y1).arg(utmNorthing2).arg(utmEasting2).arg(x2).arg(y2));
*/
QTextOStream os(¶m);
os.precision(10);
os << projection << " " << name() << " " << scale << " "
<< mapSizeX << " " << mapSizeY << " " << utmZone << " "
<< utmNorthing1 << " " << utmEasting1 << " " << x1 << " " << y1 << " "
<< utmNorthing2 << " " << utmEasting2 << " " << x2 << " " << y2;
return param;
} else {
/* param = tr("%1 %2 %3 %4 %5 %6 %7 %8 %9")
.arg(projection).arg(name).arg(scale).arg(mapSizeX).arg(mapSizeY)
.arg(longitude1*rad2deg).arg(latitude1*rad2deg).arg(x1).arg(y1);
param.append(tr(" %1 %2 %3 %4 %5")
.arg(longitude2*rad2deg).arg(latitude2*rad2deg).arg(x2).arg(y2).arg(stdLon*rad2deg));
*/
Position pos1, pos2;
calcPos(pos1, x1, y1);
calcPos(pos1, x1, y1);
QTextOStream os(¶m);
os.precision(10);
os << projection << " " << name() << " " << scale << " " <<
mapSizeX << " " << mapSizeY << " " << pos1.lon << " " << pos1.lat
<< " " << x1 << " " << y1 << " " << pos2.lon << " " << pos2.lat
<< " " << x2 << " " << y2 << " " << rad2deg(stdLon);
return param;
}
}
MapMercator::MapMercator(QString & mapInfo, const QString &subdir) : MapImage(mapInfo, subdir)
{
// read additional map info
QTextIStream mapIStream(&mapInfo);
mapIStream >> mapName >> scale >> mapSizeX >> mapSizeY;
Position pos1, pos2;
mapIStream >> pos1.lon >> pos1.lat >> x1 >> y1
>> pos2.lon >> pos2.lat >> x2 >> y2;
projection = "MERCATOR";
// precalc
xlon1 = checkLg(deg2rad(pos1.lon));
//ylat1 = log(tan(latitude1)+1.0/cos(latitude1));
ylat1 = atanh(sin(deg2rad(pos1.lat)));
xlon2 = checkLg(deg2rad(pos2.lon));
//ylat2 = log(tan(latitude2)+1.0/cos(latitude2));
ylat2 = atanh(sin(deg2rad(pos2.lat)));
setLimits();
}
bool MapMercator::calcxy(double * x, double * y, const Position & pos)
{
double xt = deg2rad(pos.lon);
//yt = log(tan(lat)+1.0/cos(lat));
double yt = atanh(sin(deg2rad(pos.lat)));
*x = x1 + (checkLg(xt - xlon1) * (x2 - x1) / checkLg(xlon2 - xlon1));
*y = y1 + ((yt - ylat1) * (y2 - y1) / (ylat2 - ylat1) );
if ( (*x < 0) || (*x >= mapSizeX) || (*y < 0) || (*y >= mapSizeY) ) {
return false;
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -