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

Problem with polylines/polygons over the date line #82

Closed
ghost opened this issue May 30, 2011 · 18 comments
Closed

Problem with polylines/polygons over the date line #82

ghost opened this issue May 30, 2011 · 18 comments
Assignees
Milestone

Comments

@ghost
Copy link

ghost commented May 30, 2011

Hi guys, when a polyline straddles the W180 line of longitude, crossing from one side to the other, the polyline does not continue on the other side of the W180 line, but is drawn back on the other side of the "current iteration" of the world.

Here is an example, polyline has 3 points draw from left to right. The first two polypoints are drawn on the left side of the W180 line, but the third which is meant to be just past the W180 line is not drawn to the right of the W180 line. It is being drawn back to the left where the current world begins:

http://fswidgets.com/beta/leaflet_test.html

@ghost ghost assigned mourner May 30, 2011
@mourner
Copy link
Member

mourner commented May 30, 2011

Hi, unfortunately Leaflet doesn't yet handle crossing of W180 automatically - the current workaround is to change the definition of points that are not drawing properly e.g. from this:
new L.LatLng(60, -150)
to this:
new L.LatLng(60, 210, true)

This way Leaflet will know that the point should be drawn beyond the -180:180 interval and not automatically clamped inside (what true does).

But I'll try to figure out how to manage this automatically.

@ghost
Copy link
Author

ghost commented May 30, 2011

Thanks Vladimir, we really appreciate all your work on Leaflet.

@codecowboy
Copy link

Is there an automatic way to do this yet? Or is the above workaround still required?

@ghost
Copy link
Author

ghost commented May 1, 2012

Is there a way to just have the polygon duplicated so it can be seen at two places at once. This is rather than having one object being shown and jumping around the world. This sucks when you create a object along the date line, then scroll a little, the object will disappear by jumping to another world. I'd rather it just exist in both worlds.

@russmo
Copy link

russmo commented May 24, 2012

I really could use the replicated feature capability described by masterofping. If this doesn't exist, I'm going to either 1) create two replicates of any feature I add to a geojson layer (one +360 and another -360 from the original feature) and add them to the same geojson layer, or 2) create a new feature class that extends layergroup or geojsonlayer and handles the replication to adjacent worlds automatically. #1 would happen in my application code. #2 would be an extension to the Leaflet library that could be ported in to the main lib. The most important thing is that mouse events and other interaction hooks for the original feature must also work for the replicates.

I know there's been talk of development better dateline handling within leaflet but wonder when that might happen or what that might actually be.

@sangwook-kim
Copy link

Anyone has any idea how google does this?

They do it awesome.... I dk how, but it seems right.

Try yourself with

var p1 = new google.maps.LatLng( -10, 170);
var p2 = new google.maps.LatLng( 10, 170);
var p3 = new google.maps.LatLng( 10, -170);
var p4 = new google.maps.LatLng( -10, -170);
var pg = new google.maps.Polygon( {paths: [p1, p2, p3, p4]});

pg.setMap(map);
....

When you zoom out.. you can see multiple polygons along with repeated maps.

@ghost
Copy link
Author

ghost commented May 30, 2012

Not sure how Google does it but we would love to see the same behavior in Leaflet. At the moment when we create any polylines that cross over the date line (e.g. Honolulu to Tokyo), when we add the second polypoint (Tokyo) the polyline is connecting "the long way around" the world and goes east instead of taking the direct route going west.

Another unintended behavior of the current code is that when we click on the map and open a popup to the east of the date line (Hawaii), then click again to the west of the date line (Japan) the map scrolls to the right a full cycle and the popup opens not where it was clicked but where the map thinks it was clicked a whole world away to the east. We are investigating a hack to get it to work for our project but we would much rather see the same behavior as Google Maps where the world is repeated and the lines of lng never go above/below +/-180.

@hayley
Copy link
Contributor

hayley commented Aug 9, 2012

Any chance this feature is actively being worked on? If not, are there any updates to the best way to implement a workaround for this issue?

@Mithgol
Copy link
Contributor

Mithgol commented Aug 10, 2012

Have you tried the workaround given above? Most likely nothing is updated in this area since then.

@wmleler
Copy link

wmleler commented Nov 18, 2012

Even if you do the workaround, unless you manually duplicate objects they will disappear as you scroll the map across the anti-meridian.

Also need to get L.Bounds to be able to cross the anti-meridian, including the ability to do a map.fitBounds to a bounds that crosses the anti-meridian.

Do you have an estimate of when this will be available? I really need this, and I'm about to write a bunch of manual code to get around this problem. Would hate to have your solution come out just when I finish duplicating that effort. Alternatively, if you have not started work on it, I can help write some of the code.

@mourner
Copy link
Member

mourner commented Dec 11, 2012

I removed LatLng wrapping/clamping by default alltogether (there's now an explicit LatLng wrap method for this). So all similar problems should be solved now in theory.

@JoeMatulka
Copy link

I very much enjoy using Leaflet. I was wondering if there is any other work done on this issue other than the work around.

Keep up the good work! 😄

@wmleler
Copy link

wmleler commented Sep 27, 2016

It was a while ago so I’m not sure, but I think they fixed this issue. —wm

On 27 Sep 2016, at 12:51 PM, JoeMatulka notifications@github.com wrote:

I very much enjoy using Leaflet. I was wondering if there is any other work done on this issue other than the work around.

Keep up the good work! 😄


You are receiving this because you commented.
Reply to this email directly, view it on GitHub #82 (comment), or mute the thread https://github.com/notifications/unsubscribe-auth/AADEtciRG6DGYzBSr1hxZB7ctNYDF6pyks5quXOkgaJpZM4AAYDm.

@RhezaBoge
Copy link

i'm sorry for my english.

there is a function that i found on leaflet 0.7.7 ("wrap" Conversion Methods). it has made me solved this problem with some additional code.

but i can't run this function again on the newest leaflet (currently 1.0.1). i don't know why.. so for a while, i just use leaflet 1.0.1 but i change little bit code on "wrap function" (use leaflet 0.7.7 code). let me know if I missed anything or had some incorrect code for "wrap" methods on the newest leaflet. or maybe "wrap" methods has been removed or changed?

@callumacrae
Copy link

callumacrae commented Oct 17, 2016

screen shot 2016-10-17 at 14 22 43

I'm getting this with leaflet 1.0.1. Looks similar to previous screenshots of this issue: topojson/topojson#242

Here's a full explanation of why it is happening: topojson/topojson#242 (comment)

I don't need antarctica so the workaround in that issue worked for me.

@chrisregner
Copy link

I'm sorry, but I'm confused. @mourner said this:

I removed LatLng wrapping/clamping by default alltogether (there's now an explicit LatLng wrap method for this). So all similar problems should be solved now in theory.

What I understood from this that I shouldn't need any work around. But I still experience the issue:

image

So I tried doing the workaround he suggested:

...the current workaround is to change the definition of points that are not drawing properly e.g. from this:
new L.LatLng(60, -150)
to this:
new L.LatLng(60, 210, true)

Recreating this "using d3 with Leaflet" tutorial, I had the similar part of code, but with dynamic values, so what I just tried adding the third true argument. And of course, that didn't work.

This is that specific part of my code

  function projectPoint(x, y) {
    const point = leafletMap.latLngToLayerPoint(new L.LatLng(y, x, true))

    this.stream.point(point.x, point.y)
  }

  // create a d3.geo.path to convert GeoJSON to SVG
  const transform = d3.geoTransform({ point: projectPoint })
  const path = d3.geoPath().projection(transform)

Here's the [gist](https://gist.github.com/chrisregner/dff1bd7a6fa053fd898d1ef70c451c88#file-map-js-L64( of my code (anchored to that particular line).

So my question is, how do I correctly apply the work around in my case? I can't use what @callumacrae has suggested because I want to keep Antartica.

Thanks.

@chrisregner
Copy link

For anyone who'll need it. I got a solution from topojson/topojson#242 (comment).

@crowmagnumb
Copy link

crowmagnumb commented Feb 10, 2020

The solution I came up with was to first collect all the LatLngs I was going to display in all objects and create a LatLng Mapper out of them. Then as I build the Leaflet objects I run the latlng through this mapper to decide if and how to convert the latlng before giving it to the leaflet object. Below is my solution in Typescript. I have not extensively tested this but it passes my basic test cases so far.

class LatLngMapper {
    private identity: boolean = false;
    private narrow: boolean = false;

    constructor(latlngs: [number, number][]) {
        if (latlngs) {
            let posCount = 0;
            let maxLng = null;
            let minLng = null;
            for (const latlng of latlngs) {
                let lng = latlng[1];
                if (!maxLng || maxLng < lng) {
                    maxLng = lng;
                }
                if (!minLng || minLng > lng) {
                    minLng = lng;
                }
                if (lng >= 0) {
                    posCount++;
                }
            }

            const allSameSign = posCount == 0 || posCount === latlngs.length;
            if (allSameSign) {
                this.identity = true;
            } else {
                this.narrow = maxLng - minLng < 180;
            }
        } else {
            this.identity = true;
        }
    }

    convert(latlng: [number, number]) {
        if (this.identity) {
            return latlng;
        }

        if (this.narrow) {
            return latlng;
        } else {
            let lng = latlng[1];
            if (lng < 0) {
                return <[number, number]>[latlng[0], lng + 360];
            } else {
                return latlng;
            }
        }
    }
}

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

No branches or pull requests