19 #include <GL/freeglut.h>
26 #define GL_BUFFER_OFFSET(i) ((char *)nullptr + (i))
29 #define MIN_CONT_STEP 1.0E-2
30 #define CONT_CHANGE 1.0E-2
31 #define D3DV_SCALE_STEP_COEF 1.1
43 void ScalarView::init()
46 pmode = mode3d =
false;
67 ScalarView::ScalarView(
const char* title, WinGeom* wg) :
70 show_element_info(false)
75 ScalarView::ScalarView(WinGeom* wg) :
76 View(
"ScalarView", wg),
78 show_element_info(false)
84 ScalarView::ScalarView(
char* title, WinGeom* wg) :
87 show_element_info(false)
92 ScalarView::~ScalarView()
97 void ScalarView::on_close()
99 if (element_id_widget != 0)
101 glDeleteLists(element_id_widget, 1);
102 element_id_widget = 0;
109 void ScalarView::show(MeshFunctionSharedPtr<double> sln,
int item, MeshFunctionSharedPtr<double> xdisp, MeshFunctionSharedPtr<double> ydisp,
double dmult)
112 Element* active_element = sln->get_active_element();
115 lin->set_max_absolute_value(std::max(fabs(range_min), fabs(range_max)));
117 lin->set_displacement(xdisp, ydisp, dmult);
120 lin->process_solution(sln, item);
125 init_element_info(sln->get_mesh());
141 if (
dynamic_cast<Solution<double>*
>(sln.get()) !=
nullptr)
142 if (active_element !=
nullptr)
145 if (active_element->active)
146 sln->set_active_element(active_element);
149 void ScalarView::show_linearizer_data(
double eps,
int item)
163 void ScalarView::update_mesh_info()
166 double vert_min = lin->get_min_value();
167 double vert_max = lin->get_max_value();
170 if ((vert_max - vert_min) < Hermes::HermesEpsilon)
178 range_min = vert_min;
179 range_max = vert_max;
182 if (fabs(range_max - range_min) < Hermes::HermesEpsilon)
185 value_irange = 1.0 / (range_max - range_min);
188 lin->calc_vertices_aabb(&vertices_min_x, &vertices_max_x, &vertices_min_y, &vertices_max_y);
191 value_range_avg = 0.0;
196 if (vertex[2] > range_max)
197 value_range_avg += range_max;
198 else if (vertex[2] < range_min)
199 value_range_avg += range_min;
201 value_range_avg += vertex[2];
204 value_range_avg /= lin->get_vertex_count();
208 void ScalarView::init_element_info(MeshSharedPtr mesh)
211 element_infos.clear();
214 element_infos.reserve(mesh->get_num_active_elements());
218 for_all_active_elements(element, mesh)
220 double sum_x = 0.0, sum_y = 0.0;
221 double max_x, max_y, min_x, min_y;
222 max_x = min_x = element->
vn[0]->
x;
223 max_y = min_y = element->
vn[0]->y;
224 for (
unsigned int i = 0; i < element->get_nvert(); i++)
226 sum_x += element->
vn[i]->
x;
227 sum_y += element->
vn[i]->y;
229 if (element->
vn[i]->
x > max_x)
230 max_x = element->
vn[i]->
x;
231 if (element->
vn[i]->
x < min_x)
232 min_x = element->
vn[i]->
x;
233 if (element->
vn[i]->y > max_y)
234 max_y = element->
vn[i]->y;
235 if (element->
vn[i]->y < min_y)
236 min_y = element->
vn[i]->y;
239 (
float)(sum_x / element->get_nvert()), (
float)(sum_y / element->get_nvert()),
240 (
float)(max_x - min_x), (
float)(max_y - min_y)));
254 void ScalarView::draw_element_infos_2d()
257 create_element_info_widgets();
260 glMatrixMode(GL_MODELVIEW);
261 glDisable(GL_TEXTURE_1D);
262 glDisable(GL_LIGHTING);
266 std::vector<ElementInfo>::const_iterator iter = element_infos.begin();
267 while (iter != element_infos.end())
270 float width = (float)(iter->width * scale);
271 float height = (float)(iter->height * scale);
274 if (width > 40.f && height > 20.f)
278 glTranslatef(iter->x, iter->y, 0.0f);
279 glScalef(1 / (
float)scale, 1 / (
float)scale, 1.0f);
282 void* font = GLUT_BITMAP_HELVETICA_10;
283 unsigned char buffer[128];
284 sprintf((
char*)buffer,
"%d", iter->id);
285 int width_px = glutBitmapLength(font, buffer);
286 int height_px = glutBitmapHeight(font);
289 glCallList(element_id_widget);
292 glTranslatef(-width_px / 2.0f, -height_px / 3.0f, 0.0f);
293 glColor3f(1.0f, 1.0f, 1.0f);
294 glRasterPos2f(0.0f, 0.0f);
295 glutBitmapString(font, buffer);
306 void ScalarView::create_element_info_widgets()
308 if (element_id_widget == 0)
310 element_id_widget = glGenLists(1);
311 glNewList(element_id_widget, GL_COMPILE);
317 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
318 glVertex2f(-radius*1.1, radius*0.5);
319 glVertex2f(radius*1.1, radius*0.5);
320 glVertex2f(radius*1.1, -radius*0.5);
321 glVertex2f(-radius*1.1, -radius*0.5);
325 glColor4f(0.2f, 0.2f, 0.4f, 1.0f);
326 glVertex2f(-radius*1.1, radius*0.5);
327 glVertex2f(radius*1.1, radius*0.5);
328 glVertex2f(radius*1.1, -radius*0.5);
329 glVertex2f(-radius*1.1, -radius*0.5);
337 void ScalarView::show_contours(
double step,
double orig)
340 throw Exceptions::ValueException(
"step", step, 0.0);
344 set_palette_filter(
true);
348 void ScalarView::draw_tri_contours(ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t& triangle)
351 int i, idx[3] = { 0, 1, 2 }, perm = 0;
352 for (i = 0; i < 2; i++)
354 if (triangle[idx[0]][2] > triangle[idx[1]][2])
356 std::swap(idx[0], idx[1]);
359 if (triangle[idx[1]][2] > triangle[idx[2]][2])
361 std::swap(idx[1], idx[2]);
365 if (fabs(triangle[idx[0]][2] - triangle[idx[2]][2]) < 1e-3 * fabs(cont_step))
369 double val = triangle[idx[0]][2];
370 val = std::ceil((val - cont_orig) / cont_step) * cont_step + cont_orig;
375 while (val < triangle[idx[r2]][2])
377 double ld = triangle[idx[l2]][2] - triangle[idx[l1]][2];
378 double rd = triangle[idx[r2]][2] - triangle[idx[r1]][2];
381 while (val < triangle[idx[l2]][2])
383 double lt = (val - triangle[idx[l1]][2]) / ld;
384 double rt = (val - triangle[idx[r1]][2]) / rd;
386 double x1 = (1.0 - lt) * triangle[idx[l1]][0] + lt * triangle[idx[l2]][0];
387 double y1 = (1.0 - lt) * triangle[idx[l1]][1] + lt * triangle[idx[l2]][1];
388 double x2 = (1.0 - rt) * triangle[idx[r1]][0] + rt * triangle[idx[r2]][0];
389 double y2 = (1.0 - rt) * triangle[idx[r1]][1] + rt * triangle[idx[r2]][1];
409 void ScalarView::prepare_gl_geometry()
415 void ScalarView::draw_values_2d()
418 glEnable(GL_TEXTURE_1D);
419 glBindTexture(GL_TEXTURE_1D, gl_pallete_tex_id);
420 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
424 glMatrixMode(GL_TEXTURE);
426 glTranslated(tex_shift, 0.0, 0.0);
427 glScaled(tex_scale, 0.0, 0.0);
430 glBegin(GL_TRIANGLES);
435 glTexCoord1d((triangle[0][2] - range_min) * value_irange);
436 glVertex2d(triangle[0][0], triangle[0][1]);
437 glTexCoord1d((triangle[1][2] - range_min) * value_irange);
438 glVertex2d(triangle[1][0], triangle[1][1]);
439 glTexCoord1d((triangle[2][2] - range_min) * value_irange);
440 glVertex2d(triangle[2][0], triangle[2][1]);
446 glMatrixMode(GL_TEXTURE);
448 glMatrixMode(GL_MODELVIEW);
451 void ScalarView::draw_edges_2d()
453 glColor3fv(edges_color);
458 int& edge_marker = it.get_marker();
460 if (show_edges || edge_marker)
462 glVertex2d(edge[0][0], edge[0][1]);
463 glVertex2d(edge[1][0], edge[1][1]);
469 #define V0 vertices_min_x - xctr, range_min - yctr, -(vertices_min_y - zctr)
470 #define V1 vertices_max_x - xctr, range_min - yctr, -(vertices_min_y - zctr)
471 #define V2 vertices_max_x - xctr, range_min - yctr, -(vertices_max_y - zctr)
472 #define V3 vertices_min_x - xctr, range_min - yctr, -(vertices_max_y - zctr)
473 #define V4 vertices_min_x - xctr, range_max - yctr, -(vertices_min_y - zctr)
474 #define V5 vertices_max_x - xctr, range_max - yctr, -(vertices_min_y - zctr)
475 #define V6 vertices_max_x - xctr, range_max - yctr, -(vertices_max_y - zctr)
476 #define V7 vertices_min_x - xctr, range_max - yctr, -(vertices_max_y - zctr)
478 void ScalarView::draw_aabb()
492 glColor3fv(edges_color);
495 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
499 glScaled(xzscale, yscale, xzscale);
502 glEnableClientState(GL_VERTEX_ARRAY);
503 glVertexPointer(3, GL_DOUBLE, 0, aabb);
506 glDrawArrays(GL_QUADS, 0, 24);
509 glDisableClientState(GL_VERTEX_ARRAY);
515 void ScalarView::on_display_2d()
517 set_ortho_projection();
518 glDisable(GL_LIGHTING);
519 glDisable(GL_DEPTH_TEST);
520 glDisable(GL_TEXTURE_2D);
524 glMatrixMode(GL_MODELVIEW);
527 glTranslated(center_x, center_y, 0.0);
528 glScaled(1.0, -1.0, 1.0);
529 glTranslated(trans_x, trans_y, 0.0);
530 glScaled(scale, scale, 1.0);
537 glDisable(GL_TEXTURE_1D);
540 glColor3fv(cont_color);
546 draw_tri_contours(triangle);
555 if (show_element_info)
556 draw_element_infos_2d();
562 void ScalarView::on_display_3d()
564 set_3d_projection(fovy, znear, zfar);
566 glClear(GL_DEPTH_BUFFER_BIT);
567 glEnable(GL_DEPTH_TEST);
570 glMatrixMode(GL_MODELVIEW);
580 ztrans = calculate_ztrans_to_fit_view();
581 do_zoom_to_fit =
false;
585 glTranslated(xtrans, ytrans, ztrans);
586 glRotated(xrot, 1, 0, 0);
587 glRotated(yrot, 0, 1, 0);
590 glEnable(GL_LIGHTING);
591 glEnable(GL_TEXTURE_1D);
592 glBindTexture(GL_TEXTURE_1D, gl_pallete_tex_id);
593 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
594 glEnable(GL_NORMALIZE);
595 glEnable(GL_POLYGON_OFFSET_FILL);
596 glPolygonOffset(1.0, 1.0);
597 glBegin(GL_TRIANGLES);
598 double normal_xzscale = 1.0 / xzscale, normal_yscale = 1.0 / yscale;
600 for (Linearizer::Iterator<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t> it = this->lin->triangles_begin(); !it.end; ++it)
602 ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::triangle_t& triangle = it.get();
604 for (
int j = 0; j < 3; j++)
606 glTexCoord2d((triangle[j][2] - range_min) * value_irange * tex_scale + tex_shift, 0.0);
608 glVertex3d((triangle[j][0] - xctr) * xzscale, (triangle[j][2] - yctr) * yscale, -(triangle[j][1] - zctr) * xzscale);
613 glDisable(GL_POLYGON_OFFSET_FILL);
616 glDisable(GL_LIGHTING);
617 glDisable(GL_TEXTURE_1D);
620 glColor3fv(edges_color);
622 for (Linearizer::Iterator<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t> it = lin->edges_begin(); !it.end; ++it)
624 ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t& edge = it.get();
626 for (
int j = 0; j < 2; j++)
627 glVertex3d((edge[j][0] - xctr) * xzscale, (edge[j][2] - yctr) * yscale, -(edge[j][1] - zctr) * xzscale);
637 glColor3fv(edges_color);
639 for (Linearizer::Iterator<ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t> it = lin->edges_begin(); !it.end; ++it)
642 double y_coord = (range_min - yctr) * yscale;
643 ScalarLinearizerDataDimensions<LINEARIZER_DATA_TYPE>::edge_t& edge = it.get();
644 int& edge_marker = it.get_marker();
648 glVertex3d((edge[0][0] - xctr) * xzscale, y_coord, -(edge[0][1] - zctr) * xzscale);
649 glVertex3d((edge[1][0] - xctr) * xzscale, y_coord, -(edge[1][1] - zctr) * xzscale);
656 void ScalarView::on_display()
661 glPolygonMode(GL_FRONT_AND_BACK, pmode ? GL_LINE : GL_FILL);
664 prepare_gl_geometry();
667 this->on_display_3d();
669 this->on_display_2d();
674 static inline void normalize(
double& x,
double& y,
double& z)
676 double l = 1.0 / sqrt(sqr(x) + sqr(y) + sqr(z));
677 x *= l; y *= l; z *= l;
680 void ScalarView::update_layout()
682 View::update_layout();
686 xctr = (vertices_max_x + vertices_min_x) / 2.0;
687 yctr = value_range_avg;
688 zctr = (vertices_max_y + vertices_min_y) / 2.0;
691 void ScalarView::reset_view(
bool force_reset)
693 if (force_reset || view_not_reset) {
694 xrot = 40.0; yrot = 0.0;
695 xtrans = ytrans = ztrans = 0.0;
701 double max_radial = std::max(vertices_max_x - vertices_min_x, vertices_max_y - vertices_min_y);
702 xzscale = 2.0 / max_radial;
705 double max_axial = std::max(range_max - yctr, fabs(range_min - yctr));
716 double tan_fovy_half = tan((
double)fovy / 2.0 / 180.0 * M_PI);
717 double max_allowed_height = (zfar - 3)*tan_fovy_half;
718 if (max_axial * xzscale > max_allowed_height || (max_axial * xzscale < 0.1 && !is_constant))
719 yscale = (znear + zfar) / 3.0 * tan_fovy_half * value_irange;
723 do_zoom_to_fit =
true;
726 View::reset_view(force_reset);
729 double ScalarView::calculate_ztrans_to_fit_view()
732 GLdouble aabb[2][16] =
747 GLdouble aabb_base[16];
750 double tan_fovy_half = tan((
double)fovy / 2.0 / 180.0 * M_PI);
751 double tan_fovx_half = tan_fovy_half * (double)output_width / output_height;
754 double optimal_viewpoint_pos = 0.0;
761 glTranslated(xtrans, ytrans, ztrans);
762 glRotated(xrot, 1, 0, 0);
763 glRotated(yrot, 0, 1, 0);
764 glScaled(xzscale, yscale, xzscale);
769 for (
int i = 0; i < 2; i++)
772 glMultMatrixd(aabb[i]);
773 glGetDoublev(GL_MODELVIEW_MATRIX, aabb_base);
777 GLdouble *coord_ptr = &aabb_base[0];
778 for (
int j = 0; j < 4; j++)
780 double perspective_center_to_origin_dist = fabs(coord_ptr[0]) / tan_fovx_half + coord_ptr[2];
781 if (perspective_center_to_origin_dist > optimal_viewpoint_pos)
782 optimal_viewpoint_pos = perspective_center_to_origin_dist;
784 perspective_center_to_origin_dist = fabs(coord_ptr[1]) / tan_fovy_half + coord_ptr[2];
785 if (perspective_center_to_origin_dist > optimal_viewpoint_pos)
786 optimal_viewpoint_pos = perspective_center_to_origin_dist;
795 return -optimal_viewpoint_pos;
798 void ScalarView::set_vertical_scaling(
double sc)
807 void ScalarView::set_min_max_range(
double min,
double max)
810 if (fabs(max - min) < Hermes::HermesEpsilon)
812 this->warn(
"Range (%f, %f) is too narrow: adjusted to (%f, %f)", min, max, min - 0.5, max);
815 View::set_min_max_range(min, max);
818 void ScalarView::init_lighting()
820 float light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
821 float light_ambient[] = { 0.1f, 0.1f, 0.1f, 1.0f };
822 float light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
825 glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
826 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
827 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
830 float material_ambient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
831 float material_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
832 float material_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
834 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient);
835 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_diffuse);
836 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular);
837 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128);
838 glDisable(GL_COLOR_MATERIAL);
840 glShadeModel(GL_SMOOTH);
841 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
842 if (GLEW_EXT_separate_specular_color)
844 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SEPARATE_SPECULAR_COLOR_EXT);
848 void ScalarView::set_3d_mode(
bool enable)
850 mode3d = enable; dragging = scaling =
false;
859 void ScalarView::on_key_down(
unsigned char key,
int x,
int y)
864 show_edges = !show_edges;
879 set_palette_filter(pal_filter != GL_LINEAR);
883 contours = !contours;
885 this->cont_step = (this->range_max - this->range_min) / 50.;
890 show_element_info = !show_element_info;
896 show_aabb = !show_aabb;
903 dragging = scaling =
false;
910 yscale *= D3DV_SCALE_STEP_COEF;
912 cont_step *= D3DV_SCALE_STEP_COEF;
920 yscale /= D3DV_SCALE_STEP_COEF;
922 cont_step /= D3DV_SCALE_STEP_COEF;
928 View::on_key_down(key, x, y);
933 void ScalarView::on_mouse_move(
int x,
int y)
935 if (mode3d && (dragging || scaling || panning))
939 yrot += 0.4 * (x - mouse_x);
940 xrot += 0.4 * (y - mouse_y);
942 if (xrot < -90) xrot = -90;
943 else if (xrot > 90) xrot = 90;
947 ztrans += 0.01 * (mouse_y - y);
948 if (ztrans > -0.25) ztrans = -0.25;
949 else if (ztrans < -7) ztrans = -7;
953 xtrans += 0.002 * (x - mouse_x);
954 ytrans += 0.002 * (mouse_y - y);
964 if (!mode3d && show_edges && !dragging && !scaling && !panning)
967 View::on_mouse_move(x, y);
971 void ScalarView::on_right_mouse_down(
int x,
int y)
973 View::on_right_mouse_down(x, y);
976 void ScalarView::on_middle_mouse_down(
int x,
int y)
979 dragging = scaling =
false;
983 void ScalarView::on_middle_mouse_up(
int x,
int y)
988 const char* ScalarView::get_help_text()
const
993 " Left mouse - pan\n"
994 " Right mouse - zoom\n"
995 " 3 - toggle 3D mode\n"
996 " C - center image\n"
997 " F - toggle smooth palette\n"
998 " H - render high-quality frame\n"
999 " K - toggle contours\n"
1000 " M - toggle mesh\n"
1001 " B - toggle bounding box\n"
1002 " I - toggle element IDs (2d only)\n"
1003 " P - cycle palettes\n"
1004 " S - save screenshot\n"
1005 " * - increase contour density\n"
1006 " / - decrease contour density\n"
1008 " Esc, Q - quit\n\n"
1010 " Left mouse - rotate\n"
1011 " Right mouse - zoom\n"
1012 " Middle mouse - pan\n"
1013 " * - increase Z scale\n"
1014 " / - decrease Z scale";
double x
vertex node coordinates
static const int fovy
Field of view in the vertical direction (in degrees).
Stores one element of a mesh.
bool show_edges
true to show edges of mesh
bool is_constant
true if the function to be displayed is constant
Common definitions for Hermes2D.
::xsd::cxx::tree::buffer< char > buffer
Binary buffer type.
float cont_color[3]
color of contours (RGB)
File containing ScalarView class.
bool show_values
true to show values
bool do_zoom_to_fit
true to automatically translate the view so that the whole model si displayed
static const double znear
Distance of the near clipping plane of the viewing frustum from the camera.
Linearizer * lin
LinearizerMultidimensional class responsible for obtaining linearized data.
bool lin_updated
true, if lin now contains new_ values
LinearizerMultidimensional< ScalarLinearizerDataDimensions< LINEARIZER_DATA_TYPE > > Linearizer
Linearizer for scalar cases - historically called Linearizer.
bool contours
true to enable drawing of contours
static const double zfar
Distance of the Far clipping plane of the viewing frustum from the camera.
bool show_aabb
true to show the bounding box
Typedefs used throughout the Linearizer functionality.
void set_criterion(LinearizerCriterion criterion)
double cont_orig
contour settings.
Node * vn[H2D_MAX_NUMBER_VERTICES]
vertex node pointers
Abstract class for criterion according to which the linearizer stops dividing elements at some point ...
float edges_color[3]
color of edges