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

Inbetween point of a line not quite accurate on low zooms. #35

Open
ibrierley opened this issue May 8, 2023 · 5 comments
Open

Inbetween point of a line not quite accurate on low zooms. #35

ibrierley opened this issue May 8, 2023 · 5 comments

Comments

@ibrierley
Copy link
Owner

There's a quirk when using this on low zoom levels (I guess most people use a high zoom level for this) which I've never been quite happy with, and I feel like it should get fixed properly at some point.

Mid point markers can be offset slightly from their visual center. I suspect this is because of projections and a midway point of a LatLng isn't actually quite what we need. Again, we'll probably only notice this at low zoom levels where the effect is more pronounced.

I've tried a LatLngBounds.center, but actually I think this still has the same issue. What I suspect we need is actually to get the projection in pixels, so we have the screen space, then take the mid point, then unproject back into a LatLng.

If anyone fancies a challenge, it may be interesting to have a stab. This may need a bit more of a fundamental rejig, as I "think" it may need access to flutter_maps internals for the crs projection there, and original it was written to not need that.

@josxha
Copy link
Contributor

josxha commented May 14, 2023

I just came across the package geodesy that might have this functionality:

LatLng midpoint = geodesy.midPointBetweenTwoGeoPoints(l1, l2);

It i inactive since a long time but it has a MIT license so the functionality could be copied over.

@ibrierley
Copy link
Owner Author

Thanks, I don't think the problem is the mid point of the latlng, but the fact we want the screen position of the midpoint of the line in screen coordinates (I may be wrong), so I think what we probably want to do is get the screen coords of both points, then calculate a simple halfway of those, and convert that back to latlng. There may be a simpler way, but I "think" that makes sense (I think flutter_map can do latlngtoscreenpos)

@Leffe108
Copy link

I had a look on this, and made an attempt using turf midpoint, but it visually got worse than the current lat/lng midpoint formula. I think @ibrierley is right that it a change to screen coordinate projection is necessary here.

I looked around a bit and found some answers:

It looks like we need the current zoom level to use CustomPoint<num> screenPosition = Epsg3857().latLngToPoint(latlng, mapController.zoom); So it might be that the edit() method would need to take current zoom level as parameter.

@EricKrg
Copy link
Contributor

EricKrg commented Apr 23, 2024

@Leffe108 @ibrierley Hey guys, I also played around bit and found a working solution using the geobase package, which in my opinion flies a bit under the radar, I used thew midpoint on the rhumbline (loxodrome) which from my testing seems to work correctly.

here are is what I tested:

import 'package:geobase/geobase.dart';
// ....

List<DragMarker> edit() {
    List<DragMarker> dragMarkers = [];

    for (var c = 0; c < points.length; c++) {
      final indexClosure = c;
      dragMarkers.add(DragMarker(
        point: points[c],
        size: pointIconSize,
        builder: (_, __, ___) => pointIcon,
        onDragStart: (_, __) => _markerToUpdate = indexClosure,
        onDragUpdate: updateMarker,
        onLongPress: (ll) => remove(indexClosure),
      ));
    }

    for (var c = 0; c < points.length - 1; c++) {
      final polyPoint = points[c];
      final polyPoint2 = points[c + 1];

      if (intermediateIcon != null) {
        final indexClosure = c;
        // point on Rhumbline
        final mid =
            Geographic.create(x: polyPoint.longitude, y: polyPoint.latitude)
                .rhumb
                .midPointTo(Geographic.create(
                    x: polyPoint2.longitude, y: polyPoint2.latitude));
        final intermediatePoint = LatLng(mid.lat, mid.lon);

        dragMarkers.add(DragMarker(
          point: intermediatePoint,
          size: intermediateIconSize,
          builder: (_, __, ___) => intermediateIcon!,
          onDragStart: (details, point) {
            points.insert(indexClosure + 1, intermediatePoint);
            _markerToUpdate = indexClosure + 1;
          },
          onDragUpdate: updateMarker,
        ));
      }
    }

maybe you can test it and confirm it, I can create a MR if you like the solution.

@ibrierley
Copy link
Owner Author

Had a quick test of this, it seems to break on lower zoom levels and you end up with some drag points that are way off, example screen shot
localhost_36457_ note the point bottom left.

Not quite sure what's happening there...sometimes I drag a point, and it just seems to "pop" out to a new location.

I'd probably prefer it tbh without a package, but I'm not sure of a sensible way to achieve that anyway unless anyone has some ideas, so this may be the way to go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants