SPH
PaletteDialog.cpp
Go to the documentation of this file.
2 #include "gui/Factory.h"
7 #include "gui/windows/Widgets.h"
8 #include "io/FileSystem.h"
9 #include <wx/button.h>
10 #include <wx/combobox.h>
11 #include <wx/dcclient.h>
12 #include <wx/panel.h>
13 #include <wx/sizer.h>
14 #include <wx/stattext.h>
15 
17 
19 private:
21 
22 public:
24  : context(std::move(context)) {}
25 
26  virtual Pixel size() const override {
27  const Pixel p = context->size();
28  return Pixel(p.y, p.x);
29  }
30 
31  virtual void setColor(const Rgba& color, const Flags<ColorFlag> flags) override {
32  context->setColor(color, flags);
33  }
34 
35  virtual void setThickness(const float thickness) override {
36  context->setThickness(thickness);
37  }
38 
39  virtual void setFontSize(const int fontSize) override {
40  context->setFontSize(fontSize);
41  }
42 
43  virtual void fill(const Rgba& color) override {
44  context->fill(color);
45  }
46 
47  virtual void drawLine(const Coords p1, const Coords p2) override {
48  context->drawLine(this->transform(p1), this->transform(p2));
49  }
50 
51  virtual void drawCircle(const Coords center, const float radius) override {
52  context->drawCircle(this->transform(center), radius);
53  }
54 
55  virtual void drawTriangle(const Coords, const Coords, const Coords) override {
57  }
58 
59  virtual void drawBitmap(const Coords, const Bitmap<Rgba>&) override {
61  }
62 
63  virtual void drawText(const Coords p, const Flags<TextAlign>, const std::string& s) override {
64  context->drawText(this->transform(p), TextAlign::VERTICAL_CENTER | TextAlign::HORIZONTAL_CENTER, s);
65  }
66 
67  virtual void drawText(const Coords p, const Flags<TextAlign>, const std::wstring& s) override {
68  context->drawText(this->transform(p), TextAlign::VERTICAL_CENTER | TextAlign::HORIZONTAL_CENTER, s);
69  }
70 
71 private:
72  Pixel transform(const Pixel& p) {
73  return Pixel(context->size().x - p.y, p.x);
74  }
75 
76  Coords transform(const Coords& p) {
77  return Coords(context->size().x - p.y, p.x);
78  }
79 };
80 
81 class PaletteCanvas : public wxPanel {
82 private:
83  Palette palette;
84 
85 public:
86  PaletteCanvas(wxWindow* parent, const Palette palette)
87  : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
88  , palette(palette) {
89  this->Connect(wxEVT_PAINT, wxPaintEventHandler(PaletteCanvas::onPaint));
90  this->SetMinSize(wxSize(320, 100));
91  }
92 
93  void setPalette(const Palette newPalette) {
94  palette = newPalette;
95  this->Refresh();
96  }
97 
98 private:
99  void onPaint(wxPaintEvent& UNUSED(evt)) {
100  wxPaintDC dc(this);
101  FlippedRenderContext context(makeAuto<WxRenderContext>(dc));
102  context.setFontSize(9);
103  Rgba background(dc.GetBackground().GetColour());
104  drawPalette(context, Pixel(40, 310), Pixel(40, 300), background.inverse(), palette);
105  }
106 };
107 
109  wxSize size,
110  const Palette initialPalette,
111  Function<void(Palette)> setPalette)
112  : wxFrame(parent, wxID_ANY, "Palette Dialog", wxGetMousePosition(), size)
113  , setPaletteCallback(setPalette) {
114 
115  selected = initial = initialPalette;
116 
117  wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
118 
119  canvas = new PaletteCanvas(this, initialPalette);
120  mainSizer->Add(canvas, 0, wxALIGN_CENTER_HORIZONTAL);
121 
122  wxBoxSizer* selectionSizer = new wxBoxSizer(wxHORIZONTAL);
123  paletteBox = new ComboBox(this, "Select palette ...");
124  selectionSizer->Add(paletteBox);
125 
126  wxButton* loadButton = new wxButton(this, wxID_ANY, "Load");
127  selectionSizer->Add(loadButton);
128 
129  wxButton* resetButton = new wxButton(this, wxID_ANY, "Reset");
130  selectionSizer->Add(resetButton);
131 
132  mainSizer->Add(selectionSizer, 0, wxALIGN_CENTER_HORIZONTAL);
133  mainSizer->AddSpacer(5);
134 
135  wxBoxSizer* rangeSizer = new wxBoxSizer(wxHORIZONTAL);
136 
137  const Size height = 30;
138  rangeSizer->Add(new wxStaticText(this, wxID_ANY, "From: ", wxDefaultPosition, wxSize(-1, height)));
139  FloatTextCtrl* lowerCtrl = new FloatTextCtrl(this, double(initialPalette.getInterval().lower()));
140  rangeSizer->Add(lowerCtrl);
141 
142  rangeSizer->Add(new wxStaticText(this, wxID_ANY, "To: ", wxDefaultPosition, wxSize(-1, height)));
143  FloatTextCtrl* upperCtrl = new FloatTextCtrl(this, double(initialPalette.getInterval().upper()));
144  rangeSizer->Add(upperCtrl);
145 
146  upperCtrl->onValueChanged = [this](const Float value) {
148  const Float lower = selected.getInterval().lower();
149  if (lower >= value) {
150  return false;
151  }
152  selected.setInterval(Interval(lower, value));
153  canvas->setPalette(selected);
154  setPaletteCallback(selected);
155  return true;
156  };
157  lowerCtrl->onValueChanged = [this](const Float value) {
158  const Float upper = selected.getInterval().upper();
159  if (value >= upper) {
160  return false;
161  }
162  if (selected.getScale() == PaletteScale::LOGARITHMIC && value <= 0.f) {
163  return false;
164  }
165  selected.setInterval(Interval(value, upper));
166  canvas->setPalette(selected);
167  setPaletteCallback(selected);
168  return true;
169  };
170 
171  mainSizer->Add(rangeSizer, 0, wxALIGN_CENTER_HORIZONTAL);
172  mainSizer->AddSpacer(5);
173 
174  wxBoxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL);
175  wxButton* okButton = new wxButton(this, wxID_ANY, "OK");
176  okButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& UNUSED(evt)) {
177  setPaletteCallback(selected);
178  this->Close();
179  });
180  buttonSizer->Add(okButton);
181  wxButton* cancelButton = new wxButton(this, wxID_ANY, "Cancel");
182  cancelButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& UNUSED(evt)) { this->Close(); });
183  buttonSizer->Add(cancelButton);
184 
185  mainSizer->Add(buttonSizer, 0, wxALIGN_CENTER_HORIZONTAL);
186  mainSizer->AddSpacer(10);
187 
188  this->SetSizerAndFit(mainSizer);
189 
190  // setup palette box
191  paletteBox->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& UNUSED(evt)) { this->update(); });
192 
193  loadButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& UNUSED(evt)) {
194  Optional<Path> path = doOpenFileDialog("Load palette", { { "Palette files", "csv" } });
195  if (!path) {
196  return;
197  }
198  paletteMap.clear();
199  for (Path file : FileSystem::iterateDirectory(path->parentPath())) {
200  if (file.extension().native() == "csv") {
201  Palette palette = initial;
202  if (palette.loadFromFile(path->parentPath() / file)) {
203  paletteMap.insert(file.native(), palette);
204  }
205  }
206  }
207  wxArrayString items;
208  int selectionIdx = 0, idx = 0;
209  for (FlatMap<std::string, Palette>::Element& e : paletteMap) {
210  items.Add(e.key);
211  if (e.key == path->fileName().native()) {
212  // this is the palette we selected
213  selectionIdx = idx;
214  }
215  ++idx;
216  }
217  paletteBox->Set(items);
218  paletteBox->SetSelection(selectionIdx);
219 
220  this->update();
221  });
222  resetButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& UNUSED(evt)) { this->setDefaultPaletteList(); });
223 
224  this->setDefaultPaletteList();
225 }
226 
227 static FlatMap<ExtColorizerId, std::string> PALETTE_ID_LIST = {
228  { ColorizerId::VELOCITY, "Velocity" },
229  { ColorizerId::TEMPERATURE, "Temperature" },
230  { QuantityId::DEVIATORIC_STRESS, "Stress" },
231  { QuantityId::DAMAGE, "Damage" },
232  { ColorizerId::MOVEMENT_DIRECTION, "Periodic" },
233  { ColorizerId::DENSITY_PERTURBATION, "Diverging 1" },
234  { QuantityId::DENSITY, "Diverging 2" },
235  { QuantityId::VELOCITY_DIVERGENCE, "Diverging 3" },
236  { QuantityId::ANGULAR_FREQUENCY, "Extremes" },
237 };
238 
239 // some extra palettes
240 namespace Palettes {
241 
242 const Palette GALAXY({ { 0.001f, Rgba(0.f, 0.02f, 0.09f) },
243  { 0.01f, Rgba(0.4f, 0.106f, 0.38f) },
244  { 0.1f, Rgba(0.78f, 0.18f, 0.38f) },
245  { 1.f, Rgba(0.91f, 0.56f, 0.81f) },
246  { 10.f, Rgba(0.29f, 0.69f, 0.93f) } },
248 
249 const Palette ACCRETION({ { 0.001f, Rgba(0.43f, 0.70f, 1.f) },
250  { 0.01f, Rgba(0.5f, 0.5f, 0.5f) },
251  { 0.1f, Rgba(0.65f, 0.12f, 0.01f) },
252  { 1.f, Rgba(0.79f, 0.38f, 0.02f) },
253  { 10.f, Rgba(0.93f, 0.83f, 0.34f) },
254  { 100.f, Rgba(0.94f, 0.90f, 0.84f) } },
256 
257 } // namespace Palettes
258 
259 void PaletteDialog::setDefaultPaletteList() {
260  paletteMap = {
261  { "(default)", initial },
262  { "Blackbody", getBlackBodyPalette(Interval(300, 12000)) },
263  { "Galaxy", Palettes::GALAXY },
264  { "Accretion", Palettes::ACCRETION },
265  };
266  for (auto& pair : PALETTE_ID_LIST) {
267  paletteMap.insert(pair.value, Factory::getPalette(pair.key));
268  }
269 
270  wxArrayString items;
271  for (FlatMap<std::string, Palette>::Element& e : paletteMap) {
272  items.Add(e.key);
273  }
274  paletteBox->Set(items);
275  paletteBox->SetSelection(0);
276  this->update();
277 }
278 
279 void PaletteDialog::update() {
280  const int idx = paletteBox->GetSelection();
281  const Interval range = selected.getInterval();
282  selected = (paletteMap.begin() + idx)->value;
283  selected.setInterval(range);
284  canvas->setPalette(selected);
285  setPaletteCallback(selected);
286 }
287 
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
Definition: Assert.h:100
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Object converting quantity values of particles into colors.
@ MOVEMENT_DIRECTION
Projected direction of motion.
@ DENSITY_PERTURBATION
Relative difference of density and initial density (rho/rho0 - 1)
@ VELOCITY
Particle velocities.
@ TEMPERATURE
Temperature, computed from internal energy.
const float radius
Definition: CurveDialog.cpp:18
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
@ HORIZONTAL_CENTER
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
@ LOGARITHMIC
Control points are interpolated on logarithmic scale. All points must be positive!
void drawPalette(IRenderContext &context, const Pixel origin, const Pixel size, const Rgba &lineColor, const Palette &palette)
Renderer drawing individual particles as dots.
@ VELOCITY_DIVERGENCE
Velocity divergence.
@ DEVIATORIC_STRESS
Deviatoric stress tensor, always a traceless tensor.
@ DAMAGE
Damage.
@ DENSITY
Density, always a scalar quantity.
Palette getBlackBodyPalette(const Interval range)
Returns palette with colors for black body emission for given temperature.
Definition: Spectrum.cpp:198
Optional< Path > doOpenFileDialog(const std::string &title, Array< FileFormat > &&formats)
Definition: Utils.cpp:45
Wrapper of an integral value providing functions for reading and modifying individual bits.
Definition: Flags.h:20
Container of key-value pairs.
Definition: FlatMap.h:19
INLINE TValue & insert(const TKey &key, const TValue &value)
Adds a new element into the map or sets new value of element with the same key.
Definition: FlatMap.h:65
INLINE Iterator< Element > begin()
Returns the iterator pointing to the first element.
Definition: FlatMap.h:155
INLINE void clear()
Removes all elements from the map.
Definition: FlatMap.h:111
virtual void drawBitmap(const Coords, const Bitmap< Rgba > &) override
Draws a bitmap, given the position of its left-top corner.
virtual void drawText(const Coords p, const Flags< TextAlign >, const std::string &s) override
virtual void drawLine(const Coords p1, const Coords p2) override
Draws a line connecting two points.
virtual void drawText(const Coords p, const Flags< TextAlign >, const std::wstring &s) override
virtual void setColor(const Rgba &color, const Flags< ColorFlag > flags) override
Selects the color for one or more drawing modes.
virtual void setFontSize(const int fontSize) override
FlippedRenderContext(AutoPtr< IRenderContext > &&context)
virtual void drawCircle(const Coords center, const float radius) override
Draws a circle, given its center and a radius.
virtual void setThickness(const float thickness) override
Modifies the thickness of the lines.
virtual Pixel size() const override
Returns the size of the canvas associated with the context.
virtual void fill(const Rgba &color) override
Fills the whole canvas with given color.
virtual void drawTriangle(const Coords, const Coords, const Coords) override
Draws a triangle given three points.
Function< bool(double)> onValueChanged
Definition: Widgets.h:17
Abstraction of a device used for rendering.
Definition: RenderContext.h:22
virtual void setFontSize(const int fontSize)=0
virtual void drawCircle(const Coords center, const float radius)=0
Draws a circle, given its center and a radius.
virtual void drawLine(const Coords p1, const Coords p2)=0
Draws a line connecting two points.
virtual void drawText(const Coords p, const Flags< TextAlign > align, const std::string &s)=0
virtual void setColor(const Rgba &color, const Flags< ColorFlag > flags)=0
Selects the color for one or more drawing modes.
virtual void setThickness(const float thickness)=0
Modifies the thickness of the lines.
virtual void fill(const Rgba &color)=0
Fills the whole canvas with given color.
virtual Pixel size() const =0
Returns the size of the canvas associated with the context.
Object representing a 1D interval of real numbers.
Definition: Interval.h:17
INLINE Float lower() const
Returns lower bound of the interval.
Definition: Interval.h:74
INLINE Float upper() const
Returns upper bound of the interval.
Definition: Interval.h:79
Wrapper of type value of which may or may not be present.
Definition: Optional.h:23
PaletteCanvas(wxWindow *parent, const Palette palette)
void setPalette(const Palette newPalette)
PaletteDialog(wxWindow *parent, wxSize size, const Palette palette, Function< void(Palette)> setPalette)
Represents a color palette, used for mapping arbitrary number to a color.
Definition: Palette.h:25
void setInterval(const Interval &newRange)
Definition: Palette.cpp:95
PaletteScale getScale() const
Returns the scale of the palette.
Definition: Palette.cpp:107
Outcome loadFromFile(const Path &path)
Loads the palette from given .csv file.
Definition: Palette.cpp:200
Interval getInterval() const
Returns the interval for which the palette is defined.
Definition: Palette.cpp:90
Object representing a path on a filesystem.
Definition: Path.h:17
Definition: Color.h:8
Palette getPalette(const ExtColorizerId id)
Definition: Factory.cpp:261
DirectoryAdapter iterateDirectory(const Path &directory)
Definition: FileSystem.cpp:338
const Palette GALAXY({ { 0.001f, Rgba(0.f, 0.02f, 0.09f) }, { 0.01f, Rgba(0.4f, 0.106f, 0.38f) }, { 0.1f, Rgba(0.78f, 0.18f, 0.38f) }, { 1.f, Rgba(0.91f, 0.56f, 0.81f) }, { 10.f, Rgba(0.29f, 0.69f, 0.93f) } }, PaletteScale::LOGARITHMIC)
const Palette ACCRETION({ { 0.001f, Rgba(0.43f, 0.70f, 1.f) }, { 0.01f, Rgba(0.5f, 0.5f, 0.5f) }, { 0.1f, Rgba(0.65f, 0.12f, 0.01f) }, { 1.f, Rgba(0.79f, 0.38f, 0.02f) }, { 10.f, Rgba(0.93f, 0.83f, 0.34f) }, { 100.f, Rgba(0.94f, 0.90f, 0.84f) } }, PaletteScale::LOGARITHMIC)
Overload of std::swap for Sph::Array.
Definition: Array.h:578
Definition: Point.h:115
Definition: Point.h:101