Skip to content

Commit

Permalink
Hodograph: Plot segments of a sounding with different styles
Browse files Browse the repository at this point in the history
Relates to #39
  • Loading branch information
Ivo Sonderegger committed Jul 5, 2021
1 parent 1a53632 commit ad8b25e
Show file tree
Hide file tree
Showing 2 changed files with 210 additions and 6 deletions.
57 changes: 51 additions & 6 deletions src/meteoJS/thermodynamicDiagram/Hodograph.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class Hodograph extends PlotDataArea {
};
},
insertDataGroupInto = (svgNode, dataGroupId, sounding, data) => {
const dataToPlot = data
const basePolylines = [data
.filter(level => {
if (sounding.options.hodograph.minPressure !== undefined
&& level.levelData.pres !== undefined
Expand All @@ -115,11 +115,56 @@ export class Hodograph extends PlotDataArea {
&& level.levelData.pres > sounding.options.hodograph.maxPressure)
return false;
return true;
})
.map(level => [ level.x, level.y ]);
svgNode
.polyline(dataToPlot)
.fill('none').stroke(sounding.options.hodograph.style);
})];
basePolylines[0].sort((a,b) => b.levelData.pres-a.levelData.pres);
const segmentPolylines = [];
for (const segment of sounding.options.hodograph.segments) {
const def = {
levels: [],
visible: segment.visible,
style: segment.style
};
basePolylines.map((basePolyline, i) => {
let lowSplit = undefined;
let highSplit = undefined;
basePolyline.map(l => {
if ((segment.minPressure !== undefined && segment.minPressure <= l.levelData.pres
&& segment.maxPressure !== undefined && segment.maxPressure >= l.levelData.pres)
|| (segment.minPressure === undefined
&& segment.maxPressure !== undefined && segment.maxPressure >= l.levelData.pres)
|| (segment.minPressure !== undefined && segment.minPressure <= l.levelData.pres
&& segment.maxPressure === undefined)) {
def.levels.push(l);
if (highSplit === undefined)
highSplit = l;
lowSplit = l;
}
});
if (highSplit !== undefined && lowSplit !== undefined && highSplit !== lowSplit) {
const indexLow = basePolyline
.findIndex(l => l.levelData.pres === lowSplit.levelData.pres);
const indexHigh = basePolyline
.findIndex(l => l.levelData.pres === highSplit.levelData.pres);
const newBaseLine = basePolyline.slice(indexLow);
basePolylines[i] = basePolyline.slice(0, indexHigh+1);
basePolylines.push(newBaseLine);
}
});
if (def.levels.length > 0)
segmentPolylines.push(def);
}
basePolylines.map(basePolyline => {
if (basePolyline.length < 2)
return;
svgNode
.polyline(basePolyline.map(level => [ level.x, level.y ]))
.fill('none').stroke(sounding.options.hodograph.style);
});
segmentPolylines.map(segmentPolyline => {
svgNode
.polyline(segmentPolyline.levels.map(level => [ level.x, level.y ]))
.fill('none').stroke(segmentPolyline.style);
});
},
grid = {},
windspeedMax = windspeedKNToMS(150),
Expand Down
159 changes: 159 additions & 0 deletions test/meteoJS/thermodynamicDiagram/hodograph.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,165 @@ describe('Hodograph class, import via default', () => {
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].fill(),
'none', 'fill');
});
describe('segments', () => {
it('test one', () => {
const sounding = new Sounding();
Array.from({length: 20 }, (v, i) => i).map(i => {
sounding.addLevel({
pres: 1000 - i * 50,
wspd: Math.random() * 100,
wdir: Math.random() * 360
});
});
const diagramSounding = new DiagramSounding(sounding, {
hodograph: {
segments: [{
minPressure: 850,
style: {
color: 'red'
}
}, {
maxPressure: 800,
minPressure: 700,
style: {
color: 'orange'
}
}, {
maxPressure: 499,
minPressure: 401,
style: {
color: 'yellow'
}
}, {
maxPressure: 60,
style: {
color: 'violet'
}
}]
}
});
const hodograph = new Hodograph({
svgNode: SVG().size(300,300),
x: 0,
y: 0,
width: 100,
height: 100
});
hodograph.addSounding(diagramSounding);
assert.ok(hodograph._svgNodeData.children()[0].visible(), 'visible');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children().length,
6, 'polyline count');
hodograph._svgNodeData.children()[0].children()[0].children()
.map(n => assert.equal(n.type, 'polyline', 'SVG node type'));
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].array().length,
2, '[0]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].stroke(),
'black', '[0]: color');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[1].array().length,
14, '[1]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[1].stroke(),
'black', '[1]: color');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[2].array().length,
4, '[2]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[2].stroke(),
'red', '[2]: color');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[3].array().length,
3, '[3]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[3].stroke(),
'orange', '[3]: color');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[4].array().length,
1, '[4]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[4].stroke(),
'yellow', '[4]: color');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[5].array().length,
1, '[5]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[5].stroke(),
'violet', '[5]: color');
});
it('test two', () => {
const sounding = new Sounding();
Array.from({length: 20 }, (v, i) => i).map(i => {
sounding.addLevel({
pres: 50 + i * 50,
wspd: Math.random() * 100,
wdir: Math.random() * 360
});
});
const diagramSounding = new DiagramSounding(sounding, {
hodograph: {
minPressure: 110,
maxPressure: 750,
segments: [{
minPressure: 850,
style: {
color: 'red'
}
}, {
maxPressure: 800,
minPressure: 700,
style: {
color: 'orange'
}
}, {
maxPressure: 499,
minPressure: 401,
style: {
color: 'yellow'
}
}, {
maxPressure: 60,
style: {
color: 'violet'
}
}]
}
});
const hodograph = new Hodograph({
svgNode: SVG().size(300,300),
x: 0,
y: 0,
width: 100,
height: 100
});
hodograph.addSounding(diagramSounding);
assert.ok(hodograph._svgNodeData.children()[0].visible(), 'visible');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children().length,
3, 'polyline count');
hodograph._svgNodeData.children()[0].children()[0].children()
.map(n => assert.equal(n.type, 'polyline', 'SVG node type'));
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].array().length,
12, '[0]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].stroke(),
'black', '[0]: color');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[1].array().length,
2, '[1]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[1].stroke(),
'orange', '[1]: color');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[2].array().length,
1, '[2]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[2].stroke(),
'yellow', '[2]: color');
diagramSounding.update({
hodograph: {
segments: [{
minPressure: 850,
style: {
color: 'red'
}
}]
}
});
assert.ok(hodograph._svgNodeData.children()[0].visible(), 'visible');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children().length,
1, 'polyline count');
hodograph._svgNodeData.children()[0].children()[0].children()
.map(n => assert.equal(n.type, 'polyline', 'SVG node type'));
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].array().length,
13, '[0]: point count');
assert.equal(hodograph._svgNodeData.children()[0].children()[0].children()[0].stroke(),
'black', '[0]: color');
});
});
});
});
describe('Hodograph class, import via name', () => {
Expand Down

0 comments on commit ad8b25e

Please sign in to comment.