Phi: initial commit for experimental weather dialog
new manual weather configuration based on a http://en.wikipedia.org/wiki/St%C3%BCve_diagram Stuve (Stüve) Diagram. work in progress, up to now it's just displaying current weather, edits are not yet written to fg.
This commit is contained in:
parent
703ee0b6fb
commit
304992be59
3 changed files with 425 additions and 1 deletions
|
@ -6,7 +6,7 @@ define([
|
|||
});
|
||||
|
||||
ko.components.register('Environment/Weather', {
|
||||
require : 'topics/Environment/Weather'
|
||||
require : 'topics/Environment/Weather2'
|
||||
});
|
||||
|
||||
ko.components.register('Environment/Position', {
|
||||
|
|
28
Phi/topics/Environment/Weather2.html
Normal file
28
Phi/topics/Environment/Weather2.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
<style>
|
||||
.yaxisLabel {
|
||||
top: 50%;
|
||||
left: 2px;
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: 0px 0px 0px;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.axisLabel {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.flot-y1-axis, .flot-x-axis {
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
<div style="height: 100%; width: 100%" data-bind="
|
||||
flotchart: {
|
||||
data: wxData,
|
||||
options: wxOptions,
|
||||
postUpdate: afterUpdate,
|
||||
hover: plotHover,
|
||||
click: plotClick,
|
||||
}"></div>
|
396
Phi/topics/Environment/Weather2.js
Normal file
396
Phi/topics/Environment/Weather2.js
Normal file
|
@ -0,0 +1,396 @@
|
|||
define([
|
||||
'knockout', 'jquery', 'text!./Weather2.html', 'props', 'flot', 'flotresize'
|
||||
], function(ko, jquery, htmlString, SGPropertyNode) {
|
||||
|
||||
function ViewModel(params, componentInfo) {
|
||||
// componentInfo.element
|
||||
|
||||
var self = this;
|
||||
|
||||
function createIsotherms() {
|
||||
var reply = [];
|
||||
for (x = -50; x < 50; x += 10) {
|
||||
reply.push([
|
||||
x, -0.02
|
||||
]);
|
||||
reply.push([
|
||||
x, 16
|
||||
]);
|
||||
reply.push(null);
|
||||
}
|
||||
/*
|
||||
* for (x = -160; x < 50; x += 10) { reply.push([ x, -56 ]);
|
||||
* reply.push([ x + 116, 50 ]); reply.push(null); }
|
||||
*/
|
||||
return reply;
|
||||
}
|
||||
|
||||
function createDryAdiabates() {
|
||||
var reply = [];
|
||||
/*
|
||||
* for (x = -35; x <= 200; x += 20) { reply.push([ x, 1050 ]);
|
||||
* reply.push([ x-160, 100 ]); reply.push(null); }
|
||||
*/
|
||||
return reply;
|
||||
}
|
||||
|
||||
function createClouds() {
|
||||
var reply = [];
|
||||
|
||||
reply.push([
|
||||
-50, 0.3, 0.
|
||||
]);
|
||||
reply.push([
|
||||
-30, 3.0, 1.8
|
||||
]);
|
||||
reply.push([
|
||||
-10, 5.0, 4
|
||||
]);
|
||||
reply.push([
|
||||
10, 7.5, 4
|
||||
]);
|
||||
reply.push([
|
||||
30, 12, 11.5
|
||||
]);
|
||||
return reply;
|
||||
}
|
||||
|
||||
jquery.get('/json/environment/config?d=4', null, function(data) {
|
||||
var wx = new SGPropertyNode(data);
|
||||
|
||||
function createProbes(k) {
|
||||
var probes = [];
|
||||
wx.getNode("boundary").getChildren("entry").forEach(function(entry) {
|
||||
probes.push([
|
||||
entry.getValue(k, 15), entry.getValue("elevation-ft", 0) * 0.3048 / 1000
|
||||
// km
|
||||
]);
|
||||
});
|
||||
wx.getNode("aloft").getChildren("entry").forEach(function(entry) {
|
||||
probes.push([
|
||||
entry.getValue(k, 15), entry.getValue("elevation-ft", 0) * 0.3048 / 1000
|
||||
// km
|
||||
]);
|
||||
});
|
||||
return probes;
|
||||
}
|
||||
|
||||
function createWind() {
|
||||
var wind = [];
|
||||
wx.getNode("boundary").getChildren("entry").forEach(function(entry) {
|
||||
wind.push([
|
||||
entry.getValue("wind-speed-kt", 0), entry.getValue("elevation-ft", 0) * 0.3048 / 1000, // km
|
||||
entry.getValue("wind-from-heading-deg", 0),
|
||||
]);
|
||||
});
|
||||
wx.getNode("aloft").getChildren("entry").forEach(function(entry) {
|
||||
wind.push([
|
||||
entry.getValue("wind-speed-kt", 0), entry.getValue("elevation-ft", 0) * 0.3048 / 1000, // km
|
||||
entry.getValue("wind-from-heading-deg", 0),
|
||||
]);
|
||||
});
|
||||
return wind;
|
||||
}
|
||||
|
||||
self.wxData()[3].data = createProbes("temperature-degc");
|
||||
self.wxData()[4].data = createProbes("dewpoint-degc");
|
||||
self.wxData()[5].data = createWind();
|
||||
self.wxData.notifySubscribers(self.wxData.peek());
|
||||
});
|
||||
|
||||
self.wxData = ko.observableArray([
|
||||
{// Series: Isotherms
|
||||
color : 'rgb(0, 0, 255)',
|
||||
data : createIsotherms(),
|
||||
label : "Isotherm",
|
||||
lines : {
|
||||
lineWidth : 0.5,
|
||||
show : true
|
||||
},
|
||||
points : {
|
||||
show : false
|
||||
},
|
||||
bars : {
|
||||
show : false
|
||||
},
|
||||
shadowSize : 0,
|
||||
yaxis : 2, // on linear scale
|
||||
}, {// Series: Dry Adiabat
|
||||
color : 'rgb(0, 255, 0)',
|
||||
data : createDryAdiabates(),
|
||||
label : "dry adiabat",
|
||||
lines : {
|
||||
lineWidth : 0.5,
|
||||
show : true
|
||||
},
|
||||
points : {
|
||||
show : true
|
||||
},
|
||||
bars : {
|
||||
show : false
|
||||
},
|
||||
shadowSize : 0,
|
||||
yaxis : 1,
|
||||
}, { // clouds
|
||||
color : 'rgb(128,128,128)',
|
||||
data : createClouds(),
|
||||
label : 'clouds',
|
||||
lines : {
|
||||
show : false
|
||||
},
|
||||
bars : {
|
||||
show : true,
|
||||
lineWidth : 0,
|
||||
barWidth : 20,
|
||||
fillColor : {
|
||||
colors : [
|
||||
{
|
||||
opacity : 0.2
|
||||
}, {
|
||||
opacity : 0.9
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
shadowSize : 2,
|
||||
yaxis : 2,
|
||||
}, { // Temperature
|
||||
color : 'rgb(255, 0, 0)',
|
||||
data : [],
|
||||
label : "temperature",
|
||||
lines : {
|
||||
lineWidth : 2,
|
||||
show : true
|
||||
},
|
||||
points : {
|
||||
show : true
|
||||
},
|
||||
bars : {
|
||||
show : false
|
||||
},
|
||||
shadowSize : 0,
|
||||
yaxis : 2,
|
||||
}, { // dewpoint
|
||||
color : 'rgb(0, 255, 0)',
|
||||
data : [],
|
||||
label : "dewpoint",
|
||||
lines : {
|
||||
lineWidth : 2,
|
||||
show : true
|
||||
},
|
||||
points : {
|
||||
show : true
|
||||
},
|
||||
bars : {
|
||||
show : false
|
||||
},
|
||||
shadowSize : 0,
|
||||
yaxis : 2,
|
||||
}, {
|
||||
color : 'rgb(0, 255, 0)',
|
||||
data : [],
|
||||
label : "windarrows",
|
||||
lines : {
|
||||
show : false
|
||||
},
|
||||
points : {
|
||||
show : false
|
||||
},
|
||||
bars : {
|
||||
show : false
|
||||
},
|
||||
windarrows : {
|
||||
show : true,
|
||||
},
|
||||
shadowSize : 0,
|
||||
yaxis : 2,
|
||||
|
||||
}
|
||||
]);
|
||||
|
||||
self.wxOptions = {
|
||||
legend : {
|
||||
show : false,
|
||||
},
|
||||
xaxis : {
|
||||
show : true,
|
||||
position : "bottom",
|
||||
color : 'blue',
|
||||
tickColor : 'green',
|
||||
min : -56,
|
||||
max : 50,
|
||||
tickLength : 0,
|
||||
},
|
||||
yaxes : [
|
||||
{ // Axis 1: Pressure (hpa), Log-P
|
||||
show : true,
|
||||
position : "left",
|
||||
color : 'blue',
|
||||
tickColor : 'blue',
|
||||
min : 100,
|
||||
max : 1050,
|
||||
// tickLength : 0,
|
||||
transform : function(v) {
|
||||
return -Math.log(v);
|
||||
},
|
||||
inverseTransform : function(v) {
|
||||
return Math.exp(-v);
|
||||
},
|
||||
|
||||
}, { // Axis 2: Altitude (km)
|
||||
show : true,
|
||||
position : "right",
|
||||
color : 'black',
|
||||
tickColor : 'green',
|
||||
min : -.020,
|
||||
max : 16,
|
||||
tickLength : 0,
|
||||
}
|
||||
],
|
||||
|
||||
grid : {
|
||||
hoverable : true,
|
||||
clickable : true
|
||||
},
|
||||
|
||||
hooks : {
|
||||
processRawData : function(plot, series, data, datapoints) {
|
||||
if (series.windarrows && series.windarrows.show) {
|
||||
datapoints.format = [
|
||||
{
|
||||
x : true,
|
||||
number : true,
|
||||
required : true
|
||||
|
||||
}, {
|
||||
y : true,
|
||||
number : true,
|
||||
required : true
|
||||
|
||||
}, {
|
||||
number : true,
|
||||
required : true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
drawSeries : function(plot, ctx, series) {
|
||||
if (series.windarrows && series.windarrows.show) {
|
||||
function drawSeriesWindarrows(datapoints) {
|
||||
var points = datapoints.points, ps = datapoints.pointsize;
|
||||
for (var i = 0; i < points.length; i += ps) {
|
||||
var ws = points[i], y = points[i+1], wd = points[i+2];
|
||||
|
||||
var x = series.xaxis.p2c(40);
|
||||
y = series.yaxis.p2c(y);
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(x,y);
|
||||
ctx.rotate((wd+180) * Math.PI/180);
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(0,0, 3, 0, Math.PI * 2, false);
|
||||
ctx.closePath();
|
||||
|
||||
ctx.moveTo(0,0);
|
||||
ctx.lineTo(0,9*5);
|
||||
var pos = 0;
|
||||
while( ws >= 5 ) {
|
||||
if( ws >= 50 ) {
|
||||
ws -= 50;
|
||||
ctx.moveTo(0,(9-pos)*5);
|
||||
ctx.lineTo(-10,(8.5-pos)*5);
|
||||
ctx.lineTo(0,(8-pos)*5);
|
||||
pos++;
|
||||
} else if( ws >= 10 ) {
|
||||
if( pos > 0 ) pos++;
|
||||
ws -= 10;
|
||||
ctx.moveTo(0,(9-pos)*5);
|
||||
ctx.lineTo(-10,(9.5-pos)*5);
|
||||
} else {
|
||||
pos++;
|
||||
ws -= 5;
|
||||
ctx.moveTo(0,(9-pos)*5);
|
||||
ctx.lineTo(-5,(9.25-pos)*5);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(plotOffset.left, plotOffset.top);
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.strokeStyle = 'black';
|
||||
|
||||
drawSeriesWindarrows(series.datapoints);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
self.afterUpdate = function(element) {
|
||||
var yaxisLabel = jquery("<div class='axisLabel yaxisLabel'></div>").text("Pressure (hpa)").appendTo(element);
|
||||
|
||||
// Since CSS transforms use the top-left corner of the label as the
|
||||
// transform origin,
|
||||
// we need to center the y-axis label by shifting it down by half
|
||||
// its
|
||||
// width.
|
||||
// Subtract 20 to factor the chart's bottom margin into the
|
||||
// centering.
|
||||
|
||||
yaxisLabel.css("margin-top", yaxisLabel.width() / 2 - 20);
|
||||
}
|
||||
|
||||
var highlighted = null;
|
||||
|
||||
self.plotHover = function(pos, item) {
|
||||
|
||||
if (highlighted) {
|
||||
self.wxData()[highlighted.seriesIndex].data[highlighted.dataIndex] = [
|
||||
pos.x1, highlighted.datapoint[1]
|
||||
];
|
||||
this.setData(self.wxData());
|
||||
this.draw();
|
||||
}
|
||||
}
|
||||
|
||||
self.plotClick = function(pos, item) {
|
||||
if (highlighted) {
|
||||
this.unhighlight(highlighted.series, highlighted.datapoint);
|
||||
highlighted = null;
|
||||
} else {
|
||||
if (item && item.seriesIndex != 3 && item.seriesIndex != 4)
|
||||
return;
|
||||
|
||||
highlighted = item;
|
||||
if (highlighted)
|
||||
this.highlight(highlighted.series, highlighted.datapoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ViewModel.prototype.dispose = function() {
|
||||
}
|
||||
|
||||
// Return component definition
|
||||
return {
|
||||
viewModel : {
|
||||
createViewModel : function(params, componentInfo) {
|
||||
return new ViewModel(params, componentInfo);
|
||||
},
|
||||
},
|
||||
template : htmlString
|
||||
};
|
||||
});
|
Loading…
Reference in a new issue