Skip to content

Commit 9fec03a

Browse files
authored
Merge pull request #3369 from plotly/2630-mesh3d-dont-modify-messy-data
Mesh3d cell data checks
2 parents 07b695a + 29f5a06 commit 9fec03a

File tree

3 files changed

+530
-80
lines changed

3 files changed

+530
-80
lines changed

src/traces/mesh3d/convert.js

+72-25
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,53 @@ proto.handlePick = function(selection) {
5252
};
5353

5454
function parseColorArray(colors) {
55-
return colors.map(str2RgbaArray);
55+
var b = [];
56+
var len = colors.length;
57+
for(var i = 0; i < len; i++) {
58+
b[i] = str2RgbaArray(colors[i]);
59+
}
60+
return b;
61+
}
62+
63+
// Unpack position data
64+
function toDataCoords(axis, coord, scale, calendar) {
65+
var b = [];
66+
var len = coord.length;
67+
for(var i = 0; i < len; i++) {
68+
b[i] = axis.d2l(coord[i], 0, calendar) * scale;
69+
}
70+
return b;
71+
}
72+
73+
// Round indices if passed as floats
74+
function toRoundIndex(a) {
75+
var b = [];
76+
var len = a.length;
77+
for(var i = 0; i < len; i++) {
78+
b[i] = Math.round(a[i]);
79+
}
80+
return b;
81+
}
82+
83+
function delaunayCells(delaunayaxis, positions) {
84+
var d = ['x', 'y', 'z'].indexOf(delaunayaxis);
85+
var b = [];
86+
var len = positions.length;
87+
for(var i = 0; i < len; i++) {
88+
b[i] = [positions[i][(d + 1) % 3], positions[i][(d + 2) % 3]];
89+
}
90+
return triangulate(b);
91+
}
92+
93+
// Validate indices
94+
function hasValidIndices(list, numVertices) {
95+
var len = list.length;
96+
for(var i = 0; i < len; i++) {
97+
if(list[i] <= -0.5 || list[i] >= numVertices - 0.5) { // Note: the indices would be rounded -0.49 is valid.
98+
return false;
99+
}
100+
}
101+
return true;
56102
}
57103

58104
proto.update = function(data) {
@@ -61,33 +107,37 @@ proto.update = function(data) {
61107

62108
this.data = data;
63109

64-
// Unpack position data
65-
function toDataCoords(axis, coord, scale, calendar) {
66-
return coord.map(function(x) {
67-
return axis.d2l(x, 0, calendar) * scale;
68-
});
69-
}
110+
var numVertices = data.x.length;
70111

71112
var positions = zip3(
72113
toDataCoords(layout.xaxis, data.x, scene.dataScale[0], data.xcalendar),
73114
toDataCoords(layout.yaxis, data.y, scene.dataScale[1], data.ycalendar),
74-
toDataCoords(layout.zaxis, data.z, scene.dataScale[2], data.zcalendar));
115+
toDataCoords(layout.zaxis, data.z, scene.dataScale[2], data.zcalendar)
116+
);
75117

76118
var cells;
77119
if(data.i && data.j && data.k) {
78-
cells = zip3(data.i, data.j, data.k);
79-
}
80-
else if(data.alphahull === 0) {
120+
121+
if(
122+
data.i.length !== data.j.length ||
123+
data.j.length !== data.k.length ||
124+
!hasValidIndices(data.i, numVertices) ||
125+
!hasValidIndices(data.j, numVertices) ||
126+
!hasValidIndices(data.k, numVertices)
127+
) {
128+
return;
129+
}
130+
cells = zip3(
131+
toRoundIndex(data.i),
132+
toRoundIndex(data.j),
133+
toRoundIndex(data.k)
134+
);
135+
} else if(data.alphahull === 0) {
81136
cells = convexHull(positions);
82-
}
83-
else if(data.alphahull > 0) {
137+
} else if(data.alphahull > 0) {
84138
cells = alphaShape(data.alphahull, positions);
85-
}
86-
else {
87-
var d = ['x', 'y', 'z'].indexOf(data.delaunayaxis);
88-
cells = triangulate(positions.map(function(c) {
89-
return [c[(d + 1) % 3], c[(d + 2) % 3]];
90-
}));
139+
} else {
140+
cells = delaunayCells(data.delaunayaxis, positions);
91141
}
92142

93143
var config = {
@@ -113,16 +163,13 @@ proto.update = function(data) {
113163
config.vertexIntensity = data.intensity;
114164
config.vertexIntensityBounds = [data.cmin, data.cmax];
115165
config.colormap = parseColorScale(data.colorscale);
116-
}
117-
else if(data.vertexcolor) {
166+
} else if(data.vertexcolor) {
118167
this.color = data.vertexcolor[0];
119168
config.vertexColors = parseColorArray(data.vertexcolor);
120-
}
121-
else if(data.facecolor) {
169+
} else if(data.facecolor) {
122170
this.color = data.facecolor[0];
123171
config.cellColors = parseColorArray(data.facecolor);
124-
}
125-
else {
172+
} else {
126173
this.color = data.color;
127174
config.meshColor = str2RgbaArray(data.color);
128175
}

src/traces/mesh3d/defaults.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,20 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3434
}
3535

3636
var coords = readComponents(['x', 'y', 'z']);
37-
var indices = readComponents(['i', 'j', 'k']);
38-
3937
if(!coords) {
4038
traceOut.visible = false;
4139
return;
4240
}
4341

44-
if(indices) {
45-
// otherwise, convert all face indices to ints
46-
indices.forEach(function(index) {
47-
for(var i = 0; i < index.length; ++i) index[i] |= 0;
48-
});
42+
readComponents(['i', 'j', 'k']);
43+
// three indices should be all provided or not
44+
if(
45+
(traceOut.i && (!traceOut.j || !traceOut.k)) ||
46+
(traceOut.j && (!traceOut.k || !traceOut.i)) ||
47+
(traceOut.k && (!traceOut.i || !traceOut.j))
48+
) {
49+
traceOut.visible = false;
50+
return;
4951
}
5052

5153
var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults');

0 commit comments

Comments
 (0)