# How can I make a DensityPlot3D over a triangle?

I know that I can plot over 3D-regions like balls via

DensityPlot3D[(x^2 + y^2 + z^2)^2, {x, y, z} ∈ Ball[{0, 0, 0}, 1]]


But, not surprisingly, this breaks down for 2D-regions like triangles.

How can I create a 3D plot over surfaces to visualize the functions defined on those surfaces?

I know that there are ways to do this for Balls for example via SliceContourPlot3D (ref Plotting a complicated 3D wave on the surface of a sphere), but I don't think this is possible in this case (and if possible, probably terribly inefficient)

You don't. DensityPlot3D will reject anything that has RegionDimension not equal to 3, e.g.

In:= RegionDimension@Triangle[{{0, 0, 0}, {1, 0, 0}, {0, 1, 1}}]
(*Out= 2 *)


Instead, you use SliceDensityPlot3D with the 2D region as follows:

SliceDensityPlot3D[(x^2 + y^2 + z^2)^2,
Triangle[{{0, 0, 0}, {1, 0, 0}, {0, 1, 1}}],
{x, y, z} \[Element] Cuboid[]] Edit: The symmetry of the function needs to be taken into account, though, when choosing the slice. For example, if your function is spherically symmetric, like (x^2 + y^2 + z^2)^2 is, then "CenterSphere" is a poor choice for slice as the surface will just show numerical noise, e.g.

SliceDensityPlot3D[(x^2 + y^2 + z^2)^2, "CenterSphere",
{x, y, z} \[Element] Cuboid[-{1, 1, 1}, {1, 1, 1}]] But, "CenterCutSphere" works very well here as the numerical noise is not visible relative to the other variations present, e.g.

SliceDensityPlot3D[(x^2 + y^2 + z^2)^2, "CenterCutSphere",
{x, y, z} \[Element] Cuboid[-{1, 1, 1}, {1, 1, 1}]] The following works for MeshRegions that represent surfaces.

First, we define a function and a MeshRegion. For simplicity, I use a sphere. A Triangle is not as easy to discretize (i.e. to refine).

f = X \[Function] X[] X[];
R = DiscretizeRegion[Sphere[{0, 0, 0}, 1], MaxCellMeasure -> 0.00001];


Next, we generate a color gradient image with tick lines as texture:

colfun = ColorData["SunsetColors"];
ticks = 20;
tickthickness = 5;
n = (spread + tickthickness) (ticks + 1);
a = DeveloperToPackedArray[List @@@ (colfun /@ (Range[0, n]/n))];
Do[
Do[
a[[i + j]] = {0., 0., 0.}
, {j, 1, tickthickness - 1}
]
, {i, 1, n, spread + tickthickness}
];
tex = Image[ConstantArray[a, 15]] Finally, we evaluate the function on all MeshCoordinates, rescale them and plot the mesh as GraphicsComplex with according VertexNormals (thanks to this post) and with VertexTextureCoordinates according to the (scaled) values of f:

p = MeshCoordinates[R];
vals = Map[f, p];
Graphics3D[{
Texture[tex], EdgeForm[],
GraphicsComplex[
p,
Polygon[MeshCells[R, 2][[All, 1]]],
VertexNormals -> RegionMeshMeshCellNormals[R, 0],
VertexTextureCoordinates ->
Transpose[{Rescale[vals, {Min[vals], Max[vals]}, {0.001, 0.999}],
ConstantArray[0.5, Length[p]]}]
]
},
Lighting -> "Neutral"
]
`

This is the result of the procedure: 