diff --git a/src/traces/contour/find_all_paths.js b/src/traces/contour/find_all_paths.js index ba54143e226..a04a34daf8e 100644 --- a/src/traces/contour/find_all_paths.js +++ b/src/traces/contour/find_all_paths.js @@ -45,9 +45,10 @@ function equalPts(pt1, pt2, xtol, ytol) { Math.abs(pt1[1] - pt2[1]) < ytol; } +// distance in index units - uses the 3rd and 4th items in points function ptDist(pt1, pt2) { - var dx = pt1[0] - pt2[0], - dy = pt1[1] - pt2[1]; + var dx = pt1[2] - pt2[2], + dy = pt1[3] - pt2[3]; return Math.sqrt(dx * dx + dy * dy); } @@ -114,9 +115,13 @@ function makePath(pi, loc, edgeflag, xtol, ytol) { ptavg, thisdist; - // check for points that are too close together (<1/5 the average dist, - // less if less smoothed) and just take the center (or avg of center 2) - // this cuts down on funny behavior when a point is very close to a contour level + /* + * Check for points that are too close together (<1/5 the average dist + * *in grid index units* (important for log axes and nonuniform grids), + * less if less smoothed) and just take the center (or avg of center 2). + * This cuts down on funny behavior when a point is very close to a + * contour level. + */ for(cnt = 1; cnt < pts.length; cnt++) { thisdist = ptDist(pts[cnt], pts[cnt - 1]); totaldist += thisdist; @@ -174,6 +179,10 @@ function makePath(pi, loc, edgeflag, xtol, ytol) { } pts.splice(0, cropstart); + // done with the index parts - remove them so path generation works right + // because it depends on only having [xpx, ypx] + for(cnt = 0; cnt < pts.length; cnt++) pts[cnt].length = 2; + // don't return single-point paths (ie all points were the same // so they got deleted?) if(pts.length < 2) return; @@ -252,6 +261,21 @@ function startStep(mi, edgeflag, loc) { return [dx, dy]; } +/* + * Find the pixel coordinates of a particular crossing + * + * @param {object} pi: the pathinfo object at this level + * @param {array} loc: the grid index [x, y] of the crossing + * @param {array} step: the direction [dx, dy] we're moving on the grid + * + * @return {array} [xpx, ypx, xi, yi]: the first two are the pixel location, + * the next two are the interpolated grid indices, which we use for + * distance calculations to delete points that are too close together. + * This is important when the grid is nonuniform (and most dramatically when + * we're on log axes and include invalid (0 or negative) values. + * It's crucial to delete these extra two before turning an array of these + * points into a path, because those routines require length-2 points. + */ function getInterpPx(pi, loc, step) { var locx = loc[0] + Math.max(step[0], 0), locy = loc[1] + Math.max(step[1], 0), @@ -263,11 +287,13 @@ function getInterpPx(pi, loc, step) { var dx = (pi.level - zxy) / (pi.z[locy][locx + 1] - zxy); return [xa.c2p((1 - dx) * pi.x[locx] + dx * pi.x[locx + 1], true), - ya.c2p(pi.y[locy], true)]; + ya.c2p(pi.y[locy], true), + locx + dx, locy]; } else { var dy = (pi.level - zxy) / (pi.z[locy + 1][locx] - zxy); return [xa.c2p(pi.x[locx], true), - ya.c2p((1 - dy) * pi.y[locy] + dy * pi.y[locy + 1], true)]; + ya.c2p((1 - dy) * pi.y[locy] + dy * pi.y[locy + 1], true), + locx, locy + dy]; } } diff --git a/test/image/baselines/2dhistogram_contour_subplots.png b/test/image/baselines/2dhistogram_contour_subplots.png index c420434a89a..ef4a2dbbbcd 100644 Binary files a/test/image/baselines/2dhistogram_contour_subplots.png and b/test/image/baselines/2dhistogram_contour_subplots.png differ diff --git a/test/image/baselines/colorscale_opacity.png b/test/image/baselines/colorscale_opacity.png index d7c4208301c..ac0b7c91f11 100644 Binary files a/test/image/baselines/colorscale_opacity.png and b/test/image/baselines/colorscale_opacity.png differ diff --git a/test/image/baselines/connectgaps_2d.png b/test/image/baselines/connectgaps_2d.png index 2e5204661fd..da76761995f 100644 Binary files a/test/image/baselines/connectgaps_2d.png and b/test/image/baselines/connectgaps_2d.png differ diff --git a/test/image/baselines/contour_heatmap_coloring.png b/test/image/baselines/contour_heatmap_coloring.png index 71729494d04..3cd6d809fe0 100644 Binary files a/test/image/baselines/contour_heatmap_coloring.png and b/test/image/baselines/contour_heatmap_coloring.png differ diff --git a/test/image/baselines/contour_lines_coloring.png b/test/image/baselines/contour_lines_coloring.png index 2c8cbf70d95..b77a3eb2e1b 100644 Binary files a/test/image/baselines/contour_lines_coloring.png and b/test/image/baselines/contour_lines_coloring.png differ diff --git a/test/image/baselines/contour_log.png b/test/image/baselines/contour_log.png new file mode 100644 index 00000000000..421db2d8fbb Binary files /dev/null and b/test/image/baselines/contour_log.png differ diff --git a/test/image/baselines/contour_transposed-irregular.png b/test/image/baselines/contour_transposed-irregular.png index 90df78bcbc3..cd063da92cc 100644 Binary files a/test/image/baselines/contour_transposed-irregular.png and b/test/image/baselines/contour_transposed-irregular.png differ diff --git a/test/image/baselines/contour_transposed.png b/test/image/baselines/contour_transposed.png index fe64b0bafeb..1e4a8b63349 100644 Binary files a/test/image/baselines/contour_transposed.png and b/test/image/baselines/contour_transposed.png differ diff --git a/test/image/baselines/simple_contour.png b/test/image/baselines/simple_contour.png index b086bf5f25f..96f454bdc1f 100644 Binary files a/test/image/baselines/simple_contour.png and b/test/image/baselines/simple_contour.png differ diff --git a/test/image/mocks/contour_log.json b/test/image/mocks/contour_log.json new file mode 100644 index 00000000000..d6b5b92fe1c --- /dev/null +++ b/test/image/mocks/contour_log.json @@ -0,0 +1,76 @@ +{ + "data": [ + { + "x": [0, 1, 2, 3, 10, 30], + "y": [0, 1, 2, 3, 10, 30], + "z": [ + [10, 9, 8, 7, 6, 5], + [9, 8, 7, 6, 5, 4], + [8, 7, 6, 5, 4, 3], + [7, 6, 5, 9, 3, 2], + [6, 5, 4, 8, 2, 1], + [5, 4, 3, 2, 1, 0] + ], + "contours": {"start": 4, "end": 6.5, "size": 1}, + "type": "contour" + }, + { + "x": [0, 1, 2, 3, 10, 30], + "y": [0, 1, 2, 3, 10, 30], + "z": [ + [10, 9, 8, 7, 6, 5], + [9, 8, 7, 6, 5, 4], + [8, 7, 6, 5, 4, 3], + [7, 6, 5, 9, 3, 2], + [6, 5, 4, 8, 2, 1], + [5, 4, 3, 2, 1, 0] + ], + "contours": {"start": 4, "end": 6.5, "size": 1}, + "type": "contour", + "showscale": false, + "xaxis": "x2" + }, + { + "x": [0, 1, 2, 3, 10, 30], + "y": [0, 1, 2, 3, 10, 30], + "z": [ + [10, 9, 8, 7, 6, 5], + [9, 8, 7, 6, 5, 4], + [8, 7, 6, 5, 4, 3], + [7, 6, 5, 9, 3, 2], + [6, 5, 4, 8, 2, 1], + [5, 4, 3, 2, 1, 0] + ], + "contours": {"start": 4, "end": 6.5, "size": 1}, + "type": "contour", + "showscale": false, + "yaxis": "y2" + }, + { + "x": [0, 1, 2, 3, 10, 30], + "y": [0, 1, 2, 3, 10, 30], + "z": [ + [10, 9, 8, 7, 6, 5], + [9, 8, 7, 6, 5, 4], + [8, 7, 6, 5, 4, 3], + [7, 6, 5, 9, 3, 2], + [6, 5, 4, 8, 2, 1], + [5, 4, 3, 2, 1, 0] + ], + "contours": {"start": 4, "end": 6.5, "size": 1}, + "type": "contour", + "showscale": false, + "xaxis": "x2", + "yaxis": "y2" + } + ], + "layout": { + "xaxis": {"domain": [0, 0.45]}, + "xaxis2": {"domain": [0.55, 1], "type": "log"}, + "yaxis": {"domain": [0, 0.45]}, + "yaxis2": {"domain": [0.55, 1], "type": "log"}, + "margin": {"l": 50, "b": 50, "r": 110, "t": 10}, + "width": 500, + "height": 400 + } +}