@@ -30,6 +30,12 @@ class LatLngBounds {
3030 /// The longitude west edge of the bounds
3131 double west;
3232
33+ /// Longitude center.
34+ final double longitudeCenter;
35+
36+ /// Longitude width. Can be more than one world, e.g. more than 360.
37+ final double longitudeWidth;
38+
3339 /// Create new [LatLngBounds] by providing two corners. Both corners have to
3440 /// be on opposite sites but it doesn't matter which opposite corners or in
3541 /// what order the corners are provided.
@@ -63,6 +69,33 @@ class LatLngBounds {
6369 );
6470 }
6571
72+ /// Creates bounds that can be larger than the world, longitude-wise.
73+ LatLngBounds .worldSafe ({
74+ required this .north,
75+ required this .south,
76+ required this .longitudeCenter,
77+ required this .longitudeWidth,
78+ }) : assert (north <= maxLatitude,
79+ "The north latitude can't be bigger than $maxLatitude : $north " ),
80+ assert (north >= minLatitude,
81+ "The north latitude can't be smaller than $minLatitude : $north " ),
82+ assert (south <= maxLatitude,
83+ "The south latitude can't be bigger than $maxLatitude : $south " ),
84+ assert (south >= minLatitude,
85+ "The south latitude can't be smaller than $minLatitude : $south " ),
86+ assert (longitudeCenter <= maxLongitude,
87+ "The longitude center can't be bigger than $maxLongitude : $longitudeCenter " ),
88+ assert (longitudeCenter >= minLongitude,
89+ "The longitude center can't be smaller than $minLongitude : $longitudeCenter " ),
90+ assert (longitudeWidth >= 0 , 'The longitude width must be positive' ),
91+ assert (
92+ north >= south,
93+ "The north latitude ($north ) can't be smaller than the "
94+ 'south latitude ($south )' ,
95+ ),
96+ east = min (longitudeCenter + longitudeWidth / 2 , maxLongitude),
97+ west = max (longitudeCenter - longitudeWidth / 2 , minLongitude);
98+
6699 /// Create a [LatLngBounds] instance from raw edge values.
67100 ///
68101 /// Potentially throws assertion errors if the coordinates exceed their max
@@ -98,15 +131,52 @@ class LatLngBounds {
98131 east >= west,
99132 "The west longitude ($west ) can't be smaller than the "
100133 'east longitude ($east )' ,
101- );
134+ ),
135+ longitudeCenter = (east + west) / 2 ,
136+ longitudeWidth = (east - west).abs ();
102137
103138 /// Create a new [LatLngBounds] from a list of [LatLng] points. This
104139 /// calculates the bounding box of the provided points.
105- factory LatLngBounds .fromPoints (List <LatLng > points) {
140+ factory LatLngBounds .fromPoints (
141+ List <LatLng > points, {
142+ bool drawInSingleWorld = false ,
143+ }) {
106144 assert (
107145 points.isNotEmpty,
108146 'LatLngBounds cannot be created with an empty List of LatLng' ,
109147 );
148+ if (drawInSingleWorld) {
149+ const double halfWorld = 180 ;
150+ double previousLongitude = points.first.longitude;
151+ double minX = previousLongitude;
152+ double maxX = minX;
153+ double minY = maxLatitude;
154+ double maxY = minLatitude;
155+ for (final point in points) {
156+ double longitude = point.longitude;
157+ while (longitude - previousLongitude >= halfWorld) {
158+ longitude -= 2 * halfWorld;
159+ }
160+ while (longitude - previousLongitude <= - halfWorld) {
161+ longitude += 2 * halfWorld;
162+ }
163+ if (minX > longitude) {
164+ minX = longitude;
165+ }
166+ if (maxX < longitude) {
167+ maxX = longitude;
168+ }
169+ if (point.latitude < minY) minY = point.latitude;
170+ if (point.latitude > maxY) maxY = point.latitude;
171+ previousLongitude = longitude;
172+ }
173+ return LatLngBounds .worldSafe (
174+ north: maxY,
175+ south: minY,
176+ longitudeCenter: (maxX + minX) / 2 ,
177+ longitudeWidth: maxX - minX,
178+ );
179+ }
110180 // initialize bounds with max values.
111181 double minX = maxLongitude;
112182 double maxX = minLongitude;
@@ -200,7 +270,7 @@ class LatLngBounds {
200270 }
201271
202272 /// Obtain simple coordinates of the bounds center
203- LatLng get simpleCenter => LatLng ((south + north) / 2 , (east + west) / 2 );
273+ LatLng get simpleCenter => LatLng ((south + north) / 2 , longitudeCenter );
204274
205275 /// Checks whether [point] is inside bounds
206276 bool contains (LatLng point) =>
@@ -221,10 +291,24 @@ class LatLngBounds {
221291 ///
222292 /// Bounding boxes that touch each other but don't overlap are counted as
223293 /// not overlapping.
224- bool isOverlapping (LatLngBounds other) => ! (south > other.north ||
225- north < other.south ||
226- east < other.west ||
227- west > other.east);
294+ bool isOverlapping (LatLngBounds other) {
295+ if (south > other.north || north < other.south) {
296+ return false ;
297+ }
298+ if (longitudeWidth >= 360 || other.longitudeWidth >= 360 ) {
299+ return true ;
300+ }
301+ // TODO may not be relevant for projections without world replication
302+ var delta = longitudeCenter - other.longitudeCenter;
303+ while (delta >= 180 ) {
304+ delta -= 360 ;
305+ }
306+ while (delta <= - 180 ) {
307+ delta += 360 ;
308+ }
309+ delta = delta.abs ();
310+ return delta < longitudeWidth || delta < other.longitudeWidth;
311+ }
228312
229313 @override
230314 int get hashCode => Object .hash (south, north, east, west);
@@ -240,5 +324,7 @@ class LatLngBounds {
240324
241325 @override
242326 String toString () =>
243- 'LatLngBounds(north: $north , south: $south , east: $east , west: $west )' ;
327+ 'LatLngBounds(north: $north , south: $south , east: $east , west: $west )'
328+ ' (longitude center: $longitudeCenter )'
329+ ' (longitude width: $longitudeWidth )' ;
244330}
0 commit comments