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