Index: src/Filling/Inserter/RandomInserter.cpp
===================================================================
--- src/Filling/Inserter/RandomInserter.cpp	(revision 896f4a7ada6369e3572c881c6619a64461c0de07)
+++ src/Filling/Inserter/RandomInserter.cpp	(revision 896f4a7ada6369e3572c881c6619a64461c0de07)
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+
+/*
+ * RandomInserter.cpp
+ *
+ *  Created on: Feb 21, 2012
+ *      Author: heber
+ */
+
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "CodePatterns/MemDebug.hpp"
+
+#include "RandomInserter.hpp"
+
+#include <algorithm>
+
+#include "Atom/atom.hpp"
+#include "CodePatterns/Log.hpp"
+#include "LinearAlgebra/RealSpaceMatrix.hpp"
+#include "RandomNumbers/RandomNumberGeneratorFactory.hpp"
+#include "RandomNumbers/RandomNumberGenerator.hpp"
+
+
+size_t RandomInserter::Max_Attempts = 10;
+
+/** Sets given 3x3 matrix to a random rotation matrix.
+ *
+ * @param a matrix to set
+ */
+inline void setRandomRotation(RealSpaceMatrix &a)
+{
+  double phi[NDIM];
+  RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();
+  const double rng_min = random.min();
+  const double rng_max = random.max();
+
+  for (int i=0;i<NDIM;i++) {
+    phi[i] = (random()/(rng_max-rng_min))*(2.*M_PI);
+    LOG(4, "DEBUG: Random angle is " << phi[i] << ".");
+  }
+
+  a.setRotation(phi);
+}
+
+/** Constructor for class RandomInserter.
+ *
+ * @param _MaxAtomComponent maximum component for random atom translations
+ * @param _MaxMoleculeComponent maximum component for random molecule translations
+ * @param  _DoRandomRotation whether to do random rotations
+ */
+RandomInserter::RandomInserter(
+    const double _MaxAtomComponent,
+    const double _MaxMoleculeComponent,
+    const bool _DoRandomRotation) :
+   random(RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator()),
+   rng_min(random.min()),
+   rng_max(random.max()),
+   MaxAtomComponent(_MaxAtomComponent),
+   MaxMoleculeComponent(_MaxMoleculeComponent),
+   DoRandomRotation(_DoRandomRotation)
+{}
+
+/** Destructor for class RandomInserter.
+ *
+ */
+RandomInserter::~RandomInserter()
+{}
+
+/** Checks whether all atoms currently are inside the cluster's shape.
+ *
+ * @param cluster cluster to check
+ * @return true - all atoms are inside cluster's shape, false - else
+ */
+bool RandomInserter::AreClustersAtomsInside(ClusterInterface::Cluster_impl cluster) const
+{
+  ClusterInterface::atomIdSet atoms = cluster->getAtomIds();
+  bool status = true;
+
+  for (ClusterInterface::atomIdSet::const_iterator iter = atoms.begin();
+      iter != atoms.end();
+      ++iter)
+    status = status && cluster->isInside(*iter);
+
+  return status;
+}
+
+/** Perform the given random translations and rotations on a cluster.
+ *
+ * @param cluster cluster to translate and rotate
+ * @param Rotations random rotation matrix
+ * @param RandomAtomTranslations vector with random translation for each atom in cluster
+ * @param RandomMoleculeTranslation vector with random translation for cluster
+ * @param offset vector with offset for cluster
+ */
+void RandomInserter::doTranslation(
+    ClusterInterface::Cluster_impl cluster,
+    const RealSpaceMatrix &Rotations,
+    const std::vector<Vector> &RandomAtomTranslations,
+    const Vector &RandomMoleculeTranslation) const
+{
+  AtomIdSet atoms = cluster->getAtoms();
+
+  ASSERT( atoms.size() <=  RandomAtomTranslations.size(),
+      "RandomInserter::doTranslation() - insufficient random atom translations given.");
+
+  cluster->transform(Rotations);
+  cluster->translate(RandomMoleculeTranslation);
+  AtomIdSet::iterator miter = atoms.begin();
+  std::vector<Vector>::const_iterator aiter = RandomAtomTranslations.begin();
+  for(;miter != atoms.end(); ++miter, ++aiter)
+    (*miter)->setPosition((*miter)->getPosition() + *aiter);
+}
+
+/** Undos a given random translations and rotations on a cluster.
+ *
+ * @param cluster cluster to translate and rotate
+ * @param Rotations random rotation matrix
+ * @param RandomAtomTranslations vector with random translation for each atom in cluster
+ * @param RandomMoleculeTranslations vector with random translation for cluster
+ * @param offset vector with offset for cluster
+ */
+void RandomInserter::undoTranslation(
+    ClusterInterface::Cluster_impl cluster,
+    const RealSpaceMatrix &Rotations,
+    const std::vector<Vector> &RandomAtomTranslations,
+    const Vector &RandomMoleculeTranslation) const
+{
+  AtomIdSet atoms = cluster->getAtoms();
+  ASSERT( atoms.size() <=  RandomAtomTranslations.size(),
+      "RandomInserter::doTranslation() - insufficient random atom translations given.");
+
+  // get inverse rotation
+  RealSpaceMatrix inverseRotations = Rotations.invert();
+
+  AtomIdSet::iterator miter = atoms.begin();
+  std::vector<Vector>::const_iterator aiter = RandomAtomTranslations.begin();
+  for(;miter != atoms.end(); ++miter, ++aiter) {
+    (*miter)->setPosition((*miter)->getPosition() - *aiter);
+  }
+  cluster->translate(zeroVec-RandomMoleculeTranslation);
+  cluster->transform(inverseRotations);
+}
+
+/** Creates a random vector
+ *
+ * @param range range of components, i.e. \f$ v[i] \in [0,range)\f$
+ * @param offset offset for each component
+ * @return \a range * rnd() + \a offset
+ */
+Vector RandomInserter::getRandomVector(const double range, const double offset) const
+{
+  Vector returnVector;
+  for (size_t i=0; i<NDIM; ++i)
+    returnVector[i] = (range*random()/((rng_max-rng_min)/2.)) + offset;
+  return returnVector;
+}
+
+/** Inserter operator that randomly translates and rotates the Cluster.
+ *
+ * \note we assume that clusters are always cloned at origin.
+ *
+ * @param offset
+ * @return true - random translations and rotations did not violate bounding shape, false - else
+ */
+bool RandomInserter::operator()(ClusterInterface::Cluster_impl cluster, const Vector &offset) const
+{
+  // calculate center
+  AtomIdSet atoms = cluster->getAtoms();
+  Vector center;
+  center.Zero();
+  for(AtomIdSet::iterator miter = atoms.begin();miter != atoms.end(); ++miter)
+    center += (*miter)->getPosition();
+  center *= 1./atoms.size();
+
+  // shift cluster to center
+  cluster->translate(zeroVec-center);
+
+  size_t attempt = 0;
+  for (;attempt < Max_Attempts; ++attempt) {
+    // generate random rotation matrix
+    RealSpaceMatrix Rotations;
+    if (DoRandomRotation)
+      setRandomRotation(Rotations);
+    else
+      Rotations.setIdentity();
+
+    // generate random molecule translation vector
+    Vector RandomMoleculeTranslation(getRandomVector(MaxMoleculeComponent, -MaxMoleculeComponent));
+
+    // generate random atom translation vector
+    std::vector<Vector> RandomAtomTranslations(atoms.size(), zeroVec);
+    std::generate_n(RandomAtomTranslations.begin(), atoms.size(),
+        boost::bind(&RandomInserter::getRandomVector, boost::cref(this), MaxAtomComponent, -MaxAtomComponent));
+
+    // apply!
+    doTranslation(cluster, Rotations, RandomAtomTranslations, RandomMoleculeTranslation);
+
+    // ... and check
+    if (!AreClustersAtomsInside(cluster)) {
+      undoTranslation(cluster, Rotations, RandomAtomTranslations, RandomMoleculeTranslation);
+    } else {
+      break;
+    }
+  }
+
+  // and move to final position
+  cluster->translate(offset+center);
+
+  return attempt != Max_Attempts;
+}
Index: src/Filling/Inserter/RandomInserter.hpp
===================================================================
--- src/Filling/Inserter/RandomInserter.hpp	(revision 896f4a7ada6369e3572c881c6619a64461c0de07)
+++ src/Filling/Inserter/RandomInserter.hpp	(revision 896f4a7ada6369e3572c881c6619a64461c0de07)
@@ -0,0 +1,77 @@
+/*
+ * RandomInserter.hpp
+ *
+ *  Created on: Feb 21, 2012
+ *      Author: heber
+ */
+
+#ifndef RANDOMINSERTER_HPP_
+#define RANDOMINSERTER_HPP_
+
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "InserterBase.hpp"
+
+#include <vector>
+
+#include "LinearAlgebra/Vector.hpp"
+
+class RandomNumberGenerator;
+class RealSpaceMatrix;
+
+/** RandomInserter implements Inserter interface such that the given \a Cluster
+ * is inserted at the position with a slight random variation.
+ *
+ * \warning As the RandomInserter rotates the molecule, the only bounding shape in
+ * Cluster that makes sense is a sphere. Otherwise, RandomInserter::Max_Attempts
+ * attempts are made at finding a lucky shot where all atoms, though rotated
+ * and randomly translated, remain inside but after that the cluster is inserted
+ * as it is.
+ */
+class RandomInserter : public InserterBase
+{
+public:
+  RandomInserter(const double _MaxAtomComponent, const double _MaxMoleculeComponent, const bool _DoRandomRotation);
+  ~RandomInserter();
+
+  bool operator()(ClusterInterface::Cluster_impl cluster, const Vector &offset) const;
+
+private:
+  bool AreClustersAtomsInside(ClusterInterface::Cluster_impl cluster) const;
+  Vector getRandomVector(const double range, const double offset) const;
+
+  void doTranslation(
+      ClusterInterface::Cluster_impl cluster,
+      const RealSpaceMatrix &Rotations,
+      const std::vector<Vector> &RandomAtomTranslations,
+      const Vector &RandomMoleculeTranslations) const;
+  void undoTranslation(
+      ClusterInterface::Cluster_impl cluster,
+      const RealSpaceMatrix &Rotations,
+      const std::vector<Vector> &RandomAtomTranslations,
+      const Vector &RandomMoleculeTranslations) const;
+
+private:
+  //!> internal random number generator
+  RandomNumberGenerator &random;
+  //!> minimum value of the random number distribution
+  const double rng_min;
+  //!> maximum value of the random number distribution
+  const double rng_max;
+  //!> range is maximum component for atom translations
+  const double MaxAtomComponent;
+  //!> range is maximum component for molecule translations
+  const double MaxMoleculeComponent;
+  //!> whether to randomly rotate or not
+  const bool DoRandomRotation;
+
+  //!> maximum number of tries to find a suitable randomized position
+  static size_t Max_Attempts;
+};
+
+
+#endif /* RANDOMINSERTER_HPP_ */
Index: src/Filling/Makefile.am
===================================================================
--- src/Filling/Makefile.am	(revision 4fbc4eb3e954566cda24e1994d562cd588d3d6df)
+++ src/Filling/Makefile.am	(revision 896f4a7ada6369e3572c881c6619a64461c0de07)
@@ -9,4 +9,5 @@
 	Filling/Generators/NodeGenerator.cpp \
 	Filling/Inserter/Inserter.cpp \
+	Filling/Inserter/RandomInserter.cpp \
 	Filling/Inserter/SimpleInserter.cpp \
 	Filling/Predicates/AnyFillPredicate.cpp \
@@ -26,4 +27,5 @@
 	Filling/Inserter/Inserter.hpp \
 	Filling/Inserter/InserterBase.hpp \
+	Filling/Inserter/RandomInserter.hpp \
 	Filling/Inserter/SimpleInserter.hpp \
 	Filling/NodeTypes.hpp \
