Index: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp
===================================================================
--- src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp	(revision e3e52ab3453d1812f2502d0534b424543c3505e8)
+++ src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp	(revision e39e7a39013eb9930f8d044d1a2c5297df13da96)
@@ -85,5 +85,5 @@
 const Observable::channels_t GLMoleculeObject_molecule::AtomsChannels(getAtomsChannels());
 const Observable::channels_t GLMoleculeObject_molecule::HullChannels(getAllAtomicChangesChannels());
-const Observable::channels_t GLMoleculeObject_molecule::BoundingBoxChannels(getAllAtomicChangesChannels());
+const Observable::channels_t GLMoleculeObject_molecule::BoundingBoxChannels(1, molecule::BoundingBoxChanged);
 const Observable::channels_t GLMoleculeObject_molecule::IndexChannels(1, molecule::IndexChanged);
 const Observable::channels_t GLMoleculeObject_molecule::NameChannels(1, molecule::MoleculeNameChanged);
@@ -403,7 +403,7 @@
 }
 
-GLMoleculeObject_molecule::BoundingBoxInfo GLMoleculeObject_molecule::initBoundingBox() const
-{
-  BoundingBoxInfo info;
+molecule::BoundingBoxInfo GLMoleculeObject_molecule::initBoundingBox() const
+{
+  molecule::BoundingBoxInfo info;
   info.position = zeroVec;
   info.radius = 0.;
@@ -411,7 +411,7 @@
 }
 
-GLMoleculeObject_molecule::BoundingBoxInfo GLMoleculeObject_molecule::updateBoundingBox() const
-{
-  BoundingBoxInfo info = BoundingBox.get();
+molecule::BoundingBoxInfo GLMoleculeObject_molecule::updateBoundingBox() const
+{
+  molecule::BoundingBoxInfo info = BoundingBox.get();
   const molecule * const _molecule = getMolecule(MolIndex.get());
   if (_molecule != NULL) {
@@ -472,5 +472,5 @@
 void GLMoleculeObject_molecule::resetBoundingBox()
 {
-  BoundingBoxInfo info = BoundingBox.get();
+  molecule::BoundingBoxInfo info = BoundingBox.get();
   setPosition(QVector3D(info.position[0], info.position[1], info.position[2]));
   setScale(info.radius + 0.3); // getBoundingSphere() only sees atoms as points, so make the box a bit bigger
Index: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp
===================================================================
--- src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp	(revision e3e52ab3453d1812f2502d0534b424543c3505e8)
+++ src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp	(revision e39e7a39013eb9930f8d044d1a2c5297df13da96)
@@ -24,9 +24,10 @@
 #include "GLMoleculeObject_bond.hpp"
 
+#include "molecule.hpp"
+
 class atom;
 class bond;
 class GLMoleculeObject_atom;
 class GLWorldScene;
-class molecule;
 
 class GLMoleculeObject_molecule : public GLMoleculeObject, public Observer
@@ -109,24 +110,8 @@
   typedef std::set<atomId_t> atoms_t;
 
-  /** Structure for the required information on the bounding box.
-   *
-   */
-  struct BoundingBoxInfo {
-    //!> position of center
-    Vector position;
-    //!> radius of sphere
-    double radius;
-  };
-
-  /** Structure for the required information on the tesselation hull.
-   *
-   */
-  struct TesselationHullInfo {
-  };
-
-  BoundingBoxInfo initBoundingBox() const;
+  molecule::BoundingBoxInfo initBoundingBox() const;
 
   QGeometryData updateTesselationHull() const;
-  BoundingBoxInfo updateBoundingBox() const;
+  molecule::BoundingBoxInfo updateBoundingBox() const;
   atoms_t updateAtoms();
   moleculeId_t updateIndex() const;
@@ -153,5 +138,5 @@
   boost::function<std::string ()> MolNameUpdater;
   boost::function<QGeometryData ()> TesselationHullUpdater;
-  boost::function<BoundingBoxInfo ()> BoundingBoxUpdater;
+  boost::function<molecule::BoundingBoxInfo ()> BoundingBoxUpdater;
   boost::function<atoms_t ()> PresentAtomsUpdater;
 
@@ -163,5 +148,5 @@
   Cacheable<QGeometryData> TesselationHull;
   //!> contains newest version of the bounding box on request
-  ObservedValue<BoundingBoxInfo> BoundingBox;
+  ObservedValue<molecule::BoundingBoxInfo> BoundingBox;
   //!> contains the current live set of atoms for the molecule
   ObservedValue<atoms_t> PresentAtoms;
Index: src/molecule.cpp
===================================================================
--- src/molecule.cpp	(revision e3e52ab3453d1812f2502d0534b424543c3505e8)
+++ src/molecule.cpp	(revision e39e7a39013eb9930f8d044d1a2c5297df13da96)
@@ -36,4 +36,5 @@
 
 #include <algorithm>
+#include <boost/assign.hpp>
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
@@ -50,4 +51,5 @@
 #include "CodePatterns/enumeration.hpp"
 #include "CodePatterns/Log.hpp"
+#include "CodePatterns/Observer/Observable.hpp"
 #include "CodePatterns/Observer/Notification.hpp"
 #include "config.hpp"
@@ -67,4 +69,13 @@
 #include "WorldTime.hpp"
 
+using namespace boost::assign;
+
+// static entities
+static Observable::channels_t getBoundingBoxChannels()
+{
+  Observable::channels_t channels;
+  channels += molecule::AtomInserted, molecule::AtomRemoved, molecule::AtomMoved;
+  return channels;
+}
 
 /************************************* Functions for class molecule *********************************/
@@ -83,4 +94,5 @@
   BondCount(this,boost::bind(&molecule::doCountBonds,this),"BondCount"),
   atomIdPool(1, 20, 100),
+  BoundingBoxSweepingAxis(std::vector<AtomDistanceMap_t>(NDIM)),
   _lastchangedatomid(-1),
   last_atom(0)
@@ -92,6 +104,11 @@
     OurChannel->addChannel(type);
 
+  // cannot initialize in initializer body as then channels have not been setup yet
+  BoundingBox.reset(
+      new Cacheable<BoundingBoxInfo>(
+          this, boost::bind(&molecule::updateBoundingBox, boost::cref(this)), "molecule_BoundingBox", getBoundingBoxChannels()));
+
   strcpy(name,World::getInstance().getDefaultName().c_str());
-};
+}
 
 molecule *NewMolecule(){
@@ -177,4 +194,14 @@
   atomIds.erase( oldId );
   atomIds.insert( newId );
+  // also update BoundingBoxSweepingAxis
+  for (int i=0;i<NDIM;++i) {
+    AtomDistanceMap_t::left_iterator iter = BoundingBoxSweepingAxis[i].left.find(oldId);
+    ASSERT(iter != BoundingBoxSweepingAxis[i].left.end(),
+        "molecule::changeAtomId() - could not find atom "+toString(oldId)
+        +" in BoundingBoxSweepingAxis.");
+    const double component = iter->second;
+    BoundingBoxSweepingAxis[i].left.erase(iter);
+    BoundingBoxSweepingAxis[i].left.insert( std::make_pair(newId, component) );
+  }
   return true;
 }
@@ -237,4 +264,12 @@
   atomIds.erase( _atom->getId() );
   {
+    BoundingBoxInfo oldinfo = updateBoundingBox();
+    for (int i=0;i<NDIM;++i)
+      BoundingBoxSweepingAxis[i].left.erase( _atom->getId() );
+    BoundingBoxInfo newinfo = updateBoundingBox();
+    if (oldinfo != newinfo)
+      NOTIFY(BoundingBoxChanged);
+  }
+  {
     NOTIFY(AtomNrChanged);
     atomIdPool.releaseId(_atom->getNr());
@@ -264,4 +299,12 @@
   std::pair<iterator,bool> res = atomIds.insert(key->getId());
   if (res.second) { // push atom if went well
+    {
+      BoundingBoxInfo oldinfo = updateBoundingBox();
+      for (int i=0;i<NDIM;++i)
+        BoundingBoxSweepingAxis[i].left.insert( std::make_pair(key->getId(), key->getPosition()[i]));
+      BoundingBoxInfo newinfo = updateBoundingBox();
+      if (oldinfo != newinfo)
+        NOTIFY(BoundingBoxChanged);
+    }
     NOTIFY(AtomNrChanged);
     key->setNr(atomIdPool.getNextId());
@@ -1033,4 +1076,25 @@
 }
 
+molecule::BoundingBoxInfo molecule::updateBoundingBox() const
+{
+  BoundingBoxInfo info;
+  Vector min = zeroVec;
+  Vector max = zeroVec;
+  for (int i=0;i<NDIM;++i) {
+    if (!BoundingBoxSweepingAxis[i].right.empty()) {
+      min[i] = BoundingBoxSweepingAxis[i].right.begin()->first;
+      max[i] = BoundingBoxSweepingAxis[i].right.rbegin()->first;
+    }
+  }
+  info.radius = (.5*(max-min)).Norm();
+  info.position = .5*(max+min);
+  return info;
+}
+
+molecule::BoundingBoxInfo molecule::getBoundingBox() const
+{
+  return **BoundingBox;
+}
+
 void molecule::update(Observable *publisher)
 {
@@ -1052,6 +1116,20 @@
         // emit others about one of our atoms moved
         _lastchangedatomid = _atom->getId();
+        // update entry in map
+        BoundingBoxInfo oldinfo = updateBoundingBox();
+        for (int i=0;i<NDIM;++i) {
+          AtomDistanceMap_t::left_iterator iter = BoundingBoxSweepingAxis[i].left.find(_atom->getId());
+          ASSERT(iter != BoundingBoxSweepingAxis[i].left.end(),
+              "molecule::recieveNotification() - could not find atom "+toString(_atom->getId())
+              +" in BoundingBoxSweepingAxis.");
+          BoundingBoxSweepingAxis[i].left.erase(iter);
+          BoundingBoxSweepingAxis[i].left.insert(
+              std::make_pair(_atom->getId(), _atom->getPosition()[i]) );
+        }
+        BoundingBoxInfo newinfo = updateBoundingBox();
         OBSERVE;
         NOTIFY(AtomMoved);
+        if (oldinfo != newinfo)
+          NOTIFY(BoundingBoxChanged);
         break;
       }
Index: src/molecule.hpp
===================================================================
--- src/molecule.hpp	(revision e3e52ab3453d1812f2502d0534b424543c3505e8)
+++ src/molecule.hpp	(revision e39e7a39013eb9930f8d044d1a2c5297df13da96)
@@ -22,4 +22,10 @@
 
 #include <string>
+
+#include <boost/bimap/bimap.hpp>
+#include <boost/bimap/unordered_set_of.hpp>
+#include <boost/bimap/multiset_of.hpp>
+#include <boost/optional.hpp>
+#include <boost/shared_ptr.hpp>
 
 #include "AtomIdSet.hpp"
@@ -115,4 +121,5 @@
     MoleculeNameChanged,
     IndexChanged,
+    BoundingBoxChanged,
     AboutToBeRemoved,
     NotificationType_MAX
@@ -271,4 +278,61 @@
 
 public:
+
+  /** Structure for the required information on the bounding box.
+   *
+   */
+  struct BoundingBoxInfo {
+    //!> position of center
+    Vector position;
+    //!> radius of sphere
+    double radius;
+
+    /** Equivalence operator for bounding box.
+     *
+     * \return true - both bounding boxes have same position and radius
+     */
+    bool operator==(const BoundingBoxInfo &_other) const
+    {  return (radius == _other.radius) && (position == _other.position); }
+
+    /** Inequivalence operator for bounding box.
+     *
+     * \return true - bounding boxes have either different positions or different radii or both
+     */
+    bool operator!=(const BoundingBoxInfo &_other) const
+    { return !(*this == _other); }
+  };
+
+private:
+
+  /** Returns the current bounding box.
+   *
+   * \return Shape with center and extension of box
+   */
+  BoundingBoxInfo updateBoundingBox() const;
+
+  // stuff for keeping bounding box up-to-date efficiently
+
+  //!> Cacheable for the bounding box, ptr such that
+  boost::shared_ptr< Cacheable<BoundingBoxInfo> > BoundingBox;
+  /** Bimap storing atomic ids and the component per axis.
+   *
+   * We need a bimap in order to have the components sorted and be able to
+   * access max and min values in linear time and also access the ids in
+   * constant time in order to update the map, when atoms move, are inserted,
+   * or removed.
+   */
+  typedef boost::bimaps::bimap<
+          boost::bimaps::unordered_set_of< atomId_t >,
+          boost::bimaps::multiset_of< double, std::greater<double> >
+      > AtomDistanceMap_t;
+  std::vector<AtomDistanceMap_t> BoundingBoxSweepingAxis;
+
+public:
+
+  /** Returns the current bounding box of this molecule.
+   *
+   * \return bounding box info with center and radius
+   */
+  BoundingBoxInfo getBoundingBox() const;
 
   /** Function to create a bounding spherical shape for the currently associated atoms.
