18 #include <GL/freeglut.h>
20 #include "vector_view.h"
28 VectorView::VectorView(
const char* title, WinGeom* wg)
41 VectorView::VectorView(
char* title, WinGeom* wg)
54 VectorView::~VectorView()
59 void VectorView::show(MeshFunctionSharedPtr<double> vsln)
61 if (vsln->get_num_components() < 2)
62 throw Hermes::Exceptions::Exception(
"The single-argument version of show() is only for vector-valued solutions.");
63 show(vsln, vsln, H2D_FN_VAL_0, H2D_FN_VAL_1);
66 void VectorView::show(MeshFunctionSharedPtr<double> xsln, MeshFunctionSharedPtr<double> ysln,
int xitem,
int yitem, MeshFunctionSharedPtr<double> xdisp, MeshFunctionSharedPtr<double> ydisp,
double dmult)
68 if (xsln !=
nullptr && ysln !=
nullptr && xsln == ysln)
69 this->warn(
"Identical solutions passed to the two-argument version of show(). Most likely this is a mistake.");
71 vec->set_displacement(xdisp, ydisp, dmult);
74 MeshFunctionSharedPtr<double> slns[2] = { xsln, ysln };
75 int items[2] = { xitem, yitem };
76 vec->process_solution(slns, items);
80 range_min = vec->get_min_value();
81 range_max = vec->get_max_value();
83 vec->calc_vertices_aabb(&vertices_min_x, &vertices_max_x, &vertices_min_y, &vertices_max_y);
95 static int n_vert(
int i) {
return (i + 1) % 3; }
96 static int p_vert(
int i) {
return (i + 2) % 3; }
98 void VectorView::set_mode(
int mode)
100 this->mode = mode % 3;
114 void VectorView::plot_arrow(
double x,
double y,
double xval,
double yval,
double max,
double min,
double gs)
117 glColor3f(0.0f, 0.0f, 0.0f);
119 glColor3f(0.5f, 0.5f, 0.5f);
122 double Real_mag = sqrt(sqr(xval) + sqr(yval));
123 double mag = Real_mag;
124 if (Real_mag > max) mag = max;
125 double length = mag / max * gs * length_coef;
126 double width = 0.1 * gs;
127 if (mode == 1) width *= 1.2;
128 double xnew = x + gs * xval * mag / (max * Real_mag) * length_coef;
129 double ynew = y - gs * yval * mag / (max * Real_mag) * length_coef;
131 if ((mag) / (max - min) < 1e-5)
133 glTranslated(x, y, 0.0);
136 glVertex2d(width, width);
137 glVertex2d(width, -width);
138 glVertex2d(-width, -width);
139 glVertex2d(-width, width);
146 glVertex2d(xnew, ynew);
149 glTranslated(x, y, 0.0);
150 glRotated(atan2(-yval, xval) * 180.0 / M_PI, 0.0, 0.0, 1.0);
152 glBegin(GL_TRIANGLES);
153 glVertex2d(length + 3 * width, 0.0);
154 glVertex2d(length - 2 * width, width);
155 glVertex2d(length - 2 * width, -width);
165 get_palette_color((mag - min) / (max - min), color);
166 glColor3f(color[0], color[1], color[2]);
168 if (mag / (max - min) < 1e-5)
171 glVertex2d(width, width);
172 glVertex2d(width, -width);
173 glVertex2d(-width, -width);
174 glVertex2d(-width, width);
181 glVertex2d(xnew, ynew);
184 glTranslated(x - 1, y, 0.0);
185 glRotated(atan2(-yval, xval) * 180.0 / M_PI, 0.0, 0.0, 1.0);
187 glBegin(GL_TRIANGLES);
188 glVertex2d(length + 3 * width, 0.0);
189 glVertex2d(length - 2 * width, width);
190 glVertex2d(length - 2 * width, -width);
198 void VectorView::draw_edges_2d()
200 glColor3f(0.5, 0.5, 0.5);
205 int& edge_marker = it.get_marker();
207 if (lines || edge_marker)
209 glVertex2d(transform_x(edge[0][0]), transform_y(edge[0][1]));
210 glVertex2d(transform_x(edge[1][0]), transform_y(edge[1][1]));
216 void VectorView::on_display()
218 set_ortho_projection();
219 glDisable(GL_LIGHTING);
220 glDisable(GL_DEPTH_TEST);
221 glDisable(GL_TEXTURE_1D);
222 glPolygonMode(GL_FRONT_AND_BACK, pmode ? GL_LINE : GL_FILL);
226 if (hexa) gt *= sqrt(3.0) / 2.0;
228 double max_length = 0.0;
234 double min = range_min, max = range_max;
235 if (range_auto) { min = vec->get_min_value(); max = vec->get_max_value(); }
236 double irange = 1.0 / (max - min);
238 if (fabs(min - max) < Hermes::HermesSqrtEpsilon) { irange = 1.0; min -= 0.5; }
242 glEnable(GL_TEXTURE_1D);
243 glBindTexture(GL_TEXTURE_1D, gl_pallete_tex_id);
244 glBegin(GL_TRIANGLES);
245 glColor3f(0.95f, 0.95f, 0.95f);
247 for (Vectorizer::Iterator<VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t> it = vec->triangles_begin(); !it.end; ++it)
249 VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t& triangle = it.get();
251 double mag = sqrt(sqr(triangle[0][2]) + sqr(triangle[0][3]));
252 glTexCoord2d((mag - min) * irange * tex_scale + tex_shift, 0.0);
253 glVertex2d(transform_x(triangle[0][0]), transform_y(triangle[0][1]));
255 double length = sqr(triangle[0][2]) + sqr(triangle[0][3]);
256 if (length > max_length)
259 mag = sqrt(sqr(triangle[1][2]) + sqr(triangle[1][3]));
260 glTexCoord2d((mag - min) * irange * tex_scale + tex_shift, 0.0);
261 glVertex2d(transform_x(triangle[1][0]), transform_y(triangle[1][1]));
263 length = sqr(triangle[1][2]) + sqr(triangle[1][3]);
264 if (length > max_length)
267 mag = sqrt(sqr(triangle[2][2]) + sqr(triangle[2][3]));
268 glTexCoord2d((mag - min) * irange * tex_scale + tex_shift, 0.0);
269 glVertex2d(transform_x(triangle[2][0]), transform_y(triangle[2][1]));
271 length = sqr(triangle[2][2]) + sqr(triangle[2][3]);
272 if (length > max_length)
276 max_length = sqrt(max_length);
278 glDisable(GL_TEXTURE_1D);
285 for (Vectorizer::Iterator<VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t> it = vec->triangles_begin(); !it.end; ++it)
287 VectorLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t& triangle = it.get();
290 int idx = -1, k, l1, l2, r2, r1, s;
292 double mr, ml, lx, rx, xval, yval;
294 double wh = output_height + gt, ww = output_width + gs;
296 double vert[3][4] = {
317 double tvert[3][2] = {
319 transform_x(triangle[0][0]),
320 transform_y(triangle[0][1])
323 transform_x(triangle[1][0]),
324 transform_y(triangle[1][1])
327 transform_x(triangle[2][0]),
328 transform_y(triangle[2][1])
332 if ((tvert[0][0] < -gs) && (tvert[1][0] < -gs) && (tvert[2][0] < -gs))
continue;
333 if ((tvert[0][0] > ww) && (tvert[1][0] > ww) && (tvert[2][0] > ww))
continue;
334 if ((tvert[0][1] < -gt) && (tvert[1][1] < -gt) && (tvert[2][1] < -gt))
continue;
335 if ((tvert[0][1] > wh) && (tvert[1][1] > wh) && (tvert[2][1] > wh))
continue;
338 for (k = 0; k < 3; k++)
340 if (tvert[k][1] < miny)
341 miny = tvert[idx = k][1];
348 double a[2], b[2], c[2], d[2];
349 for (
int n = 0; n < 2; n++)
351 a[n] = (tvert[l1][1] - tvert[l2][1])*(vert[r1][2 + n] - vert[r2][2 + n]) - (vert[l1][2 + n] - vert[l2][2 + n])*(tvert[r1][1] - tvert[r2][1]);
352 b[n] = (vert[l1][2 + n] - vert[l2][2 + n])*(tvert[r1][0] - tvert[r2][0]) - (tvert[l1][0] - tvert[l2][0])*(vert[r1][2 + n] - vert[r2][2 + n]);
353 c[n] = (tvert[l1][0] - tvert[l2][0])*(tvert[r1][1] - tvert[r2][1]) - (tvert[l1][1] - tvert[l2][1])*(tvert[r1][0] - tvert[r2][0]);
354 d[n] = -a[n] * tvert[l1][0] - b[n] * tvert[l1][1] - c[n] * vert[l1][2 + n];
355 a[n] /= c[n]; b[n] /= c[n]; d[n] /= c[n];
359 s = (int)ceil((tvert[l1][1] - gy) / gt);
361 bool shift = hexa && (s & 1);
364 if ((tvert[l1][1] == tvert[l2][1]) || (tvert[r1][1] == tvert[r2][1]))
366 if (tvert[l1][1] == tvert[l2][1])
371 else if (tvert[r1][1] == tvert[r2][1])
379 ml = (tvert[l1][0] - tvert[l2][0]) / (tvert[l1][1] - tvert[l2][1]);
380 mr = (tvert[r1][0] - tvert[r2][0]) / (tvert[r1][1] - tvert[r2][1]);
382 lx = tvert[l1][0] + ml * (lry - (tvert[l1][1]));
383 rx = tvert[r1][0] + mr * (lry - (tvert[r1][1]));
387 k = (int)floor(-lry / gt);
394 while (((lry < tvert[l2][1]) || (lry < tvert[r2][1])) && (lry < wh))
397 while (((lry <= tvert[l2][1]) && (lry <= tvert[r2][1])) && (lry < wh))
400 if (shift) gz -= 0.5*gs;
401 s = (int)ceil((lx - gz) / gs);
403 if (hexa) shift = !shift;
407 k = (int)floor(-x / gs);
411 while ((x < rx) && (x < ww))
414 xval = -a[0] * x - b[0] * lry - d[0];
415 yval = -a[1] * x - b[1] * lry - d[1];
416 plot_arrow(x, lry, xval, yval, max, min, gs);
425 if (lry >= tvert[l2][1])
428 ml = (tvert[l1][0] - tvert[l2][0]) / (tvert[l1][1] - tvert[l2][1]);
429 lx = tvert[l1][0] + ml * (lry - (tvert[l1][1]));
434 mr = (tvert[r1][0] - tvert[r2][0]) / (tvert[r1][1] - tvert[r2][1]);
435 rx = tvert[r1][0] + mr * (lry - (tvert[r1][1]));
445 void VectorView::on_mouse_move(
int x,
int y)
452 View::on_mouse_move(x, y);
455 void VectorView::on_key_down(
unsigned char key,
int x,
int y)
475 set_palette_filter(pal_filter != GL_LINEAR);
479 set_grid_type(!hexa);
484 if (mode > 2) mode = 0;
490 if (key ==
'*') length_coef *= 1.1;
else length_coef /= 1.1;
495 View::on_key_down(key, x, y);
500 const char* VectorView::get_help_text()
const
505 " Left mouse - pan\n"
506 " Right mouse - zoom\n"
507 " B - toggle view mode (type of arrows x no arrows)\n"
508 " * - extend arrows\n"
509 " / - shorten arrows\n"
510 " C - center image\n"
511 " F - toggle smooth palette\n"
512 " X - toggle hexagonal grid\n"
513 " H - render high-quality frame\n"
515 " P - cycle palettes\n"
516 " S - save screenshot\n"
Common definitions for Hermes2D.
LinearizerMultidimensional< VectorLinearizerDataDimensions< LINEARIZER_DATA_TYPE > > Vectorizer
Linearizer for vector cases - historically called Vectorizer.
Typedefs used throughout the Linearizer functionality.
void set_criterion(LinearizerCriterion criterion)
Abstract class for criterion according to which the linearizer stops dividing elements at some point ...