I have Leaflet map with one date layer joined with:
<script src="data/Hranicesttu0.js"></script>
Function:
function pop_Hranicesttu0(feature, layer) {
...
map.addLayer(layer_Hranicesttu0);
Legend is defined:
L.control.layers(baseMaps,{'<img src="legend/Hranicesttu0.png" /> Hranice státu': layer_Hranicesttu0,}
I need this Hranicesttu0.js reuse as another layer(s) (in legend too) without new file something.js. Is it possible?
Example: http://l.kelv.cz/
Related
In my Vue (2.x) application, I have a number of places where I use vue2-leaflet maps.
There are a few common features of these maps, but they are otherwise completely different, so it doesn't make sense to have all of them use a single component that contains an <l-map> (and all other relevant map components).
In order to reduce copying an pasting, I have created a few mixins with common features. For example, I have written a mixin for any maps that need to be able to auto-fit to their contents, so the only thing I need to do in each component that uses it is add :bounds="autofitBounds" to the <l-map> component.
I wanted to do create something similar for the <l-tile-layer> component, because all of our maps use the same layers.
I created a mixin that provides the url and attribution for the tile layer like this:
export default {
data () {
return {
url: process.env.VUE_APP_MAP_TILE_URL || 'https://{s}.tile.osm.org/{z}/{x}/{y}.png',
attribution: process.env.VUE_APP_MAP_TILE_COPYRIGHT || '© OpenStreetMap contributors',
};
},
};
I can use it by adding the mixin to my component and then adding the <l-tile-layer> component inside the <l-map> like this:
<l-tile-layer :url="url" :attribution="attribution" />
I wanted to see if there was a way to reduce the boilerplate further.
First, I tried to create it as a component instead, like this:
<template>
<l-tile-layer :url="url" :attribution="attribution" />
</template>
<script>
import { LTileLayer } from 'vue2-leaflet';
export default {
name: 'MyTileLayer',
components: {
LTileLayer,
},
data () {
return {
url: process.env.VUE_APP_MAP_TILE_URL || 'https://{s}.tile.osm.org/{z}/{x}/{y}.png',
attribution: process.env.VUE_APP_MAP_TILE_COPYRIGHT || '© OpenStreetMap contributors',
};
},
};
</script>
Then I can use that component inside my <l-map> without needing to add any attributes to it, like this:
<my-tile-layer>
The problem is that this doesn't render properly. Here are two screenshots - the <l-tile-layer> used directly on the left, and the <my-tile-layer> wrapper on the right.
Is there a better way to create a tile layer component with default values? Or is there a way I can fix the rendering of <my-tile-layer>?
Does anyway know how to pass a WMS cql_filter through a Leaflet TimeDimension?
I am using Geoserver and Leaflet, using the Cross Layer filter extension in Geoserver and TimeDimension plugin for Leaflet. I have two point layers, one of parking spaces (static, with no datetime field) and one of boats (moving, with a datetime field). I can display which parking spaces are vacant (boats beyond 5 metres) or taken (boats dwithin 5 metres) nicely through the TimeDimension like this:
var vacant_parking = L.tileLayer.wms(baseUrl, {
layers: 'workspace:parking_spacesLayer',
cql_filter: 'BEYOND(the_geom,collectGeometries(queryCollection(\'workspace:boatsLayer\',\'the_geom\',\'datetime=2021-11-09\')),5,meters)',
format: 'image/png',
transparent: true
});
var vacant_parking_time = L.timeDimension.layer.wms(vacant_parking, {
updateTimeDimension: true
});
But instead of filtering on just a fixed time (for eg datetime=2021-11-09) I need to pass the cql_filter through the timeDimension to be able to dynamically display which parking spaces are vacant (or taken) for any time or time period supplied by the user through the timedimension control.
I've tried a few different combinations, but these not working because the timeDimension reads only the datetime field in the layer specified ('workspace:parking_spacesLayer') and not the boats layer in the cql filter ('workspace:boatsLayer'). Specifically, I want to pre-filter the boatsLayer with the currently selected timedimension time before the cql_filter is executed on the parking_spacesLayer to highlight the vacant (or taken) parking spots at any given time.
I've tried:
nesting the boats layer inside the timeDimension layer to include the cql filter in the timedimension
var vacant_parking_time = L.timeDimension.layer.wms(
(L.tileLayer.wms(baseUrl, {
layers: 'workspace:parking_spacesLayer',
cql_filter: 'BEYOND(the_geom,collectGeometries(queryCollection(\'workspace:boatsLayer\',\'the_geom\',\'INCLUDE\')),5,meters)',
format: 'image/png',
transparent: true
})), {
updateTimeDimension: true
}).addTo(map);
adding both layers to the WMS at the same time (layers: 'workspace:parking_spacesLayer,boatsLayer') which does filter both layers through the timedimension, but does not execute the cql_filter.
and replacing a specified time like this, replacing my_date with '2021-11-03' (which works for a fixed time), or with this.time; this._timeDimension.getCurrentTime(); this._timeDimension.currentLoadedTime(); $(".timecontrol-date").text(); $(".timecontrol-date").html().split("T")[0]; (none of which work).
cql_filter: 'BEYOND(the_geom,collectGeometries(queryCollection(\'workspace:boatsLayer\',\'the_geom\',\'datetime=' + my_date + '\')),5,meters)',
But not working so far. I suspect that I might need to use .apply() or .call() function to continuously update the datetime field.
Any ideas..?
For This there is a plugin named WPS-download you can extend your geoserver with this plugin. After you can genereate MP4 videos for dynamic time change.
I am exporting Google Directions routes as KML and displaying them on a Mapbox map by reading them with Omnivore and adding them to the map,
The Google KML stores each route as two Places (the start and end points) and one LineString (the route). In Mapbox I would like to show only the routes, that is to filter out the markers somehow. I'm displaying markers out of my own database and the Google markers clutter it up.
Here is my code. I change the styling of the LineStrings just to show that I can, but do not know what magic call(s) to make to not display the Points.
Thanks.
runLayer = omnivore.kml('data/xxxx.kml')
.on('ready', function() {
var llBnds = runLayer.getBounds();
map.fitBounds(llBnds);
this.eachLayer(function (layer) {
if (layer.feature.geometry.type == 'LineString') {
layer.setStyle({
color: '#4E3508',
weight: 4
});
}
if (layer.feature.geometry.type == 'Point') {
//
// Do something useful here to not display these items!!
//
}
});
})
.addTo(map);
Welcome to SO!
Many possible solutions:
Most straight forward from the code you provided, just use the removeLayer method on your runLayer Layer Group when you get a 'Point' feature.
Cleaner solution would be to filter out those features before they are even converted into Leaflet layers, through a custom GeoJSON Layer Group passed as 3rd argument of omnivore.kml, with a specified filter option:
var customLayer = L.geoJSON(null, {
filter: function(geoJsonFeature) {
// my custom filter function: do not display Point type features.
return geoJsonFeature.geometry.type !== 'Point';
}
}).addTo(map);
var runLayer = omnivore.kml('data/xxxx.kml', null, customLayer);
You can also use the style and/or onEachFeature options on customLayer to directly apply your desired style on your LineString.
I was able to generate a tiles folder with gdal2tiles.py which allows me to show a geotiff file on a map :
And all my geotiff file generated are in gray scale and I would like to be able to color them and add a legend to see which value correspond to which color. Here is my actual code which allows me to do this :
<div id="map"></div>
<button id="populate">Populate with 10 markers</button>
<script type="text/javascript">
var map = L.map('map').setView([45, -93], 3);
/* setting some basemap options */
var tile_options = {
subdomains: '1234'
};
/* the base map tile layer */
var basemap = L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png',tile_options);
basemap.addTo(map);
/* the georeferenced map tile layer */
var layer = L.tileLayer('./outputf/{z}/{x}/{y}.png', { maxZoom: 16,tms:true });
map.addLayer(layer);
I am still looking for solution... Of if you have some better option to render a geotiff file on a map
I was able to convert grayscale to colour using gdaldem color-relief
https://gis.stackexchange.com/questions/130199/changing-color-of-raster-images-based-on-their-data-values-gdal
http://www.gdal.org/gdaldem.html#gdaldem_color_relief
I use primefaces 4.0 barchart, but i want to modify some default proprieties. This is my xhtml page
<p:barChart id="chart" value="#{marchebean.model}" legendPosition="ne" xaxisLabel="Année" yaxisLabel="Montant en DT" title="Factures payés par années" />
What i want to do
1.I want to separate between hundreds , thousands and millions in y axis by a space i.e changing the format of my numbers , i use NumberFormat.getNumberInstance(Locale.FRANCE).format(mynumber); in java but i don't know how to achieve this with charts in primefaces.
I want to display on the top of every bar the value setted in backing bean and change it's size.
Edit
Separation between thousand done, but i still don't know how display values above every bar or change their size. this is my new code
<p:barChart id="chart" value="#{marchebean.model}" extender="ext" style="height:600px;" legendPosition="ne" xaxisLabel="Année" yaxisLabel="Montant en DT" title="Factures payés par années" />
<script type="text/javascript">
function ext() {
this.cfg.axes.yaxis.tickOptions = {
formatString: "%'i"
};
this.cfg.seriesDefaults={
renderer: $.jqplot.BarRenderer,
pointLabels:{show:true}
},
$.jqplot.sprintf.thousandsSeparator = ' ';
}
</script>
First question
You can fulfill your need #1 using an extender.
Here's the related excerpt from Primefaces' manual regarding extenders:
3.14.15 Extender Chart API provide high level access to commonly used jqplot options however there are many more customization options
available in jqplot. Extender feature provide access to low level apis
to do advanced customization by enhancing the configuration object,
here is an example to increase shadow depth of the line series where
model's extender property is set to "ext".
<p:chart type="line" model="#{bean.model}" />
function ext() {
//this = chart widget instance
//this.cfg = options
this.cfg.seriesDefaults = {
shadowDepth: 5
};
}
Refer to jqPlot docs for available options.
Note: in Primefaces 4.0, the extender function name is provided as an attribute of the component tag, eg. <p:barChart extender="ext" .../>
To use whitespaces as thousands separator, use the following extender:
function ext() {
this.cfg.axes.yaxis.tickOptions = {
formatString: "%'i"
};
$.jqplot.sprintf.thousandsSeparator = ' ';
}
Second question
You will also manage to do it making some tweaking in your extender.
For example, the following piece of configuration will display values above every bar:
seriesDefaults: {
renderer: $.jqplot.BarRenderer,
pointLabels:{show:true}
},
And just use some CSS to change the size!
--
Zim