[core] Tighten geo.hpp ctors

This commit is contained in:
Bruno de Oliveira Abinader
2017-04-11 17:07:25 +03:00
committed by John Firebaugh
parent 8877452ec3
commit 2f4d162deb
12 changed files with 171 additions and 75 deletions

View File

@@ -70,28 +70,43 @@ public:
LatLng(const CanonicalTileID& id);
LatLng(const UnwrappedTileID& id);
friend constexpr bool operator==(const LatLng& a, const LatLng& b) {
friend bool operator==(const LatLng& a, const LatLng& b) {
return a.lat == b.lat && a.lon == b.lon;
}
friend constexpr bool operator!=(const LatLng& a, const LatLng& b) {
friend bool operator!=(const LatLng& a, const LatLng& b) {
return !(a == b);
}
};
class ProjectedMeters {
private:
double _northing; // Distance measured northwards.
double _easting; // Distance measured eastwards.
public:
double northing;
double easting;
ProjectedMeters(double n_ = 0, double e_ = 0)
: _northing(n_), _easting(e_) {
if (std::isnan(_northing)) {
throw std::domain_error("northing must not be NaN");
}
if (std::isnan(_easting)) {
throw std::domain_error("easting must not be NaN");
}
}
ProjectedMeters(double n = 0, double e = 0)
: northing(n), easting(e) {}
double northing() const { return _northing; }
double easting() const { return _easting; }
friend bool operator==(const ProjectedMeters& a, const ProjectedMeters& b) {
return a._northing == b._northing && a._easting == b._easting;
}
friend bool operator!=(const ProjectedMeters& a, const ProjectedMeters& b) {
return !(a == b);
}
};
constexpr bool operator==(const ProjectedMeters& a, const ProjectedMeters& b) {
return a.northing == b.northing && a.easting == b.easting;
}
class LatLngBounds {
public:
// Return a bounds covering the entire (unwrapped) world.
@@ -188,18 +203,15 @@ private:
LatLngBounds(LatLng sw_, LatLng ne_)
: sw(std::move(sw_)), ne(std::move(ne_)) {}
friend constexpr bool operator==(const LatLngBounds&, const LatLngBounds&);
friend constexpr bool operator!=(const LatLngBounds&, const LatLngBounds&);
friend bool operator==(const LatLngBounds& a, const LatLngBounds& b) {
return a.sw == b.sw && a.ne == b.ne;
}
friend bool operator!=(const LatLngBounds& a, const LatLngBounds& b) {
return !(a == b);
}
};
constexpr bool operator==(const LatLngBounds& a, const LatLngBounds& b) {
return a.sw == b.sw && a.ne == b.ne;
}
constexpr bool operator!=(const LatLngBounds& a, const LatLngBounds& b) {
return !(a == b);
}
// Determines the orientation of the map.
enum class NorthOrientation : uint8_t {
Upwards, // Default
@@ -210,43 +222,60 @@ enum class NorthOrientation : uint8_t {
/// The distance on each side between a rectangle and a rectangle within.
class EdgeInsets {
private:
double _top; // Number of pixels inset from the top edge.
double _left; // Number of pixels inset from the left edge.
double _bottom; // Number of pixels inset from the bottom edge.
double _right; // Number of pixels inset from the right edge.
public:
double top = 0; // Number of pixels inset from the top edge.
double left = 0; // Number of pixels inset from the left edge.
double bottom = 0; // Number of pixels inset from the bottom edge.
double right = 0; // Number of pixels inset from the right edge.
EdgeInsets(double t_ = 0, double l_ = 0, double b_ = 0, double r_ = 0)
: _top(t_), _left(l_), _bottom(b_), _right(r_) {
if (std::isnan(_top)) {
throw std::domain_error("top must not be NaN");
}
if (std::isnan(_left)) {
throw std::domain_error("left must not be NaN");
}
if (std::isnan(_bottom)) {
throw std::domain_error("bottom must not be NaN");
}
if (std::isnan(_right)) {
throw std::domain_error("right must not be NaN");
}
}
EdgeInsets() {}
EdgeInsets(const double t, const double l, const double b, const double r)
: top(t), left(l), bottom(b), right(r) {}
double top() const { return _top; }
double left() const { return _left; }
double bottom() const { return _bottom; }
double right() const { return _right; }
bool isFlush() const {
return top == 0 && left == 0 && bottom == 0 && right == 0;
return _top == 0 && _left == 0 && _bottom == 0 && _right == 0;
}
void operator+=(const EdgeInsets& o) {
top += o.top;
left += o.left;
bottom += o.bottom;
right += o.right;
_top += o._top;
_left += o._left;
_bottom += o._bottom;
_right += o._right;
}
EdgeInsets operator+(const EdgeInsets& o) const {
return {
top + o.top, left + o.left, bottom + o.bottom, right + o.right,
_top + o._top, _left + o._left, _bottom + o._bottom, _right + o._right,
};
}
ScreenCoordinate getCenter(uint16_t width, uint16_t height) const;
friend bool operator==(const EdgeInsets& a, const EdgeInsets& b) {
return a._top == b._top && a._left == b._left && a._bottom == b._bottom && a._right == b._right;
}
friend bool operator!=(const EdgeInsets& a, const EdgeInsets& b) {
return !(a == b);
}
};
constexpr bool operator==(const EdgeInsets& a, const EdgeInsets& b) {
return a.top == b.top && a.left == b.left && a.bottom == b.bottom && a.right == b.right;
}
constexpr bool operator!=(const EdgeInsets& a, const EdgeInsets& b) {
return !(a == b);
}
} // namespace mbgl

View File

@@ -38,8 +38,8 @@ public:
}
static LatLng latLngForProjectedMeters(const ProjectedMeters& projectedMeters) {
double latitude = (2 * std::atan(std::exp(projectedMeters.northing / util::EARTH_RADIUS_M)) - (M_PI / 2.0)) * util::RAD2DEG;
double longitude = projectedMeters.easting * util::RAD2DEG / util::EARTH_RADIUS_M;
double latitude = (2 * std::atan(std::exp(projectedMeters.northing() / util::EARTH_RADIUS_M)) - (M_PI / 2.0)) * util::RAD2DEG;
double longitude = projectedMeters.easting() * util::RAD2DEG / util::EARTH_RADIUS_M;
latitude = util::clamp(latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);
longitude = util::clamp(longitude, -util::LONGITUDE_MAX, util::LONGITUDE_MAX);

View File

@@ -643,7 +643,7 @@ jni::jdouble NativeMapView::getMetersPerPixelAtLatitude(JNIEnv&, jni::jdouble la
jni::Object<ProjectedMeters> NativeMapView::projectedMetersForLatLng(JNIEnv& env, jni::jdouble latitude, jni::jdouble longitude) {
mbgl::ProjectedMeters projectedMeters = map->projectedMetersForLatLng(mbgl::LatLng(latitude, longitude));
return ProjectedMeters::New(env, projectedMeters.northing, projectedMeters.easting);
return ProjectedMeters::New(env, projectedMeters.northing(), projectedMeters.easting());
}
jni::Object<PointF> NativeMapView::pixelForLatLng(JNIEnv& env, jdouble latitude, jdouble longitude) {

View File

@@ -32,11 +32,11 @@ BOOL MGLEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy)
mbgl::ProjectedMeters centerMeters = mbgl::Projection::projectedMetersForLatLng(centerLatLng);
mbgl::ProjectedMeters eyeMeters = mbgl::Projection::projectedMetersForLatLng(eyeLatLng);
heading = std::atan((centerMeters.northing - eyeMeters.northing) /
(centerMeters.easting - eyeMeters.easting));
heading = std::atan((centerMeters.northing() - eyeMeters.northing()) /
(centerMeters.easting() - eyeMeters.easting()));
double groundDistance = std::hypot(centerMeters.northing - eyeMeters.northing,
centerMeters.easting - eyeMeters.easting);
double groundDistance = std::hypot(centerMeters.northing() - eyeMeters.northing(),
centerMeters.easting() - eyeMeters.easting());
pitch = std::atan(eyeAltitude / groundDistance);
}

View File

@@ -4559,8 +4559,8 @@ public:
mbgl::LatLng targetLatLng = MGLLatLngFromLocationCoordinate2D(self.targetCoordinate);
mbgl::ProjectedMeters userMeters = mbgl::Projection::projectedMetersForLatLng(userLatLng);
mbgl::ProjectedMeters targetMeters = mbgl::Projection::projectedMetersForLatLng(targetLatLng);
double angle = atan2(targetMeters.easting - userMeters.easting,
targetMeters.northing - userMeters.northing);
double angle = atan2(targetMeters.easting() - userMeters.easting(),
targetMeters.northing() - userMeters.northing());
direction = mbgl::util::wrap(MGLDegreesFromRadians(angle), 0., 360.);
}
else

View File

@@ -1130,7 +1130,7 @@ double QMapboxGL::metersPerPixelAtLatitude(double latitude, double zoom) const
QMapbox::ProjectedMeters QMapboxGL::projectedMetersForCoordinate(const QMapbox::Coordinate &coordinate_) const
{
auto projectedMeters = d_ptr->mapObj->projectedMetersForLatLng(mbgl::LatLng { coordinate_.first, coordinate_.second });
return QMapbox::ProjectedMeters(projectedMeters.northing, projectedMeters.easting);
return QMapbox::ProjectedMeters(projectedMeters.northing(), projectedMeters.easting());
}
/*!
@@ -1229,10 +1229,10 @@ void QMapboxGL::setMargins(const QMargins &margins_)
QMargins QMapboxGL::margins() const
{
return QMargins(
d_ptr->margins.left,
d_ptr->margins.top,
d_ptr->margins.right,
d_ptr->margins.bottom
d_ptr->margins.left(),
d_ptr->margins.top(),
d_ptr->margins.right(),
d_ptr->margins.bottom()
);
}

View File

@@ -600,8 +600,8 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const Ed
if (width > 0 || height > 0) {
double scaleX = double(getSize().width) / width;
double scaleY = double(getSize().height) / height;
scaleX -= (padding.left + padding.right) / width;
scaleY -= (padding.top + padding.bottom) / height;
scaleX -= (padding.left() + padding.right()) / width;
scaleY -= (padding.top() + padding.bottom()) / height;
minScale = util::min(scaleX, scaleY);
}
double zoom = getZoom() + util::log2(minScale);
@@ -610,12 +610,12 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const Ed
// Calculate the center point of a virtual bounds that is extended in all directions by padding.
ScreenCoordinate centerPixel = nePixel + swPixel;
ScreenCoordinate paddedNEPixel = {
padding.right / minScale,
padding.top / minScale,
padding.right() / minScale,
padding.top() / minScale,
};
ScreenCoordinate paddedSWPixel = {
padding.left / minScale,
padding.bottom / minScale,
padding.left() / minScale,
padding.bottom() / minScale,
};
centerPixel = centerPixel + paddedNEPixel - paddedSWPixel;
centerPixel /= 2.0;

View File

@@ -200,8 +200,8 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
/// w₀: Initial visible span, measured in pixels at the initial scale.
/// Known henceforth as a <i>screenful</i>.
double w0 = std::max(state.size.width - padding.left - padding.right,
state.size.height - padding.top - padding.bottom);
double w0 = std::max(state.size.width - padding.left() - padding.right(),
state.size.height - padding.top() - padding.bottom());
/// w₁: Final visible span, measured in pixels with respect to the initial
/// scale.
double w1 = w0 / state.zoomScale(zoom - startZoom);

View File

@@ -34,8 +34,8 @@ LatLngBounds::LatLngBounds(const CanonicalTileID& id)
ScreenCoordinate EdgeInsets::getCenter(uint16_t width, uint16_t height) const {
return {
(width - left - right) / 2.0f + left,
(height - top - bottom) / 2.0f + top,
(width - left() - right()) / 2.0 + left(),
(height - top() - bottom()) / 2.0 + top(),
};
}

View File

@@ -471,14 +471,12 @@ TEST(Transform, DefaultTransform) {
// Cannot assign invalid sizes.
std::vector<Size> invalidSizes = { {}, { min, max }, { max, min } };
for (const Size& size : invalidSizes) {
ASSERT_TRUE(size.isEmpty());
bool pass = false;
try {
transform.resize(size);
ASSERT_TRUE(false) << "Should throw";
} catch (...) {
pass = true;
ASSERT_TRUE(size.isEmpty());
}
ASSERT_TRUE(pass) << "Expected to throw";
}
Size validSize { max, max };

View File

@@ -6,6 +6,75 @@
using namespace mbgl;
TEST(LatLng, InvalidLatLng) {
try {
LatLng { NAN };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "latitude must not be NaN");
}
try {
LatLng { 0, NAN };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "longitude must not be NaN");
}
try {
LatLng { 91.0 };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "latitude must be between -90 and 90");
}
try {
LatLng { 0, std::numeric_limits<double>::infinity() };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "longitude must not be infinite");
}
}
TEST(ProjectedMeters, InvalidProjectedMeters) {
try {
ProjectedMeters { NAN };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "northing must not be NaN");
}
try {
ProjectedMeters { 0, NAN };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "easting must not be NaN");
}
}
TEST(EdgeInsets, InvalidEdgeInsets) {
try {
EdgeInsets { NAN };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "top must not be NaN");
}
try {
EdgeInsets { 0, NAN };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "left must not be NaN");
}
try {
EdgeInsets { 0, 0, NAN };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "bottom must not be NaN");
}
try {
EdgeInsets { 0, 0, 0, NAN };
ASSERT_TRUE(false) << "should throw";
} catch (const std::domain_error& error) {
ASSERT_EQ(std::string(error.what()), "right must not be NaN");
}
}
TEST(LatLngBounds, World) {
auto result = LatLngBounds::world();
ASSERT_DOUBLE_EQ(-90, result.south());

View File

@@ -38,18 +38,18 @@ TEST(Projection, MetersPerPixelAtLatitude) {
TEST(Projection, ProjectedMeters) {
auto latLng = LatLng {};
auto projectedMeters = Projection::projectedMetersForLatLng(latLng);
EXPECT_EQ(projectedMeters.northing, projectedMeters.easting);
EXPECT_EQ(projectedMeters.northing(), projectedMeters.easting());
EXPECT_EQ(latLng, Projection::latLngForProjectedMeters(projectedMeters));
const auto southWest = LatLng { -util::LATITUDE_MAX, -util::LONGITUDE_MAX };
projectedMeters = Projection::projectedMetersForLatLng(southWest);
EXPECT_DOUBLE_EQ(projectedMeters.northing, -20037508.342789274);
EXPECT_DOUBLE_EQ(projectedMeters.easting, -20037508.342789244);
EXPECT_DOUBLE_EQ(projectedMeters.northing(), -20037508.342789274);
EXPECT_DOUBLE_EQ(projectedMeters.easting(), -20037508.342789244);
const auto northEast = LatLng { util::LATITUDE_MAX, util::LONGITUDE_MAX };
projectedMeters = Projection::projectedMetersForLatLng(northEast);
EXPECT_DOUBLE_EQ(projectedMeters.northing, 20037508.342789274);
EXPECT_DOUBLE_EQ(projectedMeters.easting, 20037508.342789244);
EXPECT_DOUBLE_EQ(projectedMeters.northing(), 20037508.342789274);
EXPECT_DOUBLE_EQ(projectedMeters.easting(), 20037508.342789244);
projectedMeters = ProjectedMeters { std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest() };
latLng = Projection::latLngForProjectedMeters(projectedMeters);