-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Isosurface traces #2752
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Isosurface traces #2752
Conversation
Looking good! @etpinard will likely have more to say when he's back tomorrow, but some thoughts of my own to start:
👍 the simplest way to do this would be 6 attributes
Part of the same trace. My gut reaction is the isosurfaces should by default be colored according to the isocap colorscale, but that you should be free to provide separate colors for each isosurface. What do you mean by "separate colorscales"? Each isosurface just gets a single color, right?
I think the input data format is good, though I'm not sure what you mean by "constructing a meshgrid out of the x,y,z -values and using that as the coords for the u array" though - won't the meshgrid you actually display be some sort of interpolation between the provided (x, y, z) values to find the isovalue? |
src/traces/isosurface/attributes.js
Outdated
valType: 'number', | ||
editType: 'calc', | ||
description: 'Sets the maximum iso bound of the isosurface.' | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imax
/imin
is OK if we rename u
to intensity
... but if it turns to v
or value
these should be vmax
/vmin
. I presume that if you only provide one of these, the other one is treated as +/-Infinity for the purpose of constructing the isocaps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember us having the same concerns about intensity in surface traces. We ended up naming that attribute surfacecolor
.
I think naming this field u
or v
would confusing as it is an array of scalars, not a component of a vector field. I like value
, but maybe volume
would better (that's how MATLAB seems to call this field)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About imin
and imax
, MATLAB calls it isovalue. Wouldn't isomin
and isomax
be better?
src/traces/isosurface/attributes.js
Outdated
role: 'info', | ||
editType: 'calc+clearAxisTypes', | ||
description: [ | ||
'Sets the x coordinates of the isosurface' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps "Sets the x coordinates of the volume data" (from which the isosurface will be calculated)
src/traces/isosurface/convert.js
Outdated
|
||
// var bounds = [ | ||
// isosurfaceOpts.boundmin || [xs[0], ys[0], zs[0]], | ||
// isosurfaceOpts.boundmax || [xs[xs.length - 1], ys[ys.length - 1], zs[zs.length - 1]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see, these were to be the (x,y,z) limits... yeah, I still think it's better to make 6 separate attributes just since setting a single bound is (I think) the most common use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, will do, (x|y|z)(min|max)
src/traces/isosurface/convert.js
Outdated
isosurfaceOpts.isoBounds = [trace.imin, trace.imax]; | ||
|
||
isosurfaceOpts.isoCaps = trace.isocaps; | ||
isosurfaceOpts.singleMesh = trace.singlemesh === undefined ? true : trace.singlemesh; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does singlemesh
do? BTW logic like this belongs as attributes.singlemesh.dlft = true
.
Thanks for the PRs @kig! Looking great 🎉 Unfortunately, I won't have time to look at them in detail until we release Now, would you be interested in looking at the broken tubes we noticed in #2658 (comment) to help us merge the streamtube PR? |
For @alexcjohnson, who wonders what would happen when we try plot data that cross from >imax to <imin with no values between: var width = 64
var height = 64
var depth = 64
var isomin = 1600
var isomax = 2000
var xs = []
var ys = []
var zs = []
var data = new Uint16Array(width*height*depth)
var k = 0
for (var z=0; z<depth; z++)
for (var y=0; y<height; y++)
for (var x=0; x<width; x++) {
xs.push(x/width)
ys.push(y/height)
zs.push(z/depth)
data[k] = x < width/2 ? isomax+1 : isomin-1
k++
}
Plotly.newPlot(gd, [{
type: 'isosurface',
x: xs,
y: ys,
z: zs,
value: data,
isomin: isomin,
isomax: isomax,
cmin: isomin - 100,
cmax: isomax + 100,
smoothnormals: true,
isocaps: true,
singlemesh: true,
colorscale: 'Portland',
capscolorscale: 'Jet'
}], {
scene: {
xaxis: {range: [0, 1]},
yaxis: {range: [0, 1]},
zaxis: {range: [0, 1]}
}
}) gives a blank scene. For comparison with data[k] = x < width/2 ? isomax : isomin and every else the same, we get: |
In a private convo, @alexcjohnson wrote:
@kig is this in fact the current behavior? |
In some traces, it's nice to have a separate colorscale for the caps. E.g. https://gl-vis.github.io/gl-isosurface3d/smooth_skin.html |
Got it, I'll rename u to v.
Hmm, the isosurface now works by running marching cubes on the box lattice defined by |x|,|y|,|z| and u. The result of this is a mesh with vertices at integers In other words, it constructs a mesh with marching cubes with vertices at the meshgrid positions. (If the meshgrid coords grow at a fixed rate, this amounts to scaling and translating the mesh.) |
This is the issue with marching cubes. What happens is that the data lattice is converted to a binary lattice with a 0 or 1 at each vertex depending on whether the vertex value is inside the iso range or not. Then the vertices of each 2x2 cube in the lattice are interpreted as the bits of an 8-bit number, so that each (top-left-front) corner of the lattice has a corresponding 8-bit number. Next, look up mesh fragments from a lookup array using the 8-bit number as an index, translate fragment vertices to corner, append to mesh. You could work around it by upscaling the data until you get values in the iso range. I don't know if there's a surface construction algo that would do that itself. The marching cubes isosurfaces can have holes in them since some sequences are ambiguous and you'd have to look at neighboring cells to resolve which way the planes should be pointing. Asymptotic decider algorithm would solve this according to Wikipedia. |
You should be able to get the desired result using marching cubes, following the example of our 2D SVG
Yes, the caps get a colorscale. The isosurfaces, especially with the refinement ^^, will just get a single color each (one for the low, one for the high) so I don't think it's a good idea to make people pull those colors out of a colorscale, just specify one or two colors. |
@kig - Can you please give us an update on this one? |
now in #3311 |
Isosurface trace
@etpinard @alexcjohnson
Isosurface trace for plotly.js integration WIP.