Re: Help: how to disp. 3-D vectors

*To*: mathgroup at yoda.physics.unc.edu*Subject*: Re: Help: how to disp. 3-D vectors*From*: twj*Date*: Mon, 4 Oct 93 09:25:59 CDT

John Laczik writes... >I am trying to display three data sets, a 3-D vector (v) and >two scalars (a and b), all three given for a set of points in >3-D space. My data looks something like: > >data = { {{x0,y0,z0}, {vx0,vy0,vz0}, a0, b0}, > {{x1,y1,z1}, {vx1,vy1,vz1}, a1, b1}, > ... > {{xi,yi,zi}, {vxi,vyi,vzi}, ai, bi}, > ... } > >I would like to have a 3-D display with an arrow at each point >{xi, yi, zi}, the arrow being parallel with vi and its length >and colour representing the values of ai and bi respectively. >I have tried using ListPlotVectorField3D which almost does the >job, but not quite. Am I missing something, or perhaps just asking >for too much? Scaling the arrows according to the argument ai is quite easy. Coloring according to the argument bi is more difficult. The type of data rearrangment which you need to do is something which Mathematica is good at. You need to get your data into the form... { {{x0,y0,z0}, {vx0,vy0,vz0}}, {{x1,y1,z1}, {vx1,vy1,vz1}}, ... {{xi,yi,zi}, {vxi,vyi,vzi}}, ... } where the vectors have been scaled. Suppose the data is generated like so... data = Table[ {{x=Random[], y=Random[],z=Random[]}, {y z, x z, x y}, x y z, Sqrt[x^2+y^2+z^2]}, {10}]; It can be rearranged with Map: newdata = Map[ { Part[ #, 1], Part[ #, 3] Part[ #, 2]/Sqrt[Part[ #, 2].Part[ #, 2]] }&, data] ; where the vectors are normalised and then scaled by the third argument. The fourth argument is not used in the result here. This can be plotted directly...(remember to load the package Graphics`PlotField3D`). vects = ListPlotVectorField3D[ newdata] To get shading according to the color is more difficult. This is partly because there are many ways this can be done. The solution here will use a linear mapping to transform the smallest value bi to Hue[0] and the largest to Hue[1]. First the colors are extracted cols = Map[ Last, data] ; Next the minimum and maximum values are calculated min = Min[ cols] ; max = Max[ cols] ; Here color specifications are generated with the mapping specified above cols = Map[ Hue[ (# - min)/(max-min)]&, cols] ; This step will put the colors in with each vector specification. If some of the original data did not consist of numbers then the length of the vector primitives list will not be equal to the colors list and the transpose will not work. It is important to ensure that all of the original data consists of numbers. Graphics3D[ Transpose[ { cols, First[ vects]}]] Finally they can be displayed. Show[ %] It is possible to put all this into one function. Which checks the data to ensure that it consists of numbers. SpecialVectorPlot[ idata:{ {{_,_,_}, {_,_,_}, _,_}..}] := Block[{data, ndata, cols, min, max}, data = Cases[ idata,{ _?(VectorQ[#,NumberQ]&), _?(VectorQ[#,NumberQ]&), _?NumberQ, _?NumberQ}] ; ndata = Map[ { Part[ #, 1], Part[ #, 3] Part[ #, 2]/Sqrt[Part[ #, 2].Part[ #, 2]] }&, data] ; ndata = First[ ListPlotVectorField3D[ ndata, DisplayFunction -> Identity]] ; cols = Map[ Last, data] ; min = Min[ cols] ; max = Max[ cols] ; cols = Map[ Hue[ (# - min)/(max-min)]&, cols] ; Show[ Graphics3D[ Transpose[ { cols, First[ vects]}]]] ] Tom Wickham-Jones WRI