/*
* 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);
}