I found a way to do this in ParametricPlot3D using ColorFunction, but Graphics3D does not accept ColorFunction as an option.
To get the pixels at every coordinate ParametricPlot3D view, I encode the coordinates into an RGBColor image, then recover them from the three color planes. Because the arguments to RGBColor are 0 < x < 1, first I scale all coordinates into this range. Later I unscale them.
Take the example function
ff[u_,v_]:={(2+Cos[v])Cos[u]/\[Pi],(2+Cos[v])Sin[u]/\[Pi],Sin[v]}
and the view
ParametricPlot3D[ff[u,v],{u,0,2\[Pi]},{v,0,2 \[Pi]},ViewPoint->{4,-4,8}]
My scaling and unscaling utilities need the maximum and minimum coordinates as inputs
squeeze[x_,min_,max_]:=(x-min)/(max-min)
unsqueeze[fx_,min_,max_]:=fx (max-min)+min
Now I can get an list with each pixel's {x,y,z} as
xyz=Map[unsqueeze[#,-1,1]&,ImageData[Image[ParametricPlot3D[ff[u,v],{u,0, 2\[Pi]},{v,-\[Pi]/2,\[Pi]/2},
ColorFunction->Function[{x,y,z},Glow[RGBColor[squeeze[x,-1,1],squeeze[y,-1, 1],squeeze[z,-1,1]]]],
ColorFunctionScaling->False,ViewPoint->{4,-4,8},Mesh->False,Boxed->False,Axes->False,Background->Black]]],{2}];
Now, for example, you can print the pixel coordinates or view the points in 3D with a function like
Graphics3D[Map[{Hue[(#[[3]]+1)/2],Point[#]} &,xyz[[ ;; ;;10, ;; ;;10,All]],{2}]]
My question is if there is a method for Graphics3D which can recover pixel coordinates with a similar result?
Thank you,
Russell Chipman
As nifty as your approach is, the easy way to get the nodes for this
surface is to look at the structure:
pp3D= ParametricPlot3D[ff[u,v],{u,0,2\[Pi]},{v,0,2 \[Pi]},ViewPoint-
>{4,-4,8}]
pp3D is a GraphicsComplex, and you can browse the structure with
something like
Pane[
FullForm[
pp3D]
, Scrollbars -> {False, True}
, ImageSize -> {300, 300}
]
(I don't know why Mathematica doesn't have a ScrollForm)
The first argument of the GraphicsComplex is a list of the points on
the surface, and you can retrieve them with
Graphics3D[
Point[
points=
Cases[
pp3D
, GraphicsComplex[pt__, ___] :> pt
, Infinity
]
]
]
Most of Mathematica's 3D structures can be dissected this way, and if
you need the connectivity, look at the list of primitives pp3D//Normal
produces. For example, you can get all the isolated Polygons with
Graphics3D[
polygons=
Cases[
pp3D // Normal
, _Polygon
, Infinity
]
or the mesh lines (if you specified meshing in the original.)
Graphics3D[
lines=
Cases[
pp3D // Normal
, _Line
, Infinity
]
]
Hth,
Fred Klingener
Heike
On 18 Mar 2011, at 10:59, Russell Chipman wrote:
> Dear MathGroup
> I am searching for a way to find the {x,y,z} coordinates at every pixel i=
n a Graphics3D view.
>
> I found a way to do this in ParametricPlot3D using ColorFunction, but Gra=
phics3D does not accept ColorFunction as an option.
>
> To get the pixels at every coordinate ParametricPlot3D view, I encode the=
coordinates into an RGBColor image, then recover them from the three color=
planes. Because the arguments to RGBColor are 0 < x < 1, first I scale al=
l coordinates into this range. Later I unscale them.
>
> Take the example function
>
> ff[u_,v_]:=={(2+Cos[v])Cos[u]/\[Pi],(2+Cos[v])Sin[u]/\[Pi],Sin[v]}
>
> and the view
>
> ParametricPlot3D[ff[u,v],{u,0,2\[Pi]},{v,0,2 \[Pi]},ViewPoint->{4,-4,8}]
>
> My scaling and unscaling utilities need the maximum and minimum coordinat=
es as inputs
>
> squeeze[x_,min_,max_]:==(x-min)/(max-min)
> unsqueeze[fx_,min_,max_]:==fx (max-min)+min
>
> Now I can get an list with each pixel's {x,y,z} as
>
> xyz==Map[unsqueeze[#,-1,1]&,ImageData[Image[ParametricPlot3D[ff[u,v],{u,0=
, 2\[Pi]},{v,-\[Pi]/2,\[Pi]/2},
> ColorFunction->Function[{x,y,z},Glow[RGBColor[squeeze[x,-1,1],squeeze[y,-=
1, 1],squeeze[z,-1,1]]]],
> ColorFunctionScaling->False,ViewPoint->{4,-4,8},Mesh->False,Boxed->False,=
Axes->False,Background->Black]]],{2}];
>
> Now, for example, you can print the pixel coordinates or view the points=
in 3D with a function like
>
> Graphics3D[Map[{Hue[(#[[3]]+1)/2],Point[#]} &,xyz[[ ;; ;;10, ;; ;;10,All]=
],{2}]]
>
> My question is if there is a method for Graphics3D which can recover pixe=
moon = SphericalPlot3D[1, {u, 0, Pi}, {v, 0, 2 Pi}, Mesh -> None,
TextureCoordinateFunction -> ({#5, 1 - #4} &),
PlotStyle ->
Directive[Specularity[White, 10],
Texture[Import[
"http://finkh.files.wordpress.com/2011/03/ldem_4.png"]]],
Lighting -> {"Ambient", White}, Axes -> False, Boxed -> False,
RotationAction -> "Clip"]
This is a map of the moon with elevation data represented by a
grayscale texture taken from the Planetary Data System. When I
extract the polygons from the object the texture does not travel with
the polygons. How would I select a portion of the sphere while
preserving the shape and the texture.
Then reorient so the center of the selection is up, convert to
cartesian, listplot3d and export as stl for the rapid prototyper.
Here is what I am doing: http://finkh.wordpress.com/2011/02/01/the-south-pole-of-the-moon-shackleton-crater/
Another approach to get something that looks like the first picture in your example
is make a ListPlot3D of the grey level data and then transform the coordinates in
your plot to cartesian coordinates using replacement rules.
What I mean is something like
(*importing data*)data = N[Rescale[Import["ldem_4.png", "Data"]]];
data = Join[data, data[[All, {1}]],
2];(*for periodicity purposes*)(*sector of interest*)
thetaRange = \
{30 Degree, 90 Degree};
phiRange = {25 Degree, 60 Degree};
sector = Take[data,
Round[Rescale[thetaRange, {0., Pi}, {1, Dimensions[data][[1]]}]],
Round[Rescale[phiRange, {0., 2 Pi}, {1, Dimensions[data][[2]]}]]];
(*for transforming to cartesian coordinates*)
dr = 0.1;(*max elevation relative to radius of the moon*)
pt[{ph_, th_, e_}] := {Sin[th] Cos[ph], Sin[th] Sin[ph], Cos[th]} (1 + dre);
rotMat = RotationMatrix[{pt[{Total[phiRange]/2, Total[thetaRange]/2,
1}], {0, 0, 1}}]; (* rotating the center of the sector *)
(*plot in spherical coordinates*)
plot = ListPlot3D[sector, DataRange -> {phiRange, thetaRange},
Mesh -> None, NormalsFunction -> None];
(*transformation to cartesian coordinates*)
sphPlot =
Release[plot /.
GraphicsComplex[a_, c__] ->
GraphicsComplex[Hold[rotMat.pt[#] & /@ a], Hold[c]]];
Show[sphPlot, PlotRange -> All]
Heike