// P2DVIEW_WCL.CPP // Copyright (C) 2005 Tommi Hassinen. // This package is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // This package 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 package; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /*################################################################################################*/ #include "p2dview_wcl.h" #include "project.h" #include "custom_app.h" #include "color.h" #include "local_i18n.h" #include #include using namespace std; /*################################################################################################*/ p2dview_wcl::p2dview_wcl(const char * s1, const char * s2, const char * sv) : ac_stor_wcl(new ogl_camera(ogl_ol_static(), 1.0)) { cam->ortho = true; cam->update_vdim = false; vdim[0] = (1.0 / 0.90) * 0.5; // X-scaling ; leave 5% margins... vdim[1] = (1.0 / 0.90) * 0.5; // Y-scaling ; leave 5% margins... cam->GetLD()->crd[0] = 0.50; // X-centering cam->GetLD()->crd[1] = 0.50; // Y-centering //const ogl_obj_loc_data * d = cam->GetSafeLD(); //cout << "cam crd = " << d->crd[0] << " " << d->crd[1] << " " << d->crd[2] << endl; //cout << "cam zdir = { " << d->zdir << " }" << endl << "cam ydir = { " << d->ydir << " }" << endl; if (!s1 || !strlen(s1)) assertion_failed(__FILE__, __LINE__, "invalid s1."); else { name1 = new char[strlen(s1) + 1]; strcpy(name1, s1); } if (!s2 || !strlen(s2)) assertion_failed(__FILE__, __LINE__, "invalid s2."); else { name2 = new char[strlen(s2) + 1]; strcpy(name2, s2); } if (!sv || !strlen(sv)) assertion_failed(__FILE__, __LINE__, "invalid sv."); else { namev = new char[strlen(sv) + 1]; strcpy(namev, sv); } } p2dview_wcl::~p2dview_wcl(void) { delete[] name1; delete[] name2; delete[] namev; // problem : lifetime of the camera object needs to be longer than // lifetime of this object since it is needed at the base class dtor. // solution : ask the base class to do the cleanup work for us... delete_cam_plz = true; } void p2dview_wcl::AddData(double c1, double c2, double v) { p2d_data newdata; newdata.ac_i = StoreAC(NULL); newdata.c1 = c1; newdata.c2 = c2; newdata.v = v; dv.push_back(newdata); } void p2dview_wcl::AddDataWithAC(double c1, double c2, double v, engine * eng) { p2d_data newdata; newdata.ac_i = StoreAC(eng); newdata.c1 = c1; newdata.c2 = c2; newdata.v = v; dv.push_back(newdata); } void p2dview_wcl::Finalize(void) { if (dv.empty()) return; min1 = max1 = dv[0].c1; min2 = max2 = dv[0].c2; minv = maxv = dv[0].v; for (i32u n1 = 1;n1 < dv.size();n1++) { if (dv[n1].c1 < min1) min1 = dv[n1].c1; if (dv[n1].c1 > max1) max1 = dv[n1].c1; if (dv[n1].c2 < min2) min2 = dv[n1].c2; if (dv[n1].c2 > max2) max2 = dv[n1].c2; if (dv[n1].v < minv) minv = dv[n1].v; // for "maxv" we actually calculate the average value instead of maximum value. // the max value can be very high especially if geomopt is skipped -> unreasonable scaling. maxv += dv[n1].v; // average! } maxv /= dv.size(); // average! } void p2dview_wcl::ButtonEvent(int x, int y) { if (custom_app::GetCurrentMouseTool() == custom_app::mtZoom) { mouseinfo::latest_x = x; mouseinfo::latest_y = y; } else { base_wnd * wnd = GetWnd(); project * prj = custom_app::GetAppC()->GetPrj(); if (!(wnd->GetWidth() > 1)) return; fGL sx = 1.10 * (fGL) x / (fGL) wnd->GetWidth() - 0.05; if (sx < 0.0) return; if (sx > 1.0) return; if (!(wnd->GetHeight() > 1)) return; fGL sy = 1.10 * (fGL) y / (fGL) wnd->GetHeight() - 0.05; if (sy < 0.0) return; if (sy > 1.0) return; // WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // this is not yet a generic implementation ; it is assumed that the data points // have been added in a certain order; see project::DoEnergyPlot2D() how to add them... const int dssz = (int) sqrt((double) dv.size()); // square datasets only!!! int index = (int) (((int) (sx * dssz)) * dssz + sy * dssz); if (index < 0 || index >= (int) dv.size()) return; // ok, we have a valid selection ; show the data!!! // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ostringstream str1; str1 << name1 << " = " << dv[index].c1 << " " << name2 << " = " << dv[index].c2 << " " << namev << " = " << dv[index].v << endl << ends; prj->PrintToLog(str1.str().c_str()); if (dv[index].ac_i != NOT_DEFINED) ShowAC(dv[index].ac_i); } } void p2dview_wcl::MotionEvent(int x, int y) { if (custom_app::GetCurrentMouseTool() == custom_app::mtZoom) { int dy = mouseinfo::latest_y - y; mouseinfo::latest_x = x; mouseinfo::latest_y = y; base_wnd * wnd = GetWnd(); project * prj = custom_app::GetAppC()->GetPrj(); const fGL scale = maxv - minv; maxv += mouseinfo::dist_sensitivity * scale * (fGL) dy / (fGL) wnd->GetHeight(); ostringstream str1; str1 << _("now scaling the colours to range ") << (maxv - minv) << _(" kJ/mol") << endl << ends; prj->PrintToLog(str1.str().c_str()); wnd->RequestUpdate(false); } else { ButtonEvent(x, y); } } void p2dview_wcl::UpdateWnd(void) { base_wnd * wnd = GetWnd(); if (!wnd || wnd->GetWidth() < 0 || !cam) return; wnd->SetCurrent(); cam->RenderScene(wnd, false, false); } void p2dview_wcl::InitGL(void) { // all classes that inherit pangofont_wcl must call ogl_InitPangoFont()!!! // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ogl_InitPangoFont("courier 12"); } void p2dview_wcl::RenderGL(rmode) { if (dv.empty()) return; glInitNames(); // WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // this is not yet a generic implementation ; it is assumed that the data points // have been added in a certain order; see project::DoEnergyPlot2D() how to add them... const int dssz = (int) sqrt((double) dv.size()); // square datasets only!!! // 20061024 ; it seems that the X-coordinate must be inverted... // origo of the coordinate system is at the upper-left corner. for (int n1 = 0;n1 < dssz - 1;n1++) { for (int n2 = 0;n2 < dssz - 1;n2++) { glBegin(GL_QUADS); fGL x1 = 1.0 - (dv[(n1 + 0) * dssz + (n2 + 0)].c1 - min1) / (max1 - min1); // invX fGL y1 = (dv[(n1 + 0) * dssz + (n2 + 0)].c2 - min2) / (max2 - min2); fGL x2 = 1.0 - (dv[(n1 + 1) * dssz + (n2 + 1)].c1 - min1) / (max1 - min1); // invX fGL y2 = (dv[(n1 + 1) * dssz + (n2 + 1)].c2 - min2) / (max2 - min2); SetColor(dv[(n1 + 0) * dssz + (n2 + 0)].v); glVertex3f(x1, y1, 0.1); SetColor(dv[(n1 + 1) * dssz + (n2 + 0)].v); glVertex3f(x2, y1, 0.1); SetColor(dv[(n1 + 1) * dssz + (n2 + 1)].v); glVertex3f(x2, y2, 0.1); SetColor(dv[(n1 + 0) * dssz + (n2 + 1)].v); glVertex3f(x1, y2, 0.1); glEnd(); } } } void p2dview_wcl::SetColor(GLfloat v) { GLfloat color[4]; GLfloat cv = (v - minv) / (maxv - minv); GetRBRange1(cv * cv, 1.0, color); glColor3fv(color); } /*################################################################################################*/ // eof