Raruto / leaflet-kmz

A KMZ file loader for Leaflet Maps
GNU General Public License v3.0
48 stars 27 forks source link

kml and kmz #3

Closed a-lurker closed 5 years ago

a-lurker commented 5 years ago

Identify and process both kml and kmz files

Raruto commented 5 years ago

Hi "Lurker", thank you for the time dedicated to deepen this library, below some of my thoughts:

I'm a bit new to pull requests, so hoping I'm doing this all correctly. ... More pull requests to come.

Ok, good to know, maybe next time you could pull the develop branch.

Identify and process both kml and kmz files

I think that here should be called like that._parseKML(data) (ie. moving the shortList variable creation/check within the _parseKML function)

Modified code to accept either kml or kmz files. It checks if the file begins with PK, if so it's a zipped kmz, otherwise assumes it's kml.

Could you provide a working kml example? I've also tried using your proposed version with the current kmz example, but it seems that there are a couple of breaking changes (missing icons, unpointable polygons, ...)

Have a nice day, Raruto

a-lurker commented 5 years ago

Hello Raruto

I have been looking at this further trying to understand what I need from this plugin.

My main aim is to draw thousands of lines - in one case I have a file with nearly 60,000 line strings in it. I don't need to click on them in order to see any associated information using pop ups or tool tips - just draw the lines.

To my surprise geojson-vt does this really well, as seen here.

Unfortunately the geojson-vt code is not intergrated with Leaflet. However GridLayer.GeoJSON.js in leaflet-kmz does this job well. Plus there is also the advantage of being able to use kmz files with leaflet-kmz.

But the drawing speed advantage of geojson-vt code is lost for me, when I try to show my file with 60,000 linestrings using the plugin as is. The browser just locks up, although it works OK for smaller files. The difficulty is due to this line (about line 75):

this.layer = L.featureGroup([this.gridlayer, this.geojson]);

Both layers are added to the map, which is unhelpful, as both layers are drawn. The browser cannot handle this in my case. After much experimention and research, it seems that if I want to draw 60,000 strings, it needs to be done exclusively by GridLayer.GeoJSON.js

You then end up in the position that you can't click on or move over anything and get a reponse (pop ups and tool tips), as GridLayer.GeoJSON doesn't have any click functionality.

Further reseach suggests you can use an associated L.geoJson layer to also hold the same data. That layer then acts purely as a support by providing all of it methods such getBounds(). etc plus normal access to the features, etc. The important thing is, to never draw this support layer, by attaching it to the map.

So I wrote some code to extend the fast layer GridLayer.GeoJSON with an attached slower L.geoJson layer. The first layer is drawn but the second never is. It just provides support. Like so:

L.GridLayer.GeoJSON.include({
  dummyLayer: this.geoJsonLayer,
});

I set up the options, so the plugin can use a normal slow clickable L.geoJson layer or a very fast unclickable GridLayer.GeoJSON layer. Like so:

kmzParser.load('regions.kmz',       {useFastDraw: true, name: 'regions'});
kmzParser.load('capitals.kmz',      {useFastDraw: false});
kmzParser.load('globe.kmz',         {useFastDraw: false});
kmzParser.load('multigeometry.kmz', {useFastDraw: false});

Now if you want fast drawing and clickable features (pop ups), you need to handle the clicks and search through all the features yourself. I tried this out using the leaflet-pip plugin.

I applied the plugin to the attached dummyLayer: this.geoJsonLayer and I could then click on polygons OK. You would need to write other routines for markers and lines. But polygons are the most difficult and so was a proof of concept.

The code I have now, may not suit you aims at all but it does suit mine. I can handle small kmz/kml files normally and I can choose to also draw huge amounts of linestrings at the same time.

I have updated my repository with the code. I will not issue a pull request unless the code is of some use to you. I can also cancel existing pull requests but I will need to figure out how to do that or you can yourself.

I can also provide the polygon on click code example if needed.

Longer term GridLayer.GeoJSON.js may be able to do the work, as it can return the a list of features being drawn for each tile.

Hope this is of some interest to you.

Raruto commented 5 years ago

My main aim is to draw thousands of lines

That's why I choose the geojson-vt library.

The drawing speed advantage of geojson-vt code is lost for me, when I try to show my file with 60,000 linestrings

With those sizes even qgis would probably hang a little... (the xml format itself it's not suitable for handling large amounts of data, however, as yourself notice, the basic problem is related to the fact that the browser must instantiate too many DOM listeners, and so it "freezes").

The difficulty is due to this line (about line 75):

this.layer = L.featureGroup([this.gridlayer, this.geojson]);

Both layers are added to the map, which is unhelpful, as both layers are drawn.

The basic idea was to leave the final developer free to import or not the geojson-vt.js and GridLayer.GeoJSON.js libraries (however unnecessary only for kml files with a few dozen features in it)

After much experimention and research, it seems that if I want to draw 60,000 strings, it needs to be done exclusively by GridLayer.GeoJSON.js

I agree, as you have seen, I've initially opted in using the featureGroup layer for adding some sort of “mouse interactivity” (with zero opacity, to avoid drawing lags when zooming / panning the map).

Now if you want fast drawing and clickable features (pop ups), you need to handle the clicks and search through all the features yourself. I tried this out using the leaflet-pip plugin.

Yep, it was more or less what I initially intended to do, but I never had time to going deeper into that library...

The code I have now, may not suit you aims at all but it does suit mine.

Well, then let's try to do something that can fit more than two people :)

I can also provide the polygon on click code example if needed.

Yes, it would definitely help more than a thousand words.

Raruto commented 5 years ago

Hi "Lurker", here are some updates from version 0.1.0:

See latest example for some info on this release.