Skip to content

Commit ad8b25e

Browse files
author
Ivo Sonderegger
committed
Hodograph: Plot segments of a sounding with different styles
Relates to #39
1 parent 1a53632 commit ad8b25e

File tree

2 files changed

+210
-6
lines changed

2 files changed

+210
-6
lines changed

src/meteoJS/thermodynamicDiagram/Hodograph.js

+51-6
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export class Hodograph extends PlotDataArea {
104104
};
105105
},
106106
insertDataGroupInto = (svgNode, dataGroupId, sounding, data) => {
107-
const dataToPlot = data
107+
const basePolylines = [data
108108
.filter(level => {
109109
if (sounding.options.hodograph.minPressure !== undefined
110110
&& level.levelData.pres !== undefined
@@ -115,11 +115,56 @@ export class Hodograph extends PlotDataArea {
115115
&& level.levelData.pres > sounding.options.hodograph.maxPressure)
116116
return false;
117117
return true;
118-
})
119-
.map(level => [ level.x, level.y ]);
120-
svgNode
121-
.polyline(dataToPlot)
122-
.fill('none').stroke(sounding.options.hodograph.style);
118+
})];
119+
basePolylines[0].sort((a,b) => b.levelData.pres-a.levelData.pres);
120+
const segmentPolylines = [];
121+
for (const segment of sounding.options.hodograph.segments) {
122+
const def = {
123+
levels: [],
124+
visible: segment.visible,
125+
style: segment.style
126+
};
127+
basePolylines.map((basePolyline, i) => {
128+
let lowSplit = undefined;
129+
let highSplit = undefined;
130+
basePolyline.map(l => {
131+
if ((segment.minPressure !== undefined && segment.minPressure <= l.levelData.pres
132+
&& segment.maxPressure !== undefined && segment.maxPressure >= l.levelData.pres)
133+
|| (segment.minPressure === undefined
134+
&& segment.maxPressure !== undefined && segment.maxPressure >= l.levelData.pres)
135+
|| (segment.minPressure !== undefined && segment.minPressure <= l.levelData.pres
136+
&& segment.maxPressure === undefined)) {
137+
def.levels.push(l);
138+
if (highSplit === undefined)
139+
highSplit = l;
140+
lowSplit = l;
141+
}
142+
});
143+
if (highSplit !== undefined && lowSplit !== undefined && highSplit !== lowSplit) {
144+
const indexLow = basePolyline
145+
.findIndex(l => l.levelData.pres === lowSplit.levelData.pres);
146+
const indexHigh = basePolyline
147+
.findIndex(l => l.levelData.pres === highSplit.levelData.pres);
148+
const newBaseLine = basePolyline.slice(indexLow);
149+
basePolylines[i] = basePolyline.slice(0, indexHigh+1);
150+
basePolylines.push(newBaseLine);
151+
}
152+
});
153+
if (def.levels.length > 0)
154+
segmentPolylines.push(def);
155+
}
156+
basePolylines.map(basePolyline => {
157+
if (basePolyline.length < 2)
158+
return;
159+
svgNode
160+
.polyline(basePolyline.map(level => [ level.x, level.y ]))
161+
.fill('none').stroke(sounding.options.hodograph.style);
162+
});
163+
segmentPolylines.map(segmentPolyline => {
164+
svgNode
165+
.polyline(segmentPolyline.levels.map(level => [ level.x, level.y ]))
166+
.fill('none').stroke(segmentPolyline.style);
167+
});
123168
},
124169
grid = {},
125170
windspeedMax = windspeedKNToMS(150),

test/meteoJS/thermodynamicDiagram/hodograph.test.js

+159
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,165 @@ describe('Hodograph class, import via default', () => {
383383
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].fill(),
384384
'none', 'fill');
385385
});
386+
describe('segments', () => {
387+
it('test one', () => {
388+
const sounding = new Sounding();
389+
Array.from({length: 20 }, (v, i) => i).map(i => {
390+
sounding.addLevel({
391+
pres: 1000 - i * 50,
392+
wspd: Math.random() * 100,
393+
wdir: Math.random() * 360
394+
});
395+
});
396+
const diagramSounding = new DiagramSounding(sounding, {
397+
hodograph: {
398+
segments: [{
399+
minPressure: 850,
400+
style: {
401+
color: 'red'
402+
}
403+
}, {
404+
maxPressure: 800,
405+
minPressure: 700,
406+
style: {
407+
color: 'orange'
408+
}
409+
}, {
410+
maxPressure: 499,
411+
minPressure: 401,
412+
style: {
413+
color: 'yellow'
414+
}
415+
}, {
416+
maxPressure: 60,
417+
style: {
418+
color: 'violet'
419+
}
420+
}]
421+
}
422+
});
423+
const hodograph = new Hodograph({
424+
svgNode: SVG().size(300,300),
425+
x: 0,
426+
y: 0,
427+
width: 100,
428+
height: 100
429+
});
430+
hodograph.addSounding(diagramSounding);
431+
assert.ok(hodograph._svgNodeData.children()[0].visible(), 'visible');
432+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children().length,
433+
6, 'polyline count');
434+
hodograph._svgNodeData.children()[0].children()[0].children()
435+
.map(n => assert.equal(n.type, 'polyline', 'SVG node type'));
436+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].array().length,
437+
2, '[0]: point count');
438+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].stroke(),
439+
'black', '[0]: color');
440+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[1].array().length,
441+
14, '[1]: point count');
442+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[1].stroke(),
443+
'black', '[1]: color');
444+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[2].array().length,
445+
4, '[2]: point count');
446+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[2].stroke(),
447+
'red', '[2]: color');
448+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[3].array().length,
449+
3, '[3]: point count');
450+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[3].stroke(),
451+
'orange', '[3]: color');
452+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[4].array().length,
453+
1, '[4]: point count');
454+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[4].stroke(),
455+
'yellow', '[4]: color');
456+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[5].array().length,
457+
1, '[5]: point count');
458+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[5].stroke(),
459+
'violet', '[5]: color');
460+
});
461+
it('test two', () => {
462+
const sounding = new Sounding();
463+
Array.from({length: 20 }, (v, i) => i).map(i => {
464+
sounding.addLevel({
465+
pres: 50 + i * 50,
466+
wspd: Math.random() * 100,
467+
wdir: Math.random() * 360
468+
});
469+
});
470+
const diagramSounding = new DiagramSounding(sounding, {
471+
hodograph: {
472+
minPressure: 110,
473+
maxPressure: 750,
474+
segments: [{
475+
minPressure: 850,
476+
style: {
477+
color: 'red'
478+
}
479+
}, {
480+
maxPressure: 800,
481+
minPressure: 700,
482+
style: {
483+
color: 'orange'
484+
}
485+
}, {
486+
maxPressure: 499,
487+
minPressure: 401,
488+
style: {
489+
color: 'yellow'
490+
}
491+
}, {
492+
maxPressure: 60,
493+
style: {
494+
color: 'violet'
495+
}
496+
}]
497+
}
498+
});
499+
const hodograph = new Hodograph({
500+
svgNode: SVG().size(300,300),
501+
x: 0,
502+
y: 0,
503+
width: 100,
504+
height: 100
505+
});
506+
hodograph.addSounding(diagramSounding);
507+
assert.ok(hodograph._svgNodeData.children()[0].visible(), 'visible');
508+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children().length,
509+
3, 'polyline count');
510+
hodograph._svgNodeData.children()[0].children()[0].children()
511+
.map(n => assert.equal(n.type, 'polyline', 'SVG node type'));
512+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].array().length,
513+
12, '[0]: point count');
514+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].stroke(),
515+
'black', '[0]: color');
516+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[1].array().length,
517+
2, '[1]: point count');
518+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[1].stroke(),
519+
'orange', '[1]: color');
520+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[2].array().length,
521+
1, '[2]: point count');
522+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[2].stroke(),
523+
'yellow', '[2]: color');
524+
diagramSounding.update({
525+
hodograph: {
526+
segments: [{
527+
minPressure: 850,
528+
style: {
529+
color: 'red'
530+
}
531+
}]
532+
}
533+
});
534+
assert.ok(hodograph._svgNodeData.children()[0].visible(), 'visible');
535+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children().length,
536+
1, 'polyline count');
537+
hodograph._svgNodeData.children()[0].children()[0].children()
538+
.map(n => assert.equal(n.type, 'polyline', 'SVG node type'));
539+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].array().length,
540+
13, '[0]: point count');
541+
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].stroke(),
542+
'black', '[0]: color');
543+
});
544+
});
386545
});
387546
});
388547
describe('Hodograph class, import via name', () => {

0 commit comments

Comments
 (0)