diff --git a/Phi/topics/Environment.js b/Phi/topics/Environment.js index 85d1f8696..73061d7f4 100644 --- a/Phi/topics/Environment.js +++ b/Phi/topics/Environment.js @@ -6,7 +6,7 @@ define([ }); ko.components.register('Environment/Weather', { - require : 'topics/Environment/Weather' + require : 'topics/Environment/Weather2' }); ko.components.register('Environment/Position', { diff --git a/Phi/topics/Environment/Weather2.html b/Phi/topics/Environment/Weather2.html new file mode 100644 index 000000000..10ba54a9c --- /dev/null +++ b/Phi/topics/Environment/Weather2.html @@ -0,0 +1,28 @@ + + +
diff --git a/Phi/topics/Environment/Weather2.js b/Phi/topics/Environment/Weather2.js new file mode 100644 index 000000000..44f085170 --- /dev/null +++ b/Phi/topics/Environment/Weather2.js @@ -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("").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 + }; +});