source: src/UIElements/Views/Qt4/GLMoleculeView.cpp@ 573d72

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 Candidate_v1.7.0 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 573d72 was b40b9d, checked in by Frederik Heber <heber@…>, 14 years ago

FIX: Bonds are now displayed correctly.

  • using Vector::VectorProduct() to correctly create normal vectors and fixed therewith GLMoleculeView::makeCylinder().
  • Property mode set to 100644
File size: 31.1 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * GLMoleculeView.cpp
10 *
11 * Created on: Aug 1, 2010
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include "GLMoleculeView.hpp"
21#include <GL/glu.h>
22#include <QtGui/qslider.h>
23#include <QtGui/qevent.h>
24
25#include "ui_dialoglight.h"
26
27#include "CodePatterns/MemDebug.hpp"
28
29#include <iostream>
30#include <boost/shared_ptr.hpp>
31
32#include "LinearAlgebra/Line.hpp"
33#include "atom.hpp"
34#include "Bond/bond.hpp"
35#include "element.hpp"
36#include "molecule.hpp"
37#include "periodentafel.hpp"
38#include "World.hpp"
39
40#if defined(Q_CC_MSVC)
41#pragma warning(disable:4305) // init: truncation from const double to float
42#endif
43
44
45GLMoleculeView::GLMoleculeView(QWidget *parent) :
46 QGLWidget(parent), Observer("GLMoleculeView"), X(Vector(1,0,0)), Y(Vector(0,1,0)), Z(Vector(0,0,1))
47{
48 xRot = yRot = zRot = 0.0; // default object rotation
49 scale = 5.; // default object scale
50 object = 0;
51 LightPosition[0] = 0.0f;
52 LightPosition[1] = 2.0f;
53 LightPosition[2] = 2.0f;
54 LightPosition[3] = 0.0f;
55 LightDiffuse[0] = 0.5f;
56 LightDiffuse[1] = 0.5f;
57 LightDiffuse[2] = 0.5f;
58 LightDiffuse[3] = 0.0f;
59 LightAmbient[0] = 0.0f;
60 LightAmbient[1] = 0.0f;
61 LightAmbient[2] = 0.0f;
62 LightAmbient[3] = 0.0f;
63
64 SelectionColor[0] = 0;
65 SelectionColor[1] = 128;
66 SelectionColor[2] = 128;
67
68 MultiViewEnabled = true;
69
70 isSignaller = false;
71
72 World::getInstance().signOn(this);
73}
74
75/** Destructor of GLMoleculeView.
76 * Free's the CallList.
77 */
78GLMoleculeView::~GLMoleculeView()
79{
80 makeCurrent();
81 glDeleteLists( object, 1 );
82
83 World::getInstance().signOff(this);
84}
85
86/** Paints the conents of the OpenGL window.
87 * Clears the GL buffers, enables lighting and depth.
88 * Window is either quartered (if GLMoleculeView::MultiViewEnabled) and xy, xz, yz planar views
89 * are added. Uses the CallList, constructed during InitializeGL().
90 */
91void GLMoleculeView::paintGL()
92{
93 Vector spot;
94
95 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
96 glShadeModel(GL_SMOOTH); // Enable Smooth Shading
97 glEnable(GL_LIGHTING); // Enable Light One
98 glEnable(GL_DEPTH_TEST); // Enables Depth Testing
99 glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
100 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
101
102 // 3d viewport
103 if (MultiViewEnabled)
104 glViewport( 0, 0, (GLint)width/2, (GLint)height/2 );
105 else
106 glViewport( 0, 0, (GLint)width, (GLint)height );
107 glMatrixMode( GL_PROJECTION );
108 glLoadIdentity();
109 glFrustum( -1.0, 1.0, -1.0, 1.0, 1.0, 50.0 );
110 glMatrixMode( GL_MODELVIEW );
111 glLoadIdentity();
112
113 // calculate point of view and direction
114 glTranslated(position[0],position[1],position[2]);
115 glTranslated(0.0, 0.0, -scale);
116 glRotated(xRot, 1.0, 0.0, 0.0);
117 glRotated(yRot, 0.0, 1.0, 0.0);
118 glRotated(zRot, 0.0, 0.0, 1.0);
119
120 // render scene
121 glCallList(object);
122
123 // enable light
124 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
125 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
126 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
127 glEnable(GL_LIGHT1); // Enable Light One
128
129 if (MultiViewEnabled) {
130 // xy view port
131 glViewport( (GLint)width/2, 0, (GLint)width/2, (GLint)height/2 );
132 glMatrixMode( GL_PROJECTION );
133 glLoadIdentity();
134 glScalef(1./scale, 1./scale,1./scale);
135 glOrtho(0, width/2, 0, height/2, 0,0);
136 glMatrixMode( GL_MODELVIEW );
137 glLoadIdentity();
138
139 // calculate point of view and direction
140 view = position;
141 spot = Vector(0.,0.,scale);
142 top = Vector(0.,1.,0.);
143 gluLookAt(
144 spot[0], spot[1], spot[2],
145 view[0], view[1], view[2],
146 top[0], top[1], top[2]);
147
148 // enable light
149 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
150 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
151 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
152 glEnable(GL_LIGHT1); // Enable Light One
153
154 // render scene
155 glCallList(object);
156
157 // xz viewport
158 glViewport( 0, (GLint)height/2, (GLint)width/2, (GLint)height/2 );
159 glMatrixMode( GL_PROJECTION );
160 glLoadIdentity();
161 glScalef(1./scale, 1./scale,1./scale);
162 glOrtho(0, width/2, 0, height/2, 0,0);
163 glMatrixMode( GL_MODELVIEW );
164 glLoadIdentity();
165
166 // calculate point of view and direction
167 view = position;
168 spot = Vector(0.,scale,0.);
169 top = Vector(1.,0.,0.);
170 gluLookAt(
171 spot[0], spot[1], spot[2],
172 view[0], view[1], view[2],
173 top[0], top[1], top[2]);
174
175 // enable light
176 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
177 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
178 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
179 glEnable(GL_LIGHT1); // Enable Light One
180
181 // render scene
182 glCallList(object);
183
184 //yz viewport
185 glViewport( (GLint)width/2, (GLint)height/2, (GLint)width/2, (GLint)height/2 );
186 glMatrixMode( GL_PROJECTION );
187 glLoadIdentity();
188 glScalef(1./scale, 1./scale,1./scale);
189 glOrtho(0, width/2, 0, height/2, 0,0);
190 glMatrixMode( GL_MODELVIEW );
191 glLoadIdentity();
192
193 // calculate point of view and direction
194 view= position;
195 spot = Vector(scale,0.,0.);
196 top = Vector(0.,1.,0.);
197 gluLookAt(
198 spot[0], spot[1], spot[2],
199 view[0], view[1], view[2],
200 top[0], top[1], top[2]);
201
202 // enable light
203 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
204 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
205 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // Position The Light
206 glEnable(GL_LIGHT1); // Enable Light One
207
208 // render scene
209 glCallList(object);
210 }
211 //CoordinatesBar->setText( QString ("X: %1, Y: %2, Z: %3").arg(position[0]).arg(position[1]).arg(position[2]) );
212}
213
214//void polarView{GLdouble distance, GLdouble twist,
215// GLdouble elevation, GLdouble azimuth)
216//{
217// glTranslated(0.0, 0.0, -distance);
218// glRotated(-twist, 0.0, 0.0, 1.0);
219// glRotated(-elevation, 1.0, 0.0, 0.0);
220// glRotated(azimuth, 0.0, 0.0, 1.0);
221//}
222
223/** Make a sphere.
224 * \param x position
225 * \param radius radius
226 * \param color[3] color rgb values
227 */
228void GLMoleculeView::makeSphere(const Vector &x, double radius, const unsigned char color[3])
229{
230 float blueMaterial[] = { 255./(float)color[0], 255./(float)color[1], 255./(float)color[2], 1 }; // need to recast from [0,255] with integers into [0,1] with floats
231 GLUquadricObj* q = gluNewQuadric ();
232 gluQuadricOrientation(q, GLU_OUTSIDE);
233
234 std::cout << "Setting sphere at " << x << " with color r"
235 << (int)color[0] << ",g" << (int)color[1] << ",b" << (int)color[2] << "." << endl;
236
237 glPushMatrix();
238 glTranslatef( x[0], x[1], x[2]);
239// glRotatef( xRot, 1.0, 0.0, 0.0);
240// glRotatef( yRot, 0.0, 1.0, 0.0);
241// glRotatef( zRot, 0.0, 0.0, 1.0);
242 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blueMaterial);
243 gluSphere (q, (GLdouble)radius, 10, 10);
244 glPopMatrix();
245}
246
247/** Make a cylinder.
248 * \param x origin
249 * \param y direction
250 * \param radius thickness
251 * \param height length
252 * \color[3] color rgb values
253 */
254void GLMoleculeView::makeCylinder(const Vector &x, const Vector &y, double radius, double height, const unsigned char color[3])
255{
256 float blueMaterial[] = { 255./(float)color[0], 255./(float)color[1], 255./(float)color[2], 1 };
257 GLUquadricObj* q = gluNewQuadric ();
258 gluQuadricOrientation(q, GLU_OUTSIDE);
259 Vector a,b;
260 Vector OtherAxis;
261 double alpha;
262 a = x - y;
263 // construct rotation axis
264 b = a;
265 b.VectorProduct(Z);
266 Line axis(zeroVec, b);
267 // calculate rotation angle
268 alpha = a.Angle(Z);
269 // construct other axis to check right-hand rule
270 OtherAxis = b;
271 OtherAxis.VectorProduct(Z);
272 // assure right-hand rule for the rotation
273 if (a.ScalarProduct(OtherAxis) < MYEPSILON)
274 alpha = M_PI-alpha;
275 // check
276 Vector a_rotated = axis.rotateVector(a, alpha);
277 std::cout << "Setting cylinder from "// << x << " to " << y
278 << a << " to " << a_rotated << " around " << b << " by " << alpha/M_PI*180. << ", respectively, "
279 << " with color r"
280 << (int)color[0] << ",g" << (int)color[1] << ",b" << (int)color[2] << "." << endl;
281
282 glPushMatrix();
283 glTranslatef( x[0], x[1], x[2]);
284 glRotatef( alpha/M_PI*180., b[0], b[1], b[2]);
285 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blueMaterial);
286 gluCylinder (q, (GLdouble)radius, (GLdouble)radius, (GLdouble)height, 10, 10);
287 glPopMatrix();
288}
289
290/** Defines the display CallList.
291 * Goes through all molecules and their atoms and adds spheres for atoms and cylinders
292 * for bonds. Heeds GLMoleculeView::SelectedAtom and GLMoleculeView::SelectedMolecule.
293 */
294void GLMoleculeView::initializeGL()
295{
296 double x[3] = {-1, 0, -10};
297 unsigned char white[3] = {255,255,255};
298 Vector Position, OtherPosition;
299 QSize window = size();
300 width = window.width();
301 height = window.height();
302 std::cout << "Setting width to " << width << " and height to " << height << std::endl;
303 GLfloat shininess[] = { 0.0 };
304 GLfloat specular[] = { 0, 0, 0, 1 };
305 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Let OpenGL clear to black
306 object = glGenLists(1);
307 glNewList( object, GL_COMPILE );
308 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
309 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
310
311 const std::vector<molecule*> &molecules = World::getInstance().getAllMolecules();
312
313 if (molecules.size() > 0) {
314 for (std::vector<molecule*>::const_iterator Runner = molecules.begin();
315 Runner != molecules.end();
316 Runner++) {
317 for (molecule::const_iterator atomiter = (*Runner)->begin();
318 atomiter != (*Runner)->end();
319 ++atomiter) {
320 // create atom
321 const element *ptr = (*atomiter)->getType();
322 boost::shared_ptr<Vector> MolCenter((*Runner)->DetermineCenterOfGravity());
323 Position = (*atomiter)->getPosition() - *MolCenter;
324 const unsigned char* color = NULL;
325 if ((World::getInstance().isSelected(*atomiter)) || (World::getInstance().isSelected((*Runner))))
326 color = SelectionColor;
327 else
328 color = ptr->getColor();
329 makeSphere(Position, ptr->getVanDerWaalsRadius()*0.25, color);
330
331 // create bonds
332 const BondList &bonds = (*atomiter)->getListOfBonds();
333 for (BondList::const_iterator bonditer = bonds.begin();
334 bonditer != bonds.end();
335 ++bonditer) {
336 if ((*bonditer)->leftatom->getId() == (*atomiter)->getId()) {
337 Position = (*bonditer)->leftatom->getPosition() - *MolCenter;
338 OtherPosition = (*bonditer)->rightatom->getPosition() - *MolCenter;
339 const double distance = sqrt(Position.DistanceSquared(OtherPosition))/2.;
340 const unsigned char *color1 = (*bonditer)->leftatom->getType()->getColor();
341 const unsigned char *color2 = (*bonditer)->rightatom->getType()->getColor();
342 makeCylinder(Position, OtherPosition, 0.1, distance, color1);
343 makeCylinder(OtherPosition, Position, 0.1, distance, color2);
344 }
345 }
346 }
347 }
348 } else {
349 makeSphere( x,1, white);
350 }
351 glEndList();
352}
353
354
355/* ================================== SLOTS ============================== */
356
357/** Initializes some public variables.
358 * \param *ptr pointer to QLabel statusbar
359 */
360void GLMoleculeView::init(QLabel *ptr)
361{
362 StatusBar = ptr;
363}
364
365/** Initializes the viewport statusbar.
366 * \param *ptr pointer to QLabel for showing view pointcoordinates.
367 */
368void GLMoleculeView::initCoordinates(QLabel *ptr)
369{
370 CoordinatesBar = ptr;
371}
372
373/** Slot to be called when to initialize GLMoleculeView::MolData.
374 */
375void GLMoleculeView::createView( )
376{
377 initializeGL();
378 updateGL();
379}
380
381/** Slot of window is resized.
382 * Copies new width and height to GLMoleculeView::width and GLMoleculeView::height and calls updateGL().
383 * \param w new width of window
384 * \param h new height of window
385 */
386void GLMoleculeView::resizeGL( int w, int h )
387{
388 width = w;
389 height = h;
390 updateGL();
391}
392
393/** Sets x rotation angle.
394 * sets GLMoleculeView::xRot and calls updateGL().
395 * \param degrees new rotation angle in degrees
396 */
397void GLMoleculeView::setXRotation( int degrees )
398{
399 xRot = (GLfloat)(degrees % 360);
400 updateGL();
401}
402
403
404/** Sets y rotation angle.
405 * sets GLMoleculeView::yRot and calls updateGL().
406 * \param degrees new rotation angle in degrees
407 */
408void GLMoleculeView::setYRotation( int degrees )
409{
410 yRot = (GLfloat)(degrees % 360);
411 updateGL();
412}
413
414
415/** Sets z rotation angle.
416 * sets GLMoleculeView::zRot and calls updateGL().
417 * \param degrees new rotation angle in degrees
418 */
419void GLMoleculeView::setZRotation( int degrees )
420{
421 zRot = (GLfloat)(degrees % 360);
422 updateGL();
423}
424
425/** Sets the scale of the scene.
426 * sets GLMoleculeView::scale and calls updateGL().
427 * \param distance distance divided by 100 is the new scale
428 */
429void GLMoleculeView::setScale( int distance )
430{
431 scale = (GLfloat)(distance / 100.);
432 updateGL();
433}
434
435/** Update the ambient light.
436 * \param light[4] light strength per axis and position (w)
437 */
438void GLMoleculeView::setLightAmbient( int *light )
439{
440 for(int i=0;i<4;i++)
441 LightAmbient[i] = light[i];
442 updateGL();
443}
444
445/** Update the diffuse light.
446 * \param light[4] light strength per axis and position (w)
447 */
448void GLMoleculeView::setLightDiffuse( int *light )
449{
450 for(int i=0;i<4;i++)
451 LightDiffuse[i] = light[i];
452 updateGL();
453}
454
455/** Update the position of light.
456 * \param light[4] light strength per axis and position (w)
457 */
458void GLMoleculeView::setLightPosition( int *light )
459{
460 for(int i=0;i<4;i++)
461 LightPosition[i] = light[i];
462 updateGL();
463}
464
465/** Toggles the boolean GLMoleculeView::MultiViewEnabled.
466 * Flips the boolean and calls updateGL().
467 */
468void GLMoleculeView::toggleMultiViewEnabled ( )
469{
470 MultiViewEnabled = !MultiViewEnabled;
471 cout << "Setting MultiView to " << MultiViewEnabled << "." << endl;
472 updateGL();
473}
474
475/** Launch a dialog to configure the lights.
476 */
477void GLMoleculeView::createDialogLight()
478{
479// Ui_DialogLight *Lights = new Ui_DialogLight();
480// if (Lights == NULL)
481// return;
482// // Set up the dynamic dialog here
483// QLineEdit *Field = NULL;
484// Field = Lights->findChild<QLineEdit *>("LightPositionX");
485// if (Field) Field->setText( QString("%1").arg(LightPosition[0]) );
486// Field = Lights->findChild<QLineEdit *>("LightPositionY");
487// if (Field) Field->setText( QString("%1").arg(LightPosition[1]) );
488// Field = Lights->findChild<QLineEdit *>("LightPositionZ");
489// if (Field) Field->setText( QString("%1").arg(LightPosition[2]) );
490// Field = Lights->findChild<QLineEdit *>("LightPositionW");
491// if (Field) Field->setText( QString("%1").arg(LightPosition[3]) );
492//
493// Field = Lights->findChild<QLineEdit *>("LightDiffuseX");
494// if (Field) Field->setText( QString("%1").arg(LightDiffuse[0]) );
495// Field = Lights->findChild<QLineEdit *>("LightDiffuseY");
496// if (Field) Field->setText( QString("%1").arg(LightDiffuse[1]) );
497// Field = Lights->findChild<QLineEdit *>("LightDiffuseZ");
498// if (Field) Field->setText( QString("%1").arg(LightDiffuse[2]) );
499// Field = Lights->findChild<QLineEdit *>("LightDiffuseW");
500// if (Field) Field->setText( QString("%1").arg(LightDiffuse[3]) );
501//
502// Field = Lights->findChild<QLineEdit *>("LightAmbientX");
503// if (Field) Field->setText( QString("%1").arg(LightAmbient[0]) );
504// Field = Lights->findChild<QLineEdit *>("LightAmbientY");
505// if (Field) Field->setText( QString("%1").arg(LightAmbient[1]) );
506// Field = Lights->findChild<QLineEdit *>("LightAmbientZ");
507// if (Field) Field->setText( QString("%1").arg(LightAmbient[2]) );
508// Field = Lights->findChild<QLineEdit *>("LightAmbientW");
509// if (Field) Field->setText( QString("%1").arg(LightAmbient[3]) );
510//
511// if ( Lights->exec() ) {
512// //cout << "User accepted.\n";
513// // The user accepted, act accordingly
514// Field = Lights->findChild<QLineEdit *>("LightPositionX");
515// if (Field) LightPosition[0] = Field->text().toDouble();
516// Field = Lights->findChild<QLineEdit *>("LightPositionY");
517// if (Field) LightPosition[1] = Field->text().toDouble();
518// Field = Lights->findChild<QLineEdit *>("LightPositionZ");
519// if (Field) LightPosition[2] = Field->text().toDouble();
520// Field = Lights->findChild<QLineEdit *>("LightPositionW");
521// if (Field) LightPosition[3] = Field->text().toDouble();
522//
523// Field = Lights->findChild<QLineEdit *>("LightDiffuseX");
524// if (Field) LightDiffuse[0] = Field->text().toDouble();
525// Field = Lights->findChild<QLineEdit *>("LightDiffuseY");
526// if (Field) LightDiffuse[1] = Field->text().toDouble();
527// Field = Lights->findChild<QLineEdit *>("LightDiffuseZ");
528// if (Field) LightDiffuse[2] = Field->text().toDouble();
529// Field = Lights->findChild<QLineEdit *>("LightDiffuseW");
530// if (Field) LightDiffuse[3] = Field->text().toDouble();
531//
532// Field = Lights->findChild<QLineEdit *>("LightAmbientX");
533// if (Field) LightAmbient[0] = Field->text().toDouble();
534// Field = Lights->findChild<QLineEdit *>("LightAmbientY");
535// if (Field) LightAmbient[1] = Field->text().toDouble();
536// Field = Lights->findChild<QLineEdit *>("LightAmbientZ");
537// if (Field) LightAmbient[2] = Field->text().toDouble();
538// Field = Lights->findChild<QLineEdit *>("LightAmbientW");
539// if (Field) LightAmbient[3] = Field->text().toDouble();
540// updateGL();
541// } else {
542// //cout << "User reclined.\n";
543// }
544// delete(Lights);
545}
546
547/** Slot for event of pressed mouse button.
548 * Switch discerns between buttons and stores position of event in GLMoleculeView::LeftButtonPos,
549 * GLMoleculeView::MiddleButtonPos or GLMoleculeView::RightButtonPos.
550 * \param *event structure containing information of the event
551 */
552void GLMoleculeView::mousePressEvent(QMouseEvent *event)
553{
554 std::cout << "MousePressEvent." << endl;
555 QPoint *pos = NULL;
556 switch (event->button()) { // get the right array
557 case Qt::LeftButton:
558 pos = &LeftButtonPos;
559 std::cout << "Left Button" << endl;
560 break;
561 case Qt::MidButton:
562 pos = &MiddleButtonPos;
563 std::cout << "Middle Button" << endl;
564 break;
565 case Qt::RightButton:
566 pos = &RightButtonPos;
567 std::cout << "Right Button" << endl;
568 break;
569 default:
570 break;
571 }
572 if (pos) { // store the position
573 pos->setX(event->pos().x());
574 pos->setY(event->pos().y());
575 std::cout << "Stored src position is (" << pos->x() << "," << pos->y() << ")." << endl;
576 } else {
577 std::cout << "pos is NULL." << endl;
578 }
579}
580
581/** Slot for event of pressed mouse button.
582 * Switch discerns between buttons:
583 * -# Left Button: Rotates the view of the GLMoleculeView, relative to GLMoleculeView::LeftButtonPos.
584 * -# Middle Button: nothing
585 * -# Right Button: Shifts the selected molecule or atom, relative to GLMoleculeView::RightButtonPos.
586 * \param *event structure containing information of the event
587 */
588void GLMoleculeView::mouseReleaseEvent(QMouseEvent *event)
589{
590 std::cout << "MouseReleaseEvent." << endl;
591 QPoint *srcpos = NULL;
592 QPoint destpos = event->pos();
593 int Width = (MultiViewEnabled) ? width/2 : width;
594 int Height = (MultiViewEnabled) ? height/2 : height;
595 std::cout << "Received dest position is (" << destpos.x() << "," << destpos.y() << ")." << endl;
596 switch (event->button()) { // get the right array
597 case Qt::LeftButton: // LeftButton rotates the view
598 srcpos = &LeftButtonPos;
599 std::cout << "Left Button" << endl;
600 if (srcpos) { // subtract the position and act
601 std::cout << "Stored src position is (" << srcpos->x() << "," << srcpos->y() << ")." << endl;
602 destpos -= *srcpos;
603 std::cout << "Resulting diff position is (" << destpos.x() << "," << destpos.y() << ")." << endl;
604 std::cout << "Width and Height are " << Width << "," << Height << "." << endl;
605
606 int pos = (int)floor((double)srcpos->x()/(double)Width) + ((int)floor((double)srcpos->y()/(double)Height))*2;
607 if ((MultiViewEnabled) && (pos != 2)) { // means four regions, and we are in a shifting one
608 // switch between three regions
609 // decide into which of the four screens the initial click has been made
610 std::cout << "Position is " << pos << "." << endl;
611 switch(pos) {
612 case 0: // lower left = xz
613 position[0] += -destpos.y()/100.;
614 position[2] += destpos.x()/100.;
615 break;
616 case 1: // lower right = yz
617 position[1] += -destpos.y()/100.;
618 position[2] += -destpos.x()/100.;
619 break;
620 case 2: // upper left = projected
621 std::cout << "This is impossible: Shifting in the projected region, we should rotate!." << endl;
622 break;
623 case 3: // upper right = xy
624 position[0] += destpos.x()/100.;
625 position[1] += -destpos.y()/100.;
626 break;
627 default:
628 std::cout << "click was not in any of the four regions." << endl;
629 break;
630 }
631 updateGL();
632 } else { // we are in rotation region
633 QWidget *Parent = parentWidget();
634 QSlider *sliderX = Parent->findChild<QSlider *>("sliderX");
635 QSlider *sliderY = Parent->findChild<QSlider *>("sliderY");
636 std::cout << sliderX << " and " << sliderY << endl;
637 if (sliderX) {
638 int xrange = sliderX->maximum() - sliderX->minimum();
639 double xValue = ((destpos.x() + Width) % Width);
640 xValue *= (double)xrange/(double)Width;
641 xValue += sliderX->value();
642 int xvalue = (int) xValue % xrange;
643 std::cout << "Setting x to " << xvalue << " within range " << xrange << "." << endl;
644 setXRotation(xvalue);
645 sliderX->setValue(xvalue);
646 } else {
647 std::cout << "sliderX is NULL." << endl;
648 }
649 if (sliderY) {
650 int yrange = sliderY->maximum() - sliderY->minimum();
651 double yValue = ((destpos.y() + Height) % Height);
652 yValue *= (double)yrange/(double)Height;
653 yValue += sliderY->value();
654 int yvalue = (int) yValue % yrange;
655 std::cout << "Setting y to " << yvalue << " within range " << yrange << "." << endl;
656 setYRotation(yvalue);
657 sliderY->setValue(yvalue);
658 } else {
659 std::cout << "sliderY is NULL." << endl;
660 }
661 }
662 } else {
663 std::cout << "srcpos is NULL." << endl;
664 }
665 break;
666
667 case Qt::MidButton: // MiddleButton has no function so far
668 srcpos = &MiddleButtonPos;
669 std::cout << "Middle Button" << endl;
670 if (srcpos) { // subtract the position and act
671 QWidget *Parent = parentWidget();
672 QSlider *sliderZ = Parent->findChild<QSlider *>("sliderZ");
673 QSlider *sliderScale = Parent->findChild<QSlider *>("sliderScale");
674 std::cout << sliderZ << " and " << sliderScale << endl;
675 std::cout << "Stored src position is (" << srcpos->x() << "," << srcpos->y() << ")." << endl;
676 destpos -= *srcpos;
677 std::cout << "Resulting diff position is (" << destpos.x() << "," << destpos.y() << ")." << endl;
678 std::cout << "Width and Height are " << Width << "," << Height << "." << endl;
679 if (sliderZ) {
680 int xrange = sliderZ->maximum() - sliderZ->minimum();
681 double xValue = ((destpos.x() + Width) % Width);
682 xValue *= (double)xrange/(double)Width;
683 xValue += sliderZ->value();
684 int xvalue = (int) xValue % xrange;
685 std::cout << "Setting x to " << xvalue << " within range " << xrange << "." << endl;
686 setZRotation(xvalue);
687 sliderZ->setValue(xvalue);
688 } else {
689 std::cout << "sliderZ is NULL." << endl;
690 }
691 if (sliderScale) {
692 int yrange = sliderScale->maximum() - sliderScale->minimum();
693 double yValue = ((destpos.y() + Height) % Height);
694 yValue *= (double)yrange/(double)Height;
695 yValue += sliderScale->value();
696 int yvalue = (int) yValue % yrange;
697 std::cout << "Setting y to " << yvalue << " within range " << yrange << "." << endl;
698 setScale(yvalue);
699 sliderScale->setValue(yvalue);
700 } else {
701 std::cout << "sliderScale is NULL." << endl;
702 }
703 } else {
704 std::cout << "srcpos is NULL." << endl;
705 }
706 break;
707 break;
708
709 case Qt::RightButton: // RightButton moves eitstdher the selected molecule or atom
710 srcpos = &RightButtonPos;
711 std::cout << "Right Button" << endl;
712 if (srcpos) { // subtract the position and act
713 std::cout << "Stored src position is (" << srcpos->x() << "," << srcpos->y() << ")." << endl;
714 destpos -= *srcpos;
715 std::cout << "Resulting diff position is (" << destpos.x() << "," << destpos.y() << ")." << endl;
716 std::cout << "Width and Height are " << Width << "," << Height << "." << endl;
717 if (MultiViewEnabled) {
718 // which vector to change
719 Vector SelectedPosition;
720 const std::vector<atom*> &SelectedAtoms = World::getInstance().getSelectedAtoms();
721 const std::vector<molecule*> &SelectedMolecules = World::getInstance().getSelectedMolecules();
722 if (SelectedMolecules.size()) {
723 if (SelectedAtoms.size())
724 SelectedPosition = (*SelectedAtoms.begin())->getPosition();
725 else
726 SelectedPosition = (*(*SelectedMolecules.begin())->begin())->getPosition();
727 }
728 // decide into which of the four screens the initial click has been made
729 int pos = (int)floor((double)srcpos->x()/(double)Width) + ((int)floor((double)srcpos->y()/(double)Height))*2;
730 if (!SelectedPosition.IsZero()) {
731 std::cout << "Position is " << pos << "." << endl;
732 switch(pos) {
733 case 0: // lower left = xz
734 SelectedPosition[0] += -destpos.y()/100.;
735 SelectedPosition[2] += destpos.x()/100.;
736 break;
737 case 1: // lower right = yz
738 SelectedPosition[1] += -destpos.y()/100.;
739 SelectedPosition[2] += -destpos.x()/100.;
740 break;
741 case 2: // upper left = projected
742 SelectedPosition[0] += destpos.x()/100.;
743 SelectedPosition[1] += destpos.y()/100.;
744 SelectedPosition[2] += destpos.y()/100.;
745 break;
746 case 3: // upper right = xy
747 SelectedPosition[0] += destpos.x()/100.;
748 SelectedPosition[1] += -destpos.y()/100.;
749 break;
750 default:
751 std::cout << "click was not in any of the four regions." << endl;
752 break;
753 }
754 } else {
755 std::cout << "Nothing selected." << endl;
756 }
757 // update Tables
758 if (SelectedMolecules.size()) {
759 isSignaller = true;
760 if (SelectedAtoms.size())
761 emit notifyAtomChanged( (*SelectedMolecules.begin()), (*SelectedAtoms.begin()), AtomPosition);
762 else
763 emit notifyMoleculeChanged( (*SelectedMolecules.begin()), MoleculePosition );
764 }
765 // update graphic
766 initializeGL();
767 updateGL();
768 } else {
769 cout << "MultiView is not enabled." << endl;
770 }
771 } else {
772 cout << "srcpos is NULL." << endl;
773 }
774 break;
775
776 default:
777 break;
778 }
779}
780
781/* ======================================== SLOTS ================================ */
782
783/** Hear announcement of selected molecule.
784 * \param *mol pointer to selected molecule
785 */
786void GLMoleculeView::hearMoleculeSelected(molecule *mol)
787{
788 if (isSignaller) { // if we emitted the signal, return
789 isSignaller = false;
790 return;
791 }
792 initializeGL();
793 updateGL();
794};
795
796/** Hear announcement of selected atom.
797 * \param *mol pointer to molecule containing atom
798 * \param *Walker pointer to selected atom
799 */
800void GLMoleculeView::hearAtomSelected(molecule *mol, atom *Walker)
801{
802 if (isSignaller) { // if we emitted the signal, return
803 isSignaller = false;
804 return;
805 }
806 initializeGL();
807 updateGL();
808};
809
810/** Hear announcement of changed molecule.
811 * \param *mol pointer to changed molecule
812 * \param type of change
813 */
814void GLMoleculeView::hearMoleculeChanged(molecule *mol, enum ChangesinMolecule type)
815{
816 if (isSignaller) { // if we emitted the signal, return
817 isSignaller = false;
818 return;
819 }
820 initializeGL();
821 updateGL();
822};
823
824/** Hear announcement of changed atom.
825 * \param *mol pointer to molecule containing atom
826 * \param *Walker pointer to changed atom
827 * \param type type of change
828 */
829void GLMoleculeView::hearAtomChanged(molecule *mol, atom *Walker, enum ChangesinAtom type)
830{
831 if (isSignaller) { // if we emitted the signal, return
832 isSignaller = false;
833 return;
834 }
835 initializeGL();
836 updateGL();
837};
838
839/** Hear announcement of changed element.
840 * \param *Runner pointer to changed element
841 * \param type of change
842 */
843void GLMoleculeView::hearElementChanged(element *Runner, enum ChangesinElement type)
844{
845 if (isSignaller) { // if we emitted the signal, return
846 isSignaller = false;
847 return;
848 }
849 switch(type) {
850 default:
851 case ElementName:
852 case ElementSymbol:
853 case ElementMass:
854 case ElementValence:
855 case ElementZ:
856 break;
857 case ElementCovalent:
858 case ElementVanderWaals:
859 initializeGL();
860 updateGL();
861 break;
862 }
863};
864
865/** Hear announcement of added molecule.
866 * \param *mol pointer to added molecule
867 */
868void GLMoleculeView::hearMoleculeAdded(molecule *mol)
869{
870 if (isSignaller) { // if we emitted the signal, return
871 isSignaller = false;
872 return;
873 }
874 initializeGL();
875 updateGL();
876};
877
878/** Hear announcement of added atom.
879 * \param *mol pointer to molecule containing atom
880 * \param *Walker pointer to added atom
881 */
882void GLMoleculeView::hearAtomAdded(molecule *mol, atom *Walker)
883{
884 if (isSignaller) { // if we emitted the signal, return
885 isSignaller = false;
886 return;
887 }
888 initializeGL();
889 updateGL();
890};
891
892/** Hear announcement of removed molecule.
893 * \param *mol pointer to removed molecule
894 */
895void GLMoleculeView::hearMoleculeRemoved(molecule *mol)
896{
897 if (isSignaller) { // if we emitted the signal, return
898 isSignaller = false;
899 return;
900 }
901 initializeGL();
902 updateGL();
903};
904
905/** Hear announcement of removed atom.
906 * \param *mol pointer to molecule containing atom
907 * \param *Walker pointer to removed atom
908 */
909void GLMoleculeView::hearAtomRemoved(molecule *mol, atom *Walker)
910{
911 if (isSignaller) { // if we emitted the signal, return
912 isSignaller = false;
913 return;
914 }
915 initializeGL();
916 updateGL();
917};
918
919void GLMoleculeView::update(Observable *publisher)
920{
921 initializeGL();
922 updateGL();
923}
924
925/**
926 * This method is called when a special named change
927 * of the Observable occured
928 */
929void GLMoleculeView::recieveNotification(Observable *publisher, Notification_ptr notification)
930{
931 initializeGL();
932 updateGL();
933}
934
935/**
936 * This method is called when the observed object is destroyed.
937 */
938void GLMoleculeView::subjectKilled(Observable *publisher)
939{
940
941}
942
943
Note: See TracBrowser for help on using the repository browser.