Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
HMPlane.cpp
1#include "HMPlane.h"
2
3//#include "Renderer.h"
4
5//#include "VertexBuffer.h"
6//#include "VertexBufferLayout.h"
7//#include "IndexBuffer.h"
8//#include "VertexArray.h"
9//#include "Shader.h"
10
11//#include "OpenGLText.h"
12
13#include <wx/msgdlg.h>
14#include <wx/dc.h>
15
16//HMPlane::HMPlane(Shader* shader, Shader* labelShader, const float& width, const float& height, const float limits[2])
17// : m_width(width), m_height(height), m_shader(shader), m_labelShader(labelShader)
18//{
19// // Fill mesh coords
20// for (auto accHeight = 0; accHeight <= m_height + m_meshSize; accHeight += m_meshSize) {
21// std::vector<BufferMeshCoords*> line;
22// for (auto accWidth = 0; accWidth <= m_width + m_meshSize; accWidth += m_meshSize) {
23// auto* bmc = new BufferMeshCoords;
24// bmc->x = accWidth;
25// bmc->y = accHeight;
26// bmc->z = 0.0f;
27// line.emplace_back(bmc);
28//
29// if (accHeight < 0.1f) m_meshTickX++;
30// }
31// m_meshTickY++;
32// m_coords.emplace_back(line);
33// }
34//
35//
36// m_limits[0] = limits[0];
37// m_limits[1] = limits[1];
38//
39// FillCoordsBuffer();
40// FillIndexBuffer();
41// BindOpenGLBuffers();
42//
43// CreateLabel();
44//}
45
46HMPlane::HMPlane(const double& width, const double& height, const double limits[2]) : m_width(width), m_height(height)
47{
48 // Fill mesh coords
49 for (auto accHeight = 0; accHeight <= m_height + m_meshSize; accHeight += m_meshSize) {
50 std::vector<BufferMeshCoords*> line;
51 for (auto accWidth = 0; accWidth <= m_width + m_meshSize; accWidth += m_meshSize) {
52 auto* bmc = new BufferMeshCoords;
53 bmc->x = accWidth;
54 bmc->y = accHeight;
55 bmc->z = 0.0f;
56 line.emplace_back(bmc);
57
58 if (accHeight < 0.1f) m_meshTickX++;
59 }
60 m_meshTickY++;
61 m_coords.emplace_back(line);
62 }
63 m_coordsT.resize(m_coords[0].size());
64 for (auto& line : m_coordsT) line.resize(m_coords.size());
65 for (size_t i = 0; i < m_coords.size(); ++i) {
66 const auto& line = m_coords[i];
67 for (size_t j = 0; j < line.size(); ++j) {
68 m_coordsT[j][i] = m_coords[i][j];
69 }
70 }
71
72 m_limits[0] = limits[0];
73 m_limits[1] = limits[1];
74}
75
76HMPlane::~HMPlane()
77{
78 //delete m_ib;
79 //delete m_vb;
80 //delete m_layout;
81 //delete m_va;
82 //
83 //delete m_ibL;
84 //delete m_vbL;
85 //delete m_layoutL;
86 //delete m_vaL;
87 //
88 //for (auto glText : m_glTexts) {
89 // delete glText;
90 //}
91 //m_glTexts.clear();
92
93 for (const auto& line : m_coords) {
94 for (auto* bmv : line) {
95 delete bmv;
96 }
97 }
98 m_coords.clear();
99}
100
101//void HMPlane::Draw(const Renderer& renderer, const glm::mat4& projectionViewMatrix) const
102//{
103// //const glm::mat4 mvp = projectionViewMatrix * glm::translate(glm::mat4(1.0f), glm::vec3(m_width / 2.0f, m_height / 2.0f, 0.0f));
104// const glm::mat4 mvp = projectionViewMatrix;
105//
106// m_shader->Bind();
107// //m_shader->SetUniform1f("u_scale", m_scale);
108// m_shader->SetUniformMatrix4fv("u_mvpMatrix", mvp);
109//
110// m_va->UpdateBuffer(*m_vb, m_bufferCoords.data(), m_bufferCoords.size() * sizeof(float));
111//
112// //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
113// //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
114// renderer.Draw(*m_va, *m_ib, *m_shader);
115//
116// // Unbind
117// m_va->Unbind();
118// m_vb->Unbind();
119// m_ib->Unbind();
120//
121// m_shader->Unbind();
122//}
123
124void HMPlane::DrawDC(wxGraphicsContext* gc) const
125{
126 if (m_isClear) return;
127 gc->SetPen(*wxTRANSPARENT_PEN);
128 for (const auto& line : m_coords) {
129 wxGraphicsGradientStops gStops;
130 gStops.Add(wxColor(255, 255, 255), 0);
131 for (const BufferMeshCoords* coords : line) {
132 gStops.Add(VoltToColour(coords->z), coords->x / (m_width));
133 }
134 wxGraphicsBrush brush = gc->CreateLinearGradientBrush(0, line[0]->y, m_width, line[0]->y, gStops);
135 gc->SetBrush(brush);
136 gc->DrawRectangle(0, line[0]->y, m_width, m_meshSize);
137 }
138
139 for (const auto& line : m_coordsT) {
140 wxGraphicsGradientStops gStops;
141 gStops.Add(wxColor(255, 255, 255), 0);
142 for (const BufferMeshCoords* coords : line) {
143 gStops.Add(VoltToColour(coords->z), coords->y / (m_height));
144 }
145 wxGraphicsBrush brush = gc->CreateLinearGradientBrush(line[0]->x, 0, line[0]->x, m_height, gStops);
146 gc->SetBrush(brush);
147 gc->DrawRectangle(line[0]->x, 0, m_meshSize, m_height);
148 }
149}
150
151void HMPlane::DrawDC(wxDC& dc) const
152{
153 if (m_isClear) return;
154 dc.SetPen(*wxTRANSPARENT_PEN);
155 //for (const auto& line : m_coords)
156 //{
157 // int y = wxRound(line[0]->y);
158 //
159 // wxColour prevColour(255, 255, 255);
160 // int prevX = 0;
161 //
162 // for (size_t i = 0; i < line.size(); ++i)
163 // {
164 // const BufferMeshCoords* coords = line[i];
165 //
166 // int currentX = wxRound(coords->x);
167 // wxColour currentColour = VoltToColour(coords->z);
168 //
169 // int width = currentX - prevX;
170 //
171 // if (width > 0)
172 // {
173 // wxRect rect(prevX, y, width, m_meshSize);
174 //
175 // dc.GradientFillLinear(rect,
176 // prevColour,
177 // currentColour,
178 // wxEAST);
179 // }
180 //
181 // prevX = currentX;
182 // prevColour = currentColour;
183 // }
184 //}
185
186 for (const auto& line : m_coords)
187 {
188 int y = wxRound(line[0]->y);
189
190 struct Stop {
191 double pos;
192 wxColour color;
193 };
194
195 std::vector<Stop> stops;
196
197 stops.push_back({ 0.0, wxColour(255,255,255) });
198
199 for (const BufferMeshCoords* coords : line)
200 {
201 double pos = coords->x / m_width;
202 stops.push_back({ pos, VoltToColour(coords->z) });
203 }
204
205 auto ColorAt = [&](double t) -> wxColour
206 {
207 if (t <= stops.front().pos)
208 return stops.front().color;
209
210 if (t >= stops.back().pos)
211 return stops.back().color;
212
213 for (size_t i = 0; i < stops.size() - 1; ++i)
214 {
215 if (t >= stops[i].pos && t <= stops[i + 1].pos)
216 {
217 double localT =
218 (t - stops[i].pos) /
219 (stops[i + 1].pos - stops[i].pos);
220
221 const wxColour& c1 = stops[i].color;
222 const wxColour& c2 = stops[i + 1].color;
223
224 return wxColour(
225 c1.Red() + localT * (c2.Red() - c1.Red()),
226 c1.Green() + localT * (c2.Green() - c1.Green()),
227 c1.Blue() + localT * (c2.Blue() - c1.Blue())
228 );
229 }
230 }
231
232 return stops.back().color;
233 };
234
235 for (size_t i = 0; i < stops.size() - 1; ++i)
236 {
237 int x1 = wxRound(stops[i].pos * m_width);
238 int x2 = wxRound(stops[i + 1].pos * m_width);
239
240 if (x2 <= x1)
241 continue;
242
243 double t1 = stops[i].pos;
244 double t2 = stops[i + 1].pos;
245
246 wxColour c1 = ColorAt(t1);
247 wxColour c2 = ColorAt(t2);
248
249 wxRect rect(x1, y, x2 - x1, m_meshSize);
250
251 dc.GradientFillLinear(rect, c1, c2, wxEAST);
252 }
253 }
254}
255
256//void HMPlane::DrawLabel(const Renderer& renderer, const glm::mat4& projectionViewMatrix, const float& x, const float& y) const
257//{
258// const glm::mat4 mvp = projectionViewMatrix * glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f));
259// //const glm::mat4 mvp = projectionViewMatrix;
260//
261// m_labelShader->Bind();
262// //m_shader->SetUniform1f("u_scale", m_scale);
263// m_labelShader->SetUniformMatrix4fv("u_mvpMatrix", mvp);
264// m_labelShader->SetUniform4f("u_offset", x, y, m_width, m_height);
265//
266// //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
267// //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
268// renderer.Draw(*m_vaL, *m_ibL, *m_labelShader);
269//
270// // Unbind
271// m_vaL->Unbind();
272// m_vbL->Unbind();
273// m_ibL->Unbind();
274//
275// m_labelShader->Unbind();
276//
277// glColor4d(0.0, 0.0, 0.0, 1.0);
278// m_glTexts[0]->Draw(wxPoint2DDouble(x + 35.0 + m_glTexts[0]->GetWidth() / 2.0, y));
279// m_glTexts[1]->Draw(wxPoint2DDouble(x + 35.0 + m_glTexts[1]->GetWidth() / 2.0, y + 150.0));
280// m_glTexts[2]->Draw(wxPoint2DDouble(x + 35.0 + m_glTexts[2]->GetWidth() / 2.0, y + 300.0));
281//}
282
283void HMPlane::DrawLabelDC(wxGraphicsContext* gc) const
284{
285 wxGraphicsMatrix identityMatrix = gc->GetTransform();
286 identityMatrix.Set();
287 gc->PushState();
288 gc->SetTransform(identityMatrix);
289 gc->SetPen(*wxBLACK_PEN);
290 wxGraphicsGradientStops gStops;
291 gStops.Add(VoltToColour(-1.0, 210), 0.0);
292 gStops.Add(VoltToColour(-0.5, 210), 0.25);
293 gStops.Add(VoltToColour(0.0, 210), 0.5);
294 gStops.Add(VoltToColour(0.5, 210), 0.75);
295 gStops.Add(VoltToColour(1.0, 210), 1.0);
296 wxGraphicsBrush brush = gc->CreateLinearGradientBrush(30, m_height - 45, 330, m_height - 45, gStops);
297 gc->SetBrush(brush);
298
299 gc->DrawRectangle(30, m_height - 45, 300, 30);
300
301 wxPoint2DDouble lines[10];
302 lines[0] = wxPoint2DDouble(30, m_height - 50);
303 lines[1] = wxPoint2DDouble(30, m_height - 40);
304 lines[2] = wxPoint2DDouble(105, m_height - 50);
305 lines[3] = wxPoint2DDouble(105, m_height - 40);
306 lines[4] = wxPoint2DDouble(180, m_height - 50);
307 lines[5] = wxPoint2DDouble(180, m_height - 40);
308 lines[6] = wxPoint2DDouble(255, m_height - 50);
309 lines[7] = wxPoint2DDouble(255, m_height - 40);
310 lines[8] = wxPoint2DDouble(330, m_height - 50);
311 lines[9] = wxPoint2DDouble(330, m_height - 40);
312 //gc->DrawLines(10, lines, wxWINDING_RULE);
313 for (size_t i = 0; i < 10; i += 2) {
314 gc->StrokeLine(lines[i].m_x, lines[i].m_y, lines[i + 1].m_x, lines[i + 1].m_y);
315 }
316
317 gc->SetFont(gc->CreateFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)));
318 gc->DrawText(_("Voltage (p.u.)"), 30, m_height - 15);
319 wxString voltageText = "";
320 double textWidth, textHeight;
321 voltageText = wxString::Format("%.3f", m_limits[0]);
322 gc->GetTextExtent(voltageText, &textWidth, &textHeight);
323 gc->DrawText(voltageText, 330 - textWidth / 2, m_height - 65);
324 voltageText = wxString::Format("%.3f", m_limits[0] * 0.75 + m_limits[1] * 0.25);
325 gc->GetTextExtent(voltageText, &textWidth, &textHeight);
326 gc->DrawText(voltageText, 255 - textWidth / 2, m_height - 65);
327 voltageText = wxString::Format("%.3f", m_limits[0] * 0.5 + m_limits[1] * 0.5);
328 gc->GetTextExtent(voltageText, &textWidth, &textHeight);
329 gc->DrawText(voltageText, 180 - textWidth / 2, m_height - 65);
330 voltageText = wxString::Format("%.3f", m_limits[0] * 0.25 + m_limits[1] * 0.75);
331 gc->GetTextExtent(voltageText, &textWidth, &textHeight);
332 gc->DrawText(voltageText, 105 - textWidth / 2, m_height - 65);
333 voltageText = wxString::Format("%.3f", m_limits[1]);
334 gc->GetTextExtent(voltageText, &textWidth, &textHeight);
335 gc->DrawText(voltageText, 30 - textWidth / 2, m_height - 65);
336
337 gc->PopState();
338}
339
340void HMPlane::DrawLabelDC(wxDC& dc) const
341{
342 dc.SetUserScale(1.0, 1.0);
343 dc.SetDeviceOrigin(0, 0);
344
345 dc.SetPen(*wxBLACK_PEN);
346 int xStart = 30;
347 int yStart = m_height - 45;
348 int width = 300;
349 int height = 30;
350
351 struct Stop {
352 double pos;
353 wxColour color;
354 };
355
356 std::vector<Stop> stops = {
357 {0.00, VoltToColour(-1.0, 210)},
358 {0.25, VoltToColour(-0.5, 210)},
359 {0.50, VoltToColour(0.0, 210)},
360 {0.75, VoltToColour(0.5, 210)},
361 {1.00, VoltToColour(1.0, 210)}
362 };
363
364 auto ColorAt = [&](double t) -> wxColour
365 {
366 for (size_t i = 0; i < stops.size() - 1; ++i)
367 {
368 if (t >= stops[i].pos && t <= stops[i + 1].pos)
369 {
370 double localT =
371 (t - stops[i].pos) /
372 (stops[i + 1].pos - stops[i].pos);
373
374 const wxColour& c1 = stops[i].color;
375 const wxColour& c2 = stops[i + 1].color;
376
377 return wxColour(
378 c1.Red() + localT * (c2.Red() - c1.Red()),
379 c1.Green() + localT * (c2.Green() - c1.Green()),
380 c1.Blue() + localT * (c2.Blue() - c1.Blue())
381 );
382 }
383 }
384 return stops.back().color;
385 };
386
387 for (int x = 0; x < width; ++x)
388 {
389 double t = (double)x / width;
390
391 wxColour c = ColorAt(t);
392
393 dc.SetPen(wxPen(c));
394 dc.DrawLine(xStart + x,
395 yStart,
396 xStart + x,
397 yStart + height);
398 }
399
400 dc.SetPen(*wxBLACK_PEN);
401 dc.SetBrush(*wxTRANSPARENT_BRUSH);
402 dc.DrawRectangle(xStart, yStart, width, height);
403 wxPoint2DDouble lines[10];
404 lines[0] = wxPoint2DDouble(30, m_height - 50);
405 lines[1] = wxPoint2DDouble(30, m_height - 40);
406 lines[2] = wxPoint2DDouble(105, m_height - 50);
407 lines[3] = wxPoint2DDouble(105, m_height - 40);
408 lines[4] = wxPoint2DDouble(180, m_height - 50);
409 lines[5] = wxPoint2DDouble(180, m_height - 40);
410 lines[6] = wxPoint2DDouble(255, m_height - 50);
411 lines[7] = wxPoint2DDouble(255, m_height - 40);
412 lines[8] = wxPoint2DDouble(330, m_height - 50);
413 lines[9] = wxPoint2DDouble(330, m_height - 40);
414 //gc->DrawLines(10, lines, wxWINDING_RULE);
415 for (size_t i = 0; i < 10; i += 2) {
416 dc.DrawLine(lines[i].m_x, lines[i].m_y, lines[i + 1].m_x, lines[i + 1].m_y);
417 }
418
419 dc.SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
420 dc.DrawText(_("Voltage (p.u.)"), 30, m_height - 15);
421 wxString voltageText = "";
422 int textWidth, textHeight;
423 voltageText = wxString::Format("%.3f", m_limits[0]);
424 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
425 dc.DrawText(voltageText, 330 - textWidth / 2, m_height - 65);
426 voltageText = wxString::Format("%.3f", m_limits[0] * 0.75 + m_limits[1] * 0.25);
427 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
428 dc.DrawText(voltageText, 255 - textWidth / 2, m_height - 65);
429 voltageText = wxString::Format("%.3f", m_limits[0] * 0.5 + m_limits[1] * 0.5);
430 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
431 dc.DrawText(voltageText, 180 - textWidth / 2, m_height - 65);
432 voltageText = wxString::Format("%.3f", m_limits[0] * 0.25 + m_limits[1] * 0.75);
433 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
434 dc.DrawText(voltageText, 105 - textWidth / 2, m_height - 65);
435 voltageText = wxString::Format("%.3f", m_limits[1]);
436 dc.GetTextExtent(voltageText, &textWidth, &textHeight);
437 dc.DrawText(voltageText, 30 - textWidth / 2, m_height - 65);
438}
439
440void HMPlane::SetLabelLimits(const double& min, const double& max)
441{
442 m_limits[0] = max;
443 m_limits[1] = min;
444
445 //if (m_glTexts.size() > 0) {
446 // m_glTexts[0]->SetText(wxString::Format("%.2f p.u.", m_limits[0]));
447 // m_glTexts[1]->SetText(wxString::Format("%.2f p.u.", (m_limits[0] + m_limits[1]) / 2.0f));
448 // m_glTexts[2]->SetText(wxString::Format("%.2f p.u.", m_limits[1]));
449 //}
450}
451
452void HMPlane::SetRectSlope(const wxRect2DDouble& rect, const double& angle, const double& depth)
453{
454 for (const auto& line : m_coords) {
455 for (auto* coord : line) {
456 wxPoint2DDouble pt(coord->x, coord->y);
457 if (std::abs(angle) > 0.01) {
458
459 wxPoint2DDouble rotPt;
460 rotPt.m_x = cos(angle) * (pt.m_x - rect.GetCentre().m_x) + sin(angle) * (pt.m_y - rect.GetCentre().m_y) + rect.GetCentre().m_x;
461 rotPt.m_y = sin(angle) * (pt.m_x - rect.GetCentre().m_x) - cos(angle) * (pt.m_y - rect.GetCentre().m_y) + rect.GetCentre().m_y;
462
463 pt = rotPt;
464 }
465 if (rect.Contains(pt)) {
466 coord->z += depth;
467 if (coord->z > 1.0f) coord->z = 1.0f;
468 if (coord->z < -1.0f) coord->z = -1.0f;
469 }
470
471 }
472 }
473 m_isClear = false;
474 //FillCoordsBuffer();
475 //SmoothPlane();
476}
477
478void HMPlane::Resize(const double& width, const double& height)
479{
480 //Clear();
481 m_width = width;
482 m_height = height;
483 m_meshTickX = 0;
484 m_meshTickY = 0;
485
486 for (const auto& line : m_coords) {
487 for (auto* bmv : line) {
488 delete bmv;
489 }
490 }
491 m_coords.clear();
492
493 // Fill mesh coords
494 for (auto accHeight = 0; accHeight < m_height + m_meshSize; accHeight += m_meshSize) {
495 std::vector<BufferMeshCoords*> line;
496 for (auto accWidth = 0; accWidth < m_width + m_meshSize; accWidth += m_meshSize) {
497 auto* bmc = new BufferMeshCoords;
498 bmc->x = accWidth;
499 bmc->y = accHeight;
500 bmc->z = 0.0f;
501 line.emplace_back(bmc);
502
503 if (accHeight < 0.1f) m_meshTickX++;
504 }
505 m_meshTickY++;
506 m_coords.emplace_back(line);
507 }
508 FillCoordsBuffer();
509 //FillIndexBuffer();
510
511 //BindOpenGLBuffers();
512
513 //m_va->Bind();
514 //m_vb->Bind();
515 //
516 //delete m_ib;
517 //m_ib = new IndexBuffer(m_indexBuffer.data(), m_indexBuffer.size());
518 //m_ib->Unbind();
519 m_isClear = false;
520}
521
522void HMPlane::ResizeDC(const double& width, const double& height)
523{
524 m_width = width;
525 m_height = height;
526 m_meshTickX = 0;
527 m_meshTickY = 0;
528
529 for (const auto& line : m_coords) {
530 for (auto* bmv : line) {
531 delete bmv;
532 }
533 }
534 m_coords.clear();
535 m_coordsT.clear();
536
537 // Fill mesh coords
538 for (auto accHeight = 0; accHeight < m_height + m_meshSize; accHeight += m_meshSize) {
539 std::vector<BufferMeshCoords*> line;
540 for (auto accWidth = 0; accWidth < m_width + m_meshSize; accWidth += m_meshSize) {
541 auto* bmc = new BufferMeshCoords;
542 bmc->x = accWidth;
543 bmc->y = accHeight;
544 bmc->z = 0.0f;
545 line.emplace_back(bmc);
546
547 if (accHeight < 0.1f) m_meshTickX++;
548 }
549 m_meshTickY++;
550 m_coords.emplace_back(line);
551 }
552 m_coordsT.resize(m_coords[0].size());
553 for (auto& line : m_coordsT) line.resize(m_coords.size());
554 for (size_t i = 0; i < m_coords.size(); ++i) {
555 const auto& line = m_coords[i];
556 for (size_t j = 0; j < line.size(); ++j) {
557 m_coordsT[j][i] = m_coords[i][j];
558 }
559 }
560
561 m_isClear = false;
562}
563
564void HMPlane::SmoothPlane(const unsigned int& iterations)
565{
566 const int maxTickX = static_cast<int>(m_meshTickX);
567 const int maxTickY = static_cast<int>(m_meshTickY);
568
569 std::vector< std::vector<BufferMeshCoords> > tmpCoords;
570 for (const auto& line : m_coords) {
571 std::vector<BufferMeshCoords> tmpCoordsLine;
572 for (auto* bmv : line) {
573 tmpCoordsLine.push_back(*bmv);
574 }
575 tmpCoords.push_back(tmpCoordsLine);
576 }
577
578 //Mean Blur
579 //for (int i = 0; i < maxTick; ++i) {
580 // for (int j = 0; j < maxTick; ++j) {
581 // // Get the 8 neighbors and smooth z
582 // float mid = 0.0f;
583 // float div = 0.0f;
584 //
585 // for (int ii = i - 1; ii <= i + 1; ++ii) {
586 // for (int jj = j - 1; jj <= j + 1; ++jj) {
587 //
588 // if (ii >= 0 && ii < maxTick && jj >= 0 && jj < maxTick) {
589 // mid += tmpCoords[ii][jj].z;
590 // div += 1.0;
591 // }
592 // }
593 // }
594 // m_coords[i][j]->z = mid / div;
595 // }
596 //}
597
598 // Gaussian Blur
599 float gaussianKernel[5][5] =
600 {
601 {1.0f / 256.0f, 4.0f / 256.0f, 6 / 256.0f, 4.0f / 256, 1.0f / 256.0f},
602 {4.0f / 256.0f, 16.0f / 256.0f, 24 / 256.0f, 16.0f / 256, 4.0f / 256.0f},
603 {6.0f / 256.0f, 24.0f / 256.0f, 36 / 256.0f, 24.0f / 256, 6.0f / 256.0f},
604 {4.0f / 256.0f, 16.0f / 256.0f, 24 / 256.0f, 16.0f / 256, 4.0f / 256.0f},
605 {1.0f / 256.0f, 4.0f / 256.0f, 6 / 256.0f, 4.0f / 256, 1.0f / 256.0f}
606 };
607
608 for (size_t it = 0; it < iterations; ++it) {
609 for (size_t i = 0; i < m_meshTickY; ++i) {
610 for (size_t j = 0; j < m_meshTickX; ++j) {
611 // Get the 24 neighbors and smooth z
612 float value = 0.0f;
613
614 for (size_t ii = i - 2; ii <= i + 2; ++ii) {
615 for (size_t jj = j - 2; jj <= j + 2; ++jj) {
616
617 if (ii >= 0 && ii < m_meshTickY && jj >= 0 && jj < m_meshTickX) {
618 value += tmpCoords[ii][jj].z * gaussianKernel[ii - i + 2][jj - j + 2];
619 }
620 }
621 }
622 m_coords[i][j]->z = value;
623 }
624 }
625 if (it < iterations - 1) {
626 for (size_t i = 0; i < m_meshTickY; ++i) {
627 for (size_t j = 0; j < m_meshTickX; ++j) {
628 tmpCoords[i][j].z = m_coords[i][j]->z;
629 }
630 }
631 }
632 }
633
634 FillCoordsBuffer();
635 m_isClear = false;
636}
637
638void HMPlane::Clear()
639{
640 if (!m_isClear) {
641 for (const auto& line : m_coords) {
642 for (auto* bmv : line) {
643 bmv->z = 0.0f;
644 }
645 }
646 FillCoordsBuffer();
647 m_isClear = true;
648 }
649}
650
651void HMPlane::FillCoordsBuffer()
652{
653 m_bufferCoords.clear();
654
655 for (const auto& line : m_coords) {
656 for (auto* bmv : line) {
657 m_bufferCoords.push_back(bmv->x);
658 m_bufferCoords.push_back(bmv->y);
659 m_bufferCoords.push_back(bmv->z);
660 }
661 }
662}
663
664//void HMPlane::FillIndexBuffer()
665//{
666// m_indexBuffer.clear();
667// for (auto i = 0; i < m_meshTickY - 1; ++i) {
668// for (auto j = 0; j < m_meshTickX - 1; ++j) {
669// m_indexBuffer.push_back(i * m_meshTickX + j);
670// m_indexBuffer.push_back(i * m_meshTickX + j + 1);
671// m_indexBuffer.push_back((i + 1) * m_meshTickX + j + 1);
672// m_indexBuffer.push_back(i * m_meshTickX + j);
673// m_indexBuffer.push_back((i + 1) * m_meshTickX + j);
674// m_indexBuffer.push_back((i + 1) * m_meshTickX + j + 1);
675// }
676// }
677//}
678
679//void HMPlane::BindOpenGLBuffers()
680//{
681// delete m_va;
682// delete m_vb;
683// delete m_ib;
684// // Generate vertex array (this will bind vertex buffer with its layout)
685// m_va = new VertexArray();
686//
687// // Generate vertex buffer
688// m_vb = new VertexBuffer(m_bufferCoords.data(), m_bufferCoords.size() * sizeof(float), GL_DYNAMIC_DRAW);
689//
690// m_layout = new VertexBufferLayout();
691// m_layout->Push<float>(3); // 3 = each triplet from array set the coords -> [x1, y1, z1, x2, y2, z2, ...]
692// m_va->AddBuffer(*m_vb, *m_layout); // Add buffer and bind vertex array
693//
694// // Set index buffer
695// m_ib = new IndexBuffer(m_indexBuffer.data(), m_indexBuffer.size());
696//
697// // Unbind
698// m_va->Unbind();
699// m_vb->Unbind();
700// m_ib->Unbind();
701//}
702
703//void HMPlane::CreateLabel()
704//{
705// float vertexBufferLabel[4 * 3] =
706// {
707// 0.0f, 0.0f, 1.0f,
708// 30.0f, 0.0f, 1.0f,
709// 0.0f, 300.0f, -1.0f,
710// 30.0f, 300.0f, -1.0f
711// };
712// std::copy(vertexBufferLabel, vertexBufferLabel + 3 * 4, m_vertexBufferLabel);
713//
714// unsigned int indexBufferLabel[6] =
715// {
716// 0, 1, 2,
717// 1, 2, 3
718// };
719// std::copy(indexBufferLabel, indexBufferLabel + 6, m_indexBufferLabel);
720//
721// delete m_vaL;
722// delete m_vbL;
723// delete m_ibL;
724// // Generate vertex array (this will bind vertex buffer with its layout)
725// m_vaL = new VertexArray();
726//
727// // Generate vertex buffer
728// m_vbL = new VertexBuffer(m_vertexBufferLabel, 4 * 3 * sizeof(float), GL_STATIC_DRAW);
729//
730// m_layoutL = new VertexBufferLayout();
731// m_layoutL->Push<float>(3); // 3 = each triplet from array set the coords -> [x1, y1, z1, x2, y2, z2, ...]
732// m_vaL->AddBuffer(*m_vbL, *m_layoutL); // Add buffer and bind vertex array
733//
734// // Set index buffer
735// m_ibL = new IndexBuffer(m_indexBufferLabel, 6);
736//
737// // Unbind
738// m_vaL->Unbind();
739// m_vbL->Unbind();
740// m_ibL->Unbind();
741//
742// m_glTexts.emplace_back(new OpenGLText(wxString::Format("%.2f p.u.", m_limits[0])));
743// m_glTexts.emplace_back(new OpenGLText(wxString::Format("%.2f p.u.", (m_limits[0] + m_limits[1]) / 2.0)));
744// m_glTexts.emplace_back(new OpenGLText(wxString::Format("%.2f p.u.", m_limits[1])));
745//}
746
747wxColor HMPlane::VoltToColour(double volt, int alpha) const
748{
749 //int red = 255 + 255 * (volt < 0 ? volt : 0);
750 //int green = 255;
751 //int blue = 255 - 255 * (volt >= 0 ? volt : 0);
752 //int red = volt >= 0 ? 255 : 255 - 255 * (std::abs(volt));
753 //int green = 255 - 205 * (std::abs(volt));
754 //int blue = volt <= 0 ? 255 : 255 - 255 * (std::abs(volt));
755 int red = 255, green = 255, blue = 255;
756 if (volt <= -0.5) {
757 red = -100 * volt - 50;
758 green = 200 * volt + 300;
759 blue = 255;
760 }
761 else if (volt > -0.5 && volt < 0) {
762 red = 510 * volt + 255;
763 green = 110 * volt + 255;
764 blue = 255;
765 }
766 else if (volt >= 0.0 && volt < 0.5) {
767 red = 255;
768 green = -110 * volt + 255;
769 blue = -510 * volt + 255;
770 }
771 else if (volt >= 0.5) {
772 red = 255;
773 green = -200 * volt + 300;
774 blue = 100 * volt - 50;
775 }
776 return wxColor(red, green, blue, alpha);
777}