diff options
author | zmiao <miao.zhao@mapbox.com> | 2019-12-03 11:11:29 +0200 |
---|---|---|
committer | zmiao <miao.zhao@mapbox.com> | 2019-12-05 16:47:15 +0200 |
commit | 3a4154642ec6f6297979b40c794f5a4751b69e7d (patch) | |
tree | 59a6ff38edf9d693d5515ec1a71f71a74abdd072 | |
parent | add1d53b60247ad3123d3be1f6919ce729960d11 (diff) | |
download | qtlocation-mapboxgl-3a4154642ec6f6297979b40c794f5a4751b69e7d.tar.gz |
[core] Make matrix mutable so that we only update them when needed
-rw-r--r-- | platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt | 421 | ||||
-rw-r--r-- | src/mbgl/map/transform.cpp | 71 | ||||
-rw-r--r-- | src/mbgl/map/transform_state.cpp | 55 | ||||
-rw-r--r-- | src/mbgl/map/transform_state.hpp | 28 |
4 files changed, 86 insertions, 489 deletions
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt deleted file mode 100644 index dc313b5f64..0000000000 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt +++ /dev/null @@ -1,421 +0,0 @@ -package com.mapbox.mapboxsdk.maps - -import android.content.Context -import android.graphics.PointF -import android.support.test.InstrumentationRegistry -import android.support.test.annotation.UiThreadTest -import android.support.test.runner.AndroidJUnit4 -import com.mapbox.mapboxsdk.AppCenter -import com.mapbox.mapboxsdk.camera.CameraPosition -import com.mapbox.mapboxsdk.geometry.LatLng -import com.mapbox.mapboxsdk.geometry.LatLngBounds -import com.mapbox.mapboxsdk.geometry.ProjectedMeters -import com.mapbox.mapboxsdk.maps.renderer.MapRenderer -import com.mapbox.mapboxsdk.style.layers.TransitionOptions -import com.mapbox.mapboxsdk.testapp.utils.TestConstants -import junit.framework.Assert.* -import org.junit.After -import org.junit.Assert -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class NativeMapViewTest : AppCenter() { - - private lateinit var nativeMapView: NativeMap - - companion object { - const val DELTA = 0.000001 - const val DELTA_BIG = 1.0 - const val BEARING_TEST = 60.0 - const val PITCH_TEST = 40.0 - const val ZOOM_TEST = 16.0 - val PADDING_TEST = doubleArrayOf(80.0, 150.0, 0.0, 0.0) - const val WIDTH = 500 - const val HEIGHT = WIDTH - val LATLNG_TEST = LatLng(12.0, 34.0) - } - - @Before - @UiThreadTest - fun before() { - val context = InstrumentationRegistry.getContext() - nativeMapView = NativeMapView(context, 2.0f, false, null, null, DummyRenderer(context)) - nativeMapView.resizeView(WIDTH, HEIGHT) - } - - @After - @UiThreadTest - fun after() { - nativeMapView.destroy() - } - - @Test - @UiThreadTest - fun testSetStyleUrl() { - val expected = Style.DARK - nativeMapView.styleUri = expected - val actual = nativeMapView.styleUri - assertEquals("Style URL should match", expected, actual) - } - - @Test - @UiThreadTest - fun testSetStyleJson() { - val expected = "{}" - nativeMapView.styleJson = expected - val actual = nativeMapView.styleJson - assertEquals("Style JSON should match", expected, actual) - } - - @Test - @UiThreadTest - fun testBearing() { - val expected = BEARING_TEST - nativeMapView.setBearing(expected, 0) - val actual = nativeMapView.bearing - assertEquals("Bearing should match", expected, actual, DELTA) - } - - @Test - @UiThreadTest - fun testLatLng() { - val expected = LATLNG_TEST - nativeMapView.setLatLng(expected, 0) - val actual = nativeMapView.latLng - assertEquals("Latitude should match", expected.latitude, actual.latitude, DELTA) - assertEquals("Longitude should match", expected.longitude, actual.longitude, DELTA) - } - - @Test - @UiThreadTest - fun testLatLngPadding() { - val expected = LATLNG_TEST - nativeMapView.contentPadding = PADDING_TEST - nativeMapView.setLatLng(expected, 0) - val actual = nativeMapView.latLng - assertEquals("Latitude should match", expected.latitude, actual.latitude, DELTA) - assertEquals("Longitude should match", expected.longitude, actual.longitude, DELTA) - Assert.assertArrayEquals(PADDING_TEST, nativeMapView.cameraPosition.padding, DELTA) - } - - @Test - @UiThreadTest - fun testLatLngDefault() { - val expected = LatLng() - val actual = nativeMapView.latLng - assertEquals("Latitude should match", expected.latitude, actual.latitude, DELTA) - assertEquals("Longitude should match", expected.longitude, actual.longitude, DELTA) - } - - @Test - @UiThreadTest - fun testBearingDefault() { - val expected = 0.0 - val actual = nativeMapView.bearing - assertEquals("Bearing should match", expected, actual, DELTA) - } - - @Test - @UiThreadTest - fun testPitch() { - val expected = PITCH_TEST - nativeMapView.setPitch(expected, 0) - val actual = nativeMapView.pitch - assertEquals("Pitch should match", expected, actual, DELTA) - } - - @Test - @UiThreadTest - fun testPitchDefault() { - val expected = 0.0 - val actual = nativeMapView.pitch - assertEquals("Pitch should match", expected, actual, DELTA) - } - - @Test - @UiThreadTest - fun testZoom() { - val expected = ZOOM_TEST - nativeMapView.setZoom(expected, PointF(0.0f, 0.0f), 0) - val actual = nativeMapView.zoom - assertEquals("Zoom should match", expected, actual, DELTA) - } - - @Test - @UiThreadTest - fun testZoomDefault() { - val expected = 0.0 - val actual = nativeMapView.zoom - assertEquals("Zoom should match", expected, actual, DELTA) - } - - @Test - @UiThreadTest - fun testJumpTo() { - val expected = CameraPosition.Builder() - .bearing(BEARING_TEST) - .target(LATLNG_TEST) - .tilt(PITCH_TEST) - .zoom(ZOOM_TEST) - .padding(PADDING_TEST) - .build() - // verify that the lazily set padding is ignored when a value is provided with the camera - nativeMapView.contentPadding = doubleArrayOf(1.0, 2.0, 3.0, 4.0) - nativeMapView.jumpTo(LATLNG_TEST, ZOOM_TEST, PITCH_TEST, BEARING_TEST, PADDING_TEST) - val actual = nativeMapView.cameraPosition - assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, DELTA) - assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, DELTA) - assertEquals("Bearing should match", expected.bearing, actual.bearing, DELTA) - assertEquals("Pitch should match", expected.tilt, actual.tilt, DELTA) - assertEquals("Zoom should match", expected.zoom, actual.zoom, DELTA) - Assert.assertArrayEquals(expected.padding, actual.padding, DELTA) - } - - @Test - @UiThreadTest - fun testLatLngForPixel() { - val expected = LATLNG_TEST - nativeMapView.setLatLng(LATLNG_TEST, 0) - val actual = nativeMapView.latLngForPixel( - PointF((WIDTH / 2).toFloat(), (HEIGHT / 2).toFloat()) - ) - assertEquals("Latitude should match", expected.latitude, actual.latitude, DELTA_BIG) - assertEquals("Longitude should match", expected.longitude, actual.longitude, DELTA_BIG) - } - - @Test - @UiThreadTest - fun testPixelForLatLng() { - val expected = PointF((WIDTH / 2).toFloat(), (HEIGHT / 2).toFloat()) - nativeMapView.setLatLng(LATLNG_TEST, 0) - val actual = nativeMapView.pixelForLatLng(LATLNG_TEST) - assertEquals("X should match", expected.x.toDouble(), actual.x.toDouble(), DELTA_BIG) - assertEquals("Y should match", expected.y.toDouble(), actual.y.toDouble(), DELTA_BIG) - } - - @Test - @UiThreadTest - fun testPrefetchTilesTrue() { - val expected = true - nativeMapView.prefetchTiles = true - val actual = nativeMapView.prefetchTiles - assertEquals("Flag should match", expected, actual) - } - - @Test - @UiThreadTest - fun testPrefetchTilesFalse() { - val expected = false - nativeMapView.prefetchTiles = false - val actual = nativeMapView.prefetchTiles - assertEquals("Flag should match", expected, actual) - } - - @Test - @UiThreadTest - fun testPrefetchTilesDefault() { - val expected = true - val actual = nativeMapView.prefetchTiles - assertEquals("Flag should match", expected, actual) - } - - @Test - @UiThreadTest - fun testPrefetchZoomDelta() { - val expected = 2 - nativeMapView.prefetchZoomDelta = 2 - val actual = nativeMapView.prefetchZoomDelta - assertEquals("Prefetch zoom delta should match", expected, actual) - } - - @Test - @UiThreadTest - fun testPrefetchZoomDeltaDefault() { - val expected = 4 - val actual = nativeMapView.prefetchZoomDelta - assertEquals("Prefetch zoom delta should match", expected, actual) - } - - @Test - @UiThreadTest - fun testSetContentPadding() { - val expected = doubleArrayOf(1.0, 2.0, 3.0, 4.0) - nativeMapView.contentPadding = expected - val actual = nativeMapView.contentPadding - assertEquals("Left should match", expected[0], actual[0]) - assertEquals("Top should match", expected[1], actual[1]) - assertEquals("Right should match", expected[2], actual[2]) - assertEquals("Bottom should match", expected[3], actual[3]) - } - - @Test - @UiThreadTest - fun testSetMinZoom() { - val expected = 12.0 - nativeMapView.minZoom = expected - val actual = nativeMapView.minZoom - assertEquals("Min zoom should match", expected, actual) - } - - @Test - @UiThreadTest - fun testSetMaxZoom() { - val expected = 12.0 - nativeMapView.maxZoom = expected - val actual = nativeMapView.maxZoom - assertEquals("Max zoom should match", expected, actual) - } - - @Test - @UiThreadTest - fun testGetProjectedMetersAtLatitude() { - val expected = 77973.67021115532 - val actual = nativeMapView.getMetersPerPixelAtLatitude(5.0) - assertEquals("Get projected meters should match", expected, actual) - } - - @Test - @UiThreadTest - fun testLatLngForProjectedMeters() { - val expected = LatLng(0.01796630538796444, 0.02694945852363162) - val actual = nativeMapView.latLngForProjectedMeters(ProjectedMeters(2000.0, 3000.0)) - assertEquals("Lat for projected meters", expected.latitude, actual.latitude, DELTA) - assertEquals("Lng for projected meters", expected.longitude, actual.longitude, DELTA) - } - - @Test - @UiThreadTest - fun testFlyTo() { - val expected = CameraPosition.Builder() - .zoom(12.0) - .tilt(30.0) - .target(LatLng(12.0, 14.0)) - .bearing(20.0) - .padding(PADDING_TEST) - .build() - // verify that the lazily set padding is ignored when a value is provided with the camera - nativeMapView.contentPadding = doubleArrayOf(1.0, 2.0, 3.0, 4.0) - nativeMapView.flyTo(expected.target, expected.zoom, expected.bearing, expected.tilt, PADDING_TEST, 0) - val actual = nativeMapView.cameraPosition - assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA) - assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA) - assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA) - Assert.assertArrayEquals(expected.padding, actual.padding, DELTA) - } - - @Test - @UiThreadTest - fun testEaseTo() { - val expected = CameraPosition.Builder() - .zoom(12.0) - .tilt(30.0) - .target(LatLng(12.0, 14.0)) - .bearing(20.0) - .padding(PADDING_TEST) - .build() - // verify that the lazily set padding is ignored when a value is provided with the camera - nativeMapView.contentPadding = doubleArrayOf(1.0, 2.0, 3.0, 4.0) - nativeMapView.easeTo(expected.target, expected.zoom, expected.bearing, expected.tilt, PADDING_TEST, 0, false) - val actual = nativeMapView.cameraPosition - assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA) - assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA) - assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA) - Assert.assertArrayEquals(expected.padding, actual.padding, DELTA) - } - - @Test - @UiThreadTest - fun testResetPosition() { - val expected = CameraPosition.Builder() - .zoom(0.0) - .tilt(0.0) - .target(LatLng(0.0, 0.0)) - .bearing(0.0) - .padding(PADDING_TEST) - .build() - nativeMapView.jumpTo(LatLng(1.0, 2.0), 12.0, 23.0, 1.0, PADDING_TEST) - nativeMapView.resetPosition() - val actual = nativeMapView.cameraPosition - assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA) - assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA) - assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA) - Assert.assertArrayEquals(expected.padding, actual.padding, DELTA) - } - - @Test - @UiThreadTest - fun testGetCameraForLatLngBounds() { - val expected = CameraPosition.Builder() - .zoom(3.5258764777024005) - .tilt(0.0) - .target(LatLng(23.182767623652808, 13.999999999994088)) - .bearing(0.0) - .build() - val actual = nativeMapView.getCameraForLatLngBounds( - LatLngBounds.from(30.0, 16.0, 16.0, 12.0), - intArrayOf(0, 0, 0, 0), - 0.0, - 0.0 - ) - assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA) - assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA) - assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA) - } - - @Test - @UiThreadTest - fun testMoveBy() { - val expected = CameraPosition.Builder() - .zoom(0.0) - .tilt(0.0) - .target(LatLng(4.21494310024160, -4.218749958739409)) - .bearing(0.0) - .build() - nativeMapView.moveBy(12.0, 12.0, 0) - val actual = nativeMapView.cameraPosition - assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA) - assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA) - assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA) - assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA) - } - - @Test - @UiThreadTest - fun testTransitionOptions() { - val transitionOptions = TransitionOptions(500, 500) - nativeMapView.transitionOptions = transitionOptions - assertTrue(transitionOptions.isEnablePlacementTransitions) - assertEquals(transitionOptions, nativeMapView.transitionOptions) - } - - @Test - @UiThreadTest - fun testTransitionOptions_disablePlacementTransitions() { - val transitionOptions = TransitionOptions(500, 500, false) - nativeMapView.transitionOptions = transitionOptions - assertFalse(transitionOptions.isEnablePlacementTransitions) - assertEquals(transitionOptions, nativeMapView.transitionOptions) - } - - class DummyRenderer(context: Context) : MapRenderer(context, null) { - - override fun requestRender() { - // no-op - } - - override fun queueEvent(runnable: Runnable?) { - // no-op - } - } -}
\ No newline at end of file diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 97d4fb4681..66b4809ccc 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -127,14 +127,15 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim // Minimize rotation by taking the shorter path around the circle. bearing = _normalizeAngle(bearing, state.getBearing()); - state.setProperties(TransformStateProperties().withBearing(_normalizeAngle(state.getBearing(), bearing))); + state.setBearing(_normalizeAngle(state.getBearing(), bearing)); const double startZoom = state.getZoom(); const double startBearing = state.getBearing(); const double startPitch = state.getPitch(); - state.setPanning(unwrappedLatLng != startLatLng); - state.setScaling(zoom != startZoom); - state.setRotating(bearing != startBearing); + state.setProperties(TransformStateProperties() + .withPanning(unwrappedLatLng != startLatLng) + .withScaling(zoom != startZoom) + .withRotating(bearing != startBearing)); const EdgeInsets startEdgeInsets = state.getEdgeInsets(); startTransition( @@ -145,26 +146,21 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim LatLng frameLatLng = Projection::unproject(framePoint, state.zoomScale(startZoom)); double frameZoom = util::interpolate(startZoom, zoom, t); state.setLatLngZoom(frameLatLng, frameZoom); - TransformStateProperties properties; if (bearing != startBearing) { - properties.withBearing(util::wrap(util::interpolate(startBearing, bearing, t), -M_PI, M_PI)); + state.setBearing(util::wrap(util::interpolate(startBearing, bearing, t), -M_PI, M_PI)); } - double maxPitch; if (padding != startEdgeInsets) { // Interpolate edge insets - EdgeInsets edgeInsets{util::interpolate(startEdgeInsets.top(), padding.top(), t), - util::interpolate(startEdgeInsets.left(), padding.left(), t), - util::interpolate(startEdgeInsets.bottom(), padding.bottom(), t), - util::interpolate(startEdgeInsets.right(), padding.right(), t)}; - properties.withEdgeInsets(edgeInsets); - maxPitch = getMaxPitchForEdgeInsets(edgeInsets); - } else { - maxPitch = getMaxPitchForEdgeInsets(state.getEdgeInsets()); + EdgeInsets edgeInsets; + state.setEdgeInsets({util::interpolate(startEdgeInsets.top(), padding.top(), t), + util::interpolate(startEdgeInsets.left(), padding.left(), t), + util::interpolate(startEdgeInsets.bottom(), padding.bottom(), t), + util::interpolate(startEdgeInsets.right(), padding.right(), t)}); } + double maxPitch = getMaxPitchForEdgeInsets(state.getEdgeInsets()); if (pitch != startPitch || maxPitch < startPitch) { - properties.withPitch(std::min(maxPitch, util::interpolate(startPitch, pitch, t))); + state.setPitch(std::min(maxPitch, util::interpolate(startPitch, pitch, t))); } - state.setProperties(properties); }, duration); } @@ -204,7 +200,7 @@ void Transform::flyTo(const CameraOptions& camera, const AnimationOptions& anima // Minimize rotation by taking the shorter path around the circle. bearing = _normalizeAngle(bearing, state.getBearing()); - state.setProperties(TransformStateProperties().withBearing(_normalizeAngle(state.getBearing(), bearing))); + state.setBearing(_normalizeAngle(state.getBearing(), bearing)); const double startZoom = state.scaleZoom(state.getScale()); const double startBearing = state.getBearing(); const double startPitch = state.getPitch(); @@ -297,9 +293,8 @@ void Transform::flyTo(const CameraOptions& camera, const AnimationOptions& anima } const double startScale = state.getScale(); - state.setPanning(true); - state.setScaling(true); - state.setRotating(bearing != startBearing); + state.setProperties( + TransformStateProperties().withPanning(true).withScaling(true).withRotating(bearing != startBearing)); const EdgeInsets startEdgeInsets = state.getEdgeInsets(); startTransition( @@ -324,26 +319,22 @@ void Transform::flyTo(const CameraOptions& camera, const AnimationOptions& anima // Convert to geographic coordinates and set the new viewpoint. LatLng frameLatLng = Projection::unproject(framePoint, startScale); state.setLatLngZoom(frameLatLng, frameZoom); - TransformStateProperties properties; if (bearing != startBearing) { - properties.withBearing(util::wrap(util::interpolate(startBearing, bearing, k), -M_PI, M_PI)); + state.setBearing(util::wrap(util::interpolate(startBearing, bearing, k), -M_PI, M_PI)); } - double maxPitch; + if (padding != startEdgeInsets) { // Interpolate edge insets - EdgeInsets edgeInsets{util::interpolate(startEdgeInsets.top(), padding.top(), k), - util::interpolate(startEdgeInsets.left(), padding.left(), k), - util::interpolate(startEdgeInsets.bottom(), padding.bottom(), k), - util::interpolate(startEdgeInsets.right(), padding.right(), k)}; - properties.withEdgeInsets(edgeInsets); - maxPitch = getMaxPitchForEdgeInsets(edgeInsets); - } else { - maxPitch = getMaxPitchForEdgeInsets(state.getEdgeInsets()); + state.setEdgeInsets({util::interpolate(startEdgeInsets.top(), padding.top(), k), + util::interpolate(startEdgeInsets.left(), padding.left(), k), + util::interpolate(startEdgeInsets.bottom(), padding.bottom(), k), + util::interpolate(startEdgeInsets.right(), padding.right(), k)}); } + double maxPitch = getMaxPitchForEdgeInsets(state.getEdgeInsets()); + if (pitch != startPitch || maxPitch < startPitch) { - properties.withPitch(std::min(maxPitch, util::interpolate(startPitch, pitch, k))); + state.setPitch(std::min(maxPitch, util::interpolate(startPitch, pitch, k))); } - state.setProperties(properties); }, duration); } @@ -450,7 +441,7 @@ ConstrainMode Transform::getConstrainMode() const { #pragma mark - Viewport mode void Transform::setViewportMode(mbgl::ViewportMode mode) { - state.setProperties(TransformStateProperties().withViewportMode(mode)); + state.setViewportMode(mode); } ViewportMode Transform::getViewportMode() const { @@ -525,13 +516,12 @@ void Transform::startTransition(const CameraOptions& camera, }; transitionFinishFn = [isAnimated, animation, this] { - state.setPanning(false); - state.setScaling(false); - state.setRotating(false); + state.setProperties(TransformStateProperties().withPanning(false).withScaling(false).withRotating(false)); if (animation.transitionFinishFn) { animation.transitionFinishFn(); } - observer.onCameraDidChange(isAnimated ? MapObserver::CameraChangeMode::Animated : MapObserver::CameraChangeMode::Immediate); + observer.onCameraDidChange(isAnimated ? MapObserver::CameraChangeMode::Animated + : MapObserver::CameraChangeMode::Immediate); }; if (!isAnimated) { @@ -618,8 +608,7 @@ LatLng Transform::screenCoordinateToLatLng(const ScreenCoordinate& point, LatLng return state.screenCoordinateToLatLng(flippedPoint, wrapMode); } -double Transform::getMaxPitchForEdgeInsets(const EdgeInsets &insets) const -{ +double Transform::getMaxPitchForEdgeInsets(const EdgeInsets& insets) const { double centerOffsetY = 0.5 * (insets.top() - insets.bottom()); // See TransformState::getCenterOffset. const auto height = state.getSize().height; diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 6dcc2a8545..39be04c908 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -8,7 +8,6 @@ #include <mbgl/math/clamp.hpp> namespace mbgl { - TransformState::TransformState(ConstrainMode constrainMode_, ViewportMode viewportMode_) : bounds(LatLngBounds()), constrainMode(constrainMode_), viewportMode(viewportMode_) {} @@ -37,6 +36,15 @@ void TransformState::setProperties(const TransformStateProperties& properties) { if (properties.axonometric) { setAxonometric(*properties.axonometric); } + if (properties.panning) { + setPanning(*properties.panning); + } + if (properties.scaling) { + setScaling(*properties.scaling); + } + if (properties.rotating) { + setRotating(*properties.rotating); + } if (properties.edgeInsets) { setEdgeInsets(*properties.edgeInsets); } @@ -52,7 +60,6 @@ void TransformState::setProperties(const TransformStateProperties& properties) { if (properties.viewPortMode) { setViewportMode(*properties.viewPortMode); } - updateMatrix(); } #pragma mark - Matrix @@ -62,9 +69,8 @@ void TransformState::matrixFor(mat4& matrix, const UnwrappedTileID& tileID) cons const double s = Projection::worldSize(scale) / tileScale; matrix::identity(matrix); - matrix::translate(matrix, matrix, - int64_t(tileID.canonical.x + tileID.wrap * tileScale) * s, - int64_t(tileID.canonical.y) * s, 0); + matrix::translate( + matrix, matrix, int64_t(tileID.canonical.x + tileID.wrap * tileScale) * s, int64_t(tileID.canonical.y) * s, 0); matrix::scale(matrix, matrix, s / util::EXTENT, s / util::EXTENT, 1); } @@ -108,10 +114,18 @@ void TransformState::getProjMatrix(mat4& projMatrix, uint16_t nearZ, bool aligne using NO = NorthOrientation; switch (getNorthOrientation()) { - case NO::Rightwards: matrix::rotate_y(projMatrix, projMatrix, getPitch()); break; - case NO::Downwards: matrix::rotate_x(projMatrix, projMatrix, -getPitch()); break; - case NO::Leftwards: matrix::rotate_y(projMatrix, projMatrix, -getPitch()); break; - default: matrix::rotate_x(projMatrix, projMatrix, getPitch()); break; + case NO::Rightwards: + matrix::rotate_y(projMatrix, projMatrix, getPitch()); + break; + case NO::Downwards: + matrix::rotate_x(projMatrix, projMatrix, -getPitch()); + break; + case NO::Leftwards: + matrix::rotate_y(projMatrix, projMatrix, -getPitch()); + break; + default: + matrix::rotate_x(projMatrix, projMatrix, getPitch()); + break; } matrix::rotate_z(projMatrix, projMatrix, getBearing() + getNorthOrientationAngle()); @@ -147,13 +161,11 @@ void TransformState::getProjMatrix(mat4& projMatrix, uint16_t nearZ, bool aligne } } -void TransformState::updateMatrix() { - if (size.isEmpty()) { - return; - } - if (matrixUpdated) return; +void TransformState::updateMatrix() const { + if (matrixUpdated || size.isEmpty()) return; + getProjMatrix(projectionMatrix); - coordMatrix = coordinatePointMatrix(); + coordMatrix = coordinatePointMatrix(projectionMatrix); bool err = matrix::invert(invertedMatrix, coordMatrix); @@ -452,7 +464,8 @@ ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng) vec4 p; Point<double> pt = Projection::project(latLng, scale) / util::tileSize; - vec4 c = {{ pt.x, pt.y, 0, 1 }}; + vec4 c = {{pt.x, pt.y, 0, 1}}; + updateMatrix(); matrix::transformMat4(p, c, coordMatrix); return {p[0] / p[3], size.height - p[1] / p[3]}; } @@ -470,9 +483,10 @@ TileCoordinate TransformState::screenCoordinateToTileCoordinate(const ScreenCoor // unproject two points to get a line and then find the point on that // line with z=0 + updateMatrix(); vec4 coord0; vec4 coord1; - vec4 point0 = {{ point.x, flippedY, 0, 1 }}; + vec4 point0 = {{point.x, flippedY, 0, 1}}; vec4 point1 = {{point.x, flippedY, 1, 1}}; matrix::transformMat4(coord0, point0, invertedMatrix); matrix::transformMat4(coord1, point1, invertedMatrix); @@ -496,8 +510,8 @@ LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, L return Projection::unproject(coord.p, 1 / util::tileSize, wrapMode); } -mat4 TransformState::coordinatePointMatrix() const { - mat4 proj = projectionMatrix; +mat4 TransformState::coordinatePointMatrix(const mat4& projMatrix) const { + mat4 proj = projMatrix; matrix::scale(proj, proj, util::tileSize, util::tileSize, 1); matrix::multiply(proj, getPixelMatrix(), proj); return proj; @@ -579,12 +593,12 @@ void TransformState::setScalePoint(const double newScale, const ScreenCoordinate Bc = Projection::worldSize(scale) / util::DEGREES_MAX; Cc = Projection::worldSize(scale) / util::M2PI; matrixUpdated = false; - updateMatrix(); } float TransformState::getCameraToTileDistance(const UnwrappedTileID& tileID) const { mat4 tileProjectionMatrix; matrixFor(tileProjectionMatrix, tileID); + updateMatrix(); matrix::multiply(tileProjectionMatrix, projectionMatrix, tileProjectionMatrix); vec4 tileCenter = {{util::tileSize / 2, util::tileSize / 2, 0, 1}}; vec4 projectedCenter; @@ -601,6 +615,7 @@ float TransformState::maxPitchScaleFactor() const { Point<double> pt = Projection::project(latLng, scale) / util::tileSize; vec4 p = {{ pt.x, pt.y, 0, 1 }}; vec4 topPoint; + updateMatrix(); matrix::transformMat4(topPoint, p, coordMatrix); return topPoint[3] / getCameraToCenterDistance(); } diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 572146ae71..018958751d 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -52,6 +52,18 @@ struct TransformStateProperties { axonometric = val; return *this; } + TransformStateProperties& withPanning(const optional<bool>& val) { + panning = val; + return *this; + } + TransformStateProperties& withScaling(const optional<bool>& val) { + scaling = val; + return *this; + } + TransformStateProperties& withRotating(const optional<bool>& val) { + rotating = val; + return *this; + } TransformStateProperties& withEdgeInsets(const optional<EdgeInsets>& val) { edgeInsets = val; return *this; @@ -77,11 +89,13 @@ struct TransformStateProperties { optional<double> y; optional<double> bearing; optional<double> scale; - optional<double> fov; optional<double> pitch; optional<double> xSkew; optional<double> ySkew; optional<bool> axonometric; + optional<bool> panning; + optional<bool> scaling; + optional<bool> rotating; optional<EdgeInsets> edgeInsets; optional<Size> size; optional<ConstrainMode> constrain; @@ -199,7 +213,7 @@ public: private: bool rotatedNorth() const; - void updateMatrix(); + void updateMatrix() const; // Viewport center offset, from [size.width / 2, size.height / 2], defined // by |edgeInsets| in screen coordinates, with top left origin. @@ -216,7 +230,7 @@ private: // logical dimensions Size size; - mat4 coordinatePointMatrix() const; + mat4 coordinatePointMatrix(const mat4& projMatrix) const; mat4 getPixelMatrix() const; void setScalePoint(const double scale, const ScreenCoordinate& point); @@ -251,10 +265,10 @@ private: double Bc = Projection::worldSize(scale) / util::DEGREES_MAX; double Cc = Projection::worldSize(scale) / util::M2PI; - bool matrixUpdated{false}; - mat4 projectionMatrix; - mat4 coordMatrix; - mat4 invertedMatrix; + mutable bool matrixUpdated{false}; + mutable mat4 projectionMatrix; + mutable mat4 coordMatrix; + mutable mat4 invertedMatrix; }; } // namespace mbgl |