1 // P2DVIEW_WCL.CPP
2
3 // Copyright (C) 2005 Tommi Hassinen.
4
5 // This package is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9
10 // This package is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14
15 // You should have received a copy of the GNU General Public License
16 // along with this package; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 /*################################################################################################*/
20
21 #include "p2dview_wcl.h"
22
23 #include "project.h"
24 #include "custom_app.h"
25
26 #include "color.h"
27
28 #include "local_i18n.h"
29
30 #include <cstring>
31 #include <sstream>
32 using namespace std;
33
34 /*################################################################################################*/
35
p2dview_wcl(const char * s1,const char * s2,const char * sv)36 p2dview_wcl::p2dview_wcl(const char * s1, const char * s2, const char * sv) :
37 ac_stor_wcl(new ogl_camera(ogl_ol_static(), 1.0))
38 {
39 cam->ortho = true;
40
41 cam->update_vdim = false;
42 vdim[0] = (1.0 / 0.90) * 0.5; // X-scaling ; leave 5% margins...
43 vdim[1] = (1.0 / 0.90) * 0.5; // Y-scaling ; leave 5% margins...
44
45 cam->GetLD()->crd[0] = 0.50; // X-centering
46 cam->GetLD()->crd[1] = 0.50; // Y-centering
47
48 //const ogl_obj_loc_data * d = cam->GetSafeLD();
49 //cout << "cam crd = " << d->crd[0] << " " << d->crd[1] << " " << d->crd[2] << endl;
50 //cout << "cam zdir = { " << d->zdir << " }" << endl << "cam ydir = { " << d->ydir << " }" << endl;
51
52 if (!s1 || !strlen(s1)) assertion_failed(__FILE__, __LINE__, "invalid s1.");
53 else { name1 = new char[strlen(s1) + 1]; strcpy(name1, s1); }
54
55 if (!s2 || !strlen(s2)) assertion_failed(__FILE__, __LINE__, "invalid s2.");
56 else { name2 = new char[strlen(s2) + 1]; strcpy(name2, s2); }
57
58 if (!sv || !strlen(sv)) assertion_failed(__FILE__, __LINE__, "invalid sv.");
59 else { namev = new char[strlen(sv) + 1]; strcpy(namev, sv); }
60 }
61
~p2dview_wcl(void)62 p2dview_wcl::~p2dview_wcl(void)
63 {
64 delete[] name1;
65 delete[] name2;
66 delete[] namev;
67
68 // problem : lifetime of the camera object needs to be longer than
69 // lifetime of this object since it is needed at the base class dtor.
70 // solution : ask the base class to do the cleanup work for us...
71
72 delete_cam_plz = true;
73 }
74
AddData(double c1,double c2,double v)75 void p2dview_wcl::AddData(double c1, double c2, double v)
76 {
77 p2d_data newdata;
78 newdata.ac_i = StoreAC(NULL);
79
80 newdata.c1 = c1;
81 newdata.c2 = c2;
82 newdata.v = v;
83
84 dv.push_back(newdata);
85 }
86
AddDataWithAC(double c1,double c2,double v,engine * eng)87 void p2dview_wcl::AddDataWithAC(double c1, double c2, double v, engine * eng)
88 {
89 p2d_data newdata;
90 newdata.ac_i = StoreAC(eng);
91
92 newdata.c1 = c1;
93 newdata.c2 = c2;
94 newdata.v = v;
95
96 dv.push_back(newdata);
97 }
98
Finalize(void)99 void p2dview_wcl::Finalize(void)
100 {
101 if (dv.empty()) return;
102
103 min1 = max1 = dv[0].c1;
104 min2 = max2 = dv[0].c2;
105 minv = maxv = dv[0].v;
106
107 for (i32u n1 = 1;n1 < dv.size();n1++)
108 {
109 if (dv[n1].c1 < min1) min1 = dv[n1].c1;
110 if (dv[n1].c1 > max1) max1 = dv[n1].c1;
111
112 if (dv[n1].c2 < min2) min2 = dv[n1].c2;
113 if (dv[n1].c2 > max2) max2 = dv[n1].c2;
114
115 if (dv[n1].v < minv) minv = dv[n1].v;
116
117 // for "maxv" we actually calculate the average value instead of maximum value.
118 // the max value can be very high especially if geomopt is skipped -> unreasonable scaling.
119
120 maxv += dv[n1].v; // average!
121 }
122
123 maxv /= dv.size(); // average!
124 }
125
ButtonEvent(int x,int y)126 void p2dview_wcl::ButtonEvent(int x, int y)
127 {
128 if (custom_app::GetCurrentMouseTool() == custom_app::mtZoom)
129 {
130 mouseinfo::latest_x = x;
131 mouseinfo::latest_y = y;
132 }
133 else
134 {
135 base_wnd * wnd = GetWnd();
136 project * prj = custom_app::GetAppC()->GetPrj();
137
138 if (!(wnd->GetWidth() > 1)) return;
139 fGL sx = 1.10 * (fGL) x / (fGL) wnd->GetWidth() - 0.05;
140 if (sx < 0.0) return; if (sx > 1.0) return;
141
142 if (!(wnd->GetHeight() > 1)) return;
143 fGL sy = 1.10 * (fGL) y / (fGL) wnd->GetHeight() - 0.05;
144 if (sy < 0.0) return; if (sy > 1.0) return;
145
146 // WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
147 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
148 // this is not yet a generic implementation ; it is assumed that the data points
149 // have been added in a certain order; see project::DoEnergyPlot2D() how to add them...
150 const int dssz = (int) sqrt((double) dv.size()); // square datasets only!!!
151
152 int index = (int) (((int) (sx * dssz)) * dssz + sy * dssz);
153 if (index < 0 || index >= (int) dv.size()) return;
154
155 // ok, we have a valid selection ; show the data!!!
156 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
157
158 ostringstream str1;
159 str1 << name1 << " = " << dv[index].c1 << " " << name2 << " = " << dv[index].c2 << " " << namev << " = " << dv[index].v << endl << ends;
160 prj->PrintToLog(str1.str().c_str());
161
162 if (dv[index].ac_i != NOT_DEFINED) ShowAC(dv[index].ac_i);
163 }
164 }
165
MotionEvent(int x,int y)166 void p2dview_wcl::MotionEvent(int x, int y)
167 {
168 if (custom_app::GetCurrentMouseTool() == custom_app::mtZoom)
169 {
170 int dy = mouseinfo::latest_y - y;
171
172 mouseinfo::latest_x = x;
173 mouseinfo::latest_y = y;
174
175 base_wnd * wnd = GetWnd();
176 project * prj = custom_app::GetAppC()->GetPrj();
177
178 const fGL scale = maxv - minv;
179 maxv += mouseinfo::dist_sensitivity * scale * (fGL) dy / (fGL) wnd->GetHeight();
180
181 ostringstream str1;
182 str1 << _("now scaling the colours to range ") << (maxv - minv) << _(" kJ/mol") << endl << ends;
183 prj->PrintToLog(str1.str().c_str());
184
185 wnd->RequestUpdate(false);
186 }
187 else
188 {
189 ButtonEvent(x, y);
190 }
191 }
192
UpdateWnd(void)193 void p2dview_wcl::UpdateWnd(void)
194 {
195 base_wnd * wnd = GetWnd();
196 if (!wnd || wnd->GetWidth() < 0 || !cam) return;
197
198 wnd->SetCurrent();
199 cam->RenderScene(wnd, false, false);
200 }
201
InitGL(void)202 void p2dview_wcl::InitGL(void)
203 {
204 // all classes that inherit pangofont_wcl must call ogl_InitPangoFont()!!!
205 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
206
207 ogl_InitPangoFont("courier 12");
208 }
209
RenderGL(rmode)210 void p2dview_wcl::RenderGL(rmode)
211 {
212 if (dv.empty()) return;
213
214 glInitNames();
215
216 // WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
217 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
218 // this is not yet a generic implementation ; it is assumed that the data points
219 // have been added in a certain order; see project::DoEnergyPlot2D() how to add them...
220 const int dssz = (int) sqrt((double) dv.size()); // square datasets only!!!
221
222 // 20061024 ; it seems that the X-coordinate must be inverted...
223 // origo of the coordinate system is at the upper-left corner.
224
225 for (int n1 = 0;n1 < dssz - 1;n1++)
226 {
227 for (int n2 = 0;n2 < dssz - 1;n2++)
228 {
229 glBegin(GL_QUADS);
230
231 fGL x1 = 1.0 - (dv[(n1 + 0) * dssz + (n2 + 0)].c1 - min1) / (max1 - min1); // invX
232 fGL y1 = (dv[(n1 + 0) * dssz + (n2 + 0)].c2 - min2) / (max2 - min2);
233 fGL x2 = 1.0 - (dv[(n1 + 1) * dssz + (n2 + 1)].c1 - min1) / (max1 - min1); // invX
234 fGL y2 = (dv[(n1 + 1) * dssz + (n2 + 1)].c2 - min2) / (max2 - min2);
235
236 SetColor(dv[(n1 + 0) * dssz + (n2 + 0)].v); glVertex3f(x1, y1, 0.1);
237 SetColor(dv[(n1 + 1) * dssz + (n2 + 0)].v); glVertex3f(x2, y1, 0.1);
238 SetColor(dv[(n1 + 1) * dssz + (n2 + 1)].v); glVertex3f(x2, y2, 0.1);
239 SetColor(dv[(n1 + 0) * dssz + (n2 + 1)].v); glVertex3f(x1, y2, 0.1);
240
241 glEnd();
242 }
243 }
244 }
245
SetColor(GLfloat v)246 void p2dview_wcl::SetColor(GLfloat v)
247 {
248 GLfloat color[4];
249 GLfloat cv = (v - minv) / (maxv - minv);
250 GetRBRange1(cv * cv, 1.0, color);
251 glColor3fv(color);
252 }
253
254 /*################################################################################################*/
255
256 // eof
257