source: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_bond.cpp@ d1831e

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

FIX: GLMoleculeObject_bond had both flipped ids and the side.

  • in essence, both do the same thing. We removed all switches that check the sides as flipped ids are actually nice and look good in the observerLog. We keep the side variable as it might come handy for checking which one we are.
  • Property mode set to 100644
File size: 10.8 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_bond.cpp
26 *
27 * Created on: Aug 17, 2011
28 * Author: heber
29 */
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include "GLMoleculeObject_bond.hpp"
37
38#include <Qt3D/qglmaterial.h>
39#include <Qt3D/qglscenenode.h>
40
41#include "CodePatterns/MemDebug.hpp"
42
43
44#include <cmath>
45
46#include "CodePatterns/Assert.hpp"
47#include "CodePatterns/Log.hpp"
48#include "CodePatterns/Observer/Notification.hpp"
49#include "CodePatterns/Observer/ObserverLog.hpp"
50#include "Descriptors/AtomIdDescriptor.hpp"
51#include "Atom/atom.hpp"
52#include "Bond/bond.hpp"
53#include "Element/element.hpp"
54#include "Helpers/defs.hpp"
55#include "LinearAlgebra/Line.hpp"
56#include "LinearAlgebra/Vector.hpp"
57#include "World.hpp"
58
59
60// static entities
61const Observable::channels_t
62GLMoleculeObject_bond::BondPositionChannels(1, AtomObservable::PositionChanged);
63const Observable::channels_t
64GLMoleculeObject_bond::BondDegreeChannels(1, BondObservable::DegreeChanged);
65const Observable::channels_t
66GLMoleculeObject_bond::BondElementChannels(1, AtomObservable::ElementChanged);
67
68GLMoleculeObject_bond::GLMoleculeObject_bond(
69 QGLSceneNode *mesh[],
70 QObject *parent,
71 const bondIds_t bondIds,
72 const enum SideOfBond side) :
73 GLMoleculeObject(mesh, parent),
74 Observer(std::string("GLMoleculeObject_bond")
75 +toString(bondIds.first)
76 +std::string("-")
77 +toString(bondIds.second)),
78 leftatomId(bondIds.first),
79 rightatomId(bondIds.second),
80 leftowner(getAtom(leftatomId)),
81 rightowner(getAtom(rightatomId)),
82 bondowner(getAtom(leftatomId)->getBond(getAtom(rightatomId)).get()),
83 BondSide(side),
84 leftPosition(
85 leftowner,
86 boost::bind(&GLMoleculeObject_bond::updateLeftPosition, this),
87 "BondleftPosition_"+toString(leftatomId),
88 updateLeftPosition(),
89 BondPositionChannels),
90 rightPosition(
91 rightowner,
92 boost::bind(&GLMoleculeObject_bond::updateRightPosition, this),
93 "BondrightPosition_"+toString(rightatomId),
94 updateRightPosition(),
95 BondPositionChannels),
96 leftElement(
97 leftowner,
98 boost::bind(&GLMoleculeObject_bond::updateLeftElement, this),
99 "BondleftElement"+toString(leftatomId),
100 updateLeftElement(),
101 BondElementChannels),
102 rightElement(
103 rightowner,
104 boost::bind(&GLMoleculeObject_bond::updateRightElement, this),
105 "BondrightElement"+toString(rightatomId),
106 updateRightElement(),
107 BondElementChannels),
108 Degree(
109 bondowner,
110 boost::bind(&GLMoleculeObject_bond::updateDegree, this),
111 "BondDegree"+toString(leftatomId)+"_"+toString(rightatomId),
112 updateDegree(),
113 BondDegreeChannels),
114 leftobservable_enabled(false),
115 rightobservable_enabled(false)
116{
117 // sign on as observer (obtain non-const instance before)
118 bondowner->signOn(this, BondObservable::BondRemoved);
119 bondowner->signOn(this, BondObservable::DegreeChanged);
120 bond_enabled = true;
121 leftowner->signOn(this, AtomObservable::PositionChanged);
122 leftowner->signOn(this, AtomObservable::ElementChanged);
123 leftobservable_enabled = true;
124 rightowner->signOn(this, AtomObservable::PositionChanged);
125 rightowner->signOn(this, AtomObservable::ElementChanged);
126 rightobservable_enabled = true;
127
128 resetElement();
129 resetPosition();
130 resetWidth();
131
132 connect(this, SIGNAL(elementChanged()), this, SLOT(resetElement()), Qt::QueuedConnection);
133 connect(this, SIGNAL(positionChanged()), this, SLOT(resetPosition()), Qt::QueuedConnection);
134 connect(this, SIGNAL(degreeChanged()), this, SLOT(resetWidth()), Qt::QueuedConnection);
135}
136
137GLMoleculeObject_bond::~GLMoleculeObject_bond()
138{
139 LOG(3, "DEBUG: Destroying GLMoleculeObject_bond to bond [" <<
140 leftatomId << "," << rightatomId << "] and side " << BondSide << ".");
141 // signOff() if not already done
142 removeChannels();
143}
144
145void GLMoleculeObject_bond::removeChannels()
146{
147 // at this point both atoms should still be alive, hence we may safely sign off
148 // from the AtomObservable itself
149 if (bond_enabled) {
150 if (bondowner != NULL) {
151 bondowner->signOff(this, BondObservable::BondRemoved);
152 bondowner->signOff(this, BondObservable::DegreeChanged);
153 }
154 bond_enabled = false;
155 }
156 if (leftobservable_enabled) {
157 if (leftowner != NULL) {
158 leftowner->signOff(this, AtomObservable::PositionChanged);
159 leftowner->signOff(this, AtomObservable::ElementChanged);
160 }
161 leftobservable_enabled = false;
162 }
163 if (rightobservable_enabled) {
164 if (rightowner != NULL) {
165 rightowner->signOff(this, AtomObservable::PositionChanged);
166 rightowner->signOff(this, AtomObservable::ElementChanged);
167 }
168 rightobservable_enabled = false;
169 }
170}
171
172void GLMoleculeObject_bond::removeMe()
173{
174 // sign off
175 emit BondRemoved(leftatomId, rightatomId);
176}
177
178void GLMoleculeObject_bond::update(Observable *publisher)
179{
180 ASSERT(0, "GLMoleculeObject_bond::update() - we are not signed on for any global updates.");
181}
182
183void GLMoleculeObject_bond::subjectKilled(Observable *publisher)
184{
185 // we signOff from all other sources
186 removeChannels();
187 // then indicate to remove us
188 removeMe();
189}
190
191void GLMoleculeObject_bond::recieveNotification(Observable *publisher, Notification_ptr notification)
192{
193#ifdef LOG_OBSERVER
194 if (publisher == static_cast<const Observable *>(bondowner)) {
195 observerLog().addMessage() << "++ Update of Observer "
196 << observerLog().getName(static_cast<Observer*>(this))
197 << " received notification from bond for channel "
198 << notification->getChannelNo() << ".";
199 } else if (publisher == static_cast<const Observable * const>(leftowner)) {
200 observerLog().addMessage() << "++ Update of Observer "
201 << observerLog().getName(static_cast<Observer*>(this))
202 << " received notification from leftatom " << leftatomId << " for channel "
203 << notification->getChannelNo() << ".";
204 } else if (publisher == static_cast<const Observable * const>(rightowner)) {
205 observerLog().addMessage() << "++ Update of Observer "
206 << observerLog().getName(static_cast<Observer*>(this))
207 << " received notification from rightatom " << rightatomId << " for channel "
208 << notification->getChannelNo() << ".";
209 }
210#endif
211 if (publisher == static_cast<const Observable *>(bondowner)){
212 switch (notification->getChannelNo()) {
213 case BondObservable::BondRemoved:
214// removeMe();
215 break;
216 case BondObservable::DegreeChanged:
217 emit degreeChanged();
218 break;
219 default:
220 ASSERT(0, "GLMoleculeObject_bond::recieveNotification() - unknown signal.");
221 break;
222 }
223 } else {
224 // from an atom
225 switch (notification->getChannelNo()) {
226 case AtomObservable::PositionChanged:
227 LOG(2, "INFO: Received notification of PositionChanged.");
228 emit positionChanged();
229 break;
230 case AtomObservable::ElementChanged:
231 LOG(2, "INFO: Received notification of ElementChanged.");
232 emit elementChanged();
233 break;
234 default:
235 break;
236 }
237 }
238}
239
240Vector GLMoleculeObject_bond::updateLeftPosition() const
241{
242 const atom * const _atom = getAtomConst(leftatomId);
243 return _atom->getPosition();
244}
245
246Vector GLMoleculeObject_bond::updateRightPosition() const
247{
248 const atom * const _atom = getAtomConst(rightatomId);
249 return _atom->getPosition();
250}
251
252atomicNumber_t GLMoleculeObject_bond::updateLeftElement() const
253{
254 const atom * const _atom = getAtomConst(leftatomId);
255 return _atom->getElementNo();
256}
257
258atomicNumber_t GLMoleculeObject_bond::updateRightElement() const
259{
260 const atom * const _atom = getAtomConst(rightatomId);
261 return _atom->getElementNo();
262}
263
264int GLMoleculeObject_bond::updateDegree() const
265{
266 const atom * const _leftatom = const_cast<const World &>(World::getInstance()).
267 getAtom(AtomById(leftatomId));
268 const atom * const _rightatom = const_cast<const World &>(World::getInstance()).
269 getAtom(AtomById(rightatomId));
270 if ((_leftatom != NULL) && (_rightatom != NULL)) {
271 bond::ptr _bond = _leftatom->getBond(_rightatom);
272 return _bond->getDegree();
273 } else {
274 return 1;
275 }
276}
277
278void GLMoleculeObject_bond::resetElement()
279{
280 size_t elementno = rightElement.get();
281 QGLMaterial *elementmaterial = getMaterial(elementno);
282 setMaterial(elementmaterial);
283}
284
285void GLMoleculeObject_bond::resetWidth()
286{
287 const double factor = 1.0f+.5f*(Degree.get()-1);
288 LOG(2, "DEBUG: GLMoleculeObject_bond::resetWidth() - setting bond's width to " << factor << ".");
289 setScaleX(factor);
290 setScaleY(factor);
291
292 emit changed();
293}
294
295void GLMoleculeObject_bond::resetPosition()
296{
297 Vector Position = leftPosition.get();
298 Vector OtherPosition = rightPosition.get();
299 const double distance =
300 Position.distance(OtherPosition)/2.;
301 setScaleZ(distance);
302
303 // calculate position
304 Vector Z(unitVec[2]); // cylinder are initially aligned along the Z axis
305 Vector zeroVec(0.,0.,0.);
306 Vector a,b;
307 Vector OtherAxis;
308 double alpha;
309 a = Position - OtherPosition;
310 // construct rotation axis
311 b = a;
312 b.VectorProduct(Z);
313 Line axis(zeroVec, b);
314 // calculate rotation angle
315 alpha = a.Angle(Z);
316 // construct other axis to check right-hand rule
317 OtherAxis = b;
318 OtherAxis.VectorProduct(Z);
319 // assure right-hand rule for the rotation
320 if (a.ScalarProduct(OtherAxis) < MYEPSILON)
321 alpha = M_PI-alpha;
322 // check
323 Vector a_rotated = axis.rotateVector(a, alpha);
324 LOG(3, "INFO: Created cylinder from "// << Position << " to " << OtherPosition
325 << a << " to " << a_rotated << " around " << b << " by " << alpha/M_PI*180. << ", respectively.");
326
327 // set position (cylinder offset is in its barymetric center)
328 Vector OneFourth(Position - 0.75 * a);
329 setPosition(QVector3D(OneFourth[0], OneFourth[1], OneFourth[2]));
330 setRotationVector(QVector3D(b[0], b[1], b[2]));
331 setRotationAngle(alpha/M_PI*180.);
332
333 emit changed();
334}
335
336atom * const GLMoleculeObject_bond::getAtom(const atomId_t _id)
337{
338 atom * const _atom = World::getInstance().getAtom(AtomById(_id));
339 return _atom;
340}
341
342const atom * const GLMoleculeObject_bond::getAtomConst(const atomId_t _id)
343{
344 const atom * const _atom = const_cast<const World &>(World::getInstance()).
345 getAtom(AtomById(_id));
346 return _atom;
347}
Note: See TracBrowser for help on using the repository browser.