Funkcja koloru w DensityPlot3D nie działa zgodnie z oczekiwaniami

Nov 21 2020

Próbuję ustawić funkcję koloru DensityPlot3Dwyjścia tak, aby wartości dodatnie kolorowały jeden kolor, a wartości ujemne innym kolorem. Jednak nie wydaje mi się, aby działał poprawnie. Na przykład odpowiedni kod to:

\[CapitalOmega] = 
  Parallelepiped[{-3, -3, -4}, {{6, 0, 0}, {0, 6, 0}, {0, 0, 8}}];

DensityPlot3D[x*y*z,
              {x, y, z} \[Element] \[CapitalOmega], 
              PerformanceGoal -> "Quality", 
              PlotRange -> All, 
              OpacityFunction -> Function[f, If[Abs[f] > 0.4, Abs@Tanh[f], 0]], 
              PlotLegends -> Automatic, 
              ImageSize -> Medium, 
              AxesLabel -> Automatic, 
              ColorFunction -> Function[f, Which[Sign[f] == 1, Black, Sign[f] == -1, Blue, Sign[f] == 0, Gray]]
]

Tutaj funkcja koloru, której mam użyć, to

Function[f, Which[Sign[f] == 1, Black, Sign[f] == -1, Blue, Sign[f] == 0, Gray]]

Więc weź dodatnie wartości produktu x*y*zi pokoloruj je na czarno, weź wartości ujemne i pokoloruj na niebiesko, a wszystko inne na szaro.

Ten kod, gdy jest wykonywany samodzielnie, tworzy pliki

który nie jest tym, czego chcę :(. Czy źle rozumiem argumenty funkcji koloru? Przeczytałem dokumentację i myślę, że używam go poprawnie, ale chyba nie.

(Which[Sign[#] == -1, Blue, Sign[#] == 0, Gray, Sign[#] == 1, 
   Black] &)

z tym samym wynikiem. Mam również problem z aplikacją OpacityFunction, co możesz zobaczyć na powyższym przykładowym obrazku. Funkcja OpacityFunction w przykładowym kodzie powinna generować obraz, który jest zasadniczo przezroczysty w samym środku i jednolity na ścianach sześcianu (więc powinniśmy zobaczyć tylko czarną kostkę), ale obraz pokazuje, że rogi sześcianu są ustawione na 0 krycia. Np. Punkt (-2, -2, -2) powinien mieć nieprzezroczystość|Tanh[-8]|~1

Używam tylko przykładowej funkcji powyżej, rzeczywista funkcja jest znacznie bardziej skomplikowana. Załączę wynik rzeczywistej funkcji, którą muszę pokolorować poniżej:

Używam funkcji krycia, aby wyrzucić wartości naprawdę bliskie zeru, pozostawiając interesujące bity.

Doceniam każdy wgląd!

Odpowiedzi

2 shanedrum Nov 21 2020 at 18:28

Ach, zdałem sobie sprawę, że dzieje się tak, ponieważ argumenty dostarczone do ColorFunctionskalowanymi wersjami wykreślonych wartości. Więc wartości, które widzę na wykresie, nie są dokładnymi wartościami, na których ColorFunctiondziała. Aby zatrzymać skalowanie, po prostu ustawiam

ColorFunctionScaling-> False

OpacityFunctionScaling -> False

i to rozwiązało problem.

A teraz następujący kod

DensityPlot3D[x*y*z, {x, y, z} \[Element] \[CapitalOmega], 
             PerformanceGoal -> "Quality",
             PlotRange -> All, 
             OpacityFunction -> Function[f, If[Abs[f] > 0.5, N[ Abs[Tanh[f]]], 0]], 
             PlotLegends -> Automatic,
             ImageSize -> Medium, 
             AxesLabel -> Automatic, 
             ColorFunction -> Function[{f}, If[f > 0, Green, Blue]], 
             ColorFunctionScaling -> False,
             OpacityFunctionScaling -> False
]

tworzy obraz

co przekłada się na faktyczną funkcję, której chcę idealnie używać. Jak widać, obszary z dodatnimi wartościami x y z są zabarwione na zielono, a obszary z ujemnymi wartościami x y z mają kolor niebieski. Dodatkowo Krycie również zachowuje się zgodnie z oczekiwaniami.

Te linki pomogły mi rozwiązać problem:

  1. Problemy z ColorFunction
  2. Piecewise ColorFunction dla Plot3D

Mam nadzieję, że ta odpowiedź pomoże innym, którzy mają podobne problemy.