/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2016 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MoleCuilder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MoleCuilder. If not, see . */ /* * QtObservedBond.cpp * * Created on: Mar 03, 2016 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "QtObservedBond.hpp" #include #include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp" #include "CodePatterns/MemDebug.hpp" #include #include "Atom/atom.hpp" #include "Bond/bond.hpp" #include "World.hpp" #include "UIElements/Qt4/InstanceBoard/ObservedValue_wCallback.hpp" using namespace boost::assign; static const Observable::channels_t getAllObservedAtomChannels() { Observable::channels_t channels; channels += AtomObservable::IndexChanged, AtomObservable::ElementChanged, AtomObservable::PositionChanged; return channels; } static const molecule * getMolecule(const bond::ptr _bond) { ASSERT( _bond->leftatom->getMolecule() == _bond->rightatom->getMolecule(), "getMolecule() - leftatom and rightatom belong to different molecules."); return _bond->leftatom->getMolecule(); } static const molecule * const getMoleculeConst(const bond::ptr _bond) { ASSERT( _bond->leftatom->getMolecule() == _bond->rightatom->getMolecule(), "getMolecule() - leftatom and rightatom belong to different molecules."); return _bond->leftatom->getMolecule(); } template Observable * const getObservable(const T * _ptr) { return static_cast( const_cast(_ptr)); } static QtObservedBond::ObservableCount_t initAllsignedOnChannels(const bond::ptr _bond) { const QtObservedBond::ObservableCount_t returnlist = boost::assign::list_of< QtObservedBond::ObservableCount_t::value_type > ( getObservable(_bond.get()), 1) ( getObservable(_bond->leftatom), getAllObservedAtomChannels().size()) ( getObservable(_bond->rightatom), getAllObservedAtomChannels().size()) ( getObservable(getMolecule(_bond)), 1); return returnlist; } // static entities const Observable::channels_t QtObservedBond::BondDegreeChannels(1, BondObservable::DegreeChanged); QtObservedBond::QtObservedBond( const bondId_t _id, const bond::ptr _bond, QtObservedInstanceBoard &_board, QWidget * _parent) : QWidget(_parent), Observer("QtObservedBond"), AllsignedOnChannels(initAllsignedOnChannels(_bond)), bondowner(NULL), leftatomowner(NULL), rightatomowner(NULL), moleculeowner(NULL), oldbondId(_id), oldleftatomId(_id.first), oldrightatomId(_id.second), oldmoleculeId(getMolecule(_bond)->getId()), board(_board), BoardIsGone(false), ObservedValues(QtObservedBond::MAX_ObservedTypes) { qRegisterMetaType("bondId_t"); typedef boost::function map_accessor_t; const map_accessor_t accessor = boost::bind( &ObservableCount_t::at, boost::ref(subjectKilledCount), _1); const boost::function bondSubjectKilled( boost::bind(&QtObservedBond::countValuesSubjectKilled, boost::ref(*this), boost::bind(&QtObservedBond::getIndex, boost::cref(*this)), boost::bind(accessor, getObservable(_bond.get())))); const boost::function leftatomSubjectKilled( boost::bind(&QtObservedBond::countValuesSubjectKilled, boost::ref(*this), boost::bind(&QtObservedBond::getIndex, boost::cref(*this)), boost::bind(accessor, getObservable(_bond->leftatom)))); const boost::function rightatomSubjectKilled( boost::bind(&QtObservedBond::countValuesSubjectKilled, boost::ref(*this), boost::bind(&QtObservedBond::getIndex, boost::cref(*this)), boost::bind(accessor, getObservable(_bond->rightatom)))); const boost::function moleculeSubjectKilled( boost::bind(&QtObservedBond::countValuesSubjectKilled, boost::ref(*this), boost::bind(&QtObservedBond::getIndex, boost::cref(*this)), boost::bind(accessor, getObservable(getMolecule(_bond))))); initObservedValues( ObservedValues, _id, _bond, bondSubjectKilled, leftatomSubjectKilled, rightatomSubjectKilled, moleculeSubjectKilled); // activating Observer is done by ObservedValueContainer when it's inserted } QtObservedBond::~QtObservedBond() { boost::any_cast *>(ObservedValues[BondDegree])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[leftAtomIndex])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[leftAtomElement])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[leftAtomPosition])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[rightAtomIndex])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[rightAtomElement])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[rightAtomPosition])->noteCallBackIsGone(); boost::any_cast *>(ObservedValues[moleculeIndex])->noteCallBackIsGone(); deactivateObserver(); destroyObservedValues(ObservedValues); } #ifdef HAVE_INLINE inline #endif int QtObservedBond::updateDegree(const bond &_bond) { return _bond.getDegree(); } #ifdef HAVE_INLINE inline #endif atomId_t QtObservedBond::updateLeftAtomIndex(const atom &_atom) { return _atom.getId(); } #ifdef HAVE_INLINE inline #endif atomicNumber_t QtObservedBond::updateLeftAtomElement(const atom &_atom) { return _atom.getElementNo(); } #ifdef HAVE_INLINE inline #endif Vector QtObservedBond::updateLeftAtomPosition(const atom &_atom) { return _atom.getPosition(); } #ifdef HAVE_INLINE inline #endif atomId_t QtObservedBond::updateRightAtomIndex(const atom &_atom) { return _atom.getId(); } #ifdef HAVE_INLINE inline #endif atomicNumber_t QtObservedBond::updateRightAtomElement(const atom &_atom) { return _atom.getElementNo(); } #ifdef HAVE_INLINE inline #endif Vector QtObservedBond::updateRightAtomPosition(const atom &_atom) { return _atom.getPosition(); } #ifdef HAVE_INLINE inline #endif moleculeId_t QtObservedBond::updateMoleculeIndex(const molecule &_mol) { return _mol.getId(); } void QtObservedBond::update(Observable *publisher) { ASSERT(0, "QtObservedBond::update() - we are not signed on for global updates."); } void QtObservedBond::subjectKilled(Observable *publisher) { ++(signedOffChannels[publisher]); checkForRemoval(getIndex()); } void QtObservedBond::countValuesSubjectKilled( ObservedValue_Index_t _id, unsigned int &_counter) { ASSERT( _id == getIndex(), "QtObservedBond::countValuesSubjectKilled() - bond "+toString(getIndex()) +" received countValuesSubjectKilled for bond id "+toString(_id)+"."); ++_counter; checkForRemoval(_id); } void QtObservedBond::checkForRemoval(ObservedValue_Index_t _id) { if (leftatomowner != NULL) { // left atom gone? const ObservableCount_t::const_iterator subjectkilledleftiter = subjectKilledCount.find(const_cast(leftatomowner)); ASSERT( (subjectkilledleftiter != subjectKilledCount.end()), "QtObservedBond::checkForRemoval() - leftatomowner not present in subjectKilledCount."); if (subjectkilledleftiter->second == 3) { leftatomowner = NULL; } } if (rightatomowner != NULL) { // right atom gone? const ObservableCount_t::const_iterator subjectkilledrightiter = subjectKilledCount.find(const_cast(rightatomowner)); ASSERT( (subjectkilledrightiter != subjectKilledCount.end()), "QtObservedBond::checkForRemoval() - rightatomowner not present in subjectKilledCount."); if (subjectkilledrightiter->second == 3) { rightatomowner = NULL; } } if (moleculeowner != NULL) { // molecule gone? const ObservableCount_t::const_iterator subjectkilledmoliter = subjectKilledCount.find(const_cast(moleculeowner)); ASSERT( (subjectkilledmoliter != subjectKilledCount.end()), "QtObservedBond::checkForRemoval() - moleculeowner not present in subjectKilledCount."); if (subjectkilledmoliter->second == 3) { moleculeowner = NULL; } } if (bondowner != NULL) { // only bond needs to be destroyed to signal removal const ObservableCount_t::const_iterator subjectkillediter = subjectKilledCount.find(const_cast(bondowner)); const ObservableCount_t::const_iterator allsignediter = AllsignedOnChannels.find(const_cast(bondowner)); const ObservableCount_t::const_iterator signedoffiter = signedOffChannels.find(const_cast(bondowner)); ASSERT( (subjectkillediter != subjectKilledCount.end()) && (allsignediter != AllsignedOnChannels.end()) && (signedoffiter != signedOffChannels.end()), "QtObservedBond::checkForRemoval() - something is wrong here."); if ((signedoffiter->second == allsignediter->second) && (subjectkillediter->second == allsignediter->second)) { // remove owner: no more signOff needed bondowner = NULL; emit bondRemoved(); if (!BoardIsGone) { board.markObservedBondAsDisconnected(_id); board.markObservedBondForErase(_id); } } } } void QtObservedBond::recieveNotification(Observable *publisher, Notification_ptr notification) { // ObservedValues have been updated before, hence convert updates to Qt's signals if (publisher == leftatomowner) { switch (notification->getChannelNo()) { case AtomObservable::IndexChanged: { const atomId_t newId = getLeftAtomIndex(); emit leftAtomIndexChanged(oldleftatomId, newId); oldleftatomId = newId; break; } case AtomObservable::ElementChanged: { emit leftAtomElementChanged(); break; } case AtomObservable::PositionChanged: { emit leftAtomPositionChanged(); break; } default: ASSERT(0, "QtObservedBond::recieveNotification() - we are not signed on to channel " +toString(notification->getChannelNo())+" of the left atom " +toString(getLeftAtomIndex())+"."); break; } } else if (publisher == rightatomowner) { switch (notification->getChannelNo()) { case AtomObservable::IndexChanged: { const atomId_t newId = getRightAtomIndex(); emit rightAtomIndexChanged(oldrightatomId, newId); oldrightatomId = newId; break; } case AtomObservable::ElementChanged: { emit rightAtomElementChanged(); break; } case AtomObservable::PositionChanged: { emit rightAtomPositionChanged(); break; } default: ASSERT(0, "QtObservedBond::recieveNotification() - we are not signed on to channel " +toString(notification->getChannelNo())+" of the right atom " +toString(getRightAtomIndex())+"."); break; } } else if (publisher == bondowner) { switch (notification->getChannelNo()) { case BondObservable::DegreeChanged: emit degreeChanged(); break; default: ASSERT(0, "QtObservedBond::recieveNotification() - we are not signed on to channel " +toString(notification->getChannelNo())+" of the bond " +toString(getBondIndex())+"."); break; } } else if (publisher == moleculeowner) { switch (notification->getChannelNo()) { case molecule::IndexChanged: { const moleculeId_t newId = getMoleculeIndex(); emit moleculeIndexChanged(oldmoleculeId, newId); oldmoleculeId = newId; break; } default: ASSERT(0, "QtObservedBond::recieveNotification() - we are not signed on to channel " +toString(notification->getChannelNo())+" of the molecule #" +toString(getMoleculeIndex())+"."); break; } } else ASSERT(0, "QtObservedBond::recieveNotification() - received signal from unknown source."); } static QtObservedBond::ObservableCount_t::mapped_type getObservableCountValue( const QtObservedBond::ObservableCount_t &_map, const Observable *_obs) { Observable * const obs_const = const_cast(_obs); QtObservedBond::ObservableCount_t::const_iterator iter = _map.find(obs_const); ASSERT( iter != _map.end(), "getObservableCount_tValue"); return iter->second; } static void assignObservableCountValue( QtObservedBond::ObservableCount_t &_map, const Observable *_obs, const QtObservedBond::ObservableCount_t::mapped_type &_value) { Observable * const obs_const = const_cast(_obs); QtObservedBond::ObservableCount_t::iterator iter = _map.find(obs_const); ASSERT( iter != _map.end(), "getObservableCount_tValue"); iter->second = _value; } void QtObservedBond::activateObserver() { signedOffChannels.clear(); subjectKilledCount.clear(); const atom * rightatom = getAtom(getRightAtomIndex()); { const Observable::channels_t channels = getAllObservedAtomChannels(); if (rightatom != NULL) { rightatomowner = static_cast(rightatom); for (Observable::channels_t::const_iterator iter = channels.begin(); iter != channels.end(); ++iter) rightatomowner->signOn(this, *iter); subjectKilledCount.insert( std::make_pair(const_cast(rightatomowner), 0)); signedOffChannels.insert( std::make_pair(const_cast(rightatomowner), 0)); } else { subjectKilledCount.insert( std::make_pair(const_cast(rightatomowner), channels.size())); assignObservableCountValue(signedOffChannels, rightatomowner, getObservableCountValue(AllsignedOnChannels, rightatomowner)); } } { const atom * leftatom = getAtom(getLeftAtomIndex()); const Observable::channels_t channels = getAllObservedAtomChannels(); if (leftatom != NULL) { leftatomowner = static_cast(leftatom); for (Observable::channels_t::const_iterator iter = channels.begin(); iter != channels.end(); ++iter) leftatomowner->signOn(this, *iter); subjectKilledCount.insert( std::make_pair(const_cast(leftatomowner), 0)); signedOffChannels.insert( std::make_pair(const_cast(leftatomowner), 0)); bond::ptr bondref = leftatom->getBond(rightatom); if (bondref != NULL) { // bond { bondowner = static_cast(bondref.get()); bondowner->signOn(this, BondObservable::DegreeChanged); subjectKilledCount.insert( std::make_pair(const_cast(bondowner), 0)); signedOffChannels.insert( std::make_pair(const_cast(bondowner), 0)); } const molecule * mol = leftatom->getMolecule(); if (mol != NULL) { // molecule moleculeowner = static_cast(mol); moleculeowner->signOn(this, molecule::IndexChanged); subjectKilledCount.insert( std::make_pair(const_cast(moleculeowner), 0)); signedOffChannels.insert( std::make_pair(const_cast(moleculeowner), 0)); } else { subjectKilledCount.insert( std::make_pair(const_cast(moleculeowner), 1)); assignObservableCountValue(signedOffChannels, moleculeowner, getObservableCountValue(AllsignedOnChannels, moleculeowner)); } // and mark as connected if (!BoardIsGone) board.markObservedBondAsConnected(getIndex()); } else { subjectKilledCount.insert( std::make_pair(const_cast(bondowner), 1)); assignObservableCountValue(signedOffChannels, bondowner, getObservableCountValue(AllsignedOnChannels, bondowner)); } } else { subjectKilledCount.insert( std::make_pair(const_cast(leftatomowner), channels.size())); assignObservableCountValue(signedOffChannels, leftatomowner, getObservableCountValue(AllsignedOnChannels, leftatomowner)); } } } void QtObservedBond::deactivateObserver() { // sign Off if (leftatomowner != NULL) { const ObservableCount_t::iterator subjectkilledleftiter = subjectKilledCount.find(const_cast(leftatomowner)); ASSERT( (subjectkilledleftiter != subjectKilledCount.end()), "QtObservedBond::deactivateObserver() - no entry in subjectKilledCount for left atom " +toString(leftatomowner)+", has activateObserver() been called?"); ASSERT( (subjectkilledleftiter->second == 3) || (subjectkilledleftiter->second == 0), "QtObservedBond::deactivateObserver() - cannot deal with partially signed off left atom."); if (subjectkilledleftiter->second == 0) { Observable::channels_t channels = getAllObservedAtomChannels(); for (Observable::channels_t::const_iterator iter = channels.begin(); iter != channels.end(); ++iter) leftatomowner->signOff(this, *iter); subjectkilledleftiter->second = 3; } leftatomowner = NULL; } if (rightatomowner != NULL) { const ObservableCount_t::iterator subjectkilledrightiter = subjectKilledCount.find(const_cast(rightatomowner)); ASSERT( (subjectkilledrightiter != subjectKilledCount.end()), "QtObservedBond::deactivateObserver() - no entry in subjectKilledCount for right atom" +toString(rightatomowner)+", has activateObserver() been called?"); ASSERT( (subjectkilledrightiter->second == 3) || (subjectkilledrightiter->second == 0), "QtObservedBond::deactivateObserver() - cannot deal with partially signed off right atom ."); if (subjectkilledrightiter->second == 0) { Observable::channels_t channels = getAllObservedAtomChannels(); for (Observable::channels_t::const_iterator iter = channels.begin(); iter != channels.end(); ++iter) rightatomowner->signOff(this, *iter); subjectkilledrightiter->second = 3; } rightatomowner = NULL; } if (moleculeowner != NULL) { const ObservableCount_t::iterator subjectkilledmoliter = subjectKilledCount.find(const_cast(moleculeowner)); ASSERT( (subjectkilledmoliter != subjectKilledCount.end()), "QtObservedBond::deactivateObserver() - no entry in subjectKilledCount for molecule" +toString(moleculeowner)+", has activateObserver() been called?"); if (subjectkilledmoliter->second == 0) moleculeowner->signOff(this, molecule::IndexChanged); subjectkilledmoliter->second = 1; moleculeowner = NULL; } if (bondowner != NULL) { const ObservableCount_t::iterator subjectkilledbonditer = subjectKilledCount.find(const_cast(bondowner)); ASSERT( (subjectkilledbonditer != subjectKilledCount.end()), "QtObservedBond::deactivateObserver() - no entry in subjectKilledCount for bond" +toString(bondowner)+"," +" has activateObserver() been called?"); if (subjectkilledbonditer->second == 0) bondowner->signOff(this, BondObservable::DegreeChanged); subjectkilledbonditer->second = 1; bondowner = NULL; signedOffChannels.clear(); signedOffChannels.insert(AllsignedOnChannels.begin(), AllsignedOnChannels.end()); if (!BoardIsGone) board.markObservedBondAsDisconnected(getIndex()); } } const atom * const QtObservedBond::getAtomConst(const atomId_t _id) { const atom * const _atom = const_cast(World::getInstance()). getAtom(AtomById(_id)); return _atom; } atom * const QtObservedBond::getAtom(const atomId_t _id) { atom * const _atom = World::getInstance().getAtom(AtomById(_id)); return _atom; } void QtObservedBond::initObservedValues( ObservedValues_t &_ObservedValues, const bondId_t _id, const bond::ptr _bondref, const boost::function &_bondsubjectKilled, const boost::function &_leftatomsubjectKilled, const boost::function &_rightatomsubjectKilled, const boost::function &_moleculesubjectKilled) { // fill ObservedValues: index first const boost::function BondIndexGetter = boost::bind(&QtObservedBond::getIndex, boost::cref(*this)); // fill ObservedValues: then all the other that need index const boost::function BondDegreeUpdater( boost::bind(&QtObservedBond::updateDegree, boost::cref(*_bondref))); const boost::function leftAtomIndexUpdater( boost::bind(&QtObservedBond::updateLeftAtomIndex, boost::cref(*_bondref->leftatom))); const boost::function leftAtomElementUpdater( boost::bind(&QtObservedBond::updateLeftAtomElement, boost::cref(*_bondref->leftatom))); const boost::function leftAtomPositionUpdater( boost::bind(&QtObservedBond::updateLeftAtomPosition, boost::cref(*_bondref->leftatom))); const boost::function rightAtomIndexUpdater( boost::bind(&QtObservedBond::updateRightAtomIndex, boost::cref(*_bondref->rightatom))); const boost::function rightAtomElementUpdater( boost::bind(&QtObservedBond::updateRightAtomElement, boost::cref(*_bondref->rightatom))); const boost::function rightAtomPositionUpdater( boost::bind(&QtObservedBond::updateRightAtomPosition, boost::cref(*_bondref->rightatom))); const boost::function MoleculeIndexUpdater( boost::bind(&QtObservedBond::updateMoleculeIndex, boost::cref(*_bondref->leftatom->getMolecule()))); _ObservedValues[BondDegree] = new ObservedValue_wCallback( _bondref.get(), BondDegreeUpdater, "BondDegree_bond"+toString(_id), BondDegreeUpdater(), BondDegreeChannels, _bondsubjectKilled); _ObservedValues[leftAtomIndex] = new ObservedValue_wCallback( _bondref->leftatom, leftAtomIndexUpdater, "LeftAtomIndex_bond"+toString(_id), leftAtomIndexUpdater(), Observable::channels_t(1, AtomObservable::IndexChanged), _leftatomsubjectKilled); _ObservedValues[leftAtomElement] = new ObservedValue_wCallback( _bondref->leftatom, leftAtomElementUpdater, "LeftAtomElement_bond"+toString(_id), leftAtomElementUpdater(), Observable::channels_t(1, AtomObservable::ElementChanged), _leftatomsubjectKilled); _ObservedValues[leftAtomPosition] = new ObservedValue_wCallback( _bondref->leftatom, leftAtomPositionUpdater, "LeftAtomPosition_bond"+toString(_id), leftAtomPositionUpdater(), Observable::channels_t(1, AtomObservable::PositionChanged), _leftatomsubjectKilled); _ObservedValues[rightAtomIndex] = new ObservedValue_wCallback( _bondref->rightatom, rightAtomIndexUpdater, "RightAtomIndex_bond"+toString(_id), rightAtomIndexUpdater(), Observable::channels_t(1, AtomObservable::IndexChanged), _rightatomsubjectKilled); _ObservedValues[rightAtomElement] = new ObservedValue_wCallback( _bondref->rightatom, rightAtomElementUpdater, "RightAtomElement_bond"+toString(_id), rightAtomElementUpdater(), Observable::channels_t(1, AtomObservable::ElementChanged), _rightatomsubjectKilled); _ObservedValues[rightAtomPosition] = new ObservedValue_wCallback( _bondref->rightatom, rightAtomPositionUpdater, "RightAtomPosition_bond"+toString(_id), rightAtomPositionUpdater(), Observable::channels_t(1, AtomObservable::PositionChanged), _rightatomsubjectKilled); _ObservedValues[moleculeIndex] = new ObservedValue_wCallback( _bondref->leftatom->getMolecule(), MoleculeIndexUpdater, "MoleculeIndex_bond"+toString(_id), MoleculeIndexUpdater(), Observable::channels_t(1, AtomObservable::PositionChanged), _moleculesubjectKilled); } void QtObservedBond::destroyObservedValues( std::vector &_ObservedValues) { delete boost::any_cast *>(_ObservedValues[BondDegree]); delete boost::any_cast *>(_ObservedValues[leftAtomIndex]); delete boost::any_cast *>(_ObservedValues[leftAtomElement]); delete boost::any_cast *>(_ObservedValues[leftAtomPosition]); delete boost::any_cast *>(_ObservedValues[rightAtomIndex]); delete boost::any_cast *>(_ObservedValues[rightAtomElement]); delete boost::any_cast *>(_ObservedValues[rightAtomPosition]); delete boost::any_cast *>(_ObservedValues[moleculeIndex]); _ObservedValues.clear(); } ObservedValue_Index_t QtObservedBond::getIndex() const { ASSERT( bondowner != NULL, "QtObservedBond::getIndex() - index is NULL"); return bondowner; } const QtObservedBond::bondId_t QtObservedBond::getBondIndex() const { return QtObservedBond::bondId_t(getLeftAtomIndex(), getRightAtomIndex()); } const int& QtObservedBond::getBondDegree() const { return boost::any_cast *>(ObservedValues[BondDegree])->get(); } const atomId_t& QtObservedBond::getLeftAtomIndex() const { return boost::any_cast *>(ObservedValues[leftAtomIndex])->get(); } const atomicNumber_t& QtObservedBond::getLeftAtomElement() const { return boost::any_cast *>(ObservedValues[leftAtomElement])->get(); } const Vector& QtObservedBond::getLeftAtomPosition() const { return boost::any_cast *>(ObservedValues[leftAtomPosition])->get(); } const atomId_t& QtObservedBond::getRightAtomIndex() const { return boost::any_cast *>(ObservedValues[rightAtomIndex])->get(); } const atomicNumber_t& QtObservedBond::getRightAtomElement() const { return boost::any_cast *>(ObservedValues[rightAtomElement])->get(); } const Vector& QtObservedBond::getRightAtomPosition() const { return boost::any_cast *>(ObservedValues[rightAtomPosition])->get(); } const moleculeId_t& QtObservedBond::getMoleculeIndex() const { return boost::any_cast *>(ObservedValues[moleculeIndex])->get(); }