Skip to content

Commit 2249c3c

Browse files
committed
#fi-51 contour plot fill test case
1 parent 5bb417b commit 2249c3c

File tree

3 files changed

+111
-14
lines changed

3 files changed

+111
-14
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"delaunay-triangulate": "^1.1.6",
5555
"es6-promise": "^3.0.2",
5656
"fast-isnumeric": "^1.1.1",
57-
"gl-contour2d": "git://github.com/monfera/gl-contour2d.git#integration",
57+
"gl-contour2d": "git://github.com/gl-vis/gl-contour2d.git",
5858
"gl-error2d": "^1.0.0",
5959
"gl-error3d": "^1.0.0",
6060
"gl-heatmap2d": "^1.0.2",

src/traces/contourgl/convert.js

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ proto.update = function(fullTrace, calcTrace) {
8585
// convert z from 2D -> 1D
8686
var z = calcPt.z,
8787
rowLen = z[0].length,
88-
colLen = z.length;
88+
colLen = z.length,
89+
colorOptions;
8990

9091
this.contourOptions.z = flattenZ(z, rowLen, colLen);
9192
this.heatmapOptions.z = [].concat.apply([], z);
@@ -95,16 +96,21 @@ proto.update = function(fullTrace, calcTrace) {
9596
this.contourOptions.x = this.heatmapOptions.x = calcPt.x;
9697
this.contourOptions.y = this.heatmapOptions.y = calcPt.y;
9798

98-
var colorOptions = convertColorscale(fullTrace);
99-
this.contourOptions.levels = colorOptions.levels;
100-
this.contourOptions.levelColors = colorOptions.levelColors;
10199

102100
// pass on fill information
103101
if(fullTrace.contours.coloring === 'fill') {
102+
colorOptions = convertColorscale(fullTrace, true);
103+
this.contourOptions.levels = colorOptions.levels.slice(1);
104104
// though gl-contour2d automatically defaults to a transparent layer for the last
105105
// band color, it's set manually here in case the gl-contour2 API changes
106-
this.contourOptions.fillColors = colorOptions.levelColors.concat([0,0,0,0])
107-
.map(function(d, i) {return i % 4 === 3 ? d / 2 : d}); // halve the fill alphas
106+
this.contourOptions.fillColors = colorOptions.levelColors;
107+
this.contourOptions.levelColors = [].concat.apply([], this.contourOptions.levels.map(function() {
108+
return [.25,.25,.25,1];
109+
}));
110+
} else {
111+
colorOptions = convertColorscale(fullTrace, false);
112+
this.contourOptions.levels = colorOptions.levels;
113+
this.contourOptions.levelColors = colorOptions.levelColors;
108114
}
109115

110116
// convert text from 2D -> 1D
@@ -132,20 +138,21 @@ function flattenZ(zIn, rowLen, colLen) {
132138
return zOut;
133139
}
134140

135-
function convertColorscale(fullTrace) {
141+
function convertColorscale(fullTrace, fill) {
136142
var contours = fullTrace.contours,
137143
start = contours.start,
138144
end = contours.end,
139145
cs = contours.size || 1;
140146

141147
var colorMap = makeColorMap(fullTrace);
142148

143-
var N = Math.floor((end - start) / cs) + 1,
149+
var N = Math.floor((end - start) / cs) + (fill ? 2 : 1), // for K thresholds (contour linees) there are K+1 areas
144150
levels = new Array(N),
145151
levelColors = new Array(4 * N);
146152

147153
for(var i = 0; i < N; i++) {
148-
var level = levels[i] = start + cs * (i);
154+
var level = levels[i] = start + cs * (i) - (fill ? cs / 2 : 0); // in case of fill, use band midpoint
155+
console.log(level)
149156
var color = str2RGBArray(colorMap(level));
150157

151158
for(var j = 0; j < 4; j++) {

test/jasmine/tests/gl_scatterplot_contour_test.js

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
'use strict';
22

33
var Plotly = require('@lib/index');
4+
var Lib = require('@src/lib');
5+
var d3 = require('d3');
46

57
// contourgl is not part of the dist plotly.js bundle initially
68
Plotly.register(
@@ -82,18 +84,106 @@ var plotData = {
8284
}
8385
};
8486

87+
function transpose(a) {
88+
return a[0].map(function(ignore, columnIndex) {return a.map(function(row) {return row[columnIndex];});});
89+
}
90+
91+
function jitter(n) {
92+
return n + (Math.random() - 0.5) / 2;
93+
}
94+
95+
function rotate(rad, point) {
96+
return {
97+
x: point.x * Math.cos(rad) - point.y * Math.sin(rad),
98+
y: point.x * Math.sin(rad) + point.y * Math.cos(rad)
99+
}
100+
}
101+
102+
function generator() {
103+
var x = d3.range(-12, 13, 1); // left closed, right open interval
104+
var y = d3.range(-12, 13, 1); // left closed, right open interval
105+
var i, j, p, z = new Array(x.length);
106+
for(i = 0; i < x.length; i++) {
107+
z[i] = new Array(y.length);
108+
for(j = 0; j < y.length; j++) {
109+
p = rotate(Math.PI / 4, {x: x[i], y: -y[j]})
110+
z[i][j] = jitter(Math.pow(p.x, 2) / (10 * 10) + Math.pow(p.y, 2) / (4 * 4))
111+
}
112+
}
113+
return {x: x, y: y, z: z} // looking forward to the ES2015 return {x, y, z}
114+
}
115+
116+
var model = generator();
117+
118+
// equivalent to the new example case in gl-contour2d
119+
var plotDataCircular = {
120+
"data": [
121+
{
122+
"type": "contourgl",
123+
"x": model.x.map(jitter),
124+
"y": model.y.map(jitter),
125+
"z": transpose(model.z), // gl-vis is column-major order while ploly is row-major order
126+
"colorscale": "Jet",
127+
"contours": {
128+
"start": 0,
129+
"end": 2,
130+
"size": 0.1,
131+
"coloring": "lines"
132+
},
133+
"uid": "ad5624",
134+
"zmin": 0,
135+
"zmax": 2
136+
}
137+
],
138+
"layout": {
139+
"xaxis": {
140+
"range": [
141+
-10,
142+
10
143+
],
144+
"autorange": true
145+
},
146+
"yaxis": {
147+
"range": [
148+
-10,
149+
10
150+
],
151+
"autorange": true
152+
},
153+
"height": 600,
154+
"width": 600,
155+
"autosize": true
156+
}
157+
};
158+
159+
85160
function makePlot(gd, mock) {
86161
return Plotly.plot(gd, mock.data, mock.layout);
87162
}
88163

89164
fdescribe('contourgl plots', function() {
90165

166+
// this dataset is a special case, very forgiving to the contour renderer, as it's convex,
167+
// contains no inflexion points etc.
91168
it('render without raising an error', function(done) {
92169
withSetupTeardown(done, function(gd) {
93-
return makePlot(gd, plotData)
94-
.then(function(gd) {
95-
//debugger;
96-
})
170+
return makePlot(gd, plotData);
171+
});
172+
});
173+
174+
// this dataset is less forgiving because it uses a noisy surface (random, will look different on each run)
175+
it('render without raising an error (coloring: "lines")', function(done) {
176+
withSetupTeardown(done, function(gd) {
177+
return makePlot(gd, plotDataCircular);
178+
});
179+
});
180+
181+
// same with fill
182+
fit('render without raising an error (coloring: "fill")', function(done) {
183+
var mock = Lib.extendDeep({}, plotDataCircular);
184+
mock.data[0].contours.coloring = "fill"; // or delete property - fill is the default
185+
withSetupTeardown(done, function(gd) {
186+
return makePlot(gd, mock);
97187
});
98188
});
99189

0 commit comments

Comments
 (0)