2
$\begingroup$

I have a collection of 3D points, and each is associated with a real number in [0,1]. A typical element looks like {{x,y,z},c} where c is the number to determine the color. (Sample code to generate random data below.) I would like to plot those points, coloring each according to ColorData["TemperatureMap"]. I have been unable to figure out how to get this to work, to arrange for ColorFunction->(???) to use that parameter c rather than x, y, or z to index into "TemperatureMap". This is likely straightforward for those (unlike me) who have mastered ColorFunction and ColorData.

SeedRandom[1]; n = 10; 
pts = Table[RandomReal[{-1, 1}, {3}], {n}]; 
ptsc = Map[{#, RandomReal[]} &, pts];
$\endgroup$
  • 1
    $\begingroup$ A frequently asked question (and duplicate). 2D version: (1300), (5185). 3D duplicates: (20023), (77859), (78289) $\endgroup$ – Mr.Wizard May 18 '15 at 16:44
  • $\begingroup$ @Mr.Wizard: Thanks for all those links! $\endgroup$ – Joseph O'Rourke May 18 '15 at 16:49
2
$\begingroup$

As @Mr.Wizard pointed out, multiple interesting solutions to your problem have been proposed on this site. I just wanted to add an observation here.

I realize that you did not say so explicitly, but I would think that many users would try some combination of ListPointPlot3D for this kind of task. However, it has been my impression when using the *3D list plotting functions that they may not always be as polished and agile as their 2D counterpart. I have had a few problems with them, and I am now a bit wary.

I find it often easier to reproduce their behavior by constructing a Graphics3D object explicitly; it is my understanding that it's what those functions do anyway. Similarly in this case, the following is the method I would have come up with, when confronted with your problem. I am using your mock data definitions, just with a few more points.

Graphics3D[
 {PointSize[0.03], ColorData["TemperatureMap"][ #[[2]] ], Point[ #[[1]] ]} & /@ ptsc,
 Axes -> True, Background -> Black
]

Mathematica graphics

(I added a black background because the point colors otherwise had very poor contrast on white; of course it's not required.)


Update:

Exactly the same goal can be achieved more cleanly following Guess who it is's suggestion of using Apply to improve on the somewhat ugly Part expressions I had above:

Graphics3D[
 {PointSize[0.03],
  {ColorData["TemperatureMap"][#2], Point[#1]} & @@@ ptsc
  }, Axes -> True, Background -> Black]
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you! This is just what I needed, the syntax for ColorData["TemperatureMap"][ #[[2]] ]. $\endgroup$ – Joseph O'Rourke May 18 '15 at 21:11
  • 2
    $\begingroup$ Also possible: {PointSize[0.03], {ColorData["TemperatureMap"][#2], Point[#1]} & @@@ ptsc}. The PointSize[] will be applied globally anyway, and you can use Apply[] to avoid clumsiness with Part[]. $\endgroup$ – J. M.'s discontentment May 18 '15 at 22:00
  • $\begingroup$ @J.M. Good point about the global PointSize. As for the Apply[], I'll be honest: those @@@ still hurt my brain sometimes, but it is undoubtedly more elegant here. I really need to use it more! $\endgroup$ – MarcoB May 18 '15 at 22:15
  • $\begingroup$ @J.M. I added your version with Apply as an alternative to my answer. I hope you don't mind. $\endgroup$ – MarcoB May 18 '15 at 22:24
  • 2
    $\begingroup$ Hello, @Joseph! f @@@ list is shorthand for Apply[f, list, {1}]; it changes the heads of the elements of list at the first level ({1}) to f. So, if you do something like f @@@ {{u, v}, {x, y}}, you get {f[u, v], f[x, y]} as the result, with for instance the List head of {u, v} getting turned into f. $\endgroup$ – J. M.'s discontentment May 18 '15 at 23:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.