⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 glchartpreviewrenderer.cpp

📁 开源的电子海图程序
💻 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 + -