Wicket icon indicating copy to clipboard operation
Wicket copied to clipboard

wkt.fromObject() fails for POLYGON or MULTIPOLYGON

Open chmelej opened this issue 5 years ago • 6 comments

Hi I have an example:

  var polygon = "POLYGON((30 10,10 20,20 40,40 40,30 10))";
    var mapOptions = {
        center: [50, 5],
        zoom: 16
    };

    var map = L.map('map', mapOptions);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

    var wkt = new Wkt.Wkt();
    wkt.read(polygon);
    var polygonOnMap = wkt.toObject(map.defaults);
    map.addLayer(polygonOnMap);
    map.fitBounds(polygonOnMap.getBounds());

    var serialize = wkt.write()
    
    if (serialize != polygon) {
       alert("ALERT1:" + serialize +" != "+polygon);
    } 

    var wkt2 = new Wkt.Wkt();
    wkt2.fromObject(polygonOnMap);
    var serialize2 = wkt2.write()

    if (serialize2 != polygon) {
       alert("ALERT2:" + serialize2 +" != "+polygon);
    } 

the polygon appears on the map but alert is triggered:

ALERT2:POLYGON((undefined undefined,undefined undefined)) != POLYGON((30 10,10 20,20 40,40 40,30 `10))

which is wrong :-(

I use a latest version of wicket.js, wicket-leaflet.js and leaflet.js 1.4.0

What am I doing wrong? Thanks.

chmelej avatar Feb 13 '19 17:02 chmelej

@chmelej seems wicket-leaflet uses the old format of getLatLngs()

As a workaround, you could do something like:

  // WKT fromObject for leaflet follows leaflet 0.7 format
  const compatible = {
    _latlngs: polygonOnMap.getLatLngs()[0],
    getLatLngs: () => {
      return polygonOnMap.getLatLngs()[0];
    }
  }
  compatible.constructor = polygonOnMap.constructor;

  wkt.fromObject(compatible);

scottlepp avatar Mar 18 '19 19:03 scottlepp

@scottlepp Thanks for figuring this out! Could you fix this in a Pull Request?

arthur-e avatar Mar 18 '19 21:03 arthur-e

Hi, it's better. polygon is ok but multipolygon still not work:

var polygon = 'MULTIPOLYGON(((30 10,10 20,20 40,40 40,30 10),(60 40,40 50,50 70,70 70,60 40)))';

... returns

ALERT2:POLYGON((undefined undefined,undefined undefined,undefined undefined)) != MULTIPOLYGON(((30 10,10 20,20 40,40 40,30 10),(60 40,40 50,50 70,70 70,60 40)))

thank you

chmelej avatar Mar 21 '19 12:03 chmelej

@arthur-e can you publish the latest version of this library on npm? When I try to install it, I get the source code without the changes, which were made in a pull request (#136).

destus90 avatar May 27 '19 08:05 destus90

@destus90 Oops, the version number in package.json was lagging. Sorry! 1.3.4 should be available now.

arthur-e avatar May 29 '19 15:05 arthur-e

Still seems not to work for multipolygons or polygons with holes. The following hack-round seems to have dealt with this temporarily, for the purposes of creating a WKT string, and may (perhaps?) be helpful to others and/or provide some hints as to what's up:

function wktfromlatlngsArr(latlngArr,LeafletObject) { //Returns a wkt string from a latlng sub-array. We can assemble these into multipolygons and polygons with holes
      //create a compatibility object to allow for Wicket relying on out-of-date Leaflet
      const compatible = {
        _latlngs: [latlngArr],
        getLatLngs: () => {
          return [latlngArr];
        }
      }
      compatible.constructor = LeafletObject.constructor;
      var wkt = new Wkt.Wkt();
      return wkt.fromObject(compatible).write();
    }

 function wktfromLeafletObject(LeafletObject) {
      let wktstr="";
      if(Array.isArray(LeafletObject.getLatLngs()[0][0])) { //It's a MultiPolygon
        let innerpolys=[];
        LeafletObject.getLatLngs().forEach(function(itm){ //for each component polygon
          let polyrings=[];
          itm.forEach(function(llarr){ let polywkt=this.wktfromlatlngsArr(llarr,LeafletObject).substr(8); polyrings.push(polywkt.substr(0,(polywkt.length-1))); }.bind(this)); //For each of the polygon's rings, get just coordinates in single parentheses
          innerpolys.push("("+polyrings.join(',')+")");
          }.bind(this));
        wktstr="MULTIPOLYGON("+innerpolys.join(',')+")";
      } else { //a single Polygon
        let polyrings=[];
        LeafletObject.getLatLngs().forEach(function(llarr){ let polywkt=this.wktfromlatlngsArr(llarr,LeafletObject).substr(8); polyrings.push(polywkt.substr(0,(polywkt.length-1))); }.bind(this)); //For each of the polygon's rings, get just coordinates in single parentheses
        wktstr="POLYGON("+polyrings.join(',')+")";
      }
      return wktstr;
    }

let wktpolystr=this.wktfromLeafletObject(polygon);

theca-cto avatar Mar 26 '21 19:03 theca-cto