📄 maps.cpp
字号:
return true;
}
}
bool MapMercator::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(atan(sinh(yt)));
pos.lon = rad2deg(checkLg(xt));
return true;
}
QString MapMercator::getInfo()
{
Position pos1, pos2;
calcPos(pos1, x1, y1);
calcPos(pos1, x1, y1);
QString info = tr("Mercator 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 MapMercator::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;
}
MapLambert::MapLambert(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
>> std1Lat >> std2Lat >> refLon;
std1Lat = deg2rad(std1Lat);
std2Lat = deg2rad(std2Lat);
refLon = deg2rad(refLon);
projection = "LAMBERT";
// precalc
n = log(cos(std1Lat) * (1 / cos(std2Lat)))
/ log(tan(PI_1_4 + std2Lat / 2) * -tan(PI_3_4 + std1Lat / 2));
F = (cos(n) * pow(tan(PI_1_4 + std1Lat / 2), n)) / n;
p0 = F * pow((-tan(PI_3_4)), n);
double p = F * pow(-tan(PI_3_4 + deg2rad(pos1.lat) / 2), n);
xlon1 = p * sin(n * (deg2rad(pos1.lon) - refLon));
ylat1 = p0 - p * cos(n * (deg2rad(pos1.lon) - refLon));
p = F * pow(-tan(PI_3_4 + deg2rad(pos2.lat) / 2), n);
xlon2 = p * sin(n * (deg2rad(pos2.lon) - refLon));
ylat2 = p0 - p * cos(n * (deg2rad(pos2.lon) - refLon));
if ( n > 0 ) {
n_sign = 1.0;
} else if ( n == 0 ) {
n_sign = 0.0;
} else {
n_sign = -1.0;
}
setLimits();
}
bool MapLambert::calcxy(double * x, double * y, const Position & pos)
{
double p = F * pow(-tan(PI_3_4 + deg2rad(pos.lat) / 2), n);
double xt = p * sin(n * (deg2rad(pos.lon) - refLon));
double yt = p0 - p * cos(n * (deg2rad(pos.lon) - refLon));
*x = x1 + ((xt - xlon1) * (x2 - x1) / (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 MapLambert::calcPos(Position & pos, double x, double y)
{
double xt = xlon1 + ((x - x1) * (xlon2 - xlon1) / (x2 - x1));
double yt = ylat1 + ((y - y1) * (ylat2 - ylat1) / (y2 - y1));
double p = n_sign * sqrt(xt * xt + (p0 - yt) * (p0 - yt));
double s = atan(xt / (p0 - yt));
pos.lat = rad2deg(2.0 * atan(pow(F / p, 1.0 / n)) - PI_1_2);
pos.lon = rad2deg(refLon + (s / n));
return true;
}
QString MapLambert::getInfo()
{
QString info;
Position pos1, pos2;
calcPos(pos1, x1, y1);
calcPos(pos1, x1, y1);
info = tr("Lambert Projection, SCALE 1:%1,\nLat: %2 to %3, Lon: %4 to %5\n"
"std.Latitudes: %6 %7, ref longitude %8")
.arg(scale)
.arg(pos1.lat).arg(pos2.lat)
.arg(pos1.lon).arg(pos2.lon)
.arg(rad2deg(std1Lat)).arg(rad2deg(std2Lat)).arg(rad2deg(refLon));
return info;
}
QString MapLambert::getParameterStr()
{
QString param;
Position pos1, pos2;
calcPos(pos1, x1, y1);
calcPos(pos1, x1, y1);
/* param = tr("%1 %2 %3 %4 %5 %6 %7 %8")
.arg(projection).arg(name).arg(scale).arg(mapSizeX).arg(mapSizeY)
.arg(longitude1*rad2deg).arg(latitude1*rad2deg).arg(x1);
param.append(tr(" %1 %2 %3 %4 %5 %6 %7 %8")
.arg(y1).arg(longitude2*rad2deg).arg(latitude2*rad2deg).arg(x2).arg(y2)
.arg(std1Lat*rad2deg).arg(std2Lat*rad2deg).arg(refLon*rad2deg));
*/
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(std1Lat) << " " << rad2deg(std2Lat)
<< " " << rad2deg(refLon);
return param;
}
// create static Ra
double MapFritz::Ra[201] = {0};
MapFritz::MapFritz(QString & mapInfo, const QString &subdir) : MapImage(mapInfo, subdir)
{
pixelfact = 10000 / 2817.947378;
projection = "FRITZ";
/*
* Build array for earth radii
*/
if ( !Ra[0] ) {
for (int i = -100; i <= 100; ++i) {
Ra[i + 100] = calcR(i);
}
}
// read additional map info
QTextIStream mapIStream(&mapInfo);
mapIStream >> mapName >> scale >> mapSizeX >> mapSizeY;
mapIStream >> center.lat >> center.lon;
mapSizeX2 = mapSizeX / 2;
mapSizeY2 = mapSizeY / 2;
setLimits();
}
bool MapFritz::calcxy(double * x, double * y, const Position & pos)
{
zero.lat = center.lat;
zero.lon = center.lon;
pixelfact = scale / PIXELFACT;
if ( pixelfact == 0 ) {
return false;
}
double argr = deg2rad(Ra[(int)(100 + deg2rad(pos.lat))]);
*x = argr * cos(deg2rad(pos.lat))
* deg2rad(pos.lon - zero.lon);
*y = argr * deg2rad(pos.lat - zero.lat);
double dif = argr * (1 - cos(deg2rad(pos.lon - zero.lon)));
*y += dif / 1.85;
*x /= pixelfact;
*y /= pixelfact;
*x += mapSizeX2;
*y = mapSizeY2 - *y;
if ( (*x < 0) || (*x >= mapSizeX) || (*y < 0) || (*y >= mapSizeY) ) {
return false;
} else {
return true;
}
}
bool MapFritz::calcPos(Position & pos, double x, double y)
{
// FIXME: double check the deg2rad, rad2deg conversions
// FIXME: optimize equations/iteration
zero = center;
pixelfact = scale / PIXELFACT;
x = (mapSizeX2 - x) * pixelfact;
y = (y - mapSizeY2) * pixelfact;
double latr = deg2rad(center.lat);
int i = 0;
double idxr;
do {
idxr = latr;
latr = deg2rad(zero.lat) - y / deg2rad(Ra[(int)(100 + idxr)]);
++i;
} while((fabs(latr - idxr) >= 1.0) && (i < 4));
latr = deg2rad(zero.lat) - y / deg2rad(Ra[(int)(100 + idxr)]);
// double lonr = deg2rad(zero.lon) - x
// / (deg2rad(Ra[(int)(100 + latr)]) * cos(deg2rad(latr)));
double lonr = deg2rad(zero.lon) - x
/ (deg2rad(Ra[(int)(100 + latr)]) * cos(latr));
// double dif = latr * (1 - (cos((deg2rad(fabs(lonr - zero.lon))))));
double diff = latr * (1 - cos(fabs(lonr - deg2rad(zero.lon))));
latr -= diff / 1.5;
// lonr = zero.lon - x / (deg2rad(Ra[(int)(100 + latr)]) * cos(deg2rad(latr)));
lonr = deg2rad(zero.lon) - x / (deg2rad(Ra[(int)(100 + latr)]) * cos(latr));
pos.lat = rad2deg(latr);
pos.lon = rad2deg(lonr);
return true;
}
QString MapFritz::getInfo()
{
QString info = tr("Fritz Projection, "
"SCALE 1:%1,\nCenter Lat: %2, Center Lon: %3")
.arg(scale).arg(center.lat).arg(center.lon);
return info;
}
QString MapFritz::getParameterStr()
{
QString param;
/* param = tr("%1 %2 %3 %4 %5 %6 %7")
.arg(projection).arg(name).arg(scale).arg(mapSizeX).arg(mapSizeY)
.arg(center_latitude).arg(center_longitude);*/
QTextOStream os(¶m);
os.precision(10);
os << projection << " " << name() << " " << scale
<< " " << mapSizeX << " " << mapSizeY
<< " " << center.lat << " " << center.lon;
return param;
}
double MapFritz::calcR(double lat)
{
static const double a = 6378.137;
static const double e2 = square(0.081082);
/*
* the radius of curvature of an ellipsoidal Earth in the plane of the
* meridian is given by
*
* R' = a * (1 - e^2) / (1 - e^2 * (sin(lat))^2)^(3/2)
*
* where a is the equatorial radius, b is the polar radius, and e is
* the eccentricity of the ellipsoid = sqrt(1 - b^2/a^2)
*
* a = 6378 km (3963 mi) Equatorial radius (surface to center distance)
* b = 6356.752 km (3950 mi) Polar radius (surface to center distance) e
* = 0.081082 Eccentricity
*/
double sc = sin(deg2rad(lat));
double x = a * (1.0 - e2);
double z = 1.0 - e2 * square(sc);
double y = std::pow(z, 1.5);
return (x / y) * 1000.0; // R
}
int QMapVector::compareItems( Item s1, Item s2 )
{
MapBase *m1 = (MapBase *)s1;
MapBase *m2 = (MapBase *)s2;
if (m1->limitNorthWest.lat > m2->limitNorthWest.lat)
return -1;
else if (m1->limitNorthWest.lat < m2->limitNorthWest.lat)
return 1;
else {
if (m1->limitSouthEast.lon < m2->limitSouthEast.lon)
return -1;
else if (m1->limitSouthEast.lon > m2->limitSouthEast.lon)
return 1;
else
return 0;
}
return 0;
}
MapTiled::MapTiled( QString & mapInfo, const QString &subdir ) : MapBase(mapInfo, subdir)
{
QTime medidor;
int contador = 0;
medidor.start();
projection = "TILED";
QTextIStream mapIStream(&mapInfo);
mapIStream >> mapName >> scale >> mapSizeX >> mapSizeY;
tileSizeX = mapSizeX;
tileSizeY = mapSizeY;
limitNorthWest.lat = -90;
limitSouthEast.lat = 90;
limitNorthWest.lon = 90;
limitSouthEast.lon = -90;
// read maps
QString filename(mapSelector->mapPathStr());
filename.append("/");
filename.append(name());
QFile mapFile(filename);
int iMap = 0;
MapBase *map;
maps.resize(tileSizeX*tileSizeY);
if ( mapFile.open(IO_ReadOnly) ) {
QTextStream t( &mapFile );
QString pro;
QString mapInfo;
const QStringList& list = QStringList::split('\n', t.read());
mapFile.close();
QStringList::ConstIterator it;
for(it=list.begin(); it!=list.end(); ++it) {
const QString& s = *it;
int sp = s.find(' ');
pro = s.left(sp);
mapInfo = s.right(s.length()-sp-1);
map = MapBase::newMap(pro, mapInfo, subdir);
contador++;
// add the map
if (map) {
maps.insert(iMap++, map);
if (map->limitNorthWest.lat > limitNorthWest.lat)
limitNorthWest.lat = map->limitNorthWest.lat;
if (map->limitSouthEast.lat < limitSouthEast.lat)
limitSouthEast.lat = map->limitSouthEast.lat;
if (map->limitNorthWest.lon < limitNorthWest.lon)
limitNorthWest.lon = map->limitNorthWest.lon;
if (map->limitSouthEast.lon > limitSouthEast.lon)
limitSouthEast.lon = map->limitSouthEast.lon;
}
}
ASSERT(tileSizeX*tileSizeY==iMap);
// order the maps
maps.sort();
// calculate virtual image size and tiles limits (X / Lon)
mapLimitsX.resize(tileSizeX);
iMap = (tileSizeY/2)*tileSizeX; // middle row
map = maps[iMap];
mapSizeX = 0;
Position lastLimit;
lastLimit.lon = map->limitNorthWest.lon; // east
lastLimit.lat = map->limitNorthWest.lat; // south
double lx, ly;
for (int i = 0; i < tileSizeX ; i++) {
map = maps[iMap];
iMap += 1;
map->calcxy(&lx, &ly, lastLimit);
mapLimitsX[i] = mapSizeX - (int) rint(lx);
mapSizeX = mapLimitsX[i] + map->mapSizeX;
lastLimit = map->limitSouthEast;
}
// calculate virtual image size and tiles limits (Y / Lat)
mapLimitsY.resize(tileSizeY);
iMap = tileSizeX/2;
map = maps[iMap];
mapSizeY = 0;
lastLimit = map->limitNorthWest;
for (int i = 0; i < tileSizeY ; i++) {
map = maps[iMap];
iMap += tileSizeX;
map->calcxy(&lx, &ly, lastLimit);
mapLimitsY[i] = mapSizeY - (int) rint(ly);
mapSizeY = mapLimitsY[i] + map->mapSizeY;
lastLimit = map->limitSouthEast;
}
}
}
QString MapTiled::getInfo()
{
QString info = tr("Tiled Map, "
"SCALE 1:%1, %2x%3 tiles")
.arg(scale).arg(tileSizeX).arg(tileSizeY);
return info;
}
QString MapTiled::getParameterStr()
{
QString param;
/* param = tr("%1 %2 %3 %4 %5 %6 %7")
.arg(projection).arg(name).arg(scale).arg(mapSizeX).arg(mapSizeY)
.arg(center_latitude).arg(center_longitude);*/
QTextOStream os(¶m);
os.precision(10);
os << projection << " " << name() << " " << scale
<< " " << tileSizeX << " " << tileSizeY;
return param;
}
MapTiled::~MapTiled()
{
maps.setAutoDelete(TRUE);
maps.clear();
}
bool MapTiled::calcxy( double * x, double * y, const Position & pos )
{
int tileX;
int tileY;
tileX = (int) (((pos.lon - limitNorthWest.lon) * tileSizeX)/ (limitSouthEast.lon - limitNorthWest.lon));
tileY = (int) (((pos.lat - limitSouthEast.lat) * tileSizeX)/ (limitNorthWest.lat - limitSouthEast.lat));
if ( tileX < 0 )
tileX = 0;
else if (tileX >= tileSizeX)
tileX = tileSizeX - 1;
if ( tileY < 0 )
tileY = 0;
else if (tileY >= tileSizeY)
tileY = tileSizeY - 1;
maps[tileX+tileY*tileSizeX]->calcxy(x, y, pos);
*x += mapLimitsX[tileX];
*y += mapLimitsY[tileY];
if ( (*x < 0) || (*x >= mapSizeX) || (*y < 0) || (*y >= mapSizeY) ) {
return false;
} else {
return true;
}
}
bool MapTiled::calcPos( Position & pos, double x, double y )
{
int tileX;
int tileY;
tileX = (int) (((x) * tileSizeX) / mapSizeX);
tileY = (int) (((y) * tileSizeX) / mapSizeY);
if ( tileX < 0 )
tileX = 0;
else if (tileX >= tileSizeX)
tileX = tileSizeX - 1;
if ( tileY < 0 )
tileY = 0;
else if (tileY >= tileSizeY)
tileY = tileSizeY - 1;
x -= mapLimitsX[tileX];
y -= mapLimitsY[tileY];
return maps[tileX+tileY*tileSizeX]->calcPos(pos, x, y);
}
void MapTiled::draw(QPixmap *viewer, const Position &pos)
{
double xc, yc;
calcxy(&xc, &yc, pos);
xc = rint(xc);
yc = rint(yc);
int xinic, yinic, xend, yend;
xend = viewer->width();
if (xend/2 > (int) xc) {
xinic = 0;
xend = xend/2 + (int)xc;
}
else {
xinic = (int)xc - xend/2;
xend += xinic;
}
if (xend > mapSizeX)
xend = mapSizeX;
yend = viewer->height();
if (yend/2 > (int) yc) {
yinic = 0;
yend = yend/2 + (int)yc;
}
else {
yinic = (int)yc - yend/2;
yend += yinic;
}
if (yend > mapSizeY)
yend = mapSizeY;
int startX = 0;
while (startX+1 < tileSizeX && mapLimitsX[startX+1] < xinic)
startX ++;
int startY = 0;
while (startY+1 < tileSizeY && mapLimitsY[startY+1] < yinic)
startY ++;
MapBase *map;
for (int tileY = startY;
tileY < tileSizeY && mapLimitsY[tileY] < yend; tileY++) {
for (int tileX = startX;
tileX < tileSizeX && mapLimitsX[tileX] < xend; tileX++) {
map = maps[tileX+tileY*tileSizeX];
map->draw(viewer, pos);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -