Index: src/Filling/Cluster.cpp
===================================================================
--- src/Filling/Cluster.cpp	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
+++ src/Filling/Cluster.cpp	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
@@ -0,0 +1,225 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2012 University of Bonn. All rights reserved.
+ * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
+ */
+
+/*
+ * Cluster.cpp
+ *
+ *  Created on: Jan 16, 2012
+ *      Author: heber
+ */
+
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "CodePatterns/MemDebug.hpp"
+
+#include <algorithm>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+
+#include "Cluster.hpp"
+
+#include "CodePatterns/Assert.hpp"
+#include "CodePatterns/Log.hpp"
+
+#include "Atom/atom.hpp"
+#include "Descriptors/AtomIdDescriptor.hpp"
+#include "LinearAlgebra/RealSpaceMatrix.hpp"
+#include "LinearAlgebra/Vector.hpp"
+#include "Shapes/ShapeOps.hpp"
+#include "World.hpp"
+
+/** Constructor for class Cluster.
+ *
+ * @param _s Shape of this Cluster
+ */
+Cluster::Cluster(const Shape & _s) :
+    s(_s)
+{}
+
+/** Copy Constructor for class Cluster.
+ *
+ * Here, we do not check whether we atomds reside in the Shape or not, as
+ * this should have been validated in the instance to copy \a _cluster.
+ *
+ * @param _cluster instance to copy
+ */
+Cluster::Cluster(const Cluster & _cluster) :
+    atoms(_cluster.atoms),
+    s(_cluster.s)
+{}
+
+/** Constructor for class Cluster.
+ *
+ * @param _atoms list of atoms to place in this cluster
+ * @param _s Shape of this Cluster
+ */
+Cluster::Cluster(const atomIdSet & _atoms, const Shape & _s) :
+    s(_s)
+{
+  // make sure only those atoms are in Cluster that are also inside its Shape
+  std::vector<atomId_t> tempIds(_atoms.size(), (size_t)-1);
+  std::vector<atomId_t>::iterator iter =
+      std::remove_copy_if( _atoms.begin(), _atoms.end(), tempIds.begin(),
+          !boost::bind(&Cluster::IsInShape, this, _1) );
+  tempIds.erase( iter, tempIds.end() );
+  ASSERT( tempIds.size() == _atoms.size(),
+      "Cluster::Cluster() - at least one atom is not inside the Shape.");
+  atoms.insert( tempIds.begin(), tempIds.end() );
+  LOG(1, "INFO: New cluster has " << atoms.size() << " atoms.");
+}
+
+
+/** Destructor for class Cluster.
+ *
+ */
+Cluster::~Cluster()
+{}
+
+/** Inserts an atomic by its \a id into the Cluster.
+ *
+ * We check whether the atom is inside the given Shape \a s.
+ *
+ * @param id id to insert
+ */
+void Cluster::insert(const atomId_t id)
+{
+  const bool status = IsInShape(id);
+  ASSERT(status,
+      "Cluster::insert() - atomic id "+toString(id)+" is not contained in Shape.");
+  if (status) {
+    std::pair<atomIdSet::iterator, bool> inserter = atoms.insert(id);
+    ASSERT(inserter.second,
+        "Cluster::insert() - atomic id "+toString(id)+" is already present.");
+  }
+}
+
+/** Remove atom by its \a id from the cluster.
+ *
+ * @param id atom to remove
+ */
+void Cluster::erase(const atomId_t id)
+{
+  atomIdSet::iterator iter = atoms.find(id);
+  ASSERT(iter != atoms.end(),
+      "Cluster::erase() - atomic id "+toString(id)+" unknown in this Cluster.");
+  if (iter != atoms.end())
+    atoms.erase(iter);
+}
+
+/** Checks whether a given atom is within the shape \a s.
+ *
+ * @param id atomic id to check
+ * @return true - is in Shape, false - is not contained (or does not exist)
+ */
+bool Cluster::IsInShape(const atomId_t id) const
+{
+  const atom * const _atom = getAtomById(id);
+  if (_atom != NULL)
+    return s.isInside(_atom->getPosition());
+  else
+    return false;
+}
+
+/** Helper function for looking up atomic reference by its id.
+ *
+ * @param id id to look up
+ * @return reference to atom with this id
+ */
+atom * const Cluster::getAtomById(const atomId_t id) const
+{
+  atom * const _atom = World::getInstance().getAtom(AtomById(id));
+  ASSERT(_atom != NULL,
+      "Cluster::getAtomById() - id "+toString(id)+" is unknown to World.");
+  return _atom;
+}
+
+bool isNullAtom(const atom* _atom) {
+  return _atom == NULL;
+}
+
+/** Getter for the underlying true atoms refs.
+ *
+ * @return AtomVector filled with looked-up atom references
+ */
+Cluster::AtomVector Cluster::getAtomRefs() const
+{
+  AtomVector atomVector;
+  atomVector.reserve(atoms.size());
+  BOOST_FOREACH(atomId_t _id, atoms) {
+    atom * const _atom = World::getInstance().getAtom(AtomById(_id));
+    if (_atom != NULL)
+      atomVector.push_back( _atom );
+    else
+      ASSERT( false, "Cluster::getAtomRefs() - unknown id "+toString(_id)+".");
+  }
+  return atomVector;
+}
+
+/** Clone function for this instance.
+ *
+ * @param copyMethod functor that knows how to copy atoms
+ * @param offset Vector to translate new cluster relative to old one
+ * @return another instance with newly allocated atoms
+ */
+ClusterInterface::Cluster_impl Cluster::clone(
+    CopyAtomsInterface& copyMethod,
+    const Vector &offset) const
+{
+  LOG(2, "INFO: Clone this cluster with " << atoms.size() << " atoms.");
+  /// get another cluster instance
+  Cluster * clonedInstance = new Cluster(::translate(getShape(), offset));
+
+  /// copy and move atoms
+  copyMethod(getAtomRefs());
+  AtomVector CopiedAtoms = copyMethod.getCopiedAtoms();
+  BOOST_FOREACH( atom *_atom, CopiedAtoms) {
+    _atom->setPosition( _atom->getPosition() + offset );
+  }
+
+  /// fill copied atoms into new instance
+  // dont use a set here, makes life hard with STL algos
+  std::vector<atomId_t> Copies(CopiedAtoms.size(), (size_t)-1);
+  std::transform(CopiedAtoms.begin(), CopiedAtoms.end(), Copies.begin(),
+      boost::bind(&atom::getId, _1) );
+  clonedInstance->atoms.insert(Copies.begin(), Copies.end());
+
+  return ClusterInterface::Cluster_impl(clonedInstance);
+}
+
+/** Translate atoms inside Cluster and Shape.
+ *
+ * @param offset offset to translate by
+ */
+void Cluster::translate(const Vector &offset)
+{
+  // move atoms
+  AtomVector atomVector = getAtomRefs();
+  BOOST_FOREACH(atom *_atom, atomVector) {
+    _atom->setPosition(_atom->getPosition()+offset);
+  }
+  // translate shape
+  s = ::translate(s, offset);
+}
+
+/** Transform atoms inside Cluster and Shape.
+ *
+ * @param M transformation matrix
+ */
+void Cluster::transform(const RealSpaceMatrix &M)
+{
+  // transform atoms
+  AtomVector atomVector = getAtomRefs();
+  BOOST_FOREACH(atom *_atom, atomVector) {
+    _atom->setPosition( M * _atom->getPosition() );
+  }
+  // translate shape
+  s = ::transform(s, M);
+}
Index: src/Filling/Cluster.hpp
===================================================================
--- src/Filling/Cluster.hpp	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
+++ src/Filling/Cluster.hpp	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
@@ -0,0 +1,89 @@
+/*
+ * Cluster.hpp
+ *
+ *  Created on: Jan 16, 2012
+ *      Author: heber
+ */
+
+#ifndef CLUSTER_HPP_
+#define CLUSTER_HPP_
+
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "types.hpp"
+
+#include <set>
+
+#include "ClusterInterface.hpp"
+
+#include "Atom/CopyAtoms/CopyAtomsInterface.hpp"
+#include "LinearAlgebra/Vector.hpp"
+#include "Shapes/Shape.hpp"
+
+class atom;
+class RealSpaceMatrix;
+
+/** A Cluster is a set of atoms within a given Shape that contains them.
+ *
+ */
+class Cluster : public ClusterInterface
+{
+  //!> grant unit test access
+  friend class ClusterTest;
+public:
+  typedef std::set<atomId_t> atomIdSet;
+  typedef std::vector<atom *> AtomVector;
+
+  Cluster(const Cluster & _cluster);
+  Cluster(const Shape &s);
+  Cluster(const atomIdSet &atoms, const Shape &s);
+  ~Cluster();
+
+  void insert(const atomId_t id);
+  void erase(const atomId_t id);
+
+  /** Getter for the internal set of atomic ids.
+   *
+   * @return atomIdSet with \a atoms
+   */
+  const atomIdSet & getAtomIds() const { return atoms; }
+
+  Cluster_impl clone(CopyAtomsInterface& copyMethod, const Vector &offset = zeroVec) const;
+
+  void translate(const Vector &offset);
+
+  void transform(const RealSpaceMatrix &M);
+
+  bool isInside(const atomId_t id) const {
+    return IsInShape(id);
+  }
+
+  /** Getter for the internal Shape.
+   *
+   * @return Shape \a s
+   */
+  const Shape& getShape() const { return s; }
+
+private:
+  /** Getter for the contained atoms.
+   *
+   * @return vector of atomic refs
+   */
+  AtomVector getAtomRefs() const;
+
+  //!> do not allow Cluster without Shape
+  Cluster();
+
+  bool IsInShape(const atomId_t id) const;
+  atom * const getAtomById(const atomId_t id) const;
+
+  atomIdSet atoms;
+  Shape s;
+};
+
+
+#endif /* CLUSTER_HPP_ */
Index: src/Filling/Makefile.am
===================================================================
--- src/Filling/Makefile.am	(revision 9e5a306c82483ea0f88a098c86376beb12c62ffe)
+++ src/Filling/Makefile.am	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
@@ -3,4 +3,5 @@
 
 FILLINGSOURCE = \
+	Filling/Cluster.cpp \
 	Filling/Predicates/AnyFillPredicate.cpp \
 	Filling/Predicates/FillPredicate.cpp \
@@ -12,4 +13,5 @@
 	
 FILLINGHEADER = \
+	Filling/Cluster.hpp \
 	Filling/NodeTypes.hpp \
 	Filling/Predicates/AnyFillPredicate.hpp \
@@ -23,5 +25,5 @@
 	Filling/Predicates/Ops_FillPredicate.hpp \
 	Filling/Predicates/Ops_FillPredicate_impl.hpp
-
+				  
 
 noinst_LTLIBRARIES += libMolecuilderFilling.la
Index: src/Filling/unittests/ClusterUnitTest.cpp
===================================================================
--- src/Filling/unittests/ClusterUnitTest.cpp	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
+++ src/Filling/unittests/ClusterUnitTest.cpp	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
@@ -0,0 +1,312 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
+ * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
+ */
+
+/*
+ * ClusterUnitTest.cpp
+ *
+ *  Created on: Jan 17, 2012
+ *      Author: heber
+ */
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+#include "CodePatterns/Assert.hpp"
+
+#include "Atom/CopyAtoms/CopyAtoms_Simple.hpp"
+#include "Descriptors/AtomIdDescriptor.hpp"
+#include "Element/periodentafel.hpp"
+#include "Filling/Cluster.hpp"
+#include "LinearAlgebra/Vector.hpp"
+#include "LinearAlgebra/RealSpaceMatrix.hpp"
+#include "Shapes/BaseShapes.hpp"
+#include "Shapes/Shape.hpp"
+#include "World.hpp"
+#include "WorldTime.hpp"
+
+#include "ClusterUnitTest.hpp"
+
+#ifdef HAVE_TESTRUNNER
+#include "UnitTestMain.hpp"
+#endif /*HAVE_TESTRUNNER*/
+
+/********************************************** Test classes **************************************/
+
+// Registers the fixture into the 'registry'
+CPPUNIT_TEST_SUITE_REGISTRATION( ClusterTest );
+
+
+void ClusterTest::setUp()
+{
+  // failing asserts should be thrown
+  ASSERT_DO(Assert::Throw);
+
+  // this must not compile: private default Cstor
+  // cluster = new Cluster();
+
+  shape  = new Shape(Sphere());
+
+  // create an atom
+  _atom = World::getInstance().createAtom();
+  const element * hydrogen = World::getInstance().getPeriode()->FindElement(1);
+  CPPUNIT_ASSERT(hydrogen != NULL);
+  _atom->setType(hydrogen);
+  _atom->setPosition(Vector(0.,0.,0.));
+  _atomId = _atom->getId();
+
+  cluster = new Cluster(*shape);
+}
+
+
+void ClusterTest::tearDown()
+{
+  delete cluster;
+
+  World::purgeInstance();
+  WorldTime::purgeInstance();
+}
+
+/** Test whether setting and getting works
+ *
+ */
+void ClusterTest::insert_eraseTest()
+{
+  // check for empty cluster
+  CPPUNIT_ASSERT_EQUAL( (size_t)0, cluster->getAtomIds().size() );
+
+  // Shape is sphere at (0,0,0) with radius 1
+
+  {
+    // insert present atom at center of shape
+#ifndef NDEBUG
+    CPPUNIT_ASSERT_NO_THROW( cluster->insert(_atomId) );
+#else
+    cluster->insert(_atomId);
+#endif
+    CPPUNIT_ASSERT_EQUAL( (size_t)1, cluster->getAtomIds().size() );
+#ifndef NDEBUG
+    CPPUNIT_ASSERT_NO_THROW( cluster->erase(_atomId) );
+#else
+    cluster->erase(_atomId);
+#endif
+  }
+
+  {
+    // erase non-existing atom
+    const atomId_t falseId = _atomId+1;
+    CPPUNIT_ASSERT_EQUAL( (atom *)NULL, World::getInstance().getAtom(AtomById(falseId)) );
+#ifndef NDEBUG
+    std::cout << "The following Assertion is intended and does not present a failure of the test." << std::endl;
+    CPPUNIT_ASSERT_THROW( cluster->erase(falseId), Assert::AssertionFailure );
+#else
+    cluster->erase(falseId);
+#endif
+  }
+
+  {
+    // erase non-present atom
+#ifndef NDEBUG
+    std::cout << "The following Assertion is intended and does not present a failure of the test." << std::endl;
+    CPPUNIT_ASSERT_THROW( cluster->erase(_atomId), Assert::AssertionFailure );
+#else
+    cluster->erase(_atomId);
+#endif
+  }
+
+  {
+    // insert present atom within shape
+    _atom->setPosition(Vector(.5,.5,.5));
+#ifndef NDEBUG
+    CPPUNIT_ASSERT_NO_THROW( cluster->insert(_atomId) );
+#else
+    cluster->insert(_atomId);
+#endif
+    CPPUNIT_ASSERT_EQUAL( (size_t)1, cluster->getAtomIds().size() );
+#ifndef NDEBUG
+    CPPUNIT_ASSERT_NO_THROW( cluster->erase(_atomId) );
+#else
+    cluster->erase(_atomId);
+#endif
+    _atom->setPosition(Vector(0.,0.,0.));
+  }
+
+  {
+    // insert present atom outside shape
+    _atom->setPosition(Vector(2.,0.,0.));
+#ifndef NDEBUG
+    std::cout << "The following Assertion is intended and does not present a failure of the test." << std::endl;
+    CPPUNIT_ASSERT_THROW( cluster->insert(_atomId), Assert::AssertionFailure );
+#else
+    cluster->insert(_atomId);
+#endif
+    CPPUNIT_ASSERT_EQUAL( (size_t)0, cluster->getAtomIds().size() );
+    _atom->setPosition(Vector(0.,0.,0.));
+  }
+
+  {
+    // insert present atom on boundary shape
+    _atom->setPosition(Vector(1.,0.,0.));
+#ifndef NDEBUG
+    CPPUNIT_ASSERT_NO_THROW( cluster->insert(_atomId) );
+#else
+    cluster->insert(_atomId);
+#endif
+    CPPUNIT_ASSERT_EQUAL( (size_t)1, cluster->getAtomIds().size() );
+#ifndef NDEBUG
+    CPPUNIT_ASSERT_NO_THROW( cluster->erase(_atomId) );
+#else
+    cluster->erase(_atomId);
+#endif
+    _atom->setPosition(Vector(0.,0.,0.));
+  }
+
+  {
+    // insert non-existing atom
+    const atomId_t falseId = _atomId+1;
+    CPPUNIT_ASSERT_EQUAL( (atom *)NULL, World::getInstance().getAtom(AtomById(falseId)) );
+#ifndef NDEBUG
+    std::cout << "The following Assertion is intended and does not present a failure of the test." << std::endl;
+    CPPUNIT_ASSERT_THROW( cluster->insert(falseId), Assert::AssertionFailure );
+#else
+    cluster->insert(falseId);
+#endif
+    CPPUNIT_ASSERT_EQUAL( (size_t)0, cluster->getAtomIds().size() );
+  }
+}
+
+/** Test whether setting and getting works
+ *
+ */
+void ClusterTest::setter_getterTest()
+{
+  CPPUNIT_ASSERT( *shape == cluster->getShape() );
+
+  CPPUNIT_ASSERT( cluster->atoms == cluster->getAtomIds() );
+}
+
+/** Test whether translate() works
+ *
+ */
+void ClusterTest::translateTest()
+{
+  // insert
+  cluster->insert(_atomId);
+  CPPUNIT_ASSERT_EQUAL( (size_t)1, cluster->getAtomIds().size() );
+
+  // check we are at origin
+  CPPUNIT_ASSERT_EQUAL( Vector(0.,0.,0.), cluster->getShape().getCenter() );
+  const atom * _atom = NULL;
+  CPPUNIT_ASSERT_NO_THROW( _atom = cluster->getAtomById(_atomId) );
+  CPPUNIT_ASSERT( _atom != NULL );
+  CPPUNIT_ASSERT_EQUAL( Vector(0.,0.,0.), _atom->getPosition() );
+
+  // move
+  cluster->translate( Vector(1.,0.,0.) );
+
+  CPPUNIT_ASSERT_EQUAL( Vector(1.,0.,0.), cluster->getShape().getCenter() );
+  CPPUNIT_ASSERT_EQUAL( Vector(1.,0.,0.), cluster->getAtomById(_atomId)->getPosition() );
+}
+
+
+/** Test whether transform() works
+ *
+ */
+void ClusterTest::transformTest()
+{
+  // insert
+  cluster->insert(_atomId);
+  CPPUNIT_ASSERT_EQUAL( (size_t)1, cluster->getAtomIds().size() );
+
+  // check we are at origin
+  CPPUNIT_ASSERT_EQUAL( Vector(0.,0.,0.), cluster->getShape().getCenter() );
+  const atom * _atom = NULL;
+  CPPUNIT_ASSERT_NO_THROW( _atom = cluster->getAtomById(_atomId) );
+  CPPUNIT_ASSERT( _atom != NULL );
+  CPPUNIT_ASSERT_EQUAL( Vector(0.,0.,0.), _atom->getPosition() );
+
+  // transform
+  RealSpaceMatrix M;
+  M.setIdentity();
+  cluster->transform( M );
+
+  CPPUNIT_ASSERT_EQUAL( Vector(0.,0.,0.), cluster->getShape().getCenter() );
+  CPPUNIT_ASSERT_EQUAL( Vector(0.,0.,0.), cluster->getAtomById(_atomId)->getPosition() );
+}
+
+/** Test whether IsInShape() works
+ *
+ */
+void ClusterTest::IsInShapeTest()
+{
+  // at origin we are inside
+  CPPUNIT_ASSERT( shape->isInside(_atom->getPosition() ) );
+  CPPUNIT_ASSERT( cluster->IsInShape(_atomId) );
+
+  // at boundary we are inside
+  _atom->setPosition( Vector(1.,0.,0.) );
+  CPPUNIT_ASSERT( shape->isInside(_atom->getPosition() ) );
+  CPPUNIT_ASSERT( cluster->IsInShape(_atomId) );
+
+  // now we are outside
+  _atom->setPosition( Vector(2.,0.,0.) );
+  CPPUNIT_ASSERT( !shape->isInside(_atom->getPosition() ) );
+  CPPUNIT_ASSERT( !cluster->IsInShape(_atomId) );
+}
+
+/** Test whether clone() works
+ *
+ */
+void ClusterTest::cloneTest()
+{
+  // insert atom ...
+  cluster->insert(_atomId);
+
+  // ... and clone
+  CopyAtoms_Simple copyMethod;
+  ClusterInterface::Cluster_impl clonedCluster = cluster->clone(copyMethod);
+
+  // check for present atom
+  CPPUNIT_ASSERT_EQUAL( (size_t)1, clonedCluster->getAtomIds().size() );
+
+  // check for different ids
+  CPPUNIT_ASSERT_EQUAL( (size_t)2, World::getInstance().getAllAtoms().size() );
+  CPPUNIT_ASSERT( *(cluster->getAtomIds().begin()) != *(clonedCluster->getAtomIds().begin()) );
+  // check for same position
+  atomId_t id = *(clonedCluster->getAtomIds().begin());
+  const atom * const _atom = World::getInstance().getAtom(AtomById(id));
+  CPPUNIT_ASSERT( _atom != NULL );
+  CPPUNIT_ASSERT( (*cluster->getAtomRefs().begin())->getPosition() ==_atom->getPosition() );
+
+  // check that shape is the same
+  CPPUNIT_ASSERT( cluster->getShape() == clonedCluster->getShape() );
+  CPPUNIT_ASSERT( cluster->getShape().getCenter() == clonedCluster->getShape().getCenter() );
+  CPPUNIT_ASSERT( cluster->getShape().getRadius() == clonedCluster->getShape().getRadius() );
+}
+
+/** Test whether getAtomRefs() works
+ *
+ */
+void ClusterTest::getAtomRefsTest()
+{
+  Cluster::AtomVector Atomvec;
+
+  // check with empty cluster
+  CPPUNIT_ASSERT_EQUAL( Atomvec, cluster->getAtomRefs() );
+
+  // insert into both ...
+  Atomvec.push_back(_atom);
+  cluster->insert(_atomId);
+
+  // ...and check again
+  CPPUNIT_ASSERT_EQUAL( Atomvec, cluster->getAtomRefs() );
+}
Index: src/Filling/unittests/ClusterUnitTest.hpp
===================================================================
--- src/Filling/unittests/ClusterUnitTest.hpp	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
+++ src/Filling/unittests/ClusterUnitTest.hpp	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
@@ -0,0 +1,57 @@
+/*
+ * ClusterUnitTest.hpp
+ *
+ *  Created on: Jan 17, 2012
+ *      Author: heber
+ */
+
+#ifndef CLUSTERUNITTEST_HPP_
+#define CLUSTERUNITTEST_HPP_
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "types.hpp"
+
+class atom;
+class Cluster;
+class Shape;
+
+/********************************************** Test classes **************************************/
+
+class ClusterTest : public CppUnit::TestFixture
+{
+    CPPUNIT_TEST_SUITE( ClusterTest) ;
+    CPPUNIT_TEST ( insert_eraseTest );
+    CPPUNIT_TEST ( setter_getterTest );
+    CPPUNIT_TEST ( IsInShapeTest );
+    CPPUNIT_TEST ( getAtomRefsTest );
+    CPPUNIT_TEST ( translateTest );
+    CPPUNIT_TEST ( transformTest );
+    CPPUNIT_TEST ( cloneTest );
+    CPPUNIT_TEST_SUITE_END();
+
+public:
+      void setUp();
+      void tearDown();
+      void insert_eraseTest();
+      void setter_getterTest();
+      void IsInShapeTest();
+      void getAtomRefsTest();
+      void translateTest();
+      void transformTest();
+      void cloneTest();
+
+private:
+      Cluster *cluster;
+      Shape *shape;
+      atom * _atom;
+      atomId_t _atomId;
+};
+
+#endif /* CLUSTERUNITTEST_HPP_ */
Index: src/Filling/unittests/Makefile.am
===================================================================
--- src/Filling/unittests/Makefile.am	(revision 9e5a306c82483ea0f88a098c86376beb12c62ffe)
+++ src/Filling/unittests/Makefile.am	(revision 8f6e2a881f918244cc0e6fc08507dc72a81dcf74)
@@ -3,4 +3,5 @@
 
 FILLINGTESTSSOURCES = \
+  ../Filling/unittests/ClusterUnitTest.cpp \
   ../Filling/unittests/IsInsideDomain_FillPredicateUnitTest.cpp \
   ../Filling/unittests/IsInsideSurface_FillPredicateUnitTest.cpp \
@@ -10,4 +11,5 @@
 
 FILLINGTESTSHEADERS = \
+  ../Filling/unittests/ClusterUnitTest.hpp \
   ../Filling/unittests/IsInsideDomain_FillPredicateUnitTest.hpp \
   ../Filling/unittests/IsInsideSurface_FillPredicateUnitTest.hpp \
@@ -17,4 +19,5 @@
 
 FILLINGTESTS = \
+  ClusterUnitTest \
   IsInsideDomain_FillPredicateUnitTest \
   IsInsideSurface_FillPredicateUnitTest \
@@ -28,4 +31,15 @@
 
 FILLINGLIBS =
+
+ClusterUnitTest_SOURCES = $(top_srcdir)/src/unittests/UnitTestMain.cpp \
+	../Filling/unittests/ClusterUnitTest.cpp \
+	../Filling/unittests/ClusterUnitTest.hpp
+ClusterUnitTest_LDADD = \
+	../libMolecuilderFilling.la \
+	../libMolecuilderUI.la \
+	../libMolecuilder.la \
+	$(top_builddir)/LinearAlgebra/src/LinearAlgebra/libLinearAlgebra.la \
+	${CodePatterns_LIBS} \
+	$(BOOST_LIBS)
 
 IsInsideDomain_FillPredicateUnitTest_SOURCES = $(top_srcdir)/src/unittests/UnitTestMain.cpp \
