diff --git a/Gui/DataView/MeshLayerEditDialog.cpp b/Gui/DataView/MeshLayerEditDialog.cpp
index 5f7b9461f188714e1450c8ece9f8f82198830efd..3e1d0bb8f40ab1c017dc3e035de8150ef68e3d12 100644
--- a/Gui/DataView/MeshLayerEditDialog.cpp
+++ b/Gui/DataView/MeshLayerEditDialog.cpp
@@ -188,16 +188,19 @@ MeshLib::Mesh* MeshLayerEditDialog::createPrismMesh()
 		layer_thickness.push_back(thickness);
 	}
 
-    MeshLayerMapper const mapper;
-	MeshLib::Mesh* new_mesh = mapper.createStaticLayers(*_msh, layer_thickness);
+    MeshLayerMapper mapper;
+	MeshLib::Mesh* new_mesh (nullptr);
 
 	if (_use_rasters)
 	{
         std::vector<std::string> raster_paths;
 		for (int i=nLayers; i>=0; --i)
             raster_paths.push_back(this->_edits[i]->text().toStdString());
-        new_mesh = mapper.createRasterLayers(*_msh, raster_paths);
+        if (mapper.createLayers(*_msh, raster_paths))
+            new_mesh= mapper.getMesh("SubsurfaceMesh");
 	}
+    else
+        new_mesh = mapper.createStaticLayers(*_msh, layer_thickness);
 	return new_mesh;
 }
 
@@ -218,9 +221,9 @@ MeshLib::Mesh* MeshLayerEditDialog::createTetMesh()
 		for (int i=nLayers; i>=0; --i)
 			raster_paths[i] = this->_edits[i]->text().toStdString();
 		LayeredVolume lv;
-		lv.createGeoVolumes(*_msh, raster_paths);
+		lv.createLayers(*_msh, raster_paths);
 
-		tg_mesh = lv.getMesh();
+		tg_mesh = lv.getMesh("SubsurfaceMesh");
 
 		QString file_path("");
 		if (tg_mesh)
diff --git a/MeshLib/MeshGenerators/LayeredVolume.cpp b/MeshLib/MeshGenerators/LayeredVolume.cpp
index 2f8033302b3f90319ee9a98f95b275653a995aa1..509d314c23f2c9a2baa1eebd21ef55acbbcac944 100644
--- a/MeshLib/MeshGenerators/LayeredVolume.cpp
+++ b/MeshLib/MeshGenerators/LayeredVolume.cpp
@@ -14,49 +14,17 @@
 
 #include "LayeredVolume.h"
 
-#include <fstream>
-#include <numeric>
-
 #include "Vector3.h"
 
-#include "FileIO/AsciiRasterInterface.h"
+#include "Raster.h"
 
-#include "GEOObjects.h"
-#include "PointVec.h"
-#include "Mesh.h"
-#include "convertMeshToGeo.h"
-#include "Elements/Element.h"
 #include "Elements/Tri.h"
 #include "Elements/Quad.h"
 #include "MeshGenerators/MeshLayerMapper.h"
-#include "MeshQuality/MeshValidation.h"
 #include "MeshEditing/ElementExtraction.h"
 
 
-const double LayeredVolume::_invalid_value = -9999;
-
-LayeredVolume::LayeredVolume()
-: _elevation_epsilon(0.0001), _mesh(nullptr)
-{
-}
-
-bool LayeredVolume::createGeoVolumes(const MeshLib::Mesh &mesh, const std::vector<std::string> &raster_paths, double noDataReplacementValue)
-{
-	if (mesh.getDimension() != 2 || !allRastersExist(raster_paths))
-		return false;
-
-	std::vector<GeoLib::Raster const*> rasters;
-	rasters.reserve(raster_paths.size());
-	for (auto path = raster_paths.begin(); path != raster_paths.end(); ++path)
-		rasters.push_back(FileIO::AsciiRasterInterface::getRasterFromASCFile(*path));
-
-	const bool result = this->createGeoVolumes(mesh, rasters, noDataReplacementValue);
-	std::for_each(rasters.begin(), rasters.end(), [](GeoLib::Raster const*const raster){ delete raster; });
-	return result;
-}
-
-
-bool LayeredVolume::createGeoVolumes(const MeshLib::Mesh &mesh, const std::vector<GeoLib::Raster const*> &rasters, double noDataReplacementValue)
+bool LayeredVolume::createRasterLayers(const MeshLib::Mesh &mesh, const std::vector<GeoLib::Raster const*> &rasters, double noDataReplacementValue)
 {
 	if (mesh.getDimension() != 2)
 		return false;
@@ -73,38 +41,36 @@ bool LayeredVolume::createGeoVolumes(const MeshLib::Mesh &mesh, const std::vecto
 		mesh_layer = new MeshLib::Mesh(mesh);
 
 	// map each layer and attach to subsurface mesh
-    MeshLayerMapper const mapper;
 	const std::size_t nRasters (rasters.size());
 	for (size_t i=0; i<nRasters; ++i)
 	{
-		const double replacement_value = (i==(nRasters-1)) ? noDataReplacementValue : _invalid_value;
-		if (!mapper.layerMapping(*mesh_layer, *rasters[i], replacement_value))
+		const double replacement_value = (i==(nRasters-1)) ? noDataReplacementValue : rasters[i]->getNoDataValue();
+		if (!MeshLayerMapper::layerMapping(*mesh_layer, *rasters[i], replacement_value))
 		{
 			this->cleanUpOnError();
 			return false;
 		}
-		this->addLayerToMesh(*mesh_layer, i);
+		this->addLayerToMesh(*mesh_layer, i, *rasters[i]);
 	}
 	// close boundaries between layers
 	this->addLayerBoundaries(*mesh_layer, nRasters);
 	this->removeCongruentElements(nRasters, mesh_layer->getNElements());
 	delete mesh_layer;
-	_mesh = new MeshLib::Mesh("BoundaryMesh", _nodes, _elements);
-	MeshLib::MeshValidation::removeUnusedMeshNodes(*_mesh);
 	return true;
 }
 
-void LayeredVolume::addLayerToMesh(const MeshLib::Mesh &mesh_layer, unsigned layer_id)
+void LayeredVolume::addLayerToMesh(const MeshLib::Mesh &mesh_layer, unsigned layer_id, GeoLib::Raster const& raster)
 {
 	const std::vector<MeshLib::Node*> &layer_nodes (mesh_layer.getNodes());
 	const std::size_t nNodes (layer_nodes.size());
 	const std::size_t node_id_offset (_nodes.size());
 	const std::size_t last_layer_offset (node_id_offset-nNodes);
+    const double no_data_value (raster.getNoDataValue());
 
 	for (std::size_t i=0; i<nNodes; ++i)
 	{
 		if (layer_id > 0 &&
-		   ((*layer_nodes[i])[2] == _invalid_value ||
+		   ((*layer_nodes[i])[2] == no_data_value ||
 		    (*_nodes[last_layer_offset+i])[2]-(*layer_nodes[i])[2] < _elevation_epsilon))
 			_nodes.push_back(new MeshLib::Node(*_nodes[last_layer_offset+i]));
 		else
@@ -199,36 +165,3 @@ void LayeredVolume::removeCongruentElements(std::size_t nLayers, std::size_t nEl
 	auto elem_vec_end = std::remove(_elements.begin(), _elements.end(), nullptr);
 	_elements.erase(elem_vec_end, _elements.end());
 }
-
-bool LayeredVolume::exportToGeometry(GeoLib::GEOObjects &geo_objects) const
-{
-	if (_mesh == nullptr)
-		return false;
-	MeshLib::convertMeshToGeo(*_mesh, geo_objects, std::numeric_limits<double>::min());
-	return true;
-}
-
-double LayeredVolume::calcEpsilon(const GeoLib::Raster &high, const GeoLib::Raster &low)
-{
-	const double max (*std::max_element(high.begin(), high.end()));
-	const double min (*std::min_element( low.begin(),  low.end()));
-	return ((max-min)*1e-07);
-}
-
-bool LayeredVolume::allRastersExist(const std::vector<std::string> &raster_paths) const
-{
-	for (auto raster = raster_paths.begin(); raster != raster_paths.end(); ++raster)
-	{
-		std::ifstream file_stream (*raster, std::ifstream::in);
-		if (!file_stream.good())
-			return false;
-		file_stream.close();
-	}
-	return true;
-}
-
-void LayeredVolume::cleanUpOnError()
-{
-	std::for_each(_nodes.begin(), _nodes.end(), [](MeshLib::Node *node) { delete node; });
-	std::for_each(_elements.begin(), _elements.end(), [](MeshLib::Element *elem) { delete elem; });
-}
diff --git a/MeshLib/MeshGenerators/LayeredVolume.h b/MeshLib/MeshGenerators/LayeredVolume.h
index 1801f81c90f2bb4925bfe99c1d66e9c401c5a5da..172503a64bf3f7bf510061fd38cf91182e69a167 100644
--- a/MeshLib/MeshGenerators/LayeredVolume.h
+++ b/MeshLib/MeshGenerators/LayeredVolume.h
@@ -18,26 +18,21 @@
 #include <string>
 #include <vector>
 
-#include "Raster.h"
 #include "Node.h"
+#include "SubsurfaceMapper.h"
 
 namespace GeoLib {
 	class GEOObjects;
 	class Surface;
 }
 
-namespace MeshLib {
-	class Mesh;
-	class Element;
-}
-
 /**
  * \brief Creates a volume geometry from 2D mesh layers based on raster data.
  */
-class LayeredVolume
+class LayeredVolume : public SubsurfaceMapper
 {
 public:
-	LayeredVolume();
+    LayeredVolume() {}
 	~LayeredVolume() {}
 
 	/**
@@ -47,29 +42,14 @@ public:
 	 * @param noDataReplacementValue  Default z-coordinate if there are mesh nodes not located on the DEM raster (i.e. raster_paths[0]) 
 	 * @result true if the subsurface representation has been created, false if there was an error
 	 */
-	bool createGeoVolumes(const MeshLib::Mesh &mesh, const std::vector<GeoLib::Raster const*> &rasters, double noDataReplacementValue = 0.0);
-
-	/**
-	 * Constructs a subsurface representation of a mesh using only 2D elements (i.e. layer boundaries are represented by surfaces)
-	 * @param mesh                    The 2D surface mesh that is used as a basis for the subsurface mesh
-	 * @param raster_paths            Containing all the raster-file-names for the subsurface layers from bottom to top (starting with the bottom of the oldest layer and ending with the DEM)
-	 * @param noDataReplacementValue  Default z-coordinate if there are mesh nodes not located on the DEM raster (i.e. raster_paths[0]) 
-	 * @result true if the subsurface representation has been created, false if there was an error
-	 */
-	bool createGeoVolumes(const MeshLib::Mesh &mesh, const std::vector<std::string> &raster_paths, double noDataReplacementValue = 0.0);
-
-	/// Returns the subsurface representation that can be used as input for the TetGenInterface
-	MeshLib::Mesh* getMesh() const { return _mesh; }
-
+	bool createRasterLayers(const MeshLib::Mesh &mesh, const std::vector<GeoLib::Raster const*> &rasters, double noDataReplacementValue = 0.0);
+    
 	/// Returns the region attribute vector necessary for assigning region attributes via TetGen
 	std::vector<MeshLib::Node> getAttributePoints() { return _attribute_points; }
 
-	/// Converts the subsurface representation to geometry objects and adds them to the geo storage object
-	bool exportToGeometry(GeoLib::GEOObjects &geo_objects) const;
-
 private:
 	/// Adds another layer to the subsurface mesh
-	void addLayerToMesh(const MeshLib::Mesh &mesh_layer, unsigned layer_id);
+	void addLayerToMesh(const MeshLib::Mesh &mesh_layer, unsigned layer_id, GeoLib::Raster const& raster);
 
 	/// Creates boundary surfaces between the mapped layers to make the volumes watertight
 	void addLayerBoundaries(const MeshLib::Mesh &layer, std::size_t nLayers);
@@ -77,21 +57,7 @@ private:
 	/// Removes duplicate 2D elements (possible due to outcroppings)
 	void removeCongruentElements(std::size_t nLayers, std::size_t nElementsPerLayer);
 
-	/// Calculates a data-dependent epsilon value
-	double calcEpsilon(const GeoLib::Raster &high, const GeoLib::Raster &low);
-
-	/// Checks if all raster files actually exist
-	bool allRastersExist(const std::vector<std::string> &raster_paths) const;
-
-	/// Cleans up the already created object in case of an error
-	void cleanUpOnError();
-
-	static const double _invalid_value;
-	double _elevation_epsilon;
-	std::vector<MeshLib::Node*> _nodes;
-	std::vector<MeshLib::Element*> _elements;
 	std::vector<MeshLib::Node> _attribute_points;
-	MeshLib::Mesh* _mesh;
 };
 
 #endif //LAYEREDVOLUME_H
diff --git a/MeshLib/MeshGenerators/MeshLayerMapper.cpp b/MeshLib/MeshGenerators/MeshLayerMapper.cpp
index 20eb5c939241d81a88c93a603305af7ed6264a62..2264191178d387fcb7f22d1fadb08d1b4ebbb828 100644
--- a/MeshLib/MeshGenerators/MeshLayerMapper.cpp
+++ b/MeshLib/MeshGenerators/MeshLayerMapper.cpp
@@ -12,28 +12,21 @@
  *
  */
 
-// stl
+#include "MeshLayerMapper.h"
+
 #include <algorithm>
 
-// ThirdParty/logog
 #include "logog/include/logog.hpp"
 
-#include "MeshLayerMapper.h"
-
 #include "FileIO/AsciiRasterInterface.h"
 
-// GeoLib
 #include "Raster.h"
 
-#include "Mesh.h"
-#include "Node.h"
-#include "Elements/Element.h"
 #include "Elements/Tet.h"
 #include "Elements/Hex.h"
 #include "Elements/Pyramid.h"
 #include "Elements/Prism.h"
 #include "MeshSurfaceExtraction.h"
-#include "MeshQuality/MeshValidation.h"
 
 #include "MathTools.h"
 
@@ -44,7 +37,6 @@ const unsigned MeshLayerMapper::_pyramid_base[3][4] =
 	{0, 3, 4, 1}, // Point 6 missing
 };
 
-
 MeshLib::Mesh* MeshLayerMapper::createStaticLayers(MeshLib::Mesh const& mesh, std::vector<float> const& layer_thickness_vector, std::string const& mesh_name) const
 {
 	std::vector<float> thickness;
@@ -114,27 +106,12 @@ MeshLib::Mesh* MeshLayerMapper::createStaticLayers(MeshLib::Mesh const& mesh, st
 	return new MeshLib::Mesh(mesh_name, new_nodes, new_elems);
 }
 
-MeshLib::Mesh* MeshLayerMapper::createRasterLayers(MeshLib::Mesh const& mesh, std::vector<std::string> const& raster_paths, std::string const& mesh_name) const
-{
-	if (mesh.getDimension() != 2 || !allRastersExist(raster_paths))
-		return false;
-
-	std::vector<GeoLib::Raster const*> rasters;
-	rasters.reserve(raster_paths.size());
-	for (auto path = raster_paths.begin(); path != raster_paths.end(); ++path)
-		rasters.push_back(FileIO::AsciiRasterInterface::getRasterFromASCFile(*path));
-
-	MeshLib::Mesh* result = this->createRasterLayers(mesh, rasters, mesh_name);
-	std::for_each(rasters.begin(), rasters.end(), [](GeoLib::Raster const*const raster){ delete raster; });
-	return result;
-}
-
-MeshLib::Mesh* MeshLayerMapper::createRasterLayers(MeshLib::Mesh const& mesh, std::vector<GeoLib::Raster const*> const& rasters, std::string const& mesh_name) const
+bool MeshLayerMapper::createRasterLayers(MeshLib::Mesh const& mesh, std::vector<GeoLib::Raster const*> const& rasters, double noDataReplacementValue)
 {
     const std::size_t nLayers(rasters.size());
 	if (nLayers < 1 || mesh.getDimension() != 2)
 	{
-		ERR("MeshLayerMapper::createStaticLayers(): A 2D mesh with nLayers > 0 is required as input.");
+		ERR("MeshLayerMapper::createRasterLayers(): A 2D mesh and at least two rasters required as input.");
 		return nullptr;
 	}
 
@@ -142,26 +119,22 @@ MeshLib::Mesh* MeshLayerMapper::createRasterLayers(MeshLib::Mesh const& mesh, st
     if (layerMapping(*dem_mesh, *rasters.back(), 0))
     {
         std::size_t const nNodes = mesh.getNNodes();
-	    std::vector<MeshLib::Node*> new_nodes;
-        new_nodes.reserve(nLayers * nNodes);
+        _nodes.reserve(nLayers * nNodes);
 
 	    // number of triangles in the original mesh
 	    std::size_t const nElems (std::count_if(mesh.getElements().begin(), mesh.getElements().end(),
 			[](MeshLib::Element const* elem) { return (elem->getGeomType() == MeshElemType::TRIANGLE);}));
-	    std::vector<MeshLib::Element*> new_elems;
-        new_elems.reserve(nElems * (nLayers-1));
+        _elements.reserve(nElems * (nLayers-1));
 
         for (std::size_t i=0; i<nLayers; ++i)
-            addLayerToMesh(*dem_mesh, i, *rasters[i], new_nodes, new_elems);
-
-        MeshLib::Mesh* result = new MeshLib::Mesh(mesh_name, new_nodes, new_elems);
-        MeshLib::MeshValidation::removeUnusedMeshNodes(*result);
-        return result;
+            addLayerToMesh(*dem_mesh, i, *rasters[i]);
 
+        return true;
     }
+    return false;
 }
 
-void MeshLayerMapper::addLayerToMesh(const MeshLib::Mesh &dem_mesh, unsigned layer_id, GeoLib::Raster const& raster, std::vector<MeshLib::Node*> &new_nodes, std::vector<MeshLib::Element*> &new_elems) const
+void MeshLayerMapper::addLayerToMesh(const MeshLib::Mesh &dem_mesh, unsigned layer_id, GeoLib::Raster const& raster)
 {
     std::size_t const nNodes = dem_mesh.getNNodes();
 	std::vector<MeshLib::Node*> const& nodes = dem_mesh.getNodes();
@@ -177,10 +150,10 @@ void MeshLayerMapper::addLayerToMesh(const MeshLib::Mesh &dem_mesh, unsigned lay
 
         if ((layer_id > 0) && 
             ((std::abs(elevation - no_data_value) < std::numeric_limits<double>::epsilon()) ||
-             (elevation - (*new_nodes[last_layer_node_offset + i])[2] < std::numeric_limits<double>::epsilon())))
-            new_nodes.push_back(new MeshLib::Node((*nodes[i])[0], (*nodes[i])[1], elevation, new_nodes[last_layer_node_offset +i]->getID()));
+             (elevation - (*_nodes[last_layer_node_offset + i])[2] < std::numeric_limits<double>::epsilon())))
+            _nodes.push_back(new MeshLib::Node((*nodes[i])[0], (*nodes[i])[1], elevation, _nodes[last_layer_node_offset +i]->getID()));
         else
-            new_nodes.push_back(new MeshLib::Node((*nodes[i])[0], (*nodes[i])[1], elevation, (layer_id * nNodes) + i));
+            _nodes.push_back(new MeshLib::Node((*nodes[i])[0], (*nodes[i])[1], elevation, (layer_id * nNodes) + i));
     }
 
     if (layer_id == 0)
@@ -198,8 +171,8 @@ void MeshLayerMapper::addLayerToMesh(const MeshLib::Mesh &dem_mesh, unsigned lay
         std::array<MeshLib::Node*, 6> new_elem_nodes;
         for (unsigned j=0; j<3; ++j)
         {
-            new_elem_nodes[j] = new_nodes[last_layer_node_offset + elem->getNodeIndex(j)];
-            new_elem_nodes[node_counter] = (new_nodes[last_layer_node_offset + elem->getNodeIndex(j) + nNodes]);
+            new_elem_nodes[j] = _nodes[last_layer_node_offset + elem->getNodeIndex(j)];
+            new_elem_nodes[node_counter] = (_nodes[last_layer_node_offset + elem->getNodeIndex(j) + nNodes]);
             if (new_elem_nodes[j]->getID() != new_elem_nodes[node_counter]->getID())
                 node_counter++;
             else
@@ -209,7 +182,7 @@ void MeshLayerMapper::addLayerToMesh(const MeshLib::Mesh &dem_mesh, unsigned lay
         switch (node_counter)
         {
         case 6:
-            new_elems.push_back(new MeshLib::Prism(new_elem_nodes, layer_id));
+            _elements.push_back(new MeshLib::Prism(new_elem_nodes, layer_id));
             break;
         case 5:
             std::array<MeshLib::Node*, 5> pyramid_nodes;
@@ -218,12 +191,12 @@ void MeshLayerMapper::addLayerToMesh(const MeshLib::Mesh &dem_mesh, unsigned lay
             pyramid_nodes[2] = new_elem_nodes[_pyramid_base[missing_idx][2]];
             pyramid_nodes[3] = new_elem_nodes[_pyramid_base[missing_idx][3]];
             pyramid_nodes[4] = new_elem_nodes[missing_idx];
-            new_elems.push_back(new MeshLib::Pyramid(pyramid_nodes, layer_id));
+            _elements.push_back(new MeshLib::Pyramid(pyramid_nodes, layer_id));
             break;
         case 4:
             std::array<MeshLib::Node*, 4> tet_nodes;
             std::copy(new_elem_nodes.begin(), new_elem_nodes.begin() + node_counter, tet_nodes.begin());
-            new_elems.push_back(new MeshLib::Tet(tet_nodes, layer_id));
+            _elements.push_back(new MeshLib::Tet(tet_nodes, layer_id));
             break;
         default:
             continue;
@@ -231,7 +204,7 @@ void MeshLayerMapper::addLayerToMesh(const MeshLib::Mesh &dem_mesh, unsigned lay
     }
 }
 
-bool MeshLayerMapper::layerMapping(MeshLib::Mesh &new_mesh, std::string const& rasterfile, double noDataReplacementValue = 0.0) const
+bool MeshLayerMapper::layerMapping(MeshLib::Mesh &new_mesh, std::string const& rasterfile, double noDataReplacementValue = 0.0)
 {
 	const GeoLib::Raster *raster(FileIO::AsciiRasterInterface::getRasterFromASCFile(rasterfile));
 	if (! raster) {
@@ -243,7 +216,7 @@ bool MeshLayerMapper::layerMapping(MeshLib::Mesh &new_mesh, std::string const& r
 	return result;
 }
 
-bool MeshLayerMapper::layerMapping(MeshLib::Mesh &new_mesh, GeoLib::Raster const& raster, double noDataReplacementValue = 0.0) const
+bool MeshLayerMapper::layerMapping(MeshLib::Mesh &new_mesh, GeoLib::Raster const& raster, double noDataReplacementValue = 0.0)
 {
 	if (new_mesh.getDimension() != 2)
     {
@@ -281,16 +254,3 @@ bool MeshLayerMapper::layerMapping(MeshLib::Mesh &new_mesh, GeoLib::Raster const
 
 	return true;
 }
-
-bool MeshLayerMapper::allRastersExist(const std::vector<std::string> &raster_paths) const
-{
-	for (auto raster = raster_paths.begin(); raster != raster_paths.end(); ++raster)
-	{
-		std::ifstream file_stream (*raster, std::ifstream::in);
-		if (!file_stream.good())
-			return false;
-		file_stream.close();
-	}
-	return true;
-}
-
diff --git a/MeshLib/MeshGenerators/MeshLayerMapper.h b/MeshLib/MeshGenerators/MeshLayerMapper.h
index 6eeb1bc1202d7497b7ee6570acdf2eecb0c3c05c..fa164ac36b87a1474a3ccb0861d5cf8dc63ec3ed 100644
--- a/MeshLib/MeshGenerators/MeshLayerMapper.h
+++ b/MeshLib/MeshGenerators/MeshLayerMapper.h
@@ -15,25 +15,16 @@
 #ifndef MESHLAYERMAPPER_H
 #define MESHLAYERMAPPER_H
 
-#include <string>
-#include "GeoLib/Raster.h"
-
-class QImage;
-
-namespace MeshLib {
-    class Mesh;
-    class Node;
-    class Element;
-}
+#include "SubsurfaceMapper.h"
 
 /**
-* \brief Manipulating and adding layers to an existing mesh
-*/
-class MeshLayerMapper
+ * \brief Manipulating and adding prism element layers to an existing 2D mesh
+ */
+class MeshLayerMapper : public SubsurfaceMapper
 {
 public:
-    MeshLayerMapper() {};
-    ~MeshLayerMapper() {};
+    MeshLayerMapper() {}
+    ~MeshLayerMapper() {}
 
     /**
     * Based on a 2D triangle-or quad mesh this method creates a 3D mesh with with a given number of prism- or hex-layers
@@ -47,36 +38,30 @@ public:
 
    /**
     * Based on a 2D triangle mesh this method creates a 3D mesh with with a given number of prism-layers.
-    * Note: This method would theoretically also work with quad meshes. However, this is discouraged as quad elements will most likely not
-    * be coplanar after the mapping process and result in invaled elements.
+    * Note: While this method would technically also work with quad meshes, this is discouraged as quad elements will most likely not
+    * be coplanar after the mapping process which result in invaled mesh elements.
     * \param mesh The 2D triangle mesh that is the basis for the new 3D prism mesh
-    * \param nLayers The number of layers of prism/hex elements that will be extruded from the triangle/quad elements of the original mesh
-    * \param thickness The thickness of each of these newly added layers
-    * \param mesh_name The name of the newly created mesh
-    * \return A mesh with the requested number of layers of prism/hex elements
+	* \param rasters Containing all the raster-data for the subsurface layers from bottom to top (starting with the bottom of the oldest layer and ending with the DEM)
+	* \param noDataReplacementValue  Default z-coordinate if there are mesh nodes not located on the DEM raster (i.e. raster_paths[0]) 
+    * \return A mesh with the requested number of layers of prism elements (also including Tet- & Pyramid-elements in case of degenerated prisms)
     */
-    MeshLib::Mesh* createRasterLayers(MeshLib::Mesh const& mesh, std::vector<std::string> const& raster_paths, std::string const& mesh_name = "SubsurfaceMesh") const;
-
-    MeshLib::Mesh* createRasterLayers(MeshLib::Mesh const& mesh, std::vector<GeoLib::Raster const*> const& rasters, std::string const& mesh_name = "SubsurfaceMesh") const;
+    bool createRasterLayers(MeshLib::Mesh const& mesh, std::vector<GeoLib::Raster const*> const& rasters, double noDataReplacementValue = 0.0);
 
     /**
     * Maps the elevation of nodes of a given 2D mesh according to the raster specified by the file path.
     * At locations wher no information is given, node elevation is set to noDataReplacementValue.
     */
-    bool layerMapping(MeshLib::Mesh &mesh, const std::string &rasterfile, double noDataReplacementValue) const;
+    static bool layerMapping(MeshLib::Mesh &mesh, const std::string &rasterfile, double noDataReplacementValue);
 
     /**
     * Maps the elevation of nodes of a given 2D mesh according to the raster. At locations wher no 
     * information is given, node elevation is set to noDataReplacementValue.
     */
-    bool layerMapping(MeshLib::Mesh &mesh, const GeoLib::Raster &raster, double noDataReplacementValue) const;
+    static bool layerMapping(MeshLib::Mesh &mesh, const GeoLib::Raster &raster, double noDataReplacementValue);
 
 private:
     /// Adds another layer to a subsurface mesh
-    void addLayerToMesh(const MeshLib::Mesh &mesh_layer, unsigned layer_id, GeoLib::Raster const& raster, std::vector<MeshLib::Node*> &new_nodes, std::vector<MeshLib::Element*> &new_elems) const;
-
-    /// Checks if all raster files actually exist
-	bool allRastersExist(const std::vector<std::string> &raster_paths) const;
+    void addLayerToMesh(const MeshLib::Mesh &mesh_layer, unsigned layer_id, GeoLib::Raster const& raster);
 
     static const unsigned _pyramid_base[3][4];
 };
diff --git a/MeshLib/MeshGenerators/SubsurfaceMapper.cpp b/MeshLib/MeshGenerators/SubsurfaceMapper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2d5a223fc12f87b90b39d040b05d9f7691e76aeb
--- /dev/null
+++ b/MeshLib/MeshGenerators/SubsurfaceMapper.cpp
@@ -0,0 +1,82 @@
+/**
+ * \file   SubsurfaceMapper.cpp
+ * \author Karsten Rink
+ * \date   2014-09-18
+ * \brief  Implementation of the SubsurfaceMapper class.
+ *
+ * \copyright
+ * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "SubsurfaceMapper.h"
+
+#include <vector>
+#include <fstream>
+
+#include "FileIO/AsciiRasterInterface.h"
+
+#include "Raster.h"
+
+#include "Mesh.h"
+#include "Node.h"
+#include "Elements/Element.h"
+#include "MeshQuality/MeshValidation.h"
+
+SubsurfaceMapper::SubsurfaceMapper()
+: _elevation_epsilon(0.0001)
+{
+}
+
+bool SubsurfaceMapper::createLayers(MeshLib::Mesh const& mesh, std::vector<std::string> const& raster_paths, double noDataReplacementValue)
+{
+	if (mesh.getDimension() != 2 || !allRastersExist(raster_paths))
+		return false;
+
+	std::vector<GeoLib::Raster const*> rasters;
+	rasters.reserve(raster_paths.size());
+	for (auto path = raster_paths.begin(); path != raster_paths.end(); ++path)
+		rasters.push_back(FileIO::AsciiRasterInterface::getRasterFromASCFile(*path));
+
+	bool result = createRasterLayers(mesh, rasters, noDataReplacementValue);
+	std::for_each(rasters.begin(), rasters.end(), [](GeoLib::Raster const*const raster){ delete raster; });
+    return result;
+}
+
+MeshLib::Mesh* SubsurfaceMapper::getMesh(std::string const& mesh_name) const 
+{
+    if (_nodes.empty() || _elements.empty())
+        return nullptr;
+
+    MeshLib::Mesh* result (new MeshLib::Mesh(mesh_name, _nodes, _elements)); 
+    MeshLib::MeshValidation::removeUnusedMeshNodes(*result);
+    return result;
+}
+
+double SubsurfaceMapper::calcEpsilon(GeoLib::Raster const& high, GeoLib::Raster const& low)
+{
+	const double max (*std::max_element(high.begin(), high.end()));
+	const double min (*std::min_element( low.begin(),  low.end()));
+	return ((max-min)*1e-07);
+}
+
+bool SubsurfaceMapper::allRastersExist(std::vector<std::string> const& raster_paths) const
+{
+	for (auto raster = raster_paths.begin(); raster != raster_paths.end(); ++raster)
+	{
+		std::ifstream file_stream (*raster, std::ifstream::in);
+		if (!file_stream.good())
+			return false;
+		file_stream.close();
+	}
+	return true;
+}
+
+void SubsurfaceMapper::cleanUpOnError()
+{
+	std::for_each(_nodes.begin(), _nodes.end(), [](MeshLib::Node *node) { delete node; });
+	std::for_each(_elements.begin(), _elements.end(), [](MeshLib::Element *elem) { delete elem; });
+}
diff --git a/MeshLib/MeshGenerators/SubsurfaceMapper.h b/MeshLib/MeshGenerators/SubsurfaceMapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea29d23afc160b0fcb043027b1550231f0558e12
--- /dev/null
+++ b/MeshLib/MeshGenerators/SubsurfaceMapper.h
@@ -0,0 +1,79 @@
+/**
+ * \file   SubsurfaceMapper.h
+ * \author Karsten Rink
+ * \date   2014-09-18
+ * \brief  Definition of the SubsurfaceMapper class
+ *
+ * \copyright
+ * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef SUBSURFACEMAPPER_H
+#define SUBSURFACEMAPPER_H
+
+#include <string>
+#include <vector>
+
+namespace GeoLib {
+    class Raster;
+}
+
+namespace MeshLib {
+	class Mesh;
+    class Node;
+	class Element;
+}
+
+/**
+ * \brief Base class for creation of 3D subsurface meshes based on raster data
+ */
+class SubsurfaceMapper
+{
+public:
+	/**
+	 * Returns a subsurface representation of a region represented by a 2D by reading raster files and calling the appropriate construction method.
+	 * @param mesh                    The 2D surface mesh that is used as a basis for the subsurface mesh
+	 * @param raster_paths            Containing all the raster-file-names for the subsurface layers from bottom to top (starting with the bottom of the oldest layer and ending with the DEM)
+	 * @param noDataReplacementValue  Default z-coordinate if there are mesh nodes not located on the DEM raster (i.e. raster_paths[0]) 
+	 * @result true if the subsurface representation has been created, false if there was an error
+	 */
+	virtual bool createLayers(MeshLib::Mesh const& mesh, std::vector<std::string> const& raster_paths, double noDataReplacementValue = 0.0) final;
+
+    /**
+	 * Constructs a subsurface representation based on a 2D mesh and a number of rasters representing subsurface layer boundaries.
+	 * @param mesh                    The 2D surface mesh that is used as a basis for the subsurface mesh
+	 * @param rasters                 Containing all the raster-data for the subsurface layers from bottom to top (starting with the bottom of the oldest layer and ending with the DEM)
+	 * @param noDataReplacementValue  Default z-coordinate if there are mesh nodes not located on the DEM raster (i.e. raster_paths[0]) 
+	 * @result true if the subsurface representation has been created, false if there was an error
+	 */
+	virtual bool createRasterLayers(MeshLib::Mesh const& mesh, std::vector<GeoLib::Raster const*> const& rasters, double noDataReplacementValue) = 0;
+
+	/// Returns a mesh of the subsurface representation
+	MeshLib::Mesh* getMesh(std::string const& mesh_name) const;
+
+protected:
+	SubsurfaceMapper();
+	~SubsurfaceMapper() {}
+
+	/// Adds another layer to the subsurface mesh
+	virtual void addLayerToMesh(MeshLib::Mesh const& mesh_layer, unsigned layer_id, GeoLib::Raster const& raster) = 0;
+
+	/// Calculates a data-dependent epsilon value
+	double calcEpsilon(GeoLib::Raster const& high, GeoLib::Raster const& low);
+
+	/// Checks if all raster files actually exist
+	bool allRastersExist(std::vector<std::string> const& raster_paths) const;
+
+	/// Cleans up the already created objects in case of an error
+	void cleanUpOnError();
+
+	double _elevation_epsilon;
+	std::vector<MeshLib::Node*> _nodes;
+	std::vector<MeshLib::Element*> _elements;
+};
+
+#endif //SUBSURFACEMAPPER_H
diff --git a/MeshLib/Node.h b/MeshLib/Node.h
index a59a637036c6235fcc4fa59eadd0997bdc7fefb5..527066b0d64044804a77353aedc7769f3483d50b 100644
--- a/MeshLib/Node.h
+++ b/MeshLib/Node.h
@@ -36,7 +36,7 @@ class Element;
 class Node : public GeoLib::PointWithID
 {
 	/* friend functions: */
-	friend bool MeshLayerMapper::layerMapping(MeshLib::Mesh &mesh, const GeoLib::Raster &raster, double noDataReplacementValue) const;
+	friend static bool MeshLayerMapper::layerMapping(MeshLib::Mesh &mesh, const GeoLib::Raster &raster, double noDataReplacementValue);
 	friend MeshLib::Mesh* MeshSurfaceExtraction::getMeshSurface(const MeshLib::Mesh &mesh, const MathLib::Vector3 &dir, bool keep3dMeshIds);
 
 	/* friend classes: */