...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"}]
labels = {
Rotate["This is the x", -20 Degree],
Rotate["This is the y", 60 Degree],
Rotate["This is the z\n", 95 Degree]};
Plot3D[x y, {x, 0, 1}, {y, 0, 1},
AxesLabel -> labels]
Bob Hanlon
---- David Reiss <dbr...@gmail.com> wrote:
=============
However, if I then export the plot to pdf and view the latter, the
labels look just fine!
--
Murray Eisenberg mur...@math.umass.edu
Mathematics & Statistics Dept.
Lederle Graduate Research Tower phone 413 549-1020 (H)
University of Massachusetts 413 545-2859 (W)
710 North Pleasant Street fax 413 545-1801
Amherst, MA 01003-9305
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
And here's an even worse way to do it. It puts the styled text into an
Inset, which, amazingly, can be scaled, sheared, rotated and
translated to visually approximate 3D text then the Inset is Epilogged
into a Graphics3D.
Manipulate[
DynamicModule[
{st, rt, tt}
, st = ShearingTransform[
shear
, {1, 0}
, {0, 1}
]; (* ShearingTransform *)
rt = RotationTransform[
rotate
, {0, 0}]; (* RotationTransform *)
tt = TranslationTransform[
{x, y}
]; (* TranslationTransform *)
Graphics3D[{}
, Epilog ->
GeometricTransformation[
Inset[
Style["Hello,world"
, FontFamily -> "Helvetica"
, Bold
, 14
] (* Style *)
, {0, 0}
] (* Inset *)
, tt.rt.st
] (* GeometricTransformation *)
, Axes -> True
, AxesOrigin -> 0
] (* Graphics3D *)
] (* DynamicModule *)
, {{rotate, 0}, -Pi/4,
Pi/4}
, {{shear, 0}, -Pi/4, Pi/4}
, {{x, 0.5}, 0, 1, Appearance -> "Labeled"}
, {{y, 0.5}, 0, 1, Appearance -> "Labeled"}
] (* Manipulate *)
Hth,
Fred Klingener
I completely agree that 3D text is a worthy and needed addition to
Mathematica.
Here's a little project: create the open to StarWars along with a
flyarround
http://en.wikipedia.org/wiki/Star_Wars_opening_crawl
--David
This is all I got.
testStyle = Style[
"It is a period of civil war.
Rebel spaceships, striking
from a hidden base, have
won their first victory
against the evil Galactic
Empire.\n
During the battle, rebel
spies managed to steal
secret plans to the Empire\[CloseCurlyQuote]s
ultimate weapon, the
DEATH STAR, an armored
space station with enough
power to destroy an entire
planet.\n
Pursued by the Empire\[CloseCurlyQuote]s
sinister agents, Princess
Leia races home aboard her
starship, custodian of the
stolen plans that can save
her people and restore
freedom to the galaxy..."
, FontFamily -> "Helvetica"
, Bold
, FontSize -> 24
, ShowStringCharacters -> False
, TextJustification -> 1
] (* Style *)
Text3D[s_, pos_: {0., 0., 0.}, opos_: {0., 0.}] :=
Module[{polys, x0, y0, xMin, xMax, yMin, yMax}
(* Convert the styled string to Polygon representation *)
, polys =
Cases[
ImportString[
ExportString[
s
, "PDF"
, ShowStringCharacters -> False
] (* ExportString *)
, "PDF"
] (* ImportString *)
, _Polygon
, Infinity
];
(* Get the min,
max and extents *){{xMin, xMax, x0}, {yMin, yMax,
y0}} = {Min[#], Max[#],
Mean[#]} & /@ (Cases[polys, {x_, y_} :> #, Infinity] & /@ {x,
y});
(* outer Translate positions the 3D polygons in the scene *)
Translate[
(* Translate and Scale the 2D polygons *)
(Scale[
Translate[
polys
, -{x0, y0} - opos {(xMax - xMin)/2., (yMax - yMin)/2.}
] (* Translate *)
, 1/72. (*
inches per point *)
, {0, 0} (*
scaled relative to the origin *)
] )(*
Scale *) /. {x_, y_} -> {x, y, 0.}
, pos]
] (* Module *)
text = Text3D[testStyle];
Manipulate[
Graphics3D[{
FaceForm[Yellow]
, EdgeForm[None]
, Translate[text, {0., yt, 0.}]
}
, Boxed -> False
, PlotRange -> {{-2, 2}, {-8, 8}, {-1, 1}}
, Background -> Black
, ViewPoint -> {0.0, -1, +0.25}
, ViewCenter -> {0.5, 0.5, 0.5}
, ViewVertical -> {0., 0., 1.}
, ViewAngle -> 15 Degree
, ImageSize -> {450, 300}
]
, {yt, -10, 2, 0.25, Animator, DisplayAllSteps -> True}
]
Fred Klingener
Very cool. For some reason the font gets all mashed together on my
machine when I leave it set to "Bold"...
Two resources you may already have:
http://library.wolfram.com/infocenter/MathSource/4535/
http://library.wolfram.com/infocenter/Conferences/196/
-RG
On 8/1/10 4:55 AM, in article i33cph$81k$1...@smc.vnet.net, "Fred Klingener"
Yes, there is:
rasterText[s_, bg_:None] :=
With[{r = Rasterize[Style[s, Magnification -> 10], Background ->
bg]},
Apply[Graphics3D[{EdgeForm[], Texture[r],
Polygon[{{0, 0, 0}, {#1, 0, 0}, {#1, #2, 0}, {0, #2, 0}},
VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0,
1}}]}] &, ImageDimensions[r]]]
Show[rasterText[Style["This is a text", FontFamily -> "Times"]],
Lighting -> "Neutral", Boxed -> False]
The only problem is that Mathematica doesn't allow us to use
transparent textures, so the 3D text will be on a solid background.
In Fred's bitmap solution, you can have what amounts to a transparent
background, but at the expense of a large polygon count.
Jens
>From the Doc Center, with some explicit changes to accommodate
extended range for axis labels and the clearing of box and axes:
p3d = Plot3D[Sin[x y], {x, 0, 3}, {y, 0, 3},
ColorFunction -> "Rainbow", Mesh -> None,
PlotRange -> {{-.2, 3.2}, {-0.2, 3.2}, {-1, 1}}, Boxed -> False,
Axes -> False];
(* I'll compose a label for the x axis: *)
xaxis = Style[
" x axis "
, FontFamily -> "Helvetica"
, 12
, Bold
];
(* There seem to be a lot of acceptable ways to get this into a form \
ready for Texture,but explicitly building a Raster is the only way \
I've found to control the size, resolution and aspect ratio. *)
xraster = Rasterize[
xaxis
, ImageResolution -> 300
, Background -> None
, ColorSpace -> "Grayscale"
];
aspect = Divide @@ Rasterize[xraster, "RasterSize"];
(*Draw a host polygon,centered at*)
center = {1.5, -0.15, 0.};
(*and a height in the y direction of *)
h = 0.15;
(* The Polygon corners are *)
pts = (center + h/2*#) & /@ {{-aspect, -1., 0.}, {aspect, -1,
0.}, {aspect, 1, 0.}, {-aspect, 1., 0.}};
(* ,and the Polygon becomes *)
poly = Polygon[
pts
, VertexTextureCoordinates -> {
{0, 0, 0}
, {1, 0, 0}
, {1, 1, 0}
, {0, 1, 0}
}];
(* The assembly becomes: *)
Show[{
p3d
, Graphics3D[{
Texture[xraster]
, EdgeForm[None]
, poly
}]
}]
The result doesn't meet your requirement for transparency of the
background, but none of the more obvious approaches seems to work. The
Texture machinery is evidently connected tightly to the FaceForm[]
machinery, so none of the Background or Opacity angles appear to work.
It seems essential that the Raster should have an alpha (opacity)
channel, and the Background->None ought to be the way to get it. But
it doesn't.
Setting the Style Background to be the same as p3d Background makes
the label background appear transparent, but there are some roundoff
errors that get in the way of that.
Mathematica still needs a good Text3D.
Hth,
Fred