Edit: tested with MMA 11.1, option Exclusions -> None
added to recover the previous behavior.
I have found that my approach with textures has different applications:
Now I want to use it for the enhancement of the DensityPlot
:
Options[fastDensityPlot] = Append[Options[DensityPlot], Subpoints -> 30];
SyntaxInformation[fastDensityPlot] = SyntaxInformation[DensityPlot];
fastDensityPlot[f_, {x_, xmin_, xmax_}, {y_, ymin_, ymax_}, opts : OptionsPattern[]] :=
DensityPlot[f, {x, xmin, xmax}, {y, ymin, ymax},
Evaluate@FilterRules[{opts}, Except@Subpoints]] // Normal // toTriangles //
texturize[Function[{#1, #2}, #3] & @@ {x, y, f},
OptionValue[Subpoints], OptionValue[ColorFunction]]
Here Normal
converts GraphicsComplex
to separate polygons, toTriangles
splits polygons to triangles, and texturize
puts textures on every triangle (defined below), f
is assumed to be Listable
.
f[x_, y_] := (x^2 + y^2) Exp[-x^2 - y^2] Sin[10 Sqrt[x^2 + y^2] + 10 ArcTan[x, y]]^4;
fastDensityPlot[f[x, y], {x, -3, 3}, {y, -3, 3}, PlotPoints -> 10,
MaxRecursion -> 2, ColorFunction -> Hue, Subpoints -> 20,
PlotRange -> All, ImageSize -> 600, Exclusions -> None]
This image looks a bit better. At the same time fastDensityPlot
is ~10 times faster then the regular DensityPlot
, MaxMemoryUsed
is only 64MB and ByteCount
is 10MB.
One can see that fastDensityPlot
uses the advantage of the non-equidistant mesh:
fastDensityPlot[f[x, y], {x, -3, 3}, {y, -3, 3}, PlotPoints -> 10,
MaxRecursion -> 2, ColorFunction -> Hue, Subpoints -> 20,
PlotRange -> All, ImageSize -> 600, Mesh -> All, Exclusions -> None]
Definitions of the above functions:
toTriangles = # /. Polygon[v_ /; Length[v] > 3, ___] :> (Polygon@Append[#, Mean[v]] & /@
Partition[v, 2, 1, 1]) &;
texturize[f_, n_, colf_] := # /. Polygon[{v1_, v2_, v3_}, ___] :> {Texture@
ImageData@Colorize[
Image@f[v3[[1]] + (v1[[1]] - v3[[1]]) #1 + (v2[[1]] - v3[[1]]) #2,
v3[[2]] + (v1[[2]] - v3[[2]]) #1 + (v2[[2]] - v3[[2]]) #2]
&[#, Transpose[#]] &@ConstantArray[Range[-1./n, 1 + 1./n, 1./n], n + 3],
ColorFunction -> colf, ColorFunctionScaling -> False],
Polygon[{v1, v2, v3},
VertexTextureCoordinates -> {{1 - 1.5/(n + 3),
1 - 1.5/(n + 3)}, {1.5/(n + 3), 1.5/(n + 3)}, {1.5/(n + 3),
1 - 1.5/(n + 3)}}]} &;
As in the linked answer, I add textures to every triangle with an appropriate rectangular grid. This method is fast because it uses packed arrays.