source: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp@ 7b5984

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 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 7b5984 was 7b5984, checked in by Frederik Heber <heber@…>, 10 years ago

GLMoleculeObject_molecule listens to AtomMoved signal to update hull only when necessary.

  • Property mode set to 100644
File size: 20.7 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24/*
25 * GLMoleculeObject_molecule.cpp
26 *
27 * Created on: Mar 30, 2012
28 * Author: ankele
29 */
30
31
32
33
34
35// include config.h
36#ifdef HAVE_CONFIG_H
37#include <config.h>
38#endif
39
40#include "GLMoleculeObject_molecule.hpp"
41
42#include <Qt3D/qglscenenode.h>
43#include <Qt3D/qglbuilder.h>
44
45#include "CodePatterns/MemDebug.hpp"
46
47#include "CodePatterns/Assert.hpp"
48#include "CodePatterns/Log.hpp"
49#include "CodePatterns/Observer/Notification.hpp"
50#include "CodePatterns/Observer/ObserverLog.hpp"
51
52#include "Atom/atom.hpp"
53#include "molecule.hpp"
54#include "Descriptors/AtomIdDescriptor.hpp"
55#include "Element/element.hpp"
56#include "LinearAlgebra/Vector.hpp"
57#include "LinkedCell/PointCloudAdaptor.hpp"
58#include "LinkedCell/linkedcell.hpp"
59#include "Tesselation/tesselation.hpp"
60#include "Tesselation/BoundaryLineSet.hpp"
61#include "Tesselation/BoundaryTriangleSet.hpp"
62#include "Tesselation/CandidateForTesselation.hpp"
63#include "Atom/TesselPoint.hpp"
64#include "World.hpp"
65
66#include "GLMoleculeObject_atom.hpp"
67
68static QGLSceneNode *createMoleculeMesh(const molecule *molref, QObject *parent)
69{
70// Shape shape = molref->getBoundingSphere();
71 double minradius = 2.; // TODO: set to maximum bond length value
72 LOG(3, "DEBUG: Molecule fits into sphere of radius " << minradius);
73 if (minradius < 1.)
74 minradius = 1.;
75
76 QGeometryData geo;
77 // we need at least three points for tesselation
78 if (molref->getAtomCount() >= 3) {
79 // Tesselate the points.
80 Tesselation T;
81 PointCloudAdaptor<molecule> cloud(const_cast<molecule *>(molref), molref->getName());
82 T(cloud, minradius);
83
84 // Fill the points into a Qt geometry.
85 LinkedCell_deprecated LinkedList(cloud, minradius);
86 std::map<int, int> indices;
87 std::map<int, Vector> normals;
88 int index = 0;
89 for (PointMap::const_iterator piter = T.PointsOnBoundary.begin();
90 piter != T.PointsOnBoundary.end(); ++piter) {
91 const Vector &point = piter->second->getPosition();
92 // add data to the primitive
93 geo.appendVertex(QVector3D(point[0], point[1], point[2]));
94 Vector normalvector;
95 for (LineMap::const_iterator lineiter = piter->second->lines.begin();
96 lineiter != piter->second->lines.end(); ++lineiter)
97 for (TriangleMap::const_iterator triangleiter = lineiter->second->triangles.begin();
98 triangleiter != lineiter->second->triangles.end(); ++triangleiter)
99 normalvector +=
100 triangleiter->second->NormalVector;
101 normalvector.Normalize();
102 geo.appendNormal(QVector3D(normalvector[0], normalvector[1], normalvector[2]));
103 geo.appendColor(QColor(1, 1, 1, 1));
104 geo.appendTexCoord(QVector2D(0, 0));
105 indices.insert( std::make_pair( piter->second->getNr(), index++));
106 }
107
108 // Fill the tesselated triangles into the geometry.
109 for (TriangleMap::const_iterator runner = T.TrianglesOnBoundary.begin();
110 runner != T.TrianglesOnBoundary.end(); runner++) {
111 int v[3];
112 for (size_t i=0; i<3; ++i)
113 v[i] = runner->second->endpoints[i]->getNr();
114
115 // Sort the vertices so the triangle is clockwise (relative to the normal vector).
116 Vector cross = T.PointsOnBoundary[v[1]]->getPosition() - T.PointsOnBoundary[v[0]]->getPosition();
117 cross.VectorProduct(T.PointsOnBoundary[v[2]]->getPosition() - T.PointsOnBoundary[v[0]]->getPosition());
118 if (cross.ScalarProduct(runner->second->NormalVector) > 0)
119 geo.appendIndices(indices[v[0]], indices[v[1]], indices[v[2]]);
120 else
121 geo.appendIndices(indices[v[0]], indices[v[2]], indices[v[1]]);
122 }
123 }
124
125 // Build a mesh from the geometry.
126 QGLBuilder builder;
127 builder.addTriangles(geo);
128 QGLSceneNode *mesh = builder.finalizedSceneNode();
129 return mesh;
130}
131
132GLMoleculeObject_molecule::GLMoleculeObject_molecule(QObject *parent, const molecule *molref) :
133 GLMoleculeObject(createMoleculeMesh(molref, parent), parent),
134 Observer(std::string("GLMoleculeObject_molecule")+toString(molref->getId())),
135 isSignedOn(false),
136 _molecule(molref),
137 TesselationHullUptodate(true),
138 hoverAtom(NULL)
139{
140 // sign on as observer (obtain non-const instance before)
141 _molecule->signOn(this, molecule::AtomInserted);
142 _molecule->signOn(this, molecule::AtomRemoved);
143 _molecule->signOn(this, molecule::AtomMoved);
144 isSignedOn = true;
145 /*molref->signOn(this, AtomObservable::IndexChanged);
146 molref->signOn(this, AtomObservable::PositionChanged);
147 molref->signOn(this, AtomObservable::ElementChanged);
148 molref->signOn(this, AtomObservable::BondsAdded);*/
149 setMaterial(getMaterial(1));
150 World::getInstance().signOn(this, World::SelectionChanged);
151 updateBoundingBox();
152
153 // initially, atoms and bonds should be visible
154 m_visible = false;
155
156 init();
157}
158
159GLMoleculeObject_molecule::GLMoleculeObject_molecule(QGLSceneNode *mesh[], QObject *parent, const molecule *molref) :
160 GLMoleculeObject(mesh, parent),
161 Observer(std::string("GLMoleculeObject_molecule")+toString(molref->getId())),
162 isSignedOn(false),
163 _molecule(molref),
164 TesselationHullUptodate(true),
165 hoverAtom(NULL)
166{
167 // sign on as observer (obtain non-const instance before)
168 _molecule->signOn(this, molecule::AtomInserted);
169 _molecule->signOn(this, molecule::AtomRemoved);
170 _molecule->signOn(this, molecule::AtomMoved);
171 isSignedOn = true;
172 /*molref->signOn(this, AtomObservable::IndexChanged);
173 molref->signOn(this, AtomObservable::PositionChanged);
174 molref->signOn(this, AtomObservable::ElementChanged);
175 molref->signOn(this, AtomObservable::BondsAdded);*/
176 setMaterial(getMaterial(1));
177 World::getInstance().signOn(this, World::SelectionChanged);
178 updateBoundingBox();
179
180 // initially, atoms and bonds should be visible
181 m_visible = false;
182
183 init();
184}
185
186GLMoleculeObject_molecule::~GLMoleculeObject_molecule()
187{
188 if (isSignedOn) {
189 _molecule->signOff(this, molecule::AtomInserted);
190 _molecule->signOff(this, molecule::AtomRemoved);
191 _molecule->signOff(this, molecule::AtomMoved);
192 }
193 /*_atom->signOff(this, AtomObservable::IndexChanged);
194 _atom->signOff(this, AtomObservable::PositionChanged);
195 _atom->signOff(this, AtomObservable::ElementChanged);
196 _atom->signOff(this, AtomObservable::BondsAdded);*/
197 World::getInstance().signOff(this, World::SelectionChanged);
198}
199
200/** Initialise the WorldScene with molecules and atoms from World.
201 *
202 */
203void GLMoleculeObject_molecule::init()
204{
205 if (_molecule->begin() != _molecule->end()) {
206 for (molecule::const_iterator atomiter = _molecule->begin();
207 atomiter != _molecule->end();
208 atomiter++) {
209 // create atom objects in scene
210 atomInserted((*atomiter)->getId());
211
212 // create bond objects in scene
213 const BondList &bondlist = (*atomiter)->getListOfBonds();
214 for (BondList::const_iterator bonditer = bondlist.begin();
215 bonditer != bondlist.end();
216 ++bonditer) {
217 const bond::ptr _bond = *bonditer;
218 const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == *atomiter) ?
219 GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
220 bondInserted(_bond, side);
221 }
222 }
223 }
224}
225
226void GLMoleculeObject_molecule::addAtomBonds(
227 const bond::ptr &_bond,
228 const GLMoleculeObject_bond::SideOfBond _side
229 )
230{
231 bool bond_present = false;
232 const BondIds ids = getBondIds(_bond, _side);
233 // check whether bond is not present already
234 bond_present = BondsinSceneMap.count(ids);
235 if (!bond_present)
236 bondInserted(_bond, _side);
237 else {
238 BondsinSceneMap[ids]->resetPosition();
239 BondsinSceneMap[ids]->resetWidth();
240 }
241}
242
243void GLMoleculeObject_molecule::addAtomBonds(
244 const atom *_atom)
245{
246 const bool atom_present = AtomsinSceneMap.count(_atom->getId());
247 const BondList &bondlist = _atom->getListOfBonds();
248 for (BondList::const_iterator bonditer = bondlist.begin();
249 (bonditer != bondlist.end()) && atom_present;
250 ++bonditer) {
251 const bond::ptr _bond = *bonditer;
252 // check if OtherAtom's sphere is already present
253 const atom *OtherAtom = _bond->GetOtherAtom(_atom);
254 const bool otheratom_present = AtomsinSceneMap.count(OtherAtom->getId());
255 if (otheratom_present && atom_present) {
256 const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == _atom) ?
257 GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
258 const GLMoleculeObject_bond::SideOfBond otherside = (_bond->leftatom == _atom) ?
259 GLMoleculeObject_bond::right : GLMoleculeObject_bond::left;
260 addAtomBonds(_bond, side);
261 addAtomBonds(_bond, otherside);
262 }
263 }
264}
265
266void GLMoleculeObject_molecule::reinit()
267{
268 if (_molecule->getAtomCount() > 0) {
269 for (molecule::const_iterator atomiter = _molecule->begin();
270 atomiter != _molecule->end();
271 atomiter++) {
272 // check whether atom already exists
273 const atomId_t atomid = (*atomiter)->getId();
274 const bool atom_present = AtomsinSceneMap.count(atomid);
275 if (!atom_present)
276 atomInserted((*atomiter)->getId());
277 else
278 AtomsinSceneMap[atomid]->resetPosition();
279
280
281 // create bond objects in scene
282 addAtomBonds(*atomiter);
283 }
284 }
285}
286
287void GLMoleculeObject_molecule::updateBoundingBox()
288{
289 Shape shape = _molecule->getBoundingSphere();
290 Vector v = shape.getCenter();
291 setPosition(QVector3D(v[0], v[1], v[2]));
292 setScale(shape.getRadius() + 0.3); // getBoundingShape() only sees atoms as points, so make the box a bit bigger
293}
294
295void GLMoleculeObject_molecule::update(Observable *publisher)
296{
297#ifdef LOG_OBSERVER
298 const molecule *_mol = static_cast<molecule *>(publisher);
299 observerLog().addMessage() << "++ Update of Observer " << observerLog().getName(static_cast<Observer *>(this)) << " from molecule "+toString(_mol->getId())+".";
300#endif
301}
302
303void GLMoleculeObject_molecule::subjectKilled(Observable *publisher)
304{
305 isSignedOn = false;
306}
307
308void GLMoleculeObject_molecule::recieveNotification(Observable *publisher, Notification_ptr notification)
309{
310 if (publisher == dynamic_cast<const Observable*>(_molecule)){
311 // notofication from atom
312#ifdef LOG_OBSERVER
313 observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast<Observer *>(this))
314 << " received notification from molecule " << _molecule->getId() << " for channel "
315 << notification->getChannelNo() << ".";
316#endif
317 switch (notification->getChannelNo()) {
318 case molecule::AtomInserted:
319 {
320 const atomId_t _id = _molecule->lastChanged()->getId();
321 #ifdef LOG_OBSERVER
322 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been inserted.";
323 #endif
324 TesselationHullUptodate = false;
325 atomInserted(_id);
326 break;
327 }
328 case World::AtomRemoved:
329 {
330 const atomId_t _id = _molecule->lastChanged()->getId();
331 #ifdef LOG_OBSERVER
332 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been removed.";
333 #endif
334 TesselationHullUptodate = false;
335 atomRemoved(_id);
336 break;
337 }
338 case molecule::AtomMoved:
339 {
340 const atomId_t _id = _molecule->lastChanged()->getId();
341 #ifdef LOG_OBSERVER
342 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been inserted.";
343 #endif
344 TesselationHullUptodate = false;
345 break;
346 }
347 default:
348 break;
349 }
350 }else{
351 // notification from world
352#ifdef LOG_OBSERVER
353 observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast<Observer *>(this))
354 << " received notification from world for channel "
355 << notification->getChannelNo() << ".";
356#endif
357 switch (notification->getChannelNo()) {
358 case World::SelectionChanged:
359 setSelected(World::getInstance().isSelected(_molecule));
360 break;
361 default:
362 break;
363 }
364 }
365}
366
367void GLMoleculeObject_molecule::initialize(QGLView *view, QGLPainter *painter)
368{
369 // Initialize all of the mesh objects that we have as children.
370 GLMoleculeObject::initialize(view, painter);
371 foreach (QObject *obj, children()) {
372 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
373 if (meshobj)
374 meshobj->initialize(view, painter);
375 }
376}
377
378void GLMoleculeObject_molecule::draw(QGLPainter *painter, const QVector4D &cameraPlane)
379{
380 // draw either molecule's mesh or all atoms and bonds
381 if (m_visible) {
382 updateTesselationHull();
383
384 painter->modelViewMatrix().push();
385
386 // Apply the material and effect to the painter.
387 QGLMaterial *material;
388 if (m_hovering)
389 material = m_hoverMaterial;
390 else if (m_selected)
391 material = m_selectionMaterial;
392 else
393 material = m_material;
394
395 ASSERT(material, "GLMoleculeObject::draw: chosen material is NULL");
396
397 painter->setColor(material->diffuseColor());
398 painter->setFaceMaterial(QGL::AllFaces, material);
399 if (m_effect)
400 painter->setUserEffect(m_effect);
401 else
402 painter->setStandardEffect(QGL::LitMaterial);
403
404 // Mark the object for object picking purposes.
405 int prevObjectId = painter->objectPickId();
406 if (m_objectId != -1)
407 painter->setObjectPickId(m_objectId);
408
409 m_mesh[0]->draw(painter);
410
411 // Draw a box around the mesh, if selected.
412 if (m_selected)
413 drawSelectionBox(painter);
414
415 // Turn off the user effect, if present.
416 if (m_effect)
417 painter->setStandardEffect(QGL::LitMaterial);
418
419 // Revert to the previous object identifier.
420 painter->setObjectPickId(prevObjectId);
421
422 // Restore the modelview matrix.
423 painter->modelViewMatrix().pop();
424
425 // GLMoleculeObject::draw(painter, cameraPlane);
426 } else {
427 // Draw all of the mesh objects that we have as children.
428 foreach (QObject *obj, children()) {
429 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
430 if (meshobj)
431 meshobj->draw(painter, cameraPlane);
432 }
433 }
434}
435
436/** Adds an atom of this molecule to the scene.
437 *
438 * @param _atom atom to add
439 */
440void GLMoleculeObject_molecule::atomInserted(const atomicNumber_t _id)
441{
442 LOG(3, "INFO: GLWorldScene: Received signal atomInserted for atom "+toString(_id)+".");
443 GLMoleculeObject_atom *atomObject = new GLMoleculeObject_atom(GLMoleculeObject::meshSphere, this, _id);
444 AtomNodeMap::iterator iter = AtomsinSceneMap.find(_id);
445 ASSERT(iter == AtomsinSceneMap.end(),
446 "GLWorldScene::atomAdded() - same atom with id "+toString(_id)+" added again.");
447 AtomsinSceneMap.insert( make_pair(_id, atomObject) );
448
449 qRegisterMetaType<atomId_t>("atomId_t");
450 qRegisterMetaType<bond::ptr>("bond::ptr");
451 qRegisterMetaType<GLMoleculeObject_bond::SideOfBond>("GLMoleculeObject_bond::SideOfBond");
452 connect (atomObject, SIGNAL(clicked(atomId_t)), this, SIGNAL(atomClicked(atomId_t)));
453 connect (atomObject, SIGNAL(changed()), this, SIGNAL(changed()));
454 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
455 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
456 connect (atomObject, SIGNAL(selectionChanged()), this, SIGNAL(changed()));
457 connect (atomObject, SIGNAL(BondsInserted(const bond::ptr , const GLMoleculeObject_bond::SideOfBond)), this, SLOT(bondInserted(const bond::ptr , const GLMoleculeObject_bond::SideOfBond)));
458 connect (atomObject, SIGNAL(indexChanged(GLMoleculeObject_atom*, int, int)), this, SIGNAL(changeAtomId(GLMoleculeObject_atom*, int, int)));
459
460 updateBoundingBox();
461
462 //bondsChanged(_atom);
463 emit changeOccured();
464}
465
466/** Removes an atom of this molecule from the scene.
467 *
468 * We just the id as the atom might have already been destroyed.
469 *
470 * @param _id id of atom to remove
471 */
472void GLMoleculeObject_molecule::atomRemoved(const atomicNumber_t _id)
473{
474 LOG(3, "INFO: GLWorldScene: Received signal atomRemoved for atom "+toString(_id)+".");
475 // bonds are removed by signal coming from ~bond
476 // remove atoms
477 AtomNodeMap::iterator iter = AtomsinSceneMap.find(_id);
478 ASSERT(iter != AtomsinSceneMap.end(),
479 "GLWorldScene::atomRemoved() - atom "+toString(_id)+" not on display.");
480 GLMoleculeObject_atom *atomObject = iter->second;
481 atomObject->disconnect();
482 AtomsinSceneMap.erase(iter);
483 delete atomObject;
484
485 updateBoundingBox();
486
487 emit changeOccured();
488}
489
490void GLMoleculeObject_molecule::hoverChangedSignalled(GLMoleculeObject *ob)
491{
492 // Find the atom, ob corresponds to.
493 hoverAtom = NULL;
494 GLMoleculeObject_atom *atomObject = dynamic_cast<GLMoleculeObject_atom *>(ob);
495 if (atomObject){
496 for (AtomNodeMap::iterator iter = AtomsinSceneMap.begin();iter != AtomsinSceneMap.end(); ++ iter){
497 if (iter->second == atomObject)
498 hoverAtom = World::getInstance().getAtom(AtomById(iter->first));
499 }
500 }
501
502 // Propagate signal.
503 emit hoverChanged(hoverAtom);
504}
505
506
507/** Helper function to get bond ids in the correct order for BondNodeMap.
508 *
509 * \return pair of ids in correct order.
510 */
511GLMoleculeObject_molecule::BondIds GLMoleculeObject_molecule::getBondIds(
512 const bond::ptr _bond,
513 const enum GLMoleculeObject_bond::SideOfBond _side)
514{
515 BondIds ids;
516 switch (_side) {
517 case GLMoleculeObject_bond::left:
518 ids = std::make_pair(_bond->leftatom->getId(), _bond->rightatom->getId());
519 break;
520 case GLMoleculeObject_bond::right:
521 ids = std::make_pair(_bond->rightatom->getId(), _bond->leftatom->getId());
522 break;
523 }
524 return ids;
525}
526
527/** Adds a bond to the scene.
528 *
529 * @param _bond bond to add
530 * @param side which side of the bond (left or right)
531 */
532void GLMoleculeObject_molecule::bondInserted(const bond::ptr _bond, const enum GLMoleculeObject_bond::SideOfBond _side)
533{
534 LOG(3, "INFO: GLWorldScene::bondInserted() - Adding bond "+toString(*_bond)+".");
535 //LOG(4, "INFO: Currently present bonds " << BondsinSceneMap << ".");
536
537 const BondIds ids = getBondIds(_bond, _side);
538 BondNodeMap::iterator iter = BondsinSceneMap.find(ids);
539 if (iter == BondsinSceneMap.end()) {
540 GLMoleculeObject_bond * bondObject =
541 new GLMoleculeObject_bond(GLMoleculeObject::meshCylinder, this, _bond, _side);
542 connect (
543 bondObject, SIGNAL(BondRemoved(const atomId_t, const atomId_t)),
544 this, SLOT(bondRemoved(const atomId_t, const atomId_t)));
545 connect (bondObject, SIGNAL(changed()), this, SIGNAL(changed()));
546 BondsinSceneMap.insert( make_pair(ids, bondObject) );
547 // BondIdsinSceneMap.insert( Leftids );
548 } else {
549 iter->second->resetPosition();
550 iter->second->resetWidth();
551 }
552 emit changeOccured();
553}
554
555/** Removes a bond from the scene.
556 *
557 * @param _bond bond to remove
558 */
559void GLMoleculeObject_molecule::bondRemoved(const atomId_t leftnr, const atomId_t rightnr)
560{
561 LOG(3, "INFO: GLWorldScene::bondRemoved() - Removing bond between "+toString(leftnr)+" and "+toString(rightnr)+".");
562 {
563 // left bond
564 const BondIds Leftids( make_pair(leftnr, rightnr) );
565 BondNodeMap::iterator leftiter = BondsinSceneMap.find( Leftids );
566 ASSERT(leftiter != BondsinSceneMap.end(),
567 "GLWorldScene::bondRemoved() - bond "+toString(leftnr)+"-"
568 +toString(rightnr)+" not on display.");
569 GLMoleculeObject_bond *bondObject = leftiter->second;
570 bondObject->disconnect();
571 BondsinSceneMap.erase(leftiter);
572 delete bondObject; // is done by signal from bond itself
573 //LOG(4, "INFO: Still present bonds " << BondsinSceneMap << ".");
574 }
575
576 emit changeOccured();
577}
578
579void GLMoleculeObject_molecule::setVisible(bool value)
580{
581 // first update the mesh if we are going to be visible now
582 if (value)
583 updateTesselationHull();
584 // then emit onward
585 GLMoleculeObject::setVisible(value);
586}
587
588void GLMoleculeObject_molecule::updateTesselationHull()
589{
590 if (!TesselationHullUptodate) {
591 updateMesh(createMoleculeMesh(_molecule, parent()));
592 TesselationHullUptodate = true;
593 }
594}
595
596std::ostream &operator<<(std::ostream &ost, const GLMoleculeObject_molecule::BondIds &t)
597{
598 ost << t.first << "," << t.second;
599 return ost;
600}
601
Note: See TracBrowser for help on using the repository browser.