/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010-2012 University of Bonn. All rights reserved. * Copyright (C) 2013 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 . */ /* * GLMoleculeObject_atom.cpp * * Created on: Aug 17, 2011 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "GLMoleculeObject_atom.hpp" #include #include "CodePatterns/MemDebug.hpp" #include "CodePatterns/Assert.hpp" #include "CodePatterns/Log.hpp" #include "CodePatterns/Observer/Notification.hpp" #include "Atom/atom.hpp" #include "Bond/bond.hpp" #include "Descriptors/AtomIdDescriptor.hpp" #include "Element/element.hpp" #include "LinearAlgebra/Vector.hpp" #include "GLMoleculeObject_bond.hpp" #include "World.hpp" #include "WorldTime.hpp" GLMoleculeObject_atom::GLMoleculeObject_atom(QGLSceneNode *mesh[], QObject *parent, const atomId_t _id) : GLMoleculeObject(mesh, parent), Observer(std::string("GLMoleculeObject_atom")+toString(_id)), atomicid(_id) { // sign on as observer (obtain non-const instance before) const atom *_atom = World::getInstance().getAtom(AtomById(atomicid)); if (_atom != NULL) { _atom->signOn(this, AtomObservable::IndexChanged); _atom->signOn(this, AtomObservable::PositionChanged); _atom->signOn(this, AtomObservable::ElementChanged); _atom->signOn(this, AtomObservable::BondsAdded); } else { ELOG(2, "Atom with id "+toString(atomicid)+" is already gone."); } World::getInstance().signOn(this, World::SelectionChanged); // set the object's id resetProperties(); LOG(2, "INFO: Created sphere for atom " << atomicid << "."); connect( this, SIGNAL(clicked()), this, SLOT(wasClicked())); } GLMoleculeObject_atom::~GLMoleculeObject_atom() { const atom *_atom = World::getInstance().getAtom(AtomById(atomicid)); if (_atom != NULL){ _atom->signOff(this, AtomObservable::IndexChanged); _atom->signOff(this, AtomObservable::PositionChanged); _atom->signOff(this, AtomObservable::ElementChanged); _atom->signOff(this, AtomObservable::BondsAdded); } World::getInstance().signOff(this, World::SelectionChanged); } void GLMoleculeObject_atom::update(Observable *publisher) { #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Update of Observer " << observerLog().getName(static_cast(this)) << " from atom "+toString(atomicid)+"."; #endif resetProperties(); } void GLMoleculeObject_atom::resetPosition() { const atom *_atom = World::getInstance().getAtom(AtomById(atomicid)); if (_atom != NULL) { const Vector Position = _atom->getPosition(); LOG(4, "INFO: GLMoleculeObject_atom::resetIndex() - new position is "+toString(Position)+"."); setPosition(QVector3D(Position[0], Position[1], Position[2])); } else { ELOG(2, "Atom with id "+toString(atomicid)+" is already gone."); } } void GLMoleculeObject_atom::resetElement() { size_t elementno = 0; const atom *_atom = World::getInstance().getAtom(AtomById(atomicid)); const element *_type = NULL; if (_atom != NULL) { _type = _atom->getType(); } else { ELOG(2, "Atom with id "+toString(atomicid)+" is already gone."); } if (_type != NULL) { elementno = _type->getAtomicNumber(); } else { // if no element yet, set to hydrogen elementno = 1; } LOG(4, "INFO: GLMoleculeObject_atom::resetIndex() - new element number is "+toString(elementno)+"."); // set materials QGLMaterial *elementmaterial = getMaterial(elementno); ASSERT(elementmaterial != NULL, "GLMoleculeObject_atom::GLMoleculeObject_atom() - QGLMaterial ref from getter function is NULL."); setMaterial(elementmaterial); // set scale double radius = 0.; if (_type != NULL) { radius = _type->getVanDerWaalsRadius(); } else { radius = 0.5; } setScale( radius / 4. ); } void GLMoleculeObject_atom::resetIndex() { int oldId = objectId(); LOG(4, "INFO: GLMoleculeObject_atom::resetIndex() - new index is "+toString(atomicid)+"."); setObjectId(atomicid); emit indexChanged(this, oldId, atomicid); } void GLMoleculeObject_atom::resetProperties() { // set position resetPosition(); // set element resetElement(); // set the object's id resetIndex(); // selected? setSelected(World::getInstance().isAtomSelected(atomicid)); } void GLMoleculeObject_atom::subjectKilled(Observable *publisher) { // remove id such that we don't sign off accidentally from a different atom const_cast(atomicid) = -1; } void GLMoleculeObject_atom::recieveNotification(Observable *publisher, Notification_ptr notification) { const atom *_atom = World::getInstance().getAtom(AtomById(atomicid)); if (publisher == dynamic_cast(_atom)){ // notofication from atom #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast(this)) << " received notification from atom " << _atom->getId() << " for channel " << notification->getChannelNo() << "."; #endif switch (notification->getChannelNo()) { case AtomObservable::ElementChanged: resetElement(); emit changed(); break; case AtomObservable::IndexChanged: resetIndex(); break; case AtomObservable::PositionChanged: resetPosition(); emit changed(); break; case AtomObservable::BondsAdded: { const atom *_atom = World::getInstance().getAtom(AtomById(atomicid)); if (_atom != NULL) { ASSERT(!_atom->getListOfBonds().empty(), "GLMoleculeObject_atom::recieveNotification() - received BondsAdded but ListOfBonds is empty."); const bond::ptr _bond = *(_atom->getListOfBonds().rbegin()); const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == _atom) ? GLMoleculeObject_bond::left : GLMoleculeObject_bond::right; emit BondsInserted(_bond, side); } else { ELOG(2, "Atom with id "+toString(atomicid)+" is already gone."); } break; } default: //setProperties(); break; } }else if (static_cast(publisher) == World::getPointer()) { // notification from world #ifdef LOG_OBSERVER observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast(this)) << " received notification from world for channel " << notification->getChannelNo() << "."; #endif switch (notification->getChannelNo()) { case World::SelectionChanged: setSelected(World::getInstance().isSelected(_atom)); break; default: break; } } } void GLMoleculeObject_atom::wasClicked() { LOG(4, "INFO: GLMoleculeObject_atom: atom " << atomicid << " has been clicked"); emit clicked(atomicid); }