diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/api/annotations.test.cpp | 67 | ||||
-rw-r--r-- | test/fixtures/local_glyphs/no_local_with_content_insets/expected.png | bin | 0 -> 8428 bytes | |||
-rw-r--r-- | test/fixtures/local_glyphs/no_local_with_content_insets_and_pitch/expected.png | bin | 0 -> 7263 bytes | |||
-rw-r--r-- | test/map/transform.test.cpp | 45 | ||||
-rw-r--r-- | test/text/local_glyph_rasterizer.test.cpp | 50 |
5 files changed, 148 insertions, 14 deletions
diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp index d7cb572cb0..03330dc4c6 100644 --- a/test/api/annotations.test.cpp +++ b/test/api/annotations.test.cpp @@ -434,6 +434,73 @@ TEST(Annotations, VisibleFeatures) { EXPECT_EQ(features.size(), ids.size()); } +TEST(Annotations, ViewFrustumCulling) { + // The purpose of the test is to control that annotations outside screen + // rectangle are not rendered for different camera setup, especially when + // using edge insets - viewport center is then offsetted. + + // Important premise of this test is "static const float viewportPadding = 100;" + // as defined in collision_index.cpp: tests using edge insets are writen so that + // padding is 128 (half of viewSize width). If increasing viewportPadding, + // increase the padding in test cases below. + AnnotationTest test; + + auto viewSize = test.frontend.getSize(); + auto box = ScreenBox { {}, { double(viewSize.width), double(viewSize.height) } }; + + test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json")); + test.map.addAnnotationImage(namedMarker("default_marker")); + const LatLng center = { 5.0, 5.0 }; + test.map.jumpTo(CameraOptions().withCenter(center).withZoom(3.0)); + + LatLng tl = test.map.latLngForPixel(ScreenCoordinate(0, 0)); + LatLng br = test.map.latLngForPixel(ScreenCoordinate(viewSize.width, viewSize.height)); + + std::vector<LatLng> latLngs = { + tl, + test.map.latLngForPixel(ScreenCoordinate(viewSize.width, 0)), + test.map.latLngForPixel(ScreenCoordinate(0, viewSize.height)), + br, + center}; + + std::vector<mbgl::AnnotationID> ids; + for (auto latLng : latLngs) { + ids.push_back(test.map.addAnnotation(SymbolAnnotation { { latLng.longitude(), latLng.latitude() }, "default_marker" })); + } + + std::vector<std::pair<CameraOptions, std::vector<uint64_t>>> expectedVisibleForCamera = { + // Start with all markers visible. + { CameraOptions(), { 0, 1, 2, 3, 4 } }, + // Move center to topLeft: only former center and top left (now center) are visible. + { CameraOptions().withCenter(tl), { 0, 4 } }, + // Reset center. With pitch: only top row markers and center are visible. + { CameraOptions().withCenter(center).withPitch(45), { 0, 1, 4 } }, + // Reset pitch, and use padding to move viewport center: only topleft and center are visible. + { CameraOptions().withPitch(0).withPadding(EdgeInsets { viewSize.height * 0.5, viewSize.width * 0.5, 0, 0 }), { 0, 4 } }, + // Use opposite padding to move viewport center: only bottom right and center are visible. + { CameraOptions().withPitch(0).withPadding(EdgeInsets { 0, 0, viewSize.height * 0.5, viewSize.width * 0.5 }), { 3, 4 } }, + // Use top padding to move viewport center: top row and center are visible. + { CameraOptions().withPitch(0).withPadding(EdgeInsets { viewSize.height * 0.5, 0, 0, 0 }), { 0, 1, 4 } }, + // Use bottom padding: only bottom right and center are visible. + { CameraOptions().withPitch(0).withPadding(EdgeInsets { 0, 0, viewSize.height * 0.5, 0 }), { 2, 3, 4 } }, + // Left padding and pitch: top left, bottom left and center are visible. + { CameraOptions().withPitch(45).withPadding(EdgeInsets { 0, viewSize.width * 0.5, 0, 0 }), { 0, 2, 4 } } + }; + + for (unsigned i = 0; i < expectedVisibleForCamera.size(); i++) { + auto testCase = expectedVisibleForCamera[i]; + test.map.jumpTo(testCase.first); + test.frontend.render(test.map); + auto features = test.frontend.getRenderer()->queryRenderedFeatures(box, {}); + for (uint64_t id : testCase.second) { // testCase.second is vector of ids expected. + EXPECT_NE(std::find_if(features.begin(), features.end(), [&id](auto feature) { + return id == feature.id.template get<uint64_t>(); + }), features.end()) << "Point with id " << id << " is missing in test case " << i; + EXPECT_EQ(features.size(), testCase.second.size()) << " in test case " << i; + } + } +} + TEST(Annotations, TopOffsetPixels) { AnnotationTest test; diff --git a/test/fixtures/local_glyphs/no_local_with_content_insets/expected.png b/test/fixtures/local_glyphs/no_local_with_content_insets/expected.png Binary files differnew file mode 100644 index 0000000000..f161a95c8e --- /dev/null +++ b/test/fixtures/local_glyphs/no_local_with_content_insets/expected.png diff --git a/test/fixtures/local_glyphs/no_local_with_content_insets_and_pitch/expected.png b/test/fixtures/local_glyphs/no_local_with_content_insets_and_pitch/expected.png Binary files differnew file mode 100644 index 0000000000..edb8d07a40 --- /dev/null +++ b/test/fixtures/local_glyphs/no_local_with_content_insets_and_pitch/expected.png diff --git a/test/map/transform.test.cpp b/test/map/transform.test.cpp index 33d325dfb2..3d37312b17 100644 --- a/test/map/transform.test.cpp +++ b/test/map/transform.test.cpp @@ -288,25 +288,48 @@ TEST(Transform, Padding) { ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withCenter(LatLng { 10, -100 }).withZoom(10.0)); + CameraOptions nonPaddedCameraOptions = CameraOptions().withCenter(LatLng { 10, -100 }).withZoom(10.0); + transform.jumpTo(nonPaddedCameraOptions); const LatLng trueCenter = transform.getLatLng(); ASSERT_DOUBLE_EQ(10, trueCenter.latitude()); ASSERT_DOUBLE_EQ(-100, trueCenter.longitude()); ASSERT_DOUBLE_EQ(10, transform.getZoom()); - const LatLng manualShiftedCenter = transform.getState().screenCoordinateToLatLng({ + const LatLng screenCenter = transform.screenCoordinateToLatLng({ + 1000.0 / 2.0, 1000.0 / 2.0, - 1000.0 / 4.0, + }); + const LatLng upperHalfCenter = transform.screenCoordinateToLatLng({ + 1000.0 / 2.0, + 1000.0 * 0.25, }); EdgeInsets padding(1000.0 / 2.0, 0, 0, 0); - const LatLng shiftedCenter = transform.getLatLng(padding); - ASSERT_NE(trueCenter.latitude(), shiftedCenter.latitude()); - ASSERT_NEAR(trueCenter.longitude(), shiftedCenter.longitude(), 1e-8); - ASSERT_DOUBLE_EQ(manualShiftedCenter.latitude(), shiftedCenter.latitude()); - ASSERT_DOUBLE_EQ(manualShiftedCenter.longitude(), shiftedCenter.longitude()); + // CameraOption center and zoom don't change when padding changes: center of + // viewport remains the same as padding defines viwport center offset in rendering. + CameraOptions paddedOptions = CameraOptions().withPadding(padding); + transform.jumpTo(paddedOptions); + const LatLng theSameCenter = transform.getLatLng(); + ASSERT_DOUBLE_EQ(trueCenter.latitude(), theSameCenter.latitude()); + ASSERT_DOUBLE_EQ(trueCenter.longitude(), theSameCenter.longitude()); + + // However, LatLng is now at the center of lower half - verify conversion + // from screen coordinate to LatLng. + const LatLng paddedLowerHalfScreenCenter = transform.screenCoordinateToLatLng({ + 1000.0 / 2.0, + 1000.0 * 0.75, + }); + ASSERT_NEAR(screenCenter.latitude(), paddedLowerHalfScreenCenter.latitude(), 1e-10); + ASSERT_NEAR(screenCenter.longitude(), paddedLowerHalfScreenCenter.longitude(), 1e-10); + + // LatLng previously in upper half center, should now be under screen center. + const LatLng paddedScreenCenter = transform.screenCoordinateToLatLng({ + 1000.0 / 2.0, + 1000.0 / 2.0, + }); + ASSERT_NEAR(upperHalfCenter.latitude(), paddedScreenCenter.latitude(), 1e-10); + ASSERT_NEAR(upperHalfCenter.longitude(), paddedScreenCenter.longitude(), 1e-10); } TEST(Transform, MoveBy) { @@ -440,7 +463,7 @@ TEST(Transform, Camera) { flyOptions.transitionFrameFn = [&](double t) { ASSERT_TRUE(t >= 0 && t <= 1); ASSERT_LE(latLng2.latitude(), transform.getLatLng().latitude()); - ASSERT_GE(latLng2.longitude(), transform.getLatLng({}, LatLng::Unwrapped).longitude()); + ASSERT_GE(latLng2.longitude(), transform.getLatLng(LatLng::Unwrapped).longitude()); }; flyOptions.transitionFinishFn = [&]() { // XXX Fix precision loss in flyTo: @@ -618,7 +641,7 @@ TEST(Transform, LatLngBounds) { // Try crossing the antimeridian from the right. transform.jumpTo(CameraOptions().withCenter(LatLng { 0.0, 200.0 })); - ASSERT_DOUBLE_EQ(transform.getLatLng({}, LatLng::Unwrapped).longitude(), 180.0); + ASSERT_DOUBLE_EQ(transform.getLatLng(LatLng::Unwrapped).longitude(), 180.0); ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), -180.0); // -1 | 0 | +1 diff --git a/test/text/local_glyph_rasterizer.test.cpp b/test/text/local_glyph_rasterizer.test.cpp index ec8a728e9f..86dc87b6c7 100644 --- a/test/text/local_glyph_rasterizer.test.cpp +++ b/test/text/local_glyph_rasterizer.test.cpp @@ -43,9 +43,9 @@ public: MapAdapter map { frontend, MapObserver::nullObserver(), fileSource, MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize())}; - void checkRendering(const char * name) { + void checkRendering(const char * name, double imageMatchPixelsThreshold = 0.05, double pixelMatchThreshold = 0.1) { test::checkImage(std::string("test/fixtures/local_glyphs/") + name, - frontend.render(map), 0.05, 0.1); + frontend.render(map), imageMatchPixelsThreshold, pixelMatchThreshold); } }; @@ -85,6 +85,50 @@ TEST(LocalGlyphRasterizer, NoLocal) { return response; }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); - test.checkRendering("no_local"); + test.checkRendering("no_local", 0.001, 0.1); } +TEST(LocalGlyphRasterizer, NoLocalWithContentInsets) { + // Expectations: content insets imply rendering to offsetted viewport center. + // Rendered text should be on the same offset and keep the same size as + // with no offset. + LocalGlyphRasterizerTest test({}); + + test.fileSource->glyphsResponse = [&] (const Resource& resource) { + EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); + Response response; + response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf")); + return response; + }; + auto viewSize = test.frontend.getSize(); + test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); + + // Expected image was created using center offset as in the line below - content insets, + // with no pitch defined, should produce the same output. + // test.map.moveBy({ viewSize.width * 0.25, 0 }); + + test.map.jumpTo(CameraOptions().withPadding(EdgeInsets { 0, viewSize.width * 0.25 * 2, 0, 0 })); + test.checkRendering("no_local_with_content_insets", 0.001, 0.1); +} + +TEST(LocalGlyphRasterizer, NoLocalWithContentInsetsAndPitch) { + // Expectations: content insets imply rendering to offsetted viewport center. + // Rendered text should be on the same offset and keep the same size as + // with no offset. + LocalGlyphRasterizerTest test({}); + + test.fileSource->glyphsResponse = [&] (const Resource& resource) { + EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); + Response response; + response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf")); + return response; + }; + auto viewSize = test.frontend.getSize(); + test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); + + // Expected image was verified using no-padding render, offsetted to right + // using bitmap editor. + + test.map.jumpTo(CameraOptions().withPitch(45).withPadding(EdgeInsets { 0, viewSize.width * 0.4, 0, 0 })); + test.checkRendering("no_local_with_content_insets_and_pitch", 0.001, 0.1); +} |