1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-24 19:55:53 +01:00
GPXSee/src/common/rectc.cpp

178 lines
3.4 KiB
C++

#include "wgs84.h"
#include "rectc.h"
#define MIN_LAT deg2rad(-90.0)
#define MAX_LAT deg2rad(90.0)
#define MIN_LON deg2rad(-180.0)
#define MAX_LON deg2rad(180.0)
RectC::RectC(const Coordinates &center, double radius)
{
double radDist = radius / WGS84_RADIUS;
double radLon = deg2rad(center.lon());
double radlat = deg2rad(center.lat());
double minLat = radlat - radDist;
double maxLat = radlat + radDist;
double minLon, maxLon;
if (minLat > MIN_LAT && maxLat < MAX_LAT) {
double deltaLon = asin(sin(radDist) / cos(radlat));
minLon = radLon - deltaLon;
if (minLon < MIN_LON)
minLon += 2.0 * M_PI;
maxLon = radLon + deltaLon;
if (maxLon > MAX_LON)
maxLon -= 2.0 * M_PI;
} else {
// a pole is within the distance
minLat = qMax(minLat, MIN_LAT);
maxLat = qMin(maxLat, MAX_LAT);
minLon = MIN_LON;
maxLon = MAX_LON;
}
_tl = Coordinates(rad2deg(minLon), rad2deg(maxLat));
_br = Coordinates(rad2deg(maxLon), rad2deg(minLat));
}
RectC RectC::operator|(const RectC &r) const
{
if (isNull())
return r;
if (r.isNull())
return *this;
double l1 = _tl.lon();
double r1 = _tl.lon();
if (_br.lon() - _tl.lon() < 0)
l1 = _br.lon();
else
r1 = _br.lon();
double l2 = r._tl.lon();
double r2 = r._tl.lon();
if (r._br.lon() - r._tl.lon() < 0)
l2 = r._br.lon();
else
r2 = r._br.lon();
double t1 = _tl.lat();
double b1 = _tl.lat();
if (_br.lat() - _tl.lat() < 0)
t1 = _br.lat();
else
b1 = _br.lat();
double t2 = r._tl.lat();
double b2 = r._tl.lat();
if (r._br.lat() - r._tl.lat() < 0)
t2 = r._br.lat();
else
b2 = r._br.lat();
RectC tmp;
tmp._tl.setLon(qMin(l1, l2));
tmp._br.setLon(qMax(r1, r2));
tmp._tl.setLat(qMin(t1, t2));
tmp._br.setLat(qMax(b1, b2));
return tmp;
}
RectC RectC::operator&(const RectC &r) const
{
if (isNull() || r.isNull())
return RectC();
double l1 = _tl.lon();
double r1 = _tl.lon();
if (_br.lon() - _tl.lon() < 0)
l1 = _br.lon();
else
r1 = _br.lon();
double l2 = r._tl.lon();
double r2 = r._tl.lon();
if (r._br.lon() - r._tl.lon() < 0)
l2 = r._br.lon();
else
r2 = r._br.lon();
if (l1 > r2 || l2 > r1)
return RectC();
double t1 = _tl.lat();
double b1 = _tl.lat();
if (_br.lat() - _tl.lat() < 0)
t1 = _br.lat();
else
b1 = _br.lat();
double t2 = r._tl.lat();
double b2 = r._tl.lat();
if (r._br.lat() - r._tl.lat() < 0)
t2 = r._br.lat();
else
b2 = r._br.lat();
if (t1 > b2 || t2 > b1)
return RectC();
RectC tmp;
tmp._tl.setLon(qMax(l1, l2));
tmp._br.setLon(qMin(r1, r2));
tmp._tl.setLat(qMax(t1, t2));
tmp._br.setLat(qMin(b1, b2));
return tmp;
}
RectC RectC::normalized() const
{
RectC r;
if (_br.lon() < _tl.lon()) {
r._tl.setLon(_br.lon());
r._br.setLon(_tl.lon());
} else {
r._tl.setLon(_tl.lon());
r._br.setLon(_br.lon());
}
if (_br.lat() < _tl.lat()) {
r._tl.setLat(_br.lat());
r._br.setLat(_tl.lat());
} else {
r._tl.setLat(_tl.lat());
r._br.setLat(_br.lat());
}
return r;
}
void RectC::unite(const Coordinates &c)
{
if (isNull()) {
_tl = c;
_br = c;
} else {
if (c.lon() < _tl.lon())
_tl.setLon(c.lon());
if (c.lon() > _br.lon())
_br.setLon(c.lon());
if (c.lat() > _br.lat())
_br.setLat(c.lat());
if (c.lat() < _tl.lat())
_tl.setLat(c.lat());
}
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const RectC &rect)
{
dbg.nospace() << "RectC(" << rect.topLeft() << ", " << rect.bottomRight()
<< ")";
return dbg.space();
}
#endif // QT_NO_DEBUG