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

📄 glchartrenderer.cpp

📁 开源的电子海图程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* 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 <iostream>#include <sstream>#include <math.h>#include "glchartrenderer.h"#include "util.h"#include "waypointdialog.h"/** * Constructor * @param glconf GL config to use */GLChartRenderer::GLChartRenderer(Glib::RefPtr<Gdk::GL::Config> glconf) :    Gtk::GL::DrawingArea(glconf), glerror(GL_NO_ERROR),    input_mode(PAN_MODE), left_mouse_button(false), last_x(0), last_y(0),    pointer_x(0), pointer_y(0), pointer_lat(0),    pointer_long(0), xsize(0), ysize(0), zoom(1), left_edge(0),    bottom_edge(0),    slat(-10800), wlon(-10800), nlat(10800), elon(10800),    selection_rect_drawn(false), chart(NULL), configuration(NULL){    for (int i = 0; i < 4; i++) {        for (int j = 0; j < 2; j++) {            selection_rect[i][j] = 0;        }    }}/** * Constructor * @param glconf GL config to use * @param cont GL sharing context to use */GLChartRenderer::GLChartRenderer(Glib::RefPtr<Gdk::GL::Config> glconf,                                 Glib::RefPtr<Gdk::GL::Context> cont) :    Gtk::GL::DrawingArea(glconf, cont, true), glerror(GL_NO_ERROR),    input_mode(PAN_MODE), left_mouse_button(false), last_x(0), last_y(0),    pointer_x(0), pointer_y(0), pointer_lat(0),    pointer_long(0), xsize(0), ysize(0), zoom(1), left_edge(0),    bottom_edge(0),    slat(-10800), wlon(-10800), nlat(10800), elon(10800),    selection_rect_drawn(false), chart(NULL), configuration(NULL){    for (int i = 0; i < 4; i++) {        for (int j = 0; j < 2; j++) {            selection_rect[i][j] = 0;        }    }}/** * Destructor */GLChartRenderer::~GLChartRenderer(){}/** * Initialize the glspace. * @param conf Configuration to use * @return 0 on success, -1 on failure */int GLChartRenderer::Init(Configuration *conf){    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,                                &GLChartRenderer::on_button_press_event));    signal_button_release_event().connect(sigc::mem_fun(*this,                                &GLChartRenderer::on_button_release_event));    signal_motion_notify_event().connect(sigc::mem_fun(*this,                                &GLChartRenderer::on_motion_notify_event));    signal_scroll_event().connect(sigc::mem_fun(*this,                                &GLChartRenderer::on_scroll_event));    //DEBUG    glGenTextures(1, &texture);    return 0;}/** * Set the current chart * @param ch Chart to load */void GLChartRenderer::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 GLChartRenderer::Render(){    SetView();    Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();    if (!glwindow->gl_begin(get_gl_context()))         std::cerr << "GLChartRenderer::Render() unable to get GL 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);        } 	glPopMatrix();    glPushMatrix();        // draw a selection rectangle if we have one        if (selection_rect_drawn)            DrawSelectionRect();    glPopMatrix();    // check for a gl error    if ((glerror = glGetError()) != GL_NO_ERROR)         std::cerr << "GLChartRenderer::Render(): glError : "                  << gluErrorString(glerror) << std::endl;    // swap buffers    if (glwindow->is_double_buffered())        glwindow->swap_buffers();    else        glFlush();    // end opengl mode    glwindow->gl_end();}//DEBUG/TEST featurevoid GLChartRenderer::RenderToTexture(){    SetView();    Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();    if (!glwindow->gl_begin(get_gl_context()))         std::cerr << "GLChartRenderer::Render() unable to get GL context"                   << std::endl;    glDrawBuffer(GL_BACK);    glClear(GL_COLOR_BUFFER_BIT);	glLoadIdentity();	glPushMatrix();        glTranslatef(-left_edge,                     -bottom_edge, 0);        if (chart)            chart->Draw(zoom, *configuration);     glPopMatrix();    glDrawBuffer(GL_FRONT);    glEnable(GL_TEXTURE_2D);    glBindTexture(GL_TEXTURE_2D, texture);    glTexParameteri(GL_TEXTURE_2D,                    GL_TEXTURE_WRAP_S,                    GL_REPEAT);    glTexParameteri(GL_TEXTURE_2D,                    GL_TEXTURE_WRAP_T,                    GL_REPEAT);    glTexParameteri(GL_TEXTURE_2D,                    GL_TEXTURE_MAG_FILTER,                    GL_LINEAR);    glTexImage2D(GL_TEXTURE_2D,                 0,                 GL_RGBA,                 256, 256,                 0,                 GL_RGBA,                 GL_UNSIGNED_BYTE,                 texture_ch);    glReadBuffer(GL_BACK);    glCopyTexSubImage2D(GL_TEXTURE_2D,                        0,                        0, 0,                        0, 0,                        256, 256);    glDrawBuffer(GL_FRONT);    SetView();    glBegin(GL_QUADS);    glTexCoord2f(0,0); glVertex2f(0, 0);    glTexCoord2f(1,0); glVertex2f(100, 0);    glTexCoord2f(1,1); glVertex2f(100, 100);    glTexCoord2f(0,1); glVertex2f(0, 100);    glEnd();    glDisable(GL_TEXTURE_2D);    glDrawBuffer(GL_BACK);    glwindow->gl_end();}//DEBUG/TEST featurevoid GLChartRenderer::AddWaypoint(double x, double y){    if (chart) {        x /= zoom;        y /= zoom;        x += left_edge;        y += bottom_edge;        WaypointDialog waypoint_dialog;        waypoint_t *waypoint = waypoint_dialog.Run(x, y);        if (waypoint) {            chart->waypoints.push_back(*waypoint);            signal_add_waypoint.emit(waypoint);            Render();        }    }}/** * Draw the selection rectangle */void GLChartRenderer::DrawSelectionRect(){    glEnable(GL_BLEND);	glBlendFunc(GL_SRC_ALPHA, GL_ONE);	    glColor4f(0,0,.2,.5);    glBegin(GL_QUADS);        glVertex2dv(selection_rect[0]);        glVertex2dv(selection_rect[1]);        glVertex2dv(selection_rect[2]);        glVertex2dv(selection_rect[3]);    glEnd();    glDisable(GL_BLEND);    glColor3f(0,0,.5);    glBegin(GL_LINE_LOOP);        glVertex2dv(selection_rect[0]);        glVertex2dv(selection_rect[1]);        glVertex2dv(selection_rect[2]);        glVertex2dv(selection_rect[3]);    glEnd();}/** * Viewing transformation  */void GLChartRenderer::SetView(){    Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();    if (!glwindow->gl_begin(get_gl_context()))        std::cerr << "GLChartRenderer::SetView() unable to get GL 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();    signal_set_view_rect.emit(left_edge, bottom_edge,                                xsize/zoom, ysize/zoom);}//// zooming and scrolling///** * Zoom on the render space * @param dir Direction to zoom (true = in, false = out) * @param mag Magnitude of zoom */void GLChartRenderer::Zoom(bool dir, float mag){    // we manage this such that when the user attempts    // to zoom out in a way which would expose non-chart area we handle    // it gracefully. This means either scrolling the contents of the    // window or only allowing a smaller zoom (or no zoom at all)    double old_zoom = zoom;    double xfactor = xsize/pointer_x;    double yfactor = ysize/pointer_y;    if (dir) {        zoom *= mag;        left_edge += (xsize/old_zoom - xsize/zoom)/xfactor;        bottom_edge += (ysize/old_zoom - ysize/zoom)/yfactor;    } else {        // first lets see if the zoom will bring us into territory        // outside our boundaries.        double new_zoom;        double new_left_edge;        double new_bottom_edge;        new_zoom = zoom / mag;        new_left_edge = left_edge + (xsize/old_zoom - xsize/new_zoom)/xfactor;        new_bottom_edge = bottom_edge +                            (ysize/old_zoom - ysize/new_zoom)/yfactor;        // first see if any of the new dimensions are larger than the        // chart. if so we just do a full zoom out.        if (((new_bottom_edge + ysize/new_zoom) - (new_bottom_edge))                                                        > (nlat - slat)) {            bottom_edge = slat;            double y = nlat - slat;            double x = xsize/new_zoom;            double zoomy = ysize / y;             double zoomx = xsize / x;            if (zoomy > zoomx)                zoom = zoomy;            else                zoom = zoomx;        } else if ((((new_left_edge + xsize/new_zoom) - (new_left_edge))                                                            > (elon - wlon))) {            left_edge = wlon;            double x = elon - wlon;            double y = ysize/new_zoom;            double zoomy = ysize / y;             double zoomx = xsize / x;            if (zoomy > zoomx)                zoom = zoomy;            else                zoom = zoomx;                } else {            // check if after the zoom we need to pan            if (new_left_edge < wlon)                left_edge = wlon;            else if ((new_left_edge + xsize/new_zoom) > elon)                 left_edge = elon - xsize/new_zoom;             else                left_edge = new_left_edge;            if (new_bottom_edge < slat)                bottom_edge = slat;            else if ((new_bottom_edge + ysize/new_zoom) > nlat)                bottom_edge = nlat - ysize/new_zoom;             else                bottom_edge = new_bottom_edge;            zoom = new_zoom;        }    }    Render();}/** * Zoom to fit */void GLChartRenderer::ZoomFit(){ // FIXME this doesn't center correctly.    if (chart)        SetChart(chart);}/** * Scroll about the render space * @param x x component to scroll * @param y y component to scroll */void GLChartRenderer::Scroll(gdouble x, gdouble y){    // disallow scrolling beyond lat/long    double newy = bottom_edge + y/zoom;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -