📄 glchartpreviewrenderer.cpp
字号:
/* GHelm - Nautical Navigation Software * Copyright (C) 2004 Jon Michaelchuck * * This application is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */#include <math.h>#include "glchartpreviewrenderer.h"#include "util.h"#include "waypointdialog.h"/** * Constructor */GLChartPreviewRenderer::GLChartPreviewRenderer() : glerror(GL_NO_ERROR), left_mouse_button(false), xsize(0), ysize(0), zoom(1), left_edge(0), bottom_edge(0), slat(-10800), wlon(-10800), nlat(10800), elon(10800), chart(NULL), configuration(NULL), inited(false), moving(false){ for (int i = 0; i < 4; i++) { for (int j = 0; j < 2; j++) { view_rect[i][j] = 0; } }}/** * Destructor */GLChartPreviewRenderer::~GLChartPreviewRenderer(){}/** * Initialize the glspace. * @param conf Configuration to use * @return 0 on success, -1 on failure */int GLChartPreviewRenderer::Init(Configuration *conf, Glib::RefPtr<Gdk::GL::Config> glconfig, Glib::RefPtr<Gdk::GL::Context> share_list){ set_gl_capability(glconfig, share_list, true); configuration = conf; // We need to enable our events add_events(Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::SCROLL_MASK | Gdk::VISIBILITY_NOTIFY_MASK); signal_button_press_event().connect(sigc::mem_fun(*this, &GLChartPreviewRenderer::on_button_press_event)); signal_button_release_event().connect(sigc::mem_fun(*this, &GLChartPreviewRenderer::on_button_release_event)); signal_motion_notify_event().connect(sigc::mem_fun(*this, &GLChartPreviewRenderer::on_motion_notify_event)); signal_scroll_event().connect(sigc::mem_fun(*this, &GLChartPreviewRenderer::on_scroll_event)); return 0;}/** * Set the current chart * @param ch Chart to load */void GLChartPreviewRenderer::SetChart(Chart *ch){ chart = ch; slat = chart->slat; wlon = chart->wlon; nlat = chart->nlat; elon = chart->elon; left_edge = wlon; bottom_edge = slat; if (left_edge >= 10800) left_edge = 10799; else if (left_edge <= -10800) left_edge = -10799; if (bottom_edge >= 10800) bottom_edge = 10799; else if (bottom_edge <= -10800) bottom_edge = -10799; double y = (nlat - slat); double x = (elon - wlon); double zoomy = ysize / (y); double zoomx = xsize / (x); if (zoomy < zoomx) zoom = zoomy; else zoom = zoomx; chart->absolute_zoom_factor = zoom; Render();}//// rendering///** * Render tick */void GLChartPreviewRenderer::Render(){ SetView(); Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window(); if (!glwindow->gl_begin(get_gl_context())) std::cerr << "GLChartPreviewRenderer::Render() unable to get context" << std::endl; glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glPushMatrix(); glTranslatef(-left_edge, -bottom_edge, 0); if (chart) { chart->Draw(zoom, *configuration); std::vector<waypoint_t>::iterator it; std::vector<waypoint_t>::iterator end = chart->waypoints.end(); glPointSize(8); glColor3f(0,0,1); glBegin(GL_POINTS); for (it = chart->waypoints.begin(); it != end; ++it) glVertex2dv(it->longlat); glEnd(); glPointSize(1); DrawViewRect(); } glPopMatrix(); // check for a gl error if ((glerror = glGetError()) != GL_NO_ERROR) std::cerr << "GLChartPreviewRenderer::Render(): glError : " << gluErrorString(glerror) << std::endl; // swap buffers if (glwindow->is_double_buffered()) glwindow->swap_buffers(); else glFlush(); // end opengl mode glwindow->gl_end();}/** * Draw the view rectangle */void GLChartPreviewRenderer::DrawViewRect(){ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glColor4f(0,0,.2,.5); glBegin(GL_QUADS); glVertex2dv(view_rect[0]); glVertex2dv(view_rect[1]); glVertex2dv(view_rect[2]); glVertex2dv(view_rect[3]); glEnd(); glDisable(GL_BLEND); glColor3f(0,0,.5); glBegin(GL_LINE_LOOP); glVertex2dv(view_rect[0]); glVertex2dv(view_rect[1]); glVertex2dv(view_rect[2]); glVertex2dv(view_rect[3]); glEnd();}/** * Viewing transformation */void GLChartPreviewRenderer::SetView(){ Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window(); if (!glwindow->gl_begin(get_gl_context())) std::cerr << "GLChartPreviewRenderer::SetView() unable to get context" << std::endl; glMatrixMode(GL_PROJECTION); // the projection transformation glLoadIdentity(); glOrtho(0, xsize/zoom, 0, ysize/zoom, -1, 1); glMatrixMode(GL_MODELVIEW); // modelview glViewport(0, 0, xsize, ysize); // viewport glwindow->gl_end();}//// zooming and scrolling///** * Scroll about the render space * @param x x component to scroll * @param y y component to scroll */void GLChartPreviewRenderer::Scroll(gdouble x, gdouble y){ // disallow scrolling beyond lat/long double newy = bottom_edge + y/zoom; double newx = left_edge + x/zoom; if (newy >= nlat - ysize/zoom) newy = nlat - ysize/zoom; else if (newy <= slat) newy = slat; if (newx >= elon - xsize/zoom) newx = elon - xsize/zoom; else if (newx <= wlon) newx = wlon; bottom_edge = newy; left_edge = newx; Render();}/** * Move the view rect * @param x x to move * @param y y to move */void GLChartPreviewRenderer::MoveViewRect(double x, double y){ double xn = x/zoom; double yn = y/zoom; for (int i = 0; i < 4; i++) { view_rect[i][0] += xn; view_rect[i][1] += yn; } Render();}//// rendering callbacks///** * Callback for when the window renderer is first up */void GLChartPreviewRenderer::on_realize(){ Gtk::DrawingArea::on_realize(); Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window(); if (!glwindow->gl_begin(get_gl_context())) std::cerr << "GLChartPreviewRenderer::on_realize() unable to get GL context" << std::endl; glShadeModel(GL_SMOOTH); glClearColor(.7, .7, .7, 0.0); glDisable(GL_LIGHTING); // antialiasing glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_LINE_SMOOTH); glwindow->gl_end(); inited = true;}/** * Callback for when the parent window is resized */bool GLChartPreviewRenderer::on_configure_event(GdkEventConfigure *event){ xsize = event->width; ysize = event->height; // This handles the event in which the new render // space reveals non-chart area. In this case we either scroll // or zoom to compensate. // Note that only the right and top edges are moving during a resize. if (chart) { // first see if we are too large for the chart in some dimension if ((xsize/zoom > (elon - wlon)) || (ysize/zoom > (nlat - slat))) { double y = nlat - slat; double x = elon - wlon; double zoomy = ysize / (y); double zoomx = xsize / (x); if (zoomy < zoomx) zoom = zoomy; else zoom = zoomx; } } xsize = event->width; ysize = event->height; // This handles the event in which the new render // space reveals non-chart area. In this case we either scroll // or zoom to compensate. // Note that only the right and top edges are moving during a resize. if (chart) { // first see if we are too large for the chart in some dimension if ((xsize/zoom > (elon - wlon)) || (ysize/zoom > (nlat - slat))) { double y = nlat - slat; double x = elon - wlon; double zoomy = ysize / (y); double zoomx = xsize / (x); if (zoomy < zoomx) zoom = zoomy; else zoom = zoomx; } } Scroll(1,1); // this actually fixes any off-chart issues. nice. Render(); Scroll(1,1); // this actually fixes any off-chart issues. nice. Render(); return true;}/** * Callback for when the window is redrawn */bool GLChartPreviewRenderer::on_expose_event(GdkEventExpose* event){ Render(); return true;}/** * Callback for mouse button press. * @param event Event * @return true on success, false on failure */bool GLChartPreviewRenderer::on_button_press_event(GdkEventButton *event){ double x, y; switch (event->button) { case 1: x = left_edge + event->x/zoom; y = bottom_edge + event->y/zoom; left_mouse_button = true; // check if we are in the view box if ((x >= view_rect[0][0]) && (x <= view_rect[1][0]) && (y >= view_rect[0][1]) && (y <= view_rect[2][1])) { last_x = event->x; last_y = event->y; moving = true; std::cout << "hit" << std::endl; } default: break; } return true;}/** * Mouse button release callback * @param event Event * @return true on success, false on failure */bool GLChartPreviewRenderer::on_button_release_event(GdkEventButton *event){ switch (event->button) { case 1: left_mouse_button = false; moving = false; default: break; } return true;}/** * Mouse motion callback * @param event Event * @return true on success, false on failure */bool GLChartPreviewRenderer::on_motion_notify_event(GdkEventMotion *event){ if (left_mouse_button) { if (moving) { MoveViewRect((event->x - last_x), (last_y - event->y)); last_x = event->x; last_y = event->y; } } return true;}/** * Mouse scroll wheel callback * @param event Event * @return true on success, false on failure */bool GLChartPreviewRenderer::on_scroll_event(GdkEventScroll *event){ switch (event->direction) { default: break; } return true;}//// custom signal handlers///** * chart switched signal handler */void GLChartPreviewRenderer::on_switched(Chart *chart){ if (chart) SetChart(chart); else UnloadChart();}/** * chart loaded signal handler */void GLChartPreviewRenderer::on_load_chart(Chart *chart){ SetChart(chart);}/** * chart unloaded signal handler */void GLChartPreviewRenderer::on_unload_chart(){ UnloadChart(); Render();}/** * set view rect signal handler */void GLChartPreviewRenderer::on_set_view_rect(double x, double y, double w, double h){ // this convention is important, we rely on it for the collision detection view_rect[0][0] = x; view_rect[0][1] = y; view_rect[1][0] = x + w; view_rect[1][1] = y; view_rect[2][0] = x + w; view_rect[2][1] = y + h; view_rect[3][0] = x; view_rect[3][1] = y + h; if (inited) Render();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -