mapnik / mapnik-support

Use the issues queue here to ask questions and offer help on using Mapnik (maybe if this works well we can retire the mailing list at http://mapnik.org/contact/?)
6 stars 6 forks source link

How to make layer inactive using nodejs? #118

Closed zdila closed 5 years ago

zdila commented 5 years ago

How to make layer inactive dynamically using nodejs?

This doesn't work:

    const map = new mapnik.Map(256, 256);
    await map.fromStringAsync(mapnikConfig);
    const layer = map.get_layer('hillshade');
    layer.active = false;
talaj commented 5 years ago

Hi! See https://github.com/mapnik/node-mapnik/issues/742#issuecomment-288191189.

zdila commented 5 years ago

Thanks @talaj for the comment!

In our case I'd like to use it for exporting map to PDF where user can configure which features he wants in the map: contours, hillshading, hiking trails, bicycle trails. If everytime a Map (new mapnik.Map) is created then it takes much more time to render a map in comparation when we reuse existing (pooled) Map. Time is in the first case mostly spent on executing SQL commands in Postgres so it seems that Map then cahches some SQL related stuff.

Do you think that we could reuse pooled Map and load new XML and it would still use those cached SQL stuff? (I know, I should just try it...)?

talaj commented 5 years ago

There is one way how to avoid loading the style for every request with current node-mapnik API, but you need to modify your Mapnik XML styles a bit.

You would have to put <Style> elements to a separate XML file and also every single layer or a group of layers to separate files too. You would end up with something like this:

styles = new mapnik.Map(256, 256);
styles.load("styles.xml")

hillshade = new mapnik.Map();
hillshade.load("hillshade.xml")

contours = new mapnik.Map();
contours.load("contours.xml")
...

// Let's render some of the layers now

map = styles.clone();
map.add_layer(hillshade.get_layer(0));
...
map.render();

It's worth noting that datasources are shared between copies of layers, they are not deep-copied. This means that to copy a layer is a fast operation, but you cannot use such layers concurrently.

Do you think that we could reuse pooled Map and load new XML and it would still use those cached SQL stuff?

Mapnik itself doesn't cache datasource data. Postgis datasource only has connection pool, which is a kind of cache. If subsequent rendering requests are faster then the first one, I would say its probably caused by caching on the side of Postgresql server.

Constructing a Map object for every rendering request is definitely not good. Even though also openstreetmaps.org is doing so, if this code is still relevant. I think it's unfortunate that node-mapnik API intentionally doesn't allow to modify a layer object. If there is add_layer() method, remove_layer() could be also there.

zdila commented 5 years ago

Thanks for helpful answer!

Regarding remove_layer I've asked at https://github.com/mapnik/node-mapnik/issues/467#issuecomment-450688198

PS: We use our own library for XML generation - https://github.com/FreemapSlovakia/jsnik - so I can improve it to generate also segments of XML

zdila commented 5 years ago

remove_layer has been meanwhile implemented.