Avoid queryRenderedFeatures erroring out on non existing layers - mapbox-gl-js

I have upgraded an app to the last version of mapbox-gl-js and it broke it.
queryRenderedFeatures has changed and now it errors out on non existing layers.
For multiple reasons, we cannot predict which layers will exist at this point (some are built dynamically).
Is there any way to work around this behaviour ?
Basically we'd like to be able to do the below (one of the layers is there on not) and still get a result.
Thx,
JM
features = map.queryRenderedFeatures([{
x: x1,
y: y1
}, {
x: x2,
y: y2
}], {
layers: [
'Layer A',
'Possibly non existing Layer B',
'Layer C'
]
});

You could could filter out layers that don't exist like this:
features = map.queryRenderedFeatures(
[{x: x1, y: y1}, {x: x2, y: y2}],
{layers:
['Layer A', 'Possibly non existing Layer B', 'Layer C']
.filter((layer)=>{map.getLayer(layer)})]
});
That should avoid triggering an error
https://jsfiddle.net/o8fLvh7e/

Related

Blender 2.77: How to I create a path for an object to follow with latitude, longitude, & altitude (in feet) coordinates in csv format?

I have a csv of lat., long., and altitude data from flight 24.
I want to make a path for an object to follow in blender, but the path has to be generated from the above data.
I also want to import a 3D-model of the place where the aircraft flew over.
The problem is I need to use blender 2.77 because the another add-on I want to use only supports v. 2.77. Add-ons like blender-osm and blender-gis only supports the most up to date version of blender.
Lets say you have x y z coordinates for each point of a path then you can easily able to create a path curve using bpy. Here is an example:
import bpy
def create_curve(coords_list):
crv = bpy.data.curves.new('crv', 'CURVE')
crv.dimensions = '3D'
spline = crv.splines.new(type='NURBS')
spline.points.add(len(coords_list) - 1)
for p, new_co in zip(spline.points, coords_list):
p.co = (new_co + [1.0])
obj = bpy.data.objects.new('object_name', crv)
bpy.data.scenes[0].collection.objects.link(obj)
cords_list = [
[0,0,0],
[1, 0, 1],
[2, 0, -1],
[0, 0, 2]
]
create_curve(cords_list)
Output:

Smoothly rotate icons via interpolate on MapboxGL

I'm trying to animate the rotation of my map markers when their values change using MapboxGL's data driven styling and the interpolate expression. Here is the relevant part of the layer config:
{
layout: {
'icon-rotate': ['interpolate', ['linear'], ['number', ['get', 'winddir'], 0], -180,-180, -90,-90, 0,0, 90, 90, 180, 180]
}
}
The winddir property will be a value between -180 & 180.
The markers appear on the map rotated correctly. However, when they change, they "snap" to the next position. I'm thinking I'm not using the "stops" correctly. Here are the interpolate docs.
As the documentation says:
Layout property. Optional number. Units in degrees. Defaults to 0. Requires icon-image. Supports interpolate expressions.
It does not include the magic term "transitionable". So, animation transitions are not applied to icon-rotate.

Horizontal axis labels are not using 100% width (Google Charts)

Here is a chart rendered using one of the Google Charts demos. My actual use case is very similar to this, a vertical axis with integer labels and a horizontal axis with string labels.
Fiddle: https://jsfiddle.net/1f0dvehq/
The X-axis has the labels starting at what seems to be an arbitrary distance from 0,0. I need those red and blue lines to start at X=0, and have the first X-axis label shift so that it sits below 0,0, as in the following screenshot:
I have tried passing minValue options to the horizontal axis via hAxis but this doesn't seem to work with strings like it does with integers.
The following options are being passed to the fiddle chart (again, from the demo code):
var options = {
title: 'Company Performance',
curveType: 'function',
legend: { position: 'bottom' }
};
How can I align the X axis labels so they take up 100% of the chart width, with the first label falling underneath the Y axis itself? I would like to accomplish this from within the chart configuration itself if possible, rather than CSS or extraneous JS.
If anyone could also explain the logic of this setting it would be much appreciated. It strikes me as odd that it's the default setting, and from my experience with google frameworks they usually choose default values that adhere to a convention, but this seems nonsensical. I would expect the "2004" label to be left justified on the X-axis, and the intervals between the X labels to be evenly spaced with "2007" flush against the right edge of the chart.
can't explain why, but this is default behavior for a discrete axis.
if you would like to display strings on the x-axis,
but still have the behavior of a continuous axis,
you can use the ticks option to format the axis labels.
using object notation, you can provide the value (v:) of each tick,
as well as the formatted value (f:)...
{v: 0, f: '2004'}
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Year', 'Sales', 'Expenses'],
[0, 1000, 400],
[1, 1170, 460],
[2, 660, 1120],
[3, 1030, 540]
]);
var options = {
title: 'Company Performance',
curveType: 'function',
legend: {position: 'bottom'},
hAxis: {
ticks: [
{v: 0, f: '2004'},
{v: 1, f: '2005'},
{v: 2, f: '2006'},
{v: 3, f: '2007'}
]
}
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="curve_chart"></div>

Highcharts - navigation by 3rd element in series 'hidden' in plot

I have some info which is in this format (speed, frequency, date). What happens is that I need to plot this chart with speed x frequency, but I want to allow the users to use the navigation filtering by the date, which is not appearing on the chart.
Also, I have some info which is not built dynamically, which is the limits of speed x frequency. This info will be fixed as reference points on the plot. So, when I filter the plot info (not the limits), it must always display these limit plots.
You can have an idea by this chart, the area plots show the limits for the points (speed, frequency). Then, I would add points of speed x frequency (x date), and filter then by date.
Can you guys give me some advice on this?
here is a JSFIDDLE
JSFIDDLE
data: [
[0, 20, here is a date], [10, 20,here is a date],
[50, 39.9994, here is a date], [100,49.7494, here is a date]
],
Guys, notice that every element of the array in the series has 3 elements [a, b, c], suppose the third one (c) is a DATE and not a random number as it is right now. I want to be able to use the commented the navigator code to filter this series by this C element, which doesn't in fact appear on the chart you see, it is a hidden element, just to filter the data.
There will be a little tricky, if you want to have a navigator in the same chart. Navigator works only with datetime data and it must be connected with the axis from the main chart.
So, you have data in that format:
var points = [
[5, 9, Date.UTC(2016, 1, 0)],
[65, 6, Date.UTC(2016, 1, 1)],
...
You need two x axes - one which represents the data and the other which is connected to the navigator. The second axis must be visible to work with the navigator and must be connected with the datetime data.
So now, except two x axes, you need two series - one with the actual data, and the other consists of [date, y] values from the first series. The additional data will be visible in the navigator - note, that in the navigator you cannot use scatter series - so it will be converted to line series - to happen it without errors, your data should be sorted by date.
series: [{
id: 'main-series',
data: points.map(function(point) {
return [point[0], point[1], point[2], point[1]]
}),
showInNavigator: false,
xAxis: 1,
keys: ['x', 'y', 'date', 'holdY'] //holdY is for easier hiding points
}, {
xAxis: 0,
data: points.map(function(point) {
return [point[2], point[1]];
}),
showInNavigator: true,
enableMouseTracking: false,
color: 'transparent',
showInLegend: false
}],
xAxis: [{
minRange: 1000 * 3600 * 24,
type: 'datetime',
tickLength: 0,
tickLength: 0,
labels: {
enabled: false
},
}, {
type: 'linear'
}],
The last thing you need a callback which will hide/show points after the extremes in the navigator are set. Hiding/showing depends on the third point's property which is date. There is no directly API to hide/show specific points (except pie), but it can be achieved by setting point's value to null (that is why I preserved the real y in holdY).
events: {
afterSetExtremes: function(e) {
var points = this.chart.get('main-series').points;
points.forEach(function(point) {
point.update({
y: e.min <= point.date && point.date <= e.max ? point.holdY : null
}, false, false);
});
this.chart.redraw();
}
}
example: https://jsfiddle.net/3wuwdonn/1/
I would consider using a navigator as a separate chart, then you wouldn't need the second x axis and series in the main chart and you wouldn't need to make them look invisible.
example with a navigator only chart here: http://jsfiddle.net/f7Y9p/

Ricksahw Graph as 'NXY' (one x multiple y) from array possible?

Im using shutterstock rickshaw chart library to visualize some sensordata via ajax-php-sql.
In all examples, rickshaw relies on data for the series in the form
[ [ { x: xval1, y: yval1}, { x: xval2, y: yval2}, ...]
[ { x: xval1, y: yvalS2_1}, { x: xval2, y: yvalS2_2}, ...]
]
which I find a bit tedious compared to e.g. xmgrace's 'nxy' mode:
one x-column, n y-columns - which is exactly what I get from the sql query (because my sensors are sampled at identic timestamps).
So the question would be is it possible to privide rickshaw's data input always the same x-data vector and individual y-data vectors, held in an array?
Thank You!
Alex