Index: src/Actions/FillAction/FillSurfaceAction.cpp
===================================================================
--- src/Actions/FillAction/FillSurfaceAction.cpp	(revision 6801f4f3b7ed127fa9a9c8afe64f82d34df963d2)
+++ src/Actions/FillAction/FillSurfaceAction.cpp	(revision 16c7dd3fc6c66022b4b13c912de169a1f812196c)
@@ -46,7 +46,9 @@
 #include "Filling/Mesh/MeshAdaptor.hpp"
 #include "Filling/Predicates/IsVoidNode_FillPredicate.hpp"
+#include "Filling/Preparators/ShapeSurfaceFillerPreparator.hpp"
 #include "molecule.hpp"
 #include "Shapes/BaseShapes.hpp"
 #include "Shapes/ShapeRegistry.hpp"
+#include "Shapes/ShapeType.hpp"
 #include "World.hpp"
 
@@ -98,30 +100,57 @@
   }
 
-  // create predicate, mesh, and filler
-  FillSurfaceState *UndoState = NULL;
-  bool successflag = false;
-  {
-    FillPredicate *voidnode_predicate = new FillPredicate(
-        IsVoidNode_FillPredicate(
-            Sphere(zeroVec, params.mindistance.get())
-            )
-        );
-
-
-    std::vector<Shape*> selectedShapes = ShapeRegistry::getInstance().getSelectedShapes();
-    if (selectedShapes.size() != 1){
-      STATUS("There has to be exactly 1 selected shape.");
+  // prepare the filler preparator
+  if (ShapeRegistry::getInstance().countSelectedShapes() != (size_t)1) {
+    STATUS("Not exactly one shape selected.");
+    return Action::failure;
+  }
+  const std::vector<Shape*> shapes = ShapeRegistry::getInstance().getSelectedShapes();
+  const Shape &shape = **shapes.begin();
+
+  // hard check whether shape is of allowed type, not all are implemented
+  // but these only fail with an assertion, hence not with disable-debug
+  switch (shape.getType()) {
+    case NowhereType:
+    case EverywhereType:
+      STATUS("The shape type "+toString(shape.getType())+" is currently not supported.");
+      return Action::failure;
+      break;
+    default:
+      break;
+  }
+
+  ShapeSurfaceFillerPreparator filler_preparator(filler);
+  if (params.SphereRadius.get() != 0.) {
+    if (World::getInstance().beginAtomSelection() == World::getInstance().endAtomSelection()) {
+      STATUS("You have given a sphere radius "+toString(params.SphereRadius.get())
+          +" != 0, but have not select any atoms.");
       return Action::failure;
     }
-
-    boost::function<const NodeSet ()> func = 
-        boost::bind(&Shape::getHomogeneousPointsOnSurface, boost::ref(*selectedShapes[0]), params.N.get());
-    Mesh *mesh = new MeshAdaptor(func);
-    Inserter *inserter = new Inserter(
-        Inserter::impl_ptr(new SurfaceInserter(*selectedShapes[0], params.AlignedAxis.get())));
-
+    std::vector<atom*> atoms(World::getInstance().getSelectedAtoms());
+    filler_preparator.addSurfacePredicate(
+        params.SphereRadius.get(),
+        atoms);
+  }
+  filler_preparator.addVoidPredicate(params.mindistance.get());
+  filler_preparator.addSurfaceRandomInserter(
+      shape,
+      params.AlignedAxis.get(),
+      params.RandAtomDisplacement.get(),
+      params.RandMoleculeDisplacement.get());
+  filler_preparator.addShapeMesh(
+      shape,
+      params.N.get());
+  if (!filler_preparator()) {
+    STATUS("Filler was not fully constructed.");
+    return Action::failure;
+  }
+
+  // use filler
+  bool successflag = false;
+  FillSurfaceState *UndoState = NULL;
+  {
     // fill
     {
-      Filler *fillerFunction = new Filler(*mesh, *voidnode_predicate, *inserter);
+      Filler *fillerFunction = filler_preparator.obtainFiller();
       ClusterInterface::Cluster_impl cluster( new Cluster( filler->getAtomIds(), filler->getBoundingSphere() ) );
       CopyAtoms_withBonds copyMethod;
@@ -160,9 +189,4 @@
       }
     }
-
-    // remove
-    delete mesh;
-    delete inserter;
-    delete voidnode_predicate;
   }
 
Index: src/Actions/FillAction/FillSurfaceAction.def
===================================================================
--- src/Actions/FillAction/FillSurfaceAction.def	(revision 6801f4f3b7ed127fa9a9c8afe64f82d34df963d2)
+++ src/Actions/FillAction/FillSurfaceAction.def	(revision 16c7dd3fc6c66022b4b13c912de169a1f812196c)
@@ -20,11 +20,14 @@
 // ValueStorage by the token "Z" -> first column: int, Z, "Z"
 // "undefine" if no parameters are required, use (NOPARAM_DEFAULT) for each (undefined) default value
-#define paramtypes (unsigned int)(double)(Vector)
-#define paramtokens ("count")("min-distance")("Alignment-Axis")
-#define paramdescriptions ("number of instances to be added, changed according to geometric needs")("minimum distance between added instances")("The filler molecule is rotated relative to this alignment axis")
-#define paramdefaults (PARAM_DEFAULT(12))(PARAM_DEFAULT(1.))(NOPARAM_DEFAULT)
-#define paramreferences (N)(mindistance)(AlignedAxis)
+#define paramtypes (unsigned int)(double)(double)(double)(double)(Vector)
+#define paramtokens ("count")("min-distance")("tesselation-radius")("random-atom-displacement")("random-molecule-displacement")("Alignment-Axis")
+#define paramdescriptions ("number of instances to be added, changed according to geometric needs")("minimum distance between added instances")("radius of rolling sphere in tesselating selected molecule's surfaces")("magnitude of random atom displacement")("magnitude of random molecule displacement")("The filler molecule is rotated relative to this alignment axis")
+#define paramdefaults (PARAM_DEFAULT(12))(PARAM_DEFAULT(1.))(PARAM_DEFAULT(0.))(PARAM_DEFAULT(0.))(PARAM_DEFAULT(0.))(NOPARAM_DEFAULT)
+#define paramreferences (N)(mindistance)(SphereRadius)(RandAtomDisplacement)(RandMoleculeDisplacement)(AlignedAxis)
 #define paramvalids \
 (DummyValidator< unsigned int >()) \
+(BoxLengthValidator()) \
+(BoxLengthValidator()) \
+(BoxLengthValidator()) \
 (BoxLengthValidator()) \
 (VectorNotZeroValidator())
@@ -36,5 +39,5 @@
 #define CATEGORY Fill
 #define MENUNAME "fill"
-#define MENUPOSITION 1
+#define MENUPOSITION 2
 #define ACTIONNAME Surface
 #define TOKEN "fill-surface"
