SPH
ContourRenderer.cpp
Go to the documentation of this file.
2 #include "gui/objects/Camera.h"
7 
9 
11  : scheduler(scheduler) {
12  kernel = CubicSpline<3>();
14 }
15 
17  const IColorizer& colorizer,
18  const ICamera& UNUSED(camera)) {
19  cached.positions = storage.getValue<Vector>(QuantityId::POSITION).clone();
20  cached.values.resize(cached.positions.size());
21 
22  parallelFor(*scheduler, 0, cached.positions.size(), [this, &colorizer](const Size i) {
23  cached.values[i] = colorizer.evalScalar(i).value();
24  });
25  cached.palette = colorizer.getPalette();
26 
27  finder->build(*scheduler, cached.positions);
28 }
29 
31  return !cached.values.empty();
32 }
33 
34 // See https://en.wikipedia.org/wiki/Marching_squares
35 static FlatMap<Size, Pixel> MS_TABLE = {
36  // no contour
37  { 0b0000, { -1, -1 } },
38  { 0b1111, { -1, -1 } },
39 
40  // single edge
41  { 0b1110, { 2, 3 } },
42  { 0b1101, { 1, 2 } },
43  { 0b1011, { 0, 1 } },
44  { 0b0111, { 3, 0 } },
45  { 0b0001, { 2, 3 } },
46  { 0b0010, { 1, 2 } },
47  { 0b0100, { 0, 1 } },
48  { 0b1000, { 3, 0 } },
49  { 0b1100, { 1, 3 } },
50  { 0b1001, { 0, 2 } },
51  { 0b0011, { 1, 3 } },
52  { 0b0110, { 0, 2 } },
53 
55  { 0b1010, { -1, -1 } },
56  { 0b0101, { -1, -1 } },
57 };
58 
59 static FlatMap<Size, std::pair<Pixel, Pixel>> MS_EDGE_TO_VTX = {
60  { 0, { Pixel(0, 0), Pixel(1, 0) } },
61  { 1, { Pixel(1, 0), Pixel(1, 1) } },
62  { 2, { Pixel(1, 1), Pixel(0, 1) } },
63  { 3, { Pixel(0, 1), Pixel(0, 0) } },
64 };
65 
66 static bool isCoordValid(const UnorderedMap<float, Coords>& map, const Coords& p) {
67  for (auto& isoAndCoord : map) {
68  if (getLength(p - isoAndCoord.value) < 100) {
69  return false;
70  }
71  }
72  return true;
73 }
74 
76  Statistics& UNUSED(stats),
77  IRenderOutput& output) const {
78  const Pixel size = params.camera->getSize();
79  const Optional<CameraRay> ray1 = params.camera->unproject(Coords(0, 0));
80  const Optional<CameraRay> ray2 = params.camera->unproject(Coords(size));
81  const Vector pos1(ray1->origin[X], ray1->origin[Y], 0._f);
82  const Vector pos2(ray2->origin[X], ray2->origin[Y], 0._f);
83  const Size resX = params.contours.gridSize;
84  const Size resY = Size(resX * float(size.y) / float(size.x));
85  const Vector dxdp = Vector(1._f / resX, 1._f / resY, 0._f) * (pos2 - pos1);
86 
87  Bitmap<float> grid(Pixel(resX, resY));
88  grid.fill(0.f);
90  for (Size y = 0; y < resY; ++y) {
91  for (Size x = 0; x < resX; ++x) {
92  const Vector pos = pos1 + dxdp * Vector(x, y, 0);
93  const Float h = dxdp[X];
94  finder->findAll(pos, 2._f * h, neighs);
95 
96  Float sum = 0._f;
97  Float weight = 0._f;
98  for (const NeighbourRecord& n : neighs) {
99  const float w = float(kernel.value(pos - cached.positions[n.index], h));
100  sum += cached.values[n.index] * w;
101  weight += w;
102  }
103  if (weight > 0._f) {
104  grid[Pixel(x, y)] = float(sum / weight);
105  }
106  }
107  }
108 
109  Bitmap<Rgba> bitmap(size);
110  AntiAliasedRenderContext context(bitmap);
111  context.fill(Rgba::black());
112 
113  /*context.setColor(Rgba::gray(0.25f), ColorFlag::LINE);
114  for (Size x = 0; x < resX; ++x) {
115  const int i = x * params.size.x / resX;
116  context.drawLine(Coords(i, 0), Coords(i, params.size.y - 1));
117  }
118  for (Size y = 0; y < resY; ++y) {
119  const int i = y * params.size.y / resY;
120  context.drawLine(Coords(0, i), Coords(params.size.x - 1, i));
121  }*/
122 
124 
125  const Coords gridToPixel = Coords(size) / Coords(resX, resY);
126 
128 
129  for (Size x = 0; x < resX - 1; ++x) {
130  for (Size y = 0; y < resY - 1; ++y) {
131  Pixel p(x, y);
132  const float v1 = grid[p + Pixel(0, 0)];
133  const float v2 = grid[p + Pixel(1, 0)];
134  const float v3 = grid[p + Pixel(1, 1)];
135  const float v4 = grid[p + Pixel(0, 1)];
136 
137  const float vmin = min(v1, v2, v3, v4);
138  const float vmax = max(v1, v2, v3, v4);
139  const float isoMin = params.contours.isoStep * (int(vmin / params.contours.isoStep) + 1);
140  const float isoMax = params.contours.isoStep * (int(vmax / params.contours.isoStep));
141  const float step = max(params.contours.isoStep, (isoMax - isoMin) / 3);
142 
143 
144  for (float iso = isoMin; iso <= isoMax; iso += step) {
145  if (cached.palette) {
146  context.setColor(cached.palette.value()(iso), ColorFlag::LINE);
147  }
148 
149  const int f1 = int(v1 > iso);
150  const int f2 = int(v2 > iso);
151  const int f3 = int(v3 > iso);
152  const int f4 = int(v4 > iso);
153 
154  const Size flag = f1 << 3 | f2 << 2 | f3 << 1 | f4;
155  const Pixel edge = MS_TABLE[flag];
156  if (edge != Pixel(-1, -1)) {
157  const std::pair<Pixel, Pixel>& ps1 = MS_EDGE_TO_VTX[edge.x];
158  const std::pair<Pixel, Pixel>& ps2 = MS_EDGE_TO_VTX[edge.y];
159  const Pixel p11 = p + ps1.first;
160  const Pixel p12 = p + ps1.second;
161  const Pixel p21 = p + ps2.first;
162  const Pixel p22 = p + ps2.second;
163 
164  SPH_ASSERT((grid[p11] > iso) != (grid[p12] > iso));
165  SPH_ASSERT((grid[p21] > iso) != (grid[p22] > iso));
166 
167  const float rati1 = (grid[p11] - iso) / (grid[p11] - grid[p12]);
168  SPH_ASSERT(rati1 >= 0.f && rati1 <= 1.f, rati1);
169  const Coords c1 = lerp(Coords(p11), Coords(p12), rati1) * gridToPixel;
170 
171  const float rati2 = (grid[p21] - iso) / (grid[p21] - grid[p22]);
172  SPH_ASSERT(rati2 >= 0.f && rati2 <= 1.f, rati2);
173  const Coords c2 = lerp(Coords(p21), Coords(p22), rati2) * gridToPixel;
174  context.drawLine(c1, c2);
175 
176  const Coords labelCoord = (c1 + c2) * 0.5f;
177  if (Optional<Coords&> topmostCoord = labelMap.tryGet(iso)) {
178  if (labelCoord.y < topmostCoord->y && isCoordValid(labelMap, labelCoord)) {
179  topmostCoord.value() = labelCoord;
180  }
181  } else {
182  labelMap.insert(iso, labelCoord);
183  }
184  }
185  }
186  }
187  }
188 
189  if (params.contours.showLabels) {
190  for (const auto& isoAndCoord : labelMap) {
191  context.setFontSize(9);
192  if (cached.palette) {
193  context.setColor(cached.palette.value()(isoAndCoord.key), ColorFlag::TEXT);
194  }
195  context.drawText(isoAndCoord.value, TextAlign::TOP, std::to_wstring(int(isoAndCoord.key)));
196  }
197  }
198 
200  if (params.showKey) {
201  if (cached.palette) {
202  const Pixel origin(size.x - 50, 231);
204  if (params.particles.grayScale) {
205  palette =
206  cached.palette->transform([](const Rgba& color) { return Rgba(color.intensity()); });
207  } else {
208  palette = cached.palette.value();
209  }
210  drawPalette(context, origin, Pixel(30, 201), params.background.inverse(), palette);
211  }
212  }
213 
214  output.update(bitmap, context.getLabels(), true);
215 }
216 
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Defines projection transforming 3D particles onto 2D screen.
Object converting quantity values of particles into colors.
Renderer drawing iso-contours of specified quantity.
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
INLINE Float weight(const Vector &r1, const Vector &r2)
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
NAMESPACE_SPH_BEGIN constexpr INLINE T min(const T &f1, const T &f2)
Minimum & Maximum value.
Definition: MathBasic.h:15
INLINE T lerp(const T v1, const T v2, const TAmount amount)
Definition: MathUtils.h:341
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
void drawPalette(IRenderContext &context, const Pixel origin, const Pixel size, const Rgba &lineColor, const Palette &palette)
Renderer drawing individual particles as dots.
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
INLINE void parallelFor(IScheduler &scheduler, const Size from, const Size to, TFunctor &&functor)
Executes a functor concurrently from all available threads.
Definition: Scheduler.h:98
Key-value associative container.
INLINE Float getLength(const Vector &v)
Returns the length of the vector. Enabled only for vectors of floating-point precision.
Definition: Vector.h:579
BasicVector< Float > Vector
Definition: Vector.h:539
@ Y
Definition: Vector.h:23
@ X
Definition: Vector.h:22
Definition: Bitmap.h:17
void fill(const Type &value)
Definition: Bitmap.h:44
virtual bool isInitialized() const override
Checks if the renderer has been initialized.
virtual void render(const RenderParams &params, Statistics &stats, IRenderOutput &output) const override
Draws particles into the bitmap, given the data provided in initialize.
Optional< Palette > palette
virtual void initialize(const Storage &storage, const IColorizer &colorizer, const ICamera &camera) override
Prepares the objects for rendering and updates its data.
ContourRenderer(SharedPtr< IScheduler > scheduler, const GuiSettings &settings)
Cubic spline (M4) kernel.
Definition: Kernel.h:150
Container of key-value pairs.
Definition: FlatMap.h:19
void build(IScheduler &scheduler, ArrayView< const Vector > points)
Constructs the struct with an array of vectors.
virtual Size findAll(const Size index, const Float radius, Array< NeighbourRecord > &neighbours) const =0
Finds all neighbours within given radius from the point given by index.
Interface defining a camera or view, used by a renderer.
Definition: Camera.h:62
virtual Pixel getSize() const =0
Returns the current resolution of the camera.
virtual Optional< CameraRay > unproject(const Coords &coords) const =0
Returns a ray in particle coordinates corresponding to given coordinates in the image plane.
Interface for objects assigning colors to particles.
Definition: Colorizer.h:34
virtual Optional< Palette > getPalette() const =0
Returns recommended palette for drawing this colorizer.
virtual void update(const Bitmap< Rgba > &bitmap, Array< Label > &&labels, const bool isFinal)=0
May be called once after render finishes or multiple times for progressive renderers.
INLINE Float value(const Vector &r, const Float h) const noexcept
Definition: Kernel.h:26
Wrapper of type value of which may or may not be present.
Definition: Optional.h:23
Represents a color palette, used for mapping arbitrary number to a color.
Definition: Palette.h:25
virtual Array< IRenderOutput::Label > getLabels() const override
virtual void setColor(const Rgba &color, const Flags< ColorFlag > flags) override
Selects the color for one or more drawing modes.
virtual void drawText(const Coords p, const Flags< TextAlign > align, const std::string &s) override
virtual void setFontSize(const int newFontSize) override
virtual void drawLine(const Coords p1, const Coords p2) override
Draws a line connecting two points.
Definition: Color.h:8
Rgba inverse() const
Returns an inverse color.
Definition: Color.h:151
float intensity() const
Returns the average intensity of the color.
Definition: Color.h:115
static Rgba black()
Definition: Color.h:190
static Rgba white()
Definition: Color.h:194
static const Settings & getDefaults()
\brief Returns a reference to object containing default values of all settings.
Object holding various statistics about current run.
Definition: Statistics.h:22
Container storing all quantities used within the simulations.
Definition: Storage.h:230
Array< TValue > & getValue(const QuantityId key)
Retrieves a quantity values from the storage, given its key and value type.
Definition: Storage.cpp:191
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: UnorderedMap.h:51
INLINE Optional< TValue & > tryGet(const TKey &key)
Returns a reference to the value matching the given key, or NOTHING if no such value exists.
Definition: UnorderedMap.h:104
constexpr Size sum()
Definition: Multipole.h:31
AutoPtr< ISymmetricFinder > getFinder(const RunSettings &settings)
Definition: Factory.cpp:156
Definition: Point.h:115
Holds information about a neighbour particles.
Definition: Point.h:101
Parameters of the rendered image.
Definition: IRenderer.h:60
bool showLabels
Show numerical values of iso-lines.
Definition: IRenderer.h:155
Rgba background
Background color of the rendered image.
Definition: IRenderer.h:71
struct RenderParams::@33 particles
Parameters of the particle renderer.
AutoPtr< ICamera > camera
Camera used for rendering.
Definition: IRenderer.h:63
bool showKey
If true, a color palette and a distance scale is included in the image.
Definition: IRenderer.h:74
float isoStep
Step between subsequent iso-lines.
Definition: IRenderer.h:149
Size gridSize
Horizontal resolution of the grid.
Definition: IRenderer.h:152
struct RenderParams::@37 contours
bool grayScale
If true, the palette is converted to grayscale.
Definition: IRenderer.h:89