Services & Resources / Wolfram Forums / MathGroup Archive
-----

MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Extracting Graphics3D from Plots

  • To: mathgroup at smc.vnet.net
  • Subject: [mg95656] Re: Extracting Graphics3D from Plots
  • From: Fred Klingener <gigabitbucket at BrockEng.com>
  • Date: Sat, 24 Jan 2009 06:17:54 -0500 (EST)
  • References: <200901221201.HAA11196@smc.vnet.net> <glc4th$38g$1@smc.vnet.net>

On Jan 23, 5:07 am, "Ernst H.K. Stelzer" <stel... at embl.de> wrote:
> Dear Mathematicans,
>
> a problem I have been struggling for quite a while is how to extract a ma=
nipulatable Graphics3D object from the result of e.g. a Plot3D or Revolutio=
nPlot3D call.  By manipulatable I mean an object I can rotate or translat=
e using "RotationTransform" and then combine with other objects such as "Cy=
linder".  What I do not intend to do is use "Epilog" in a Plot3D call.

The first good news is that there's enormous power built into the new
(as of v6) graphics structure, and the second is that there are tools
of enormous power to retrieve and manipulate its components. The bad
news is that all those are largely undocumented, practically
encrypted.

> I am actually looking for the CORRECT Mathematica-way, i.e. the one antic=
ipated by the Wolfram people and not some workaround that might fail in fut=
ure versions of Mathematica.

I won't take responsibility for CORRECTNESS or the projected lifetime
of the methods, especially considering the level of Wolfram's
documentation, but here are some notes I took at  the Graphics school
last summer in Champaign.

(* Starting with an example of Plot3D from the Doc Center: *)

p3D = Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}]

(* The internal structure of p3D can be exposed with *)

InputForm[p3D] // Short[#, 20] &

(* So the plot is itself a Graphics3D object with the GraphicsComplex
first argument, and, just to emphasize its nature, can be reproduced
by *)

Graphics3D[First[p3D]]

(* The function Normal[] is useful for disassembling the
GraphicsComplex into graphics primitives. *)

Normal[p3D] // InputForm // Short[#, 20] &

(* Knowing the structure, you can isolate, manipulate and display its
parts. In the following example, all the Polygons are removed *)

DeleteCases[p3D, _Polygon, Infinity]

(* The basic types of graphics objects, if they're present, can be
easily extracted: *)

(points = Cases[Normal[p3D] , _Point, Infinity] // Flatten //
First) //
 Short[#, 10] &
(lines = Cases[Normal[p3D] , _Line, Infinity] // Flatten // First) //
 Short[#, 10] &
(polygons = Cases[Normal[p3D] , _Polygon, Infinity]) // Short[#, 10] &

(* and the parts can be manipulated as Graphics primitives. *)

Graphics3D[lines]
Graphics3D[Rotate[lines, Pi/6, {0.7, 0.7, 0.7}]]

(* While Normal[] is handy for accessing the primitives, you can get
to the underlying form of GraphicsComplex by frontal assault. The raw
list of nodes in the GraphicsComplex can be retrieved by the following
Replace[]:*)

(nl = First[p3D] /. GraphicsComplex[nodelist_, rest___] ->
nodelist) //
 Short[#, 20] &

(* Here, nodelist is the raw list of (in this case 3D) points, and
rest is the description of the way the primitives are constructed from
the node list. The extracted variable can be used as an argument to
new or independent primitives:  *)

Graphics3D[Point[nl]]

(* or it can be manipulated by a lower level transformations. *)

r = RotationTransform[Pi/6, {1, -1, 0}]
Graphics3D[Point[r@nl]]

(* or the transformed result can be directly injected into a
reconstructed GraphicsComplex *)

Graphics3D[
 First[p3D] /.
  GraphicsComplex[nodelist_, rest___] -> GraphicsComplex[r[nodelist],
rest]
]

(* Putting it all together for your example: *)

img = Import["ExampleData/rose.gif"];
imgS = Rasterize[img, "Data", RasterSize -> {32, 32}]/255.0;

Graphics3D[
 First[
   Plot3D[
     Sin[x y], {x, 0, 3}, {y, 0, 3}
    , ColorFunction -> (RGBColor[
        imgS[[1 + Round[10 #1], 1 + Round[10 #2]]]] &)
    , ColorFunctionScaling -> False, Mesh -> False, PlotPoints -> 32]
   ]
   /. GraphicsComplex[nodelist_, rest___] -> GraphicsComplex[
    RotationTransform[Pi/6, {1, -1, 0}][nodelist], rest]
 ]

Hth,
Fred Klingener


  • Prev by Date: two graphs have different color on surface
  • Next by Date: Re: Which editor do you use for math
  • Previous by thread: Re: Extracting Graphics3D from Plots
  • Next by thread: Re: Newbie Question - Change 3D Bar Chart Background Color