Created
December 6, 2024 16:08
-
-
Save ninjaasmoke/4b80b1f8733a4eef15f93108f6b4fa5a to your computer and use it in GitHub Desktop.
a comparison of different implementations for drawing markers on a map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class LatLng { | |
| final double latitude; | |
| final double longitude; | |
| LatLng(this.latitude, this.longitude); | |
| } | |
| class LatLngBounds { | |
| final LatLng southwest; | |
| final LatLng northeast; | |
| LatLngBounds(this.southwest, this.northeast); | |
| bool contains(LatLng point) { | |
| return point.latitude >= southwest.latitude && | |
| point.latitude <= northeast.latitude && | |
| point.longitude >= southwest.longitude && | |
| point.longitude <= northeast.longitude; | |
| } | |
| } | |
| class Marker { | |
| final LatLng position; | |
| Marker(this.position); | |
| } | |
| enum MarkerType { type1, type2, type3 } | |
| class MarkerSource { | |
| final Set<Marker> markers; | |
| MarkerSource(this.markers); | |
| } | |
| Set<Marker> calculateVisibleMarkers1( | |
| LatLngBounds bounds, | |
| Map<MarkerType, MarkerSource> markerSources, | |
| Map<MarkerType, bool> visibility, | |
| Set<Marker> allRenderedMarkers, | |
| ) { | |
| final visibleMarkers = markerSources.values | |
| .map((source) => source.markers.where((marker) => bounds.contains(marker.position))) | |
| .expand((element) => element) | |
| .toSet(); | |
| for (var type in MarkerType.values) { | |
| if (visibility[type] == true) { | |
| visibleMarkers.addAll( | |
| markerSources[type]?.markers.where((marker) => bounds.contains(marker.position)) ?? {}, | |
| ); | |
| } | |
| } | |
| allRenderedMarkers.addAll(visibleMarkers); | |
| return visibleMarkers; | |
| } | |
| Set<Marker> calculateVisibleMarkers2( | |
| LatLngBounds bounds, | |
| Map<MarkerType, MarkerSource> markerSources, | |
| Map<MarkerType, bool> visibility, | |
| Set<Marker> allRenderedMarkers, | |
| ) { | |
| final visibleMarkers = <Marker>{}; | |
| for (var type in MarkerType.values) { | |
| if (visibility[type] == true && markerSources[type] != null) { | |
| visibleMarkers.addAll( | |
| markerSources[type]! | |
| .markers | |
| .where((marker) => bounds.contains(marker.position)), | |
| ); | |
| } | |
| } | |
| if (visibleMarkers.isNotEmpty) { | |
| allRenderedMarkers.addAll(visibleMarkers); | |
| } | |
| return visibleMarkers; | |
| } | |
| Set<Marker> calculateVisibleMarkers3( | |
| LatLngBounds bounds, | |
| Map<MarkerType, MarkerSource> markerSources, | |
| Map<MarkerType, bool> visibility, | |
| Set<Marker> allRenderedMarkers, | |
| ) { | |
| final visibleMarkers = <Marker>{}; | |
| markerSources.forEach((type, source) { | |
| if (visibility[type] == true) { | |
| visibleMarkers.addAll( | |
| source.markers.where((marker) => bounds.contains(marker.position)), | |
| ); | |
| } | |
| }); | |
| allRenderedMarkers.addAll(visibleMarkers); | |
| return visibleMarkers; | |
| } | |
| void exec() { | |
| final bounds = LatLngBounds(LatLng(10, 10), LatLng(20, 20)); | |
| final markers = List.generate( | |
| 400000, (i) => Marker(LatLng(10 + i % 10, 10 + i % 10))).toSet(); | |
| final markerSources = { | |
| MarkerType.type1: MarkerSource(markers), | |
| MarkerType.type2: MarkerSource(markers), | |
| MarkerType.type3: MarkerSource(markers), | |
| }; | |
| final visibility = { | |
| MarkerType.type1: true, | |
| MarkerType.type2: false, | |
| MarkerType.type3: true, | |
| }; | |
| final allRenderedMarkers = <Marker>{}; | |
| final stopwatch = Stopwatch()..start(); | |
| calculateVisibleMarkers1( | |
| bounds, markerSources, visibility, allRenderedMarkers); | |
| stopwatch.stop(); | |
| print('Implementation 1: ${stopwatch.elapsedMilliseconds}ms'); | |
| stopwatch.reset(); | |
| stopwatch.start(); | |
| calculateVisibleMarkers2( | |
| bounds, markerSources, visibility, allRenderedMarkers); | |
| stopwatch.stop(); | |
| print('Implementation 2: ${stopwatch.elapsedMilliseconds}ms'); | |
| stopwatch.reset(); | |
| stopwatch.start(); | |
| calculateVisibleMarkers3( | |
| bounds, markerSources, visibility, allRenderedMarkers); | |
| stopwatch.stop(); | |
| print('Implementation 3: ${stopwatch.elapsedMilliseconds}ms'); | |
| } | |
| void main() { | |
| for (int i = 0; i < 5; ++i) { | |
| print("------------------------------------"); | |
| print("Simulation ${i + 1}"); | |
| exec(); | |
| } | |
| return; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Conclusion:
Implementation 3 consistently outperforms others in terms of time