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

MultiPolygon and MultiLineString does not work in Leaflet 1.0.2 #104

Open
Searlon opened this issue Jan 10, 2017 · 6 comments
Open

MultiPolygon and MultiLineString does not work in Leaflet 1.0.2 #104

Searlon opened this issue Jan 10, 2017 · 6 comments

Comments

@Searlon
Copy link

Searlon commented Jan 10, 2017

I'm upgrading my versions of Leaflet and Wkt to the latest versions:
Old Leaflet version 0.7.5 -> New Leaflet version 1.0.2
Old Wkt version 1.3 -> New Wkt version 1.3.2

MultiPolygon and MultLineString shapes no longer work. I can no longer create the leaflet objects from Wkt or convert a leaflet object to Wkt. It looks like this is because Leaflet has changed how they construct these shapes. There are no longer unique constructors for these types (no L.MultiPolygon or L.MultiLineString), instead they are using L.Polygon and L.Polyline.

See this JSFiddle for a simple examples https://jsfiddle.net/6tt646oc/3/

@arthur-e
Copy link
Owner

It seems to me this was already reported in #95 and supposedly fixed by PR #98. Can you comment on how these this issue and its supposed fix compare?

@Searlon
Copy link
Author

Searlon commented Jan 10, 2017

I'm not in a position where I can easily test that change right now. But looking at it I would think it will fix the problem when creating a MultiPolygon or MultiPolyline from a Wkt String.
However I think you're still going to have a problem deconstructing a leaflet object. So going from a Leaflet Object that is a MultiPolygon or MultiPolyline to a Wkt string is going to error.

If you look at my example in JSFiddle and click the "Wkt from single geoJson" button, you'll notice the error states that tmp[0].equals is not a function in the following bit of code

`if (obj.constructor === L.Polyline || obj.constructor === L.polyline) {
verts = [];
tmp = obj.getLatLngs();

    if (!tmp[0].equals(tmp[tmp.length - 1])) {

        for (i = 0; i < tmp.length; i += 1) {
            verts.push({
                x: tmp[i].lng,
                y: tmp[i].lat
            });
        }

        return {
            type: 'linestring',
            components: verts
        };

    }
}`

This is because the Polyline LatLng object is not a flat array for a MultiPolyline.

@arthur-e
Copy link
Owner

@crash-dive Maybe you could take a look at this and create a pull request?

@crash-dive
Copy link
Contributor

@arthur-e I am sorry to say we encountered this issue and tried to fix in Wicket but decided it was easier to write it ourselves because we had much simpler requirements such as not needing to support deconstruction of multipolygons or holes in the polygons.

What we ended up with is in TypeScript and attached. It is designed for a specific narrow circumstance so it does not convert everything.

    export class WKT
    {
        public ToPolygon(wkt: string, polygonOptions: L.PolylineOptions): L.Polygon
        {
            var latLongs = [];

            if (wkt.startsWith('POLYGON'))
            {
                //Single Polygon
                var polygon = wkt.replace('POLYGON', '')
                                 .trim()
                                 .slice(1, wkt.length) //Remove first (
                                 .slice(0, wkt.length - 1); //Remove last )

                latLongs.push(this.CreatePolygonArray(polygon));
            }
            else
            {
                //Multi Polygon
                var polygons = wkt.replace('MULTIPOLYGON', '')
                                  .trim()
                                  .slice(1, wkt.length) //Remove first (
                                  .slice(0, wkt.length - 1) //Remove last )
                                  .split(')),');

                for (var polygon of polygons)
                {
                    latLongs.push(this.CreatePolygonArray(polygon));
                }
            }
            
            return new L.Polygon(latLongs, polygonOptions);
        }

        private CreatePolygonArray (polygon: string): L.LatLng[][]
        {
            var polygonComponents = polygon.split('),').filter(this.RemoveEmptyStrings);
            var polyArray: L.LatLng[][] = [];

            for (var polygonComponent of polygonComponents)
            {
                polyArray.push(this.CreatePolygonCordArray(polygonComponent));
            }
            return polyArray;
        }

        private CreatePolygonCordArray (polygonComponent: string): L.LatLng[]
        {
            var cordArray: L.LatLng[] = [];
            var cords = polygonComponent.trim()
                                        .replace(/\(|\)/g,'') //Removes ( & ) from the string g makes it apply to all instances not just the first
                                        .split(',')
                                        .filter(this.RemoveEmptyStrings)

            for (var cord of cords)
            {
                var latLong = cord.split(' ').filter(this.RemoveEmptyStrings);
                cordArray.push(new L.LatLng(parseFloat(latLong[1]), parseFloat(latLong[0])));
            }

            //Slice to remove the last cord which in WKT is the same as the first one
            return cordArray.slice(0, cordArray.length-1);
        }

        private RemoveEmptyStrings(value: string): boolean
        {
            return value !== '';
        }

        public FromPolygon(polygon: L.Polygon): string
        {
            //The array that comes from getLatLngs is multidimensional to support multipolygons
            //The UI does not allow multipolygons to be drawn so we access the first array within it with [0]
            var latLongs = polygon.getLatLngs()[0];

            var latLongsArray: string[] = [];
            for (var latLong of latLongs)
            {
                latLongsArray.push(latLong.lng + ' ' + latLong.lat);
            }

            //Adds first line to close polygon
            latLongsArray.push(latLongs[0].lng + ' ' + latLongs[0].lat);

            return 'POLYGON((' + latLongsArray.join(',') + '))';
        }
    }

@jblamber
Copy link

I believe this is the same issue as #103

@nickescallon
Copy link
Contributor

nickescallon commented Apr 12, 2018

Looks like the original fix was accidentally removed when module loader support was added here: #121.

I've reintroduced it, as well as additional leaflet 1.x support here:
#126

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

5 participants