Re: AxesLabel parallel to 3D axes?
- To: mathgroup at smc.vnet.net
- Subject: [mg111423] Re: AxesLabel parallel to 3D axes?
- From: Fred Klingener <gigabitbucket at BrockEng.com>
- Date: Sun, 1 Aug 2010 04:55:10 -0400 (EDT)
- References: <i2rm0a$r4c$1@smc.vnet.net>
On Jul 29, 6:43 am, David Reiss <dbre... at gmail.com> wrote:
> If one sets the AxesLabel option for, for example, Plot3D, is there
> any way to set things up so that resulting labels are always parallel
> to their own axes?
>
> ...here is an example, and a customer would like the labels to align
> along/paralle the axes rather than what is shown here....
>
> Plot3D[x y, {x, 0, 1}, {y, 0, 1},
> AxesLabel -> {"This is the x", "This is the y", "This is the z"}]
I've used a couple of approaches to this, a raster and a vector. The
vector form is much faster, looks far better, but is a hack, based on
undocumented features. I don't think I'd use it on anything critically
important.
The first resolves the styled text to a Raster, applies raster point
properties to a flat 3D grid of square Polygons, then orients and
places it in the scene using 3D transformations. Here's a sketch
fontSize = 14;
imageResolution = 75; (* dpi, say *)
imgData =
Rasterize[
Style[
"hello,world."
, FontFamily -> "Helvetica"
, Bold
, FontSize -> fontSize]
(* give back just the raster data *)
, "Data"
(* pick an image resolution for the application *)
, ImageResolution -> imageResolution
(* The combination of the next two option settings produces an
array of 2-
Lists with the form {gray, alpha} each in the range {0, 255} *)
, Background -> None
, ColorSpace -> "Grayscale"];
d = Dimensions[imgData]
The next line is required to shuffle the rows of the raster and
convert the byte values {0, 255} from the Rasterize to the {0., 1.}
required for use in GrayLevel[]
imgData2 = Reverse[imgData/255.];
This constructs a 2D grid in the x-y plane of square 3D Polygons with
FaceForms derived from the Raster.
polyGray3D =
Table[
Table[
{
FaceForm[
GrayLevel[imgData2[[j + 1, i + 1]]]
]
, Polygon[{
{i, j, 0.}
, {i + 1, j, 0.}
, {i + 1, j + 1, 0.}
, {i, j + 1, 0.}
}]
}
, {i, 0, d[[2]] - 1}]
, {j, 0, d[[1]] - 1}];
Then the Polygon grid can be scaled (maybe using imageResolution) and
placed in a scene. I'll apply a Background to make sure that works
right.
Graphics3D[{
Cuboid[{0, 0, 0}, {1, 1, 1}]
, EdgeForm[None]
(* Translate a bit in the y direction *)
, Translate[
(* and rescale to inches *)
Scale[
polyGray3D
, 1/imageResolution
, {0, 0, 0}
]
, {0., -0.25, 0}
]
}
, Axes -> True
, AxesOrigin -> 0
, Background -> Blue
, PlotRange -> {{-.2, 1.2}, {-.5, 1.2}, {-0.2, 1.2}}
]
______________________
The second approach exploits the Export/Import mechanism, using the
"PDF' mode to generate a vector representation of the letter forms.
vectorImg =
First@
First@
ImportString[
ExportString[
Style[
"hello,world."
, FontFamily -> "Helvetica"
, Bold
, FontSize -> fontSize
, ShowStringCharacters -> False
]
, "PDF"
, ShowStringCharacters -> False
]
, "PDF"
];
Graphics[vectorImg, Axes -> True]
vectorImage is composed of 2D Polygons, which represent the letter
forms. The scale is evidently somewhere around printer points (1/72
inch).
Stripping out everything but the Polygons from vectorImage still
leaves a complete rendering of the text.
Graphics[polygons2D = Cases[vectorImg, _Polygon, Infinity]]
These polygons can be converted to 3D Polygons oriented any way we
like, but laying them on the x-y plane is as good as any.
Graphics3D[{
Cuboid[{0, 0, 0}, {1, 1, 1}]
, EdgeForm[None]
, FaceForm[Black]
(* Translate a bit in the y direction *)
, Translate[
(* and rescale from points to inches *)
Scale[
polygons2D /. {x_, y_} :> {x, y, 0.}
, 1/72
, {0, 0, 0}
]
, {0., -0.25, 0}
]
}
, Axes -> True
, AxesOrigin -> 0
, Background -> Blue
, PlotRange -> {{-.2, 1.2}, {-.5, 1.2}, {-0.2, 1.2}}
]
Decent built-in 3D text is long overdue in Mathematica. I think.
Hth,
Fred Klingener