Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods to access projection #380

Merged
merged 8 commits into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions android/src/main/java/com/mapbox/mapboxgl/MapboxMapController.java
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,22 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) {
result.success(reply);
break;
}
case "map#toScreenLocation": {
Map<String, Object> reply = new HashMap<>();
PointF pointf = mapboxMap.getProjection().toScreenLocation(new LatLng(call.argument("latitude"),call.argument("longitude")));
reply.put("x", pointf.x);
reply.put("y", pointf.y);
result.success(reply);
break;
}
case "map#toLatLng": {
Map<String, Object> reply = new HashMap<>();
LatLng latlng = mapboxMap.getProjection().fromScreenLocation(new PointF( ((Double) call.argument("x")).floatValue(), ((Double) call.argument("y")).floatValue()));
reply.put("latitude", latlng.getLatitude());
reply.put("longitude", latlng.getLongitude());
result.success(reply);
break;
}
case "camera#move": {
final CameraUpdate cameraUpdate = Convert.toCameraUpdate(call.argument("cameraUpdate"), mapboxMap, density);
if (cameraUpdate != null) {
Expand Down
6 changes: 6 additions & 0 deletions example/lib/map_ui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:mapbox_gl/mapbox_gl.dart';

Expand Down Expand Up @@ -266,6 +268,10 @@ class MapUiBodyState extends State<MapUiBody> {
},
onMapLongClick: (point, latLng) async {
print("Map long press: ${point.x},${point.y} ${latLng.latitude}/${latLng.longitude}");
Point convertedPoint = await mapController.toScreenLocation(latLng);
LatLng convertedLatLng = await mapController.toLatLng(point);
print("Map long press converted: ${convertedPoint.x},${convertedPoint.y} ${convertedLatLng.latitude}/${convertedLatLng.longitude}");

List features = await mapController.queryRenderedFeatures(point, [], null);
if (features.length>0) {
print(features[0]);
Expand Down
20 changes: 20 additions & 0 deletions ios/Classes/MapboxMapController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,26 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
reply["sw"] = [visibleRegion.sw.latitude, visibleRegion.sw.longitude] as NSObject
reply["ne"] = [visibleRegion.ne.latitude, visibleRegion.ne.longitude] as NSObject
result(reply)
case "map#toScreenLocation":
guard let arguments = methodCall.arguments as? [String: Any] else { return }
guard let latitude = arguments["latitude"] as? Double else { return }
guard let longitude = arguments["longitude"] as? Double else { return }
let latlng = CLLocationCoordinate2DMake(latitude, longitude)
let returnVal = mapView.convert(latlng, toPointTo: mapView)
var reply = [String: NSObject]()
reply["x"] = returnVal.x as NSObject
reply["y"] = returnVal.y as NSObject
result(reply)
case "map#toLatLng":
guard let arguments = methodCall.arguments as? [String: Any] else { return }
guard let x = arguments["x"] as? Double else { return }
guard let y = arguments["y"] as? Double else { return }
let screenPoint: CGPoint = CGPoint(x: y, y:y)
let coordinates: CLLocationCoordinate2D = mapView.convert(screenPoint, toCoordinateFrom: mapView)
var reply = [String: NSObject]()
reply["latitude"] = coordinates.latitude as NSObject
reply["longitude"] = coordinates.longitude as NSObject
result(reply)
case "camera#move":
guard let arguments = methodCall.arguments as? [String: Any] else { return }
guard let cameraUpdate = arguments["cameraUpdate"] as? [Any] else { return }
Expand Down
2 changes: 1 addition & 1 deletion lib/mapbox_gl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export 'package:mapbox_gl_platform_interface/mapbox_gl_platform_interface.dart'
Line,
LineOptions;

part 'src/bitmap.dart';

part 'src/controller.dart';
part 'src/mapbox_map.dart';
part 'src/global.dart';
49 changes: 0 additions & 49 deletions lib/src/bitmap.dart

This file was deleted.

17 changes: 17 additions & 0 deletions lib/src/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -670,4 +670,21 @@ class MapboxMapController extends ChangeNotifier {
await MapboxGlPlatform.getInstance(_id)
.setSymbolTextIgnorePlacement(enable);
}

/// Returns the point on the screen that corresponds to a geographical coordinate ([latLng]). The screen location is in screen pixels (not display pixels) relative to the top left of the map (not of the whole screen)
///
/// Note: The resulting x and y coordinates are rounded to [int] on web, on other platforms they may differ very slightly (in the range of about 10^-10) from the actual nearest screen coordinate.
/// You therefore might want to round them appropriately, depending on your use case.
///
/// Returns null if [latLng] is not currently visible on the map.
Future<Point> toScreenLocation(LatLng latLng) async{
return MapboxGlPlatform.getInstance(_id).toScreenLocation(latLng);
}

/// Returns the geographic location (as [LatLng]) that corresponds to a point on the screen. The screen location is specified in screen pixels (not display pixels) relative to the top left of the map (not the top left of the whole screen).
Future<LatLng> toLatLng(Point screenLocation) async{
return MapboxGlPlatform.getInstance(_id).toLatLng(screenLocation);
}


}
1 change: 1 addition & 0 deletions mapbox_gl_platform_interface/lib/src/location.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,4 @@ class LatLngBounds {
@override
int get hashCode => hashValues(southwest, northeast);
}

Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,14 @@ abstract class MapboxGlPlatform {
throw UnimplementedError(
'setSymbolTextIgnorePlacement() has not been implemented.');
}

Future<Point> toScreenLocation(LatLng latLng) async{
throw UnimplementedError(
'toScreenLocation() has not been implemented.');
}

Future<LatLng> toLatLng(Point screenLocation) async{
throw UnimplementedError(
'toLatLng() has not been implemented.');
}
}
51 changes: 39 additions & 12 deletions mapbox_gl_platform_interface/lib/src/method_channel_mapbox_gl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -182,23 +182,22 @@ class MethodChannelMapboxGl extends MapboxGlPlatform {
}

@override
Future<List<Symbol>> addSymbols(List<SymbolOptions> options, [List<Map> data]) async {
Future<List<Symbol>> addSymbols(List<SymbolOptions> options,
[List<Map> data]) async {
final List<dynamic> symbolIds = await _channel.invokeMethod(
'symbols#addAll',
<String, dynamic>{
'options': options.map((o) => o.toJson()).toList(),
},
);
final List<Symbol> symbols = symbolIds.asMap().map(
(i, id) => MapEntry(
final List<Symbol> symbols = symbolIds
.asMap()
.map((i, id) => MapEntry(
i,
Symbol(
id,
options.elementAt(i),
data != null && data.length > i ? data.elementAt(i) : null
)
)
).values.toList();
Symbol(id, options.elementAt(i),
data != null && data.length > i ? data.elementAt(i) : null)))
.values
.toList();

return symbols;
}
Expand All @@ -212,7 +211,7 @@ class MethodChannelMapboxGl extends MapboxGlPlatform {
}

@override
Future<LatLng> getSymbolLatLng(Symbol symbol) async{
Future<LatLng> getSymbolLatLng(Symbol symbol) async {
Map mapLatLng =
await _channel.invokeMethod('symbol#getGeometry', <String, dynamic>{
'symbol': symbol._id,
Expand Down Expand Up @@ -249,7 +248,7 @@ class MethodChannelMapboxGl extends MapboxGlPlatform {
}

@override
Future<List<LatLng>> getLineLatLngs(Line line) async{
Future<List<LatLng>> getLineLatLngs(Line line) async {
List latLngList =
await _channel.invokeMethod('line#getGeometry', <String, dynamic>{
'line': line._id,
Expand Down Expand Up @@ -453,4 +452,32 @@ class MethodChannelMapboxGl extends MapboxGlPlatform {
return new Future.error(e);
}
}

@override
Future<Point> toScreenLocation(LatLng latLng) async {
try {
var screenPosMap = await _channel
.invokeMethod('map#toScreenLocation', <String, dynamic>{
'latitude': latLng.latitude,
'longitude':latLng.longitude,
});
return Point(screenPosMap['x'], screenPosMap['y']);
} on PlatformException catch (e) {
return new Future.error(e);
}
}

@override
Future<LatLng> toLatLng(Point screenLocation) async {
try {
var latLngMap = await _channel
.invokeMethod('map#toLatLng', <String, dynamic>{
'x': screenLocation.x,
'y':screenLocation.y,
});
return LatLng(latLngMap['latitude'], latLngMap['longitude']);
} on PlatformException catch (e) {
return new Future.error(e);
}
}
}
12 changes: 12 additions & 0 deletions mapbox_gl_web/lib/src/mapbox_map_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -611,4 +611,16 @@ class MapboxMapController extends MapboxGlPlatform
_map.keyboard.disable();
}
}

@override
Future<Point> toScreenLocation(LatLng latLng) async {
var screenPosition = _map.project(LngLat(latLng.longitude, latLng.latitude));
return Point(screenPosition.x.round(), screenPosition.y.round());
}

@override
Future<LatLng> toLatLng(Point screenLocation) async {
var lngLat = _map.unproject(mapbox.Point(screenLocation.x, screenLocation.y));
return LatLng(lngLat.lat, lngLat.lng);
}
}