summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzmiao <miao.zhao@mapbox.com>2019-12-03 11:11:29 +0200
committerzmiao <miao.zhao@mapbox.com>2019-12-05 16:47:15 +0200
commit3a4154642ec6f6297979b40c794f5a4751b69e7d (patch)
tree59a6ff38edf9d693d5515ec1a71f71a74abdd072
parentadd1d53b60247ad3123d3be1f6919ce729960d11 (diff)
downloadqtlocation-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.kt421
-rw-r--r--src/mbgl/map/transform.cpp71
-rw-r--r--src/mbgl/map/transform_state.cpp55
-rw-r--r--src/mbgl/map/transform_state.hpp28
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