arthur-e / Wicket

A modest library for moving between Well-Known Text (WKT) and various framework geometries
https://arthur-e.github.io/Wicket/
Other
586 stars 227 forks source link

Wicket generates invalid WKT from Google Maps v3 Polygon with hole #64

Closed 4tapsmobile closed 8 years ago

4tapsmobile commented 9 years ago

Initially, we retrieve this from PostGIS:

POLYGON((-87.6031179311616 41.7888101645398,-87.6029387172624 41.7888127767185,-87.6029387172624 41.7888354825745,-87.6027529456616 41.7888384966255,-87.6025688808599 41.7888417116132,-87.6023627175022 41.7888435200437,-87.6022213226765 41.7888454624319,-87.6022205141927 41.7887902048123,-87.602156643976 41.7887896020017,-87.6021579016174 41.7888429172335,-87.6019916234583 41.7888447926429,-87.6019855149144 41.7887056103279,-87.6019681774294 41.7878378908616,-87.6021392166595 41.7878362163627,-87.6021473913286 41.7881626088692,-87.6022056919905 41.7881620730323,-87.6022049733383 41.7881415772659,-87.6023982009559 41.7881395678767,-87.6023978416298 41.7881035997991,-87.6024115858537 41.7881035997991,-87.6024116756852 41.7881086902545,-87.6024692576949 41.7881078195188,-87.6024692576949 41.7881030639617,-87.6024843493917 41.7881030639617,-87.6024853375385 41.7881390990192,-87.6026992264076 41.7881368217113,-87.6026992264076 41.7881440555125,-87.6027375844703 41.788143787594,-87.6027360573343 41.7880701099508,-87.6026865601621 41.7880705788088,-87.6026865601621 41.7879936190718,-87.6027340810407 41.7879930832334,-87.6027313860948 41.7878297193064,-87.6029088033634 41.7878287146069,-87.602905838923 41.7878460624158,-87.6029323392239 41.7886963002393,-87.6031155955418 41.7886944918046,-87.6031179311616 41.7888101645398),(-87.6027596830263 41.7886993812759,-87.6027498913897 41.7882650206224,-87.6021457743611 41.7882691063724,-87.6021543981878 41.7887024623125,-87.6027596830263 41.7886993812759))

Then we use Wicket to construct a google maps polygon and render it. It appears correctly and we can even edit its vertices. When attempting to serialize it back to WKT to send to our back-end, this is what we get:

MULTIPOLYGON(((),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()),((),(),(),(),()))

Any ideas / workarounds?

arthur-e commented 9 years ago

This might be related to Issue #33. The Google Maps API is very difficult to support for holes in polygon-class geometries owing to the difficulty of determining whether an inner ring is a hole or another polygon.

brandfocus commented 9 years ago

+1

jbgarr commented 9 years ago

+1

Montago commented 8 years ago

+1

Montago commented 8 years ago

@arthur-e Holes are ALWAYS defined by being counter clockwise http://stackoverflow.com/questions/7494474/google-maps-api-polygon-with-hole-in-center

the gmap demo is also able to show this by flipping 2 coordinates:

MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), ((20 35, 45 20, 30 5, 10 10, 10 30, 20 35), (30 20, 20 15, 20 25, 30 20))) vs MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), ((20 35, 45 20, 30 5, 10 10, 10 30, 20 35), (30 20, 20 25, 20 15, 30 20)))

Montago commented 8 years ago

ARGH... I've traced the source of this problem... it has NOTHING to do with orientation or holes ..

the problem is Wkt.Wkt.prototype.extract.multipolygon that malfunctions !

extract.multipolygon recieves a perfectly defined array of coordinates, then sends each coordinate to extract.polygon which forwards to extract.multilinestring WHICH IS WRONG !

extract.multilinestring expects an array but receives an object of {x, y}

fixing this should be easy peasy

Montago commented 8 years ago

this seems to fix the problem:

    multilinestring: function (multilinestring)
    {
        var i, parts = [];

        if(multilinestring.length)
            for (i = 0; i < multilinestring.length; i += 1)
            {
                parts.push(this.extract.linestring.apply(this, [multilinestring[i]]));
            }
        else
            parts.push(this.extract.point.apply(this, [multilinestring]));

        return parts.join(',');
    },
arthur-e commented 8 years ago

This still produces a MULTIPOLYGON, but at least the coordinates are now displayed.

> wkt = new Wkt.Wkt('POLYGON((-87.6031179311616 41.7888101645398, ...');
> gob = wkt.toObject()
> wkt2 = new Wkt.Wkt(gob)
> wkt2.toString()
"MULTIPOLYGON(((-87.60311793116159 41.7888101645398), ..."
arthur-e commented 8 years ago

I've updated the gh-pages branch so you can see how these work in the sandboxes. It's clear the Google Maps extension still can't handle holes; the original POLYGON is not rendered with its inner ring as a hole:

https://arthur-e.github.io/Wicket/sandbox-gmaps3.html

However, if the same POLYGON string from the top of this issue is pasted into the Leaflet sandbox, it displays perfectly:

https://arthur-e.github.io/Wicket/

All test cases passed before and after this partial fix and the Leaflet extension has always handled inner rings just fine. I believe the underlying problem is documented in #33 --These are basically the same issue with inner rings in the Google Maps extension..

Montago commented 8 years ago

The reason it creates a multipolygon is because the 'hole' has the wrong direction, it should be CCW..

I've made a fix for that in Patch-2

https://github.com/arthur-e/Wicket/issues/84

arthur-e commented 8 years ago

@Montago I implemented the changes you copied me on. Is there something I missed ("Patch-2")? A Pull Request would help.

Montago commented 8 years ago

I'm completely new to this GitHub thing.. committing changes ... i think i managed to do so now. look in #84

arthur-e commented 8 years ago

Partial fix implemented in 1.3.2.; please reference issue #33 going forward.