You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sorry for hijacking this issue thread like this, but it's probably best to ask about this publicly.
I have taken over maintenance of the latlong2 package today and would like your opinion on whether you need something changed or whether something does not work correctly and needs fixing in that package. flutter_map is by far the most popular package depending on it and, thus, it made sense to me to somehow involve you in the process of finalising a stable 1.0.0 release.
jifalops has published version 0.10.0 yesterday (the first update since 2 years) and I pushed a "hotfix" 0.10.1 just a few minutes ago.
TL;DR: Please let me know if you have any wishes/feature requests for latlong2 :)
While we're talking about latlong2 and version 0.10.1, I've just realized (flutter/flutter#185676 (comment)) that below 1.0.0, "minor" changes are considered "major", and therefore "breaking". For instance, 0.10.1 doesn't match ^0.9.1.
If I had to answer your initial question quickly, I'd say that we have troubles with "latlong segments" and their direction.
If we go from -179 to 179, does it mean 2 degrees west or 358 degrees east? Should it be latlong2's problem?
I'll have another look at the code and I'll get back to you.
While we're talking about latlong2 and version 0.10.1, I've just realized (flutter/flutter#185676 (comment)) that below 1.0.0, "minor" changes are considered "major", and therefore "breaking". For instance, 0.10.1 doesn't match ^0.9.1.
I thought that this was common knowledge! But yes, indeed, I personally would have labelled version 0.10.0 rather 0.9.2 as it did not really break anything. Well, the new hashCodecould theoretically break stuff, but I doubt it, personally.
"The old maintainer" published version 0.10.0 quickly before they transferred the repo over to my profile.
So - sorry for the troubles here. This will be a lot better when 1.0.0 would eventually be published.
If I had to answer your initial question quickly, I'd say that we have troubles with "latlong segments" and their direction.
If we go from -179 to 179, does it mean 2 degrees west or 358 degrees east? Should it be latlong2's problem?
Thanks for the comment! I see... I will think about whether there is something I could change in latlong2 for this or whether it is only worth some documentation.
I'll have another look at the code and I'll get back to you.
No worries and take your time, please!
Besides: 1.0.0-dev.0 is already published over at pub.dev. It contains a major revamp of the entire codebase with quite a lot of (most likely) breaking changes.
All of them should be fixable through renames, though.
This is just to warn you beforehand already!
Thanks for the comment! I see... I will think about whether there is something I could change in latlong2 for this or whether it is only worth some documentation.
It's not a matter of documentation - unless you just mean to say "btw we only support trips from Tokyo to Los Angeles via Europe".
Obviously the problem is not with coordinates, but with list of coordinates.
One way to solve it would be to add an "int worldNumber" field in LatLng. Would start with 0, then - if relevant - would be set to 1 or -1 for the next coordinate (if beyond 180, respectively -180). But that would take extra space for all LatLng objects. Not good.
Another way would be to accept values beyond -180, 180: it wouldn't take more space as there wouldn't be an extra field.
Or create a new LatLngList object, that would help manage that "which world are we talking about?" feature. That wouldn't be a breaking change.
The goal being something like: "I want to list of LatLng without confusion, e.g. to support round the world yacht races".
Hey, thanks for opening this, glad to see its still in safe hands!
I would say that I don't think it's for LatLng to care about what 'world' it's in. LatLng is a mathematical library for representation of coordinates that can also do some geographic maths based on coordinates - I don't know how the distance calculations handle 'worlds', but I'm making the probably inaccurate assumption that they assume the shortest path where no heading is provided, and if a heading is provided to get an offset then it should work as expected.
The 'world' is a very flutter_map construct and I don't think we should 'force' down our requirements onto external libraries - we already have LatLngBounds for example.
I could get behind something like LatLngList and a reworked LatLngBounds in the flutter_map core.
I guess the ability to have a latlng outside the normal bounds may be within the remit of LatLng2 though ? i.e if its -95,-185 or something, which could give a hint, although maybe a bit hacky ? Also I think previously we've thought it would be useful for different crs's (eg pixel flat game world crs, was it CrsSimple ?) to be able to reuse this in flutter_map (could there be a BoundlessLatLng method that skips the min/max checks?) . I'm a bit out of touch if that's still the case though, or if it would break other stuff!
@JaffaKetchup I see things differently, as there are already classes in latlng2, like Path, that definitely would need the concept of world:
classPath<TextendsLatLng> {classPath<TextendsLatLng> {
/// Coordinates managed by this classfinalList<T> _coordinates;
/// For [Distance] calculationsfinalDistance _distance =constDistance();
And distances are computed "in a single world":
doubledistance(finalLatLng p1, finalLatLng p2) {
var a = equatorRadius,
b = polarRadius,
f = flattening; // WGS-84 ellipsoid paramsvar l = p2.longitudeInRad - p1.longitudeInRad; // <======= here, it's problematicvar u1 = math.atan((1- f) * math.tan(p1.latitudeInRad));
var u2 = math.atan((1- f) * math.tan(p2.latitudeInRad));
As a "minor breaking change", I would consider a new method called double distanceWestEast(final LatLng west, final LatLng east), where the longitude difference would be computed correctly. Perhaps deprecating distance too.
Perhaps also the concept of addWest and addEast for Path.
To be continued...
That said, the process could be: let's improve things in flutter_map first, then see how relevant that would be in latlong2 too.
The 'world' is a very flutter_map construct and I don't think we should 'force' down our requirements onto external libraries
Understandable. On the other hand, I also believe that this is something most dependents are somewhat "expecting" from the package.
This is, however, where this (previous) comment kicks in:
One way to solve it would be to add an "int worldNumber" field in LatLng. Would start with 0, then - if relevant - would be set to 1 or -1 for the next coordinate (if beyond 180, respectively -180). But that would take extra space for all LatLng objects. Not good.
Indeed, this was the first thing I was thinking about when thinking through this.
Of course, there could be a subclass for LatLng, which does have that field. But this is not only sub-optimal, but also somehow weird to think about, I believe...
I already thought about improving the current distance function before - by adding a third (optional named) parameter that could be an enum like this:
enumSegmentDirection {
/// Always picks the shortest angular path. May cross the antimeridian.
shortestPath,
/// Always travels eastward (increasing longitude, wrapping at 180).
eastward,
/// Always travels westward (decreasing longitude, wrapping at -180).
westward,
}
Does this make sense? Is there something crucial I am missing?
I should also test how the current approach works with distances that cross either pole and whether something like the enum above would also be needed/useful for those edge cases.
I guess the ability to have a latlng outside the normal bounds may be within the remit of LatLng2 though ?
Yes, version 0.10.0 added a getter LatLng#isValid, which does exactly this. Although, it is not quite correct (IMHO) as it happily accepts both latitude -90 and 90 as valid as well as both longitude -180 and 180.
Hence, there is still some ambiguity for some "evil" inputs.
could there be a BoundlessLatLng method that skips the min/max checks?
0.9.1 should have already removed the assertions two years ago - if there is something which still does not work, please let me know and I will fix it in another interim 0.10.2 release.
@ThexXTURBOXx Regarding distances, make sure that limit cases can be asked and do work, like the size of the equator [(0,-180),(0,180)].
Would it make sense to also maintain "strictlyEastward" and "strictlyWestward", in case you want to compute the size of equator with [(0,0),(0,0))?
Instead of numerous "switch", a solution may be to implement just one method in SegmentDirection, called getLongitudeDelta(LatLng latLng1, LatLng latLng2).
Could even be in an abstract class, implemented by SegmentDirection: we'd have the added value of enum and the flexibility of abstract classes. That's only if we want to give developers more flexibility that they probably need, in case they find a new typical case to implement.
Quickly said: regarding SegmentDirection, you forgot the current behavior, that may be called "lazy" or "greenwich".
True, thank you! Even though, I really like "greenwich", I feel like I should call it "lazy" instead in order to not confuse new users too much...
Regarding distances, make sure that limit cases can be asked and do work, like the size of the equator [(0,-180),(0,180)].
Will do - all of such edge cases will go into the test suite.
Would it make sense to also maintain "strictlyEastward" and "strictlyWestward", in case you want to compute the size of equator with [(0,0),(0,0))?
Also a good idea. I am guessing this indeed makes sense and there is an issue, which is about something similar: ThexXTURBOXx/dart-latlong#17
Even though, it is not really about latlong2, it shows nonetheless that something like this would be nice to have.
Instead of numerous "switch", a solution may be to implement just one method in SegmentDirection, called getLongitudeDelta(LatLng latLng1, LatLng latLng2).
Could even be in an abstract class, implemented by SegmentDirection: we'd have the added value of enum and the flexibility of abstract classes. That's only if we want to give developers more flexibility that they probably need, in case they find a new typical case to implement.
Exactly my thinking. Even though, I will need to also add getLatitudeDelta and some more SegmentDirections since we may also want to support calculating distances from one of the poles around the world to itself again.
This would call for strictlySouthward and strictlyNorthward as well - leading to two additional parameters for the distance function (one for lat, one for lng).
Please let me know if there is anything else I can do for flutter_map! :)
We'll let you know.
I guess the first idea that comes to mind is: get me the closest LatLng with those latitude and longitude, according to the SegmentDirection. But that would mean longitude beyond -180 and 180. Maybe here we could return -1, 0, 1 as previous, current, next world. getClosestLongitudeWorld? To be investigated.
Hey, sorry I haven't managed to keep up with this. I'll try and give it a read over and get up to speed tonight. But thanks guys for working on this :)
Ok, I've finally found some time to look through it all, and I do like the way it's going. I think it all makes sense.
The only thing I would nitpick is the LongitudeDirection.lazy name. In my head at least, lazy inferred shortest path. I do get why you've called it that, but I think another name would work best, maybe "greenwich" as suggested. (If this was flutter_map territory, I guess this is basically "single/one world"? but yeah I don't think that's a good name for here.)
(Also the API reference for the prereleases seems to have split up all the libraries so maybe there's some weird exporting going on somewhere.)
What's happening with Path? From what I can see it hasn't been changed at all, and I would say that it needs a serious overhaul. .distance doesn't seem to have an externally settable calculator; the idea of .center is really simplistic; it looks like it's trying to be a list or iterable without implementing either of those interfaces; and now of course the concepts (distance, area) are more complicated because of all this. I guess it's a similar problem to what our Polygon, Polyline, and LatLngBounds are trying to do recently all rolled into one?
So is the answer to have a single path concept somewhere (maybe in latlong2) which takes care of all this, then flutter_map's job for Polygon and Polyline just become different ways to render paths? Is a path a list of latlngs: surely each 'join' between two latlngs needs to be described by a 'direction' (either implicitly or explicitly)? Trying to find the center of a path is something we have multiple ways of doing, including one that relies on 'dart_polylabel2': is this something that latlong2 wants to consider adding to path, or is it better to remove the concept of 'center' altogether?
(Then we need to think about LatLngBounds because it's obviously got a different purpose, but many of the same issues. I don't think we could just start using paths in it's place. See also #2205.)
Basically, where does the line go between FM and latlong2, and what's happening to 'path'?
What do other mapping libraries do about all of this? geojson just says that things crossing the anti-meridian need to be split into separate geometries. Does it make sense to consider how we would parse geojson into latlong2 concepts and flutter_map concepts, and how we would generate geojson from those concepts?
Maybe I've completely missed something with Path though, I'm on my phone and only looking at the pub.dev generated dartdoc.
@JaffaKetchup You're right, there's probably something to do with Path, and lists of LatLng in general: how (and where) do we add a point to a list? Probably with an optional LongitudeDirection parameter. Probably defaulting to a Distance that can be set in the constructor.
That said, the new concept of LongitudeDirection looks bug-free, interesting enough, and definitely relevant for latlong2 users.
I would create a release of latlong2 at this stage - modulo the lazy/greenwich settlement.
I am back from my vacation now - sorry for the delay!
Ok, I've finally found some time to look through it all, and I do like the way it's going. I think it all makes sense.
The only thing I would nitpick is the LongitudeDirection.lazy name. In my head at least, lazy inferred shortest path. I do get why you've called it that, but I think another name would work best, maybe "greenwich" as suggested. (If this was flutter_map territory, I guess this is basically "single/one world"? but yeah I don't think that's a good name for here.)
I have changed this to greenwich. I agree that this makes more sense.
(Also the API reference for the prereleases seems to have split up all the libraries so maybe there's some weird exporting going on somewhere.)
Indeed. I have restructured the code into the standard lib/src setup, which solved this issue.
What's happening with Path? From what I can see it hasn't been changed at all, and I would say that it needs a serious overhaul. .distance doesn't seem to have an externally settable calculator; the idea of .center is really simplistic; it looks like it's trying to be a list or iterable without implementing either of those interfaces; and now of course the concepts (distance, area) are more complicated because of all this. I guess it's a similar problem to what our Polygon, Polyline, and LatLngBounds are trying to do recently all rolled into one?
I do agree! I noticed that Path is overall just a "bad" (?) wrapper around List<LatLng>. It is bad because it misses quite a lot of functions from the List class, which makes it hard to work with.
After fiddling around with it for a bit, I believe that the concept of a Path can be made much easier and nicer using the following code:
typedefPath=List<LatLng>;
extensionPathExtensionsonPath { // TODO: List<LatLng> or Path here? Both work...// Put all the functions from the original Path class here
}
This way, the new Path immediately has all the functions from the original List class - just with a few more.
Have not noticed any problems with this approach yet. I have not tested with all the functions though, yet.
Big disadvantage I can see in this approach, though: We cannot save the distance and latLngFactory in the object and they would probably need to be specified in every method call, which is bad.
Apart from this problem: Yes, .distance and .center also have both their own disadvantages and shortcomings, which I will try to solve before releasing 1.0.0 as stability for the future is of utmost importance for me and the current interface cannot stay stable for that long.
So is the answer to have a single path concept somewhere (maybe in latlong2) which takes care of all this, then flutter_map's job for Polygon and Polyline just become different ways to render paths? Is a path a list of latlngs: surely each 'join' between two latlngs needs to be described by a 'direction' (either implicitly or explicitly)? Trying to find the center of a path is something we have multiple ways of doing, including one that relies on 'dart_polylabel2': is this something that latlong2 wants to consider adding to path, or is it better to remove the concept of 'center' altogether? (Then we need to think about LatLngBounds because it's obviously got a different purpose, but many of the same issues. I don't think we could just start using paths in it's place. See also #2205.) Basically, where does the line go between FM and latlong2, and what's happening to 'path'?
What do other mapping libraries do about all of this? geojson just says that things crossing the anti-meridian need to be split into separate geometries. Does it make sense to consider how we would parse geojson into latlong2 concepts and flutter_map concepts, and how we would generate geojson from those concepts?
Maybe I've completely missed something with Path though, I'm on my phone and only looking at the pub.dev generated dartdoc.
I don't think you missed something. It is just exactly like you described: not the easiest task to solve.
I am also quite conflicted on deciding which features should go into latlong2, which should go into dependents and which should go into dart_polylabel2...
I think representing path as a list of latlngs is too simplistic if we want to specify which direction to take between each pair. If we don't then what's the alternative (and what's the point of direction if not used in a case like this)?
I've got some ideas of how this could be represented using a custom Iterable and Iterator implementation along with maybe a type extension if we really want to lock down the API. But I'm a little worried of over engineering.
Personally I would say distance can remain on path, but center should be removed altogether (especially because from what I understand it might not be the geographical center (respecting the sphere etc)?).
A fair description of a path would be an origin and a list of vectors. May prove problematic regarding numerous rounding side-effect.
Or, if we're more accurate, an origin and a list of (LatLng, LongitudeDirection)s, or (LatLng, worldNumber)s.
But that would take more space.
I guess it'd be reasonable to maintain a couple of Paths:
the lazy "I don't change worlds anyway" Path, that most developers would use, something like LocalPath, OneWorldPath, GreenwichPath, similar to what we currently have
a 100% accurate MagellanPath that handles paths crossing the -180 / 180 boundaries, with a worldNumber attached to each LatLng
both paths would somehow returns the nth LatLng and the nth world number (always 0 for GreenwichPath)
Agreed, that makes sense. I guess we would need to use world numbers right? Because if the next point skips a world then a direction won't accurately describe it.
Should be pretty simple to make a class which holds an origin and a list of point-worldnumber pairs. Make it Iterable then the Iterator can return something like (LatLng, int). Or we could return the vector if we think that's something we need more often. When you say rounding side effects are you referring to floating point stuff and ending up with drift from what was really intended?
And provide similar methods to list manipulation like add and remove (with optional parameters for the world numbers). If we wanted to have both variants then they both inherit from a super class, we just save memory when using a single world.
It does make consuming it more complicated of course but at least it's accurate.
An alternative would be to spit out potentially multiple points when iterated? Rather than getting a world number out it would fake an additional point on the anti-meridian? Although then idk if that's easy to calculate ('straight line' or 'great circle'?) and it doesn't really fit with what we've been doing. And maybe it causes problems later? But it does simplify the consumption a bit. And if two same anti-meridian points are next to each other, does that infer a world apart or 'nil move'? Similar to what geojson does.
Would it make sense to also maintain "strictlyEastward" and "strictlyWestward", in case you want to compute the size of equator with [(0,0),(0,0))?
Hi, I currently read this thread and stumbled over this one. I really don't know if it still relevant but I wondered if there's even a use case for "strictlyNorthward" and "strictlySouthward". In that case going over the poles would be the shortest path. So, there are always different ways and I believe there may be even more edge cases to look at. So maybe an initial azimuth could make more sense than defining a lot of edgy enum values or similar...
Do we want to move #2205 forward without this? It is kinda treading a little into this territory (behaviour of latlong bounds across the anti-meridian) but not sure, think it's probably OK?
Still thinking about how to organize latlong2 exactly. I think, it's okay to move forward without touching latlong2 for now.
A stable 1.0.0 release will take a considerable amount of time anyway, so I'm not sure if it would be worth waiting for that...
The stable 1.0.0 release would most likely count as breaking either way, so flutter_map would need to increase its major version as well
After some time, I finally had some time to think through most of the stuff, but I am not satisfied with the result(s), sadly.
You can take a look at my unordered thoughts here: ThexXTURBOXx/dart-latlong@5772262
Implementing the concept of multiple worlds means having to deal with "invalid" coordinates in some places, I believe. WorldLatLng tries to address this issue to some extent, but it is not entirely clear what should happen in some of the cases you might come across in production.
I also added a preliminary implementation of LatLngBounds, which may be useful (because if I understood correctly, it may make sense to move this from flutter_map to latlong2, right?).
However: what happens if we calculate the center of a LatLngBounds with a southWest object that is in world 0 (let's say, a normal LatLng object) and a northEast object in world 3 (i.e., a WorldLatLng instance)? Should the center be a LatLng object with invalid coordinates or a WorldLatLng object with proper worldNumber? I would think the latter - but does the user really expect this or may they expect configurable behaviour or something else?
Using the conversion helper functions in both LatLng and WorldLatLng, one can convert between the two views, so one could force a specific view in the end by calling the respective helper function.
But all of this gets rather complicated the more edge cases you think about... I am a bit overwhelmed by all the possibilities currently and don't know whether my current chain of thought may lead to a dead end.
Activity
monsieurtanuki commentedon Apr 28, 2026
Hi @ThexXTURBOXx!
While we're talking about
latlong2and version0.10.1, I've just realized (flutter/flutter#185676 (comment)) that below1.0.0, "minor" changes are considered "major", and therefore "breaking". For instance,0.10.1doesn't match^0.9.1.If I had to answer your initial question quickly, I'd say that we have troubles with "latlong segments" and their direction.
If we go from -179 to 179, does it mean 2 degrees west or 358 degrees east? Should it be
latlong2's problem?I'll have another look at the code and I'll get back to you.
ThexXTURBOXx commentedon Apr 28, 2026
I thought that this was common knowledge! But yes, indeed, I personally would have labelled version
0.10.0rather0.9.2as it did not really break anything. Well, the newhashCodecould theoretically break stuff, but I doubt it, personally."The old maintainer" published version
0.10.0quickly before they transferred the repo over to my profile.So - sorry for the troubles here. This will be a lot better when
1.0.0would eventually be published.Thanks for the comment! I see... I will think about whether there is something I could change in latlong2 for this or whether it is only worth some documentation.
No worries and take your time, please!
Besides: 1.0.0-dev.0 is already published over at pub.dev. It contains a major revamp of the entire codebase with quite a lot of (most likely) breaking changes.
All of them should be fixable through renames, though.
This is just to warn you beforehand already!
monsieurtanuki commentedon Apr 29, 2026
It's not a matter of documentation - unless you just mean to say "btw we only support trips from Tokyo to Los Angeles via Europe".
Obviously the problem is not with coordinates, but with list of coordinates.
One way to solve it would be to add an "int worldNumber" field in LatLng. Would start with 0, then - if relevant - would be set to 1 or -1 for the next coordinate (if beyond 180, respectively -180). But that would take extra space for all LatLng objects. Not good.
Another way would be to accept values beyond -180, 180: it wouldn't take more space as there wouldn't be an extra field.
Or create a new LatLngList object, that would help manage that "which world are we talking about?" feature. That wouldn't be a breaking change.
The goal being something like: "I want to list of LatLng without confusion, e.g. to support round the world yacht races".
JaffaKetchup commentedon Apr 29, 2026
Hey, thanks for opening this, glad to see its still in safe hands!
I would say that I don't think it's for
LatLngto care about what 'world' it's in.LatLngis a mathematical library for representation of coordinates that can also do some geographic maths based on coordinates - I don't know how the distance calculations handle 'worlds', but I'm making the probably inaccurate assumption that they assume the shortest path where no heading is provided, and if a heading is provided to get an offset then it should work as expected.The 'world' is a very flutter_map construct and I don't think we should 'force' down our requirements onto external libraries - we already have
LatLngBoundsfor example.I could get behind something like
LatLngListand a reworkedLatLngBoundsin the flutter_map core.ibrierley commentedon Apr 29, 2026
I guess the ability to have a latlng outside the normal bounds may be within the remit of LatLng2 though ? i.e if its -95,-185 or something, which could give a hint, although maybe a bit hacky ? Also I think previously we've thought it would be useful for different crs's (eg pixel flat game world crs, was it CrsSimple ?) to be able to reuse this in flutter_map (could there be a BoundlessLatLng method that skips the min/max checks?) . I'm a bit out of touch if that's still the case though, or if it would break other stuff!
monsieurtanuki commentedon Apr 29, 2026
@JaffaKetchup I see things differently, as there are already classes in
latlng2, likePath, that definitely would need the concept of world:And distances are computed "in a single world":
As a "minor breaking change", I would consider a new method called
double distanceWestEast(final LatLng west, final LatLng east), where the longitude difference would be computed correctly. Perhaps deprecatingdistancetoo.Perhaps also the concept of
addWestandaddEastforPath.To be continued...
That said, the process could be: let's improve things in flutter_map first, then see how relevant that would be in latlong2 too.
ThexXTURBOXx commentedon Apr 29, 2026
Understandable. On the other hand, I also believe that this is something most dependents are somewhat "expecting" from the package.
This is, however, where this (previous) comment kicks in:
Indeed, this was the first thing I was thinking about when thinking through this.
Of course, there could be a subclass for LatLng, which does have that field. But this is not only sub-optimal, but also somehow weird to think about, I believe...
I already thought about improving the current
distancefunction before - by adding a third (optional named) parameter that could be an enum like this:Does this make sense? Is there something crucial I am missing?
I should also test how the current approach works with distances that cross either pole and whether something like the enum above would also be needed/useful for those edge cases.
Yes, version 0.10.0 added a getter
LatLng#isValid, which does exactly this. Although, it is not quite correct (IMHO) as it happily accepts both latitude -90 and 90 as valid as well as both longitude -180 and 180.Hence, there is still some ambiguity for some "evil" inputs.
0.9.1 should have already removed the assertions two years ago - if there is something which still does not work, please let me know and I will fix it in another interim 0.10.2 release.
monsieurtanuki commentedon Apr 29, 2026
@ThexXTURBOXx Quickly said: regarding SegmentDirection, you forgot the current behavior, that may be called "lazy" or "greenwich".
monsieurtanuki commentedon Apr 30, 2026
@ThexXTURBOXx Regarding distances, make sure that limit cases can be asked and do work, like the size of the equator [(0,-180),(0,180)].
Would it make sense to also maintain "strictlyEastward" and "strictlyWestward", in case you want to compute the size of equator with [(0,0),(0,0))?
Instead of numerous "switch", a solution may be to implement just one method in SegmentDirection, called
getLongitudeDelta(LatLng latLng1, LatLng latLng2).Could even be in an abstract class, implemented by SegmentDirection: we'd have the added value of enum and the flexibility of abstract classes. That's only if we want to give developers more flexibility that they probably need, in case they find a new typical case to implement.
ThexXTURBOXx commentedon Apr 30, 2026
True, thank you! Even though, I really like "greenwich", I feel like I should call it "lazy" instead in order to not confuse new users too much...
Will do - all of such edge cases will go into the test suite.
Also a good idea. I am guessing this indeed makes sense and there is an issue, which is about something similar: ThexXTURBOXx/dart-latlong#17
Even though, it is not really about
latlong2, it shows nonetheless that something like this would be nice to have.Exactly my thinking. Even though, I will need to also add
getLatitudeDeltaand some moreSegmentDirections since we may also want to support calculating distances from one of the poles around the world to itself again.This would call for
strictlySouthwardandstrictlyNorthwardas well - leading to two additional parameters for the distance function (one for lat, one for lng).4 remaining items
ThexXTURBOXx commentedon May 7, 2026
Addressed all the comments in 1.0.0-dev.2.
Please let me know if there is anything else I can do for
flutter_map! :)monsieurtanuki commentedon May 11, 2026
Cool!
We'll let you know.
I guess the first idea that comes to mind is: get me the closest LatLng with those latitude and longitude, according to the SegmentDirection. But that would mean longitude beyond -180 and 180. Maybe here we could return -1, 0, 1 as previous, current, next world.
getClosestLongitudeWorld? To be investigated.JaffaKetchup commentedon May 11, 2026
Hey, sorry I haven't managed to keep up with this. I'll try and give it a read over and get up to speed tonight. But thanks guys for working on this :)
JaffaKetchup commentedon May 16, 2026
Ok, I've finally found some time to look through it all, and I do like the way it's going. I think it all makes sense.
The only thing I would nitpick is the
LongitudeDirection.lazyname. In my head at least, lazy inferred shortest path. I do get why you've called it that, but I think another name would work best, maybe "greenwich" as suggested. (If this was flutter_map territory, I guess this is basically "single/one world"? but yeah I don't think that's a good name for here.)(Also the API reference for the prereleases seems to have split up all the libraries so maybe there's some weird exporting going on somewhere.)
What's happening with
Path? From what I can see it hasn't been changed at all, and I would say that it needs a serious overhaul..distancedoesn't seem to have an externally settable calculator; the idea of.centeris really simplistic; it looks like it's trying to be a list or iterable without implementing either of those interfaces; and now of course the concepts (distance, area) are more complicated because of all this. I guess it's a similar problem to what ourPolygon,Polyline, andLatLngBoundsare trying to do recently all rolled into one?So is the answer to have a single path concept somewhere (maybe in latlong2) which takes care of all this, then flutter_map's job for
PolygonandPolylinejust become different ways to render paths? Is a path a list of latlngs: surely each 'join' between two latlngs needs to be described by a 'direction' (either implicitly or explicitly)? Trying to find the center of a path is something we have multiple ways of doing, including one that relies on 'dart_polylabel2': is this something that latlong2 wants to consider adding to path, or is it better to remove the concept of 'center' altogether?(Then we need to think about
LatLngBoundsbecause it's obviously got a different purpose, but many of the same issues. I don't think we could just start using paths in it's place. See also #2205.)Basically, where does the line go between FM and latlong2, and what's happening to 'path'?
What do other mapping libraries do about all of this? geojson just says that things crossing the anti-meridian need to be split into separate geometries. Does it make sense to consider how we would parse geojson into latlong2 concepts and flutter_map concepts, and how we would generate geojson from those concepts?
Maybe I've completely missed something with
Paththough, I'm on my phone and only looking at the pub.dev generated dartdoc.monsieurtanuki commentedon May 23, 2026
@JaffaKetchup You're right, there's probably something to do with Path, and lists of LatLng in general: how (and where) do we add a point to a list? Probably with an optional LongitudeDirection parameter. Probably defaulting to a Distance that can be set in the constructor.
That said, the new concept of
LongitudeDirectionlooks bug-free, interesting enough, and definitely relevant for latlong2 users.I would create a release of latlong2 at this stage - modulo the lazy/greenwich settlement.
ThexXTURBOXx commentedon May 31, 2026
I am back from my vacation now - sorry for the delay!
I have changed this to greenwich. I agree that this makes more sense.
Indeed. I have restructured the code into the standard
lib/srcsetup, which solved this issue.I do agree! I noticed that
Pathis overall just a "bad" (?) wrapper aroundList<LatLng>. It is bad because it misses quite a lot of functions from theListclass, which makes it hard to work with.After fiddling around with it for a bit, I believe that the concept of a
Pathcan be made much easier and nicer using the following code:This way, the new
Pathimmediately has all the functions from the originalListclass - just with a few more.Have not noticed any problems with this approach yet. I have not tested with all the functions though, yet.
Big disadvantage I can see in this approach, though: We cannot save the
distanceandlatLngFactoryin the object and they would probably need to be specified in every method call, which is bad.Apart from this problem: Yes,
.distanceand.centeralso have both their own disadvantages and shortcomings, which I will try to solve before releasing 1.0.0 as stability for the future is of utmost importance for me and the current interface cannot stay stable for that long.I don't think you missed something. It is just exactly like you described: not the easiest task to solve.
I am also quite conflicted on deciding which features should go into
latlong2, which should go into dependents and which should go intodart_polylabel2...JaffaKetchup commentedon May 31, 2026
Hey no worries, hope you had a good holiday!
I think representing path as a list of latlngs is too simplistic if we want to specify which direction to take between each pair. If we don't then what's the alternative (and what's the point of direction if not used in a case like this)?
I've got some ideas of how this could be represented using a custom Iterable and Iterator implementation along with maybe a type extension if we really want to lock down the API. But I'm a little worried of over engineering.
Personally I would say distance can remain on path, but center should be removed altogether (especially because from what I understand it might not be the geographical center (respecting the sphere etc)?).
monsieurtanuki commentedon Jun 1, 2026
A fair description of a path would be an origin and a list of vectors. May prove problematic regarding numerous rounding side-effect.
Or, if we're more accurate, an origin and a list of (LatLng, LongitudeDirection)s, or (LatLng, worldNumber)s.
But that would take more space.
I guess it'd be reasonable to maintain a couple of Paths:
LocalPath,OneWorldPath,GreenwichPath, similar to what we currently haveMagellanPaththat handles paths crossing the -180 / 180 boundaries, with a worldNumber attached to each LatLngGreenwichPath)JaffaKetchup commentedon Jun 1, 2026
Agreed, that makes sense. I guess we would need to use world numbers right? Because if the next point skips a world then a direction won't accurately describe it.
Should be pretty simple to make a class which holds an origin and a list of point-worldnumber pairs. Make it Iterable then the Iterator can return something like
(LatLng, int). Or we could return the vector if we think that's something we need more often. When you say rounding side effects are you referring to floating point stuff and ending up with drift from what was really intended?And provide similar methods to list manipulation like add and remove (with optional parameters for the world numbers). If we wanted to have both variants then they both inherit from a super class, we just save memory when using a single world.
It does make consuming it more complicated of course but at least it's accurate.
An alternative would be to spit out potentially multiple points when iterated? Rather than getting a world number out it would fake an additional point on the anti-meridian? Although then idk if that's easy to calculate ('straight line' or 'great circle'?) and it doesn't really fit with what we've been doing. And maybe it causes problems later? But it does simplify the consumption a bit. And if two same anti-meridian points are next to each other, does that infer a world apart or 'nil move'? Similar to what geojson does.
monsieurtanuki commentedon Jun 1, 2026
Yes
S-Man42 commentedon Jun 22, 2026
Hi, I currently read this thread and stumbled over this one. I really don't know if it still relevant but I wondered if there's even a use case for "strictlyNorthward" and "strictlySouthward". In that case going over the poles would be the shortest path. So, there are always different ways and I believe there may be even more edge cases to look at. So maybe an initial azimuth could make more sense than defining a lot of edgy enum values or similar...
Just what came to mind...
JaffaKetchup commentedon Oct 8, 2026
Do we want to move #2205 forward without this? It is kinda treading a little into this territory (behaviour of latlong bounds across the anti-meridian) but not sure, think it's probably OK?
ThexXTURBOXx commentedon Oct 12, 2026
Still thinking about how to organize
latlong2exactly. I think, it's okay to move forward without touchinglatlong2for now.A stable 1.0.0 release will take a considerable amount of time anyway, so I'm not sure if it would be worth waiting for that...
The stable 1.0.0 release would most likely count as breaking either way, so
flutter_mapwould need to increase its major version as wellThexXTURBOXx commentedon Nov 8, 2026
After some time, I finally had some time to think through most of the stuff, but I am not satisfied with the result(s), sadly.
You can take a look at my unordered thoughts here: ThexXTURBOXx/dart-latlong@5772262
Implementing the concept of multiple worlds means having to deal with "invalid" coordinates in some places, I believe.
WorldLatLngtries to address this issue to some extent, but it is not entirely clear what should happen in some of the cases you might come across in production.I also added a preliminary implementation of
LatLngBounds, which may be useful (because if I understood correctly, it may make sense to move this from flutter_map to latlong2, right?).However: what happens if we calculate the center of a
LatLngBoundswith asouthWestobject that is in world 0 (let's say, a normalLatLngobject) and anorthEastobject in world 3 (i.e., aWorldLatLnginstance)? Should the center be aLatLngobject with invalid coordinates or aWorldLatLngobject with properworldNumber? I would think the latter - but does the user really expect this or may they expect configurable behaviour or something else?Using the conversion helper functions in both
LatLngandWorldLatLng, one can convert between the two views, so one could force a specific view in the end by calling the respective helper function.But all of this gets rather complicated the more edge cases you think about... I am a bit overwhelmed by all the possibilities currently and don't know whether my current chain of thought may lead to a dead end.