Edit Thanks to matheorem for simplifying this a good deal.
Image3D
is relatively new and doesn't have all the options that other Graphics3D
objects have, but we can work with it because it can be used with Show
like any other 3D graphics object. The strategy here is to only give those options to Image3D
which are unique to it, while giving all other options to Show
.
Image3D
produces a plot where the data ranges for the three dimensions are equal to the dimensions of the input array, similar to the 2D functions ArrayPlot
and MatrixPlot
. However, unlike those functions we can't supply the option DataRange
to Image3D
. So we need to manually specify a scaling function for the tickmarks. That is, when you give the Ticks
manually, you can specify the position and the label for each tick mark, i.e. in a list like $\{\{x_1, label_1\},\{x_2, label_2\},...\}$. This is tedious to do by hand, so we can do it functionally.
There are two ways I can think of to do this. The first is by using the CustomTicks
package and the second is by sending a function to Ticks
.
I like to use the CustomTicks
package, available here: http://library.wolfram.com/infocenter/Demos/5599/ It makes it really easy to rescale the tickmark values. Just download the CustomTicks.m file and place it somewhere in your $Path
.
And this isn't really clear from this example, because the data is random, but in order for the plot ranges to match up it is necessary to reverse the first two levels of the 3D array.
Needs["CustomTicks`"]
colorArray =
ParallelTable[
With[{v = RandomReal[]},
Append[List @@ ColorData["LightTemperatureMap"][v],
If[v >= .8, .5, 0]]], {z, 0, .1, .005}, {y, 0, 1, .1}, {x, 0, 10,
2}];
{xmax, ymax, zmax} = {10, 1, .1};
{zdim, ydim, xdim} = Dimensions[colorArray][[;; 3]];
Show[Image3D[Reverse[colorArray,{1,2}], "Real", ColorSpace -> "RGB"],
ViewPoint -> {1.3, -2.4, 2},
SphericalRegion -> True,
Boxed -> True,
BoxRatios -> {1, 1, 1},
Axes -> True,
AxesLabel -> {"X", "Y", "Z"},
ImageSize -> 350,
ImageResolution -> 750,
Ticks -> {
LinTicks[0, 10, TickPostTransformation -> (# xdim/xmax &)],
LinTicks[0, 1, TickPostTransformation -> (# ydim/ymax &)],
LinTicks[0, .1, TickPostTransformation -> (# zdim/zmax &)]}]

A somewhat less elegant solution that doesn't rely on an external package is
Show[Image3D[Reverse[colorArray,{1,2}], "Real", ColorSpace -> "RGB"],
ViewPoint -> {1.3, -2.4, 2},
SphericalRegion -> True,
Boxed -> True,
BoxRatios -> {1, 1, 1},
Axes -> True,
AxesLabel -> {"X", "Y", "Z"},
ImageSize -> 350,
ImageResolution -> 750,
Ticks -> {
Function[{min, max}, {# xdim/xmax, NumberForm[N@#, {3, 2}] } & /@
FindDivisions[Round[{min, max}] xmax/xdim, 5]],
Function[{min, max}, {# ydim/ymax, NumberForm[N@#, {3, 2}] } & /@
FindDivisions[Round[{min, max}] ymax/ydim, 5]],
Function[{min, max}, {# zdim/zmax, NumberForm[N@#, {3, 2}] } & /@
FindDivisions[Round[{min, max}] zmax/zdim, 5]]
}]

Raster3D
? This allows you to specify the range of x, y and z. $\endgroup$Image3D
has better plot quality for medium sized bins, so I wish there could be a solution forImage3D
. I have tried to extract a bare frame and useShow
to combine it and the 3D image, but that did not work. $\endgroup$