Skip to content

Commit

Permalink
Merge pull request #4578 from plotly/fix4514-preserve-gl3d-scene-aspe…
Browse files Browse the repository at this point in the history
…ctratio

Preserve gl3d scene aspectratio after orthographic scroll zoom
  • Loading branch information
archmoj authored Feb 12, 2020
2 parents 9e864a5 + 1828797 commit 4d24c36
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 34 deletions.
67 changes: 33 additions & 34 deletions src/plots/gl3d/scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ proto.initializeGLPlot = function() {
y: s * o.y,
z: s * o.z
});
scene.fullSceneLayout.aspectmode = layout[scene.id].aspectmode = 'manual';
}

relayoutCallback(scene);
Expand Down Expand Up @@ -470,12 +471,12 @@ proto.recoverContext = function() {
var axisProperties = [ 'xaxis', 'yaxis', 'zaxis' ];

function computeTraceBounds(scene, trace, bounds) {
var sceneLayout = scene.fullSceneLayout;
var fullSceneLayout = scene.fullSceneLayout;

for(var d = 0; d < 3; d++) {
var axisName = axisProperties[d];
var axLetter = axisName.charAt(0);
var ax = sceneLayout[axisName];
var ax = fullSceneLayout[axisName];
var coords = trace[axLetter];
var calendar = trace[axLetter + 'calendar'];
var len = trace['_' + axLetter + 'length'];
Expand Down Expand Up @@ -508,13 +509,13 @@ function computeTraceBounds(scene, trace, bounds) {
}

function computeAnnotationBounds(scene, bounds) {
var sceneLayout = scene.fullSceneLayout;
var annotations = sceneLayout.annotations || [];
var fullSceneLayout = scene.fullSceneLayout;
var annotations = fullSceneLayout.annotations || [];

for(var d = 0; d < 3; d++) {
var axisName = axisProperties[d];
var axLetter = axisName.charAt(0);
var ax = sceneLayout[axisName];
var ax = fullSceneLayout[axisName];

for(var j = 0; j < annotations.length; j++) {
var ann = annotations[j];
Expand Down Expand Up @@ -725,42 +726,40 @@ proto.plot = function(sceneData, fullLayout, layout) {
});
}

var axesScaleRatio = [1, 1, 1];

// Compute axis scale per category
for(i = 0; i < 3; ++i) {
axis = fullSceneLayout[axisProperties[i]];
axisType = axis.type;
var axisRatio = axisTypeRatios[axisType];
axesScaleRatio[i] = Math.pow(axisRatio.acc, 1.0 / axisRatio.count) / dataScale[i];
}

/*
* Dynamically set the aspect ratio depending on the users aspect settings
*/
var axisAutoScaleFactor = 4;
var aspectRatio;

if(fullSceneLayout.aspectmode === 'auto') {
if(Math.max.apply(null, axesScaleRatio) / Math.min.apply(null, axesScaleRatio) <= axisAutoScaleFactor) {
/*
* USE DATA MODE WHEN AXIS RANGE DIMENSIONS ARE RELATIVELY EQUAL
*/

aspectRatio = axesScaleRatio;
} else {
/*
* USE EQUAL MODE WHEN AXIS RANGE DIMENSIONS ARE HIGHLY UNEQUAL
*/
aspectRatio = [1, 1, 1];
}
} else if(fullSceneLayout.aspectmode === 'cube') {
var aspectmode = fullSceneLayout.aspectmode;
if(aspectmode === 'cube') {
aspectRatio = [1, 1, 1];
} else if(fullSceneLayout.aspectmode === 'data') {
aspectRatio = axesScaleRatio;
} else if(fullSceneLayout.aspectmode === 'manual') {
} else if(aspectmode === 'manual') {
var userRatio = fullSceneLayout.aspectratio;
aspectRatio = [userRatio.x, userRatio.y, userRatio.z];
} else if(aspectmode === 'auto' || aspectmode === 'data') {
var axesScaleRatio = [1, 1, 1];
// Compute axis scale per category
for(i = 0; i < 3; ++i) {
axis = fullSceneLayout[axisProperties[i]];
axisType = axis.type;
var axisRatio = axisTypeRatios[axisType];
axesScaleRatio[i] = Math.pow(axisRatio.acc, 1.0 / axisRatio.count) / dataScale[i];
}

if(aspectmode === 'data') {
aspectRatio = axesScaleRatio;
} else { // i.e. 'auto' option
if(
Math.max.apply(null, axesScaleRatio) /
Math.min.apply(null, axesScaleRatio) <= 4
) {
// USE DATA MODE WHEN AXIS RANGE DIMENSIONS ARE RELATIVELY EQUAL
aspectRatio = axesScaleRatio;
} else {
// USE EQUAL MODE WHEN AXIS RANGE DIMENSIONS ARE HIGHLY UNEQUAL
aspectRatio = [1, 1, 1];
}
}
} else {
throw new Error('scene.js aspectRatio was not one of the enumerated types');
}
Expand Down
92 changes: 92 additions & 0 deletions test/jasmine/tests/gl3d_plot_interact_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,98 @@ describe('Test gl3d drag and wheel interactions', function() {
.catch(failTest)
.then(done);
});

it('@gl should preserve aspectratio values when orthographic scroll zoom i.e. after restyle', function(done) {
var coords = {
x: [1, 2, 10, 4, 5],
y: [10, 2, 4, 4, 2],
z: [10, 2, 4, 8, 16],
};

var mock = {
data: [{
type: 'scatter3d',
x: coords.x,
y: coords.y,
z: coords.z,
mode: 'markers',
marker: {
color: 'red',
size: 16,
}
}, {
type: 'scatter3d',
x: [coords.x[0]],
y: [coords.y[0]],
z: [coords.z[0]],
mode: 'markers',
marker: {
color: 'blue',
size: 32,
}
}],
layout: {
width: 400,
height: 400,
scene: {
camera: {
projection: {
type: 'orthographic'
}
},
}
}
};

var sceneTarget;
var relayoutEvent;
var relayoutCnt = 0;

Plotly.plot(gd, mock)
.then(function() {
gd.on('plotly_relayout', function(e) {
relayoutCnt++;
relayoutEvent = e;
});

sceneTarget = gd.querySelector('.svg-container .gl-container #scene canvas');
})
.then(function() {
var aspectratio = gd._fullLayout.scene.aspectratio;
expect(aspectratio.x).toBeCloseTo(0.898, 3, 'aspectratio.x');
expect(aspectratio.y).toBeCloseTo(0.798, 3, 'aspectratio.y');
expect(aspectratio.z).toBeCloseTo(1.396, 3, 'aspectratio.z');
})
.then(function() {
return scroll(sceneTarget);
})
.then(function() {
expect(relayoutCnt).toEqual(1);

var aspectratio = relayoutEvent['scene.aspectratio'];
expect(aspectratio.x).toBeCloseTo(0.816, 3, 'aspectratio.x');
expect(aspectratio.y).toBeCloseTo(0.725, 3, 'aspectratio.y');
expect(aspectratio.z).toBeCloseTo(1.269, 3, 'aspectratio.z');
})
.then(function() {
// select a point
var i = 2;

return Plotly.restyle(gd, {
x: [[coords.x[i]]],
y: [[coords.y[i]]],
z: [[coords.z[i]]],
}, 1);
})
.then(function() {
var aspectratio = gd._fullLayout.scene.aspectratio;
expect(aspectratio.x).toBeCloseTo(0.816, 3, 'aspectratio.x');
expect(aspectratio.y).toBeCloseTo(0.725, 3, 'aspectratio.y');
expect(aspectratio.z).toBeCloseTo(1.269, 3, 'aspectratio.z');
})
.catch(failTest)
.then(done);
});
});

describe('Test gl3d relayout calls', function() {
Expand Down

0 comments on commit 4d24c36

Please sign in to comment.