AxesLabel parallel to 3D axes?

1332 views
Skip to first unread message

David Reiss

unread,
Jul 29, 2010, 6:43:22 AM7/29/10
to
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"}]


Bob Hanlon

unread,
Jul 30, 2010, 6:55:05 AM7/30/10
to

If the ViewPoint is not allowed to change:

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:

=============

Murray Eisenberg

unread,
Jul 31, 2010, 2:39:27 AM7/31/10
to
But -- at least on my 1600x1200 monitor, Windows XP, the axes labels now
have considerably degraded resolution and therefore look quite awful.

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

Fred Klingener

unread,
Aug 1, 2010, 4:55:13 AM8/1/10
to

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

Fred Klingener

unread,
Aug 1, 2010, 4:55:24 AM8/1/10
to
On Jul 29, 6:43 am, David Reiss <dbre...@gmail.com> wrote:

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

David Reiss

unread,
Aug 3, 2010, 6:35:49 AM8/3/10
to
Thank you all for your various thoughts about this issue.

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

Fred Klingener

unread,
Aug 4, 2010, 5:50:02 AM8/4/10
to
On Aug 3, 6:35 am, David Reiss <dbre...@gmail.com> wrote:
> ...

> 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

telefunkenvf14

unread,
Aug 6, 2010, 6:58:01 AM8/6/10
to
> , FontFamily -> "Helvetica"
> , Bold
> 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

Christopher O. Young

unread,
May 12, 2011, 4:31:45 AM5/12/11
to
Isn't there some way to paste images onto surfaces in 3D views? Then, if we
could just have a flat rectangle with an image of the label on it, we'd be
all set. Especially if the rectangle could be transparent while the
lettering on it could be kept opaque.


On 8/1/10 4:55 AM, in article i33cph$81k$1...@smc.vnet.net, "Fred Klingener"

JUN

unread,
May 13, 2011, 6:26:17 AM5/13/11
to
On May 12, 1:31 am, "Christopher O. Young" <c...@comcast.net> wrote:
> Isn't there some way to paste images onto surfaces in 3D views? Then, if we
> could just have a flat rectangle with an image of the label on it, we'd be
> all set. Especially if the rectangle could be transparent while the
> lettering on it could be kept opaque.
>
> On 8/1/10 4:55 AM, in article i33cph$81...@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

Fred Klingener

unread,
May 13, 2011, 6:26:50 AM5/13/11
to
On May 12, 4:31 am, "Christopher O. Young" <c...@comcast.net> wrote:
> Isn't there some way to paste images onto surfaces in 3D views? Then, if we
> could just have a flat rectangle with an image of the label on it, we'd be
> all set. Especially if the rectangle could be transparent while the
> lettering on it could be kept opaque.
...
Probably the best way now, if you are using version 8 is to compose an
image of your label and apply it as a Texture to a Polygon sized and
located where you want it.

>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


Reply all
Reply to author
Forward
0 new messages