diff --git a/BaseLib/StringTools.cpp b/BaseLib/StringTools.cpp
index fa9853ea76f5abfdb998e9d9550936994730770b..a6a89c78ca1a772bb36380b6aa2ea7b340546899 100644
--- a/BaseLib/StringTools.cpp
+++ b/BaseLib/StringTools.cpp
@@ -60,6 +60,15 @@ void trim(std::string &str, char ch)
 		str.erase(str.begin(), str.end());
 }
 
+void simplify(std::string &str)
+{
+	trim (str);
+	str.erase(
+	    std::unique(str.begin(), str.end(), [](char a, char b) { return a == ' ' && b == ' '; }), 
+		str.end() 
+	);  
+}
+
 std::string stringToUpper(std::string const& str)
 {
     std::string s = str;
diff --git a/BaseLib/StringTools.h b/BaseLib/StringTools.h
index cd1e2fdd6164d97adbdbc8160ed6585f74071d55..77a451f3c893392d954bae2c4f902cc594592705 100644
--- a/BaseLib/StringTools.h
+++ b/BaseLib/StringTools.h
@@ -69,9 +69,16 @@ template<typename T> T str2number (const std::string &str)
 
 /**
  * Strip whitespace (or other characters) from the beginning and end of a string.
+ * Equivalent functionality to Qt::QString::trim().
  */
 void trim(std::string &str, char ch=' ');
 
+/**
+ * Removes multiple whitespaces (or other characters) from within a string.
+ * Equivalent functionality to Qt::QString::simplify().
+ */
+void simplify(std::string &str);
+
 /**
  * Returns same string with all characters in upper case.
  *
diff --git a/FileIO/ImportFileTypes.h b/FileIO/ImportFileTypes.h
index 5af5932c8d3a4b0d3af12017fd010b0793c21a83..6b7eb2ee6eba1f6af6c4915cb88831749fd1c4cc 100644
--- a/FileIO/ImportFileTypes.h
+++ b/FileIO/ImportFileTypes.h
@@ -84,7 +84,7 @@ public:
 		else if (t==ImportFileType::SHAPE)
 			return "ESRI Shape files (*.shp)";
 		else if (t==ImportFileType::TETGEN)
-			return "TetGen node files (*.node)";
+			return "TetGen node files (*.node *.poly)";
 		else if (t==ImportFileType::VTK)
 			return "VTK files (*.vtk *.vti *.vtr *.vts *.vtp *.vtu)";
 		else return "All files (*.*)";
diff --git a/FileIO/TetGenInterface.cpp b/FileIO/TetGenInterface.cpp
index 98e1718ae70d31596f121c9a8af3834d525a8fbc..ad009c5e93b724430ddd8995a4ba680cfb4eb6e2 100644
--- a/FileIO/TetGenInterface.cpp
+++ b/FileIO/TetGenInterface.cpp
@@ -14,8 +14,10 @@
 
 #include <cstddef>
 #include <string>
+#include <fstream>
 
 // BaseLib
+#include "FileTools.h"
 #include "StringTools.h"
 
 // ThirdParty/logog
@@ -33,7 +35,7 @@
 namespace FileIO
 {
 TetGenInterface::TetGenInterface() :
-	_nodes(), _elements(), _zero_based_idx (false)
+	_zero_based_idx (false)
 {
 }
 
@@ -41,8 +43,153 @@ TetGenInterface::~TetGenInterface()
 {
 }
 
+bool TetGenInterface::readTetGenPoly (std::string const& poly_fname,
+	                                  GeoLib::GEOObjects &geo_objects)
+{
+	std::ifstream poly_stream (poly_fname.c_str());
+
+	if (!poly_stream)
+	{
+		ERR ("TetGenInterface::readTetGenPoly failed to open %s", poly_fname.c_str());
+		return false;
+	}
+
+	std::vector<MeshLib::Node*> nodes;
+	if (!readNodesFromStream (poly_stream, nodes))
+	{
+		// remove nodes read until now
+		for (std::size_t k(0); k<nodes.size(); ++k)
+			delete nodes[k];
+		return false;
+	}
+	const std::size_t nNodes (nodes.size());
+	std::vector<GeoLib::Point*> *points = new std::vector<GeoLib::Point*>;
+	points->reserve(nNodes);
+	for (std::size_t k(0); k<nNodes; ++k)
+	{
+		points->push_back(new GeoLib::Point(nodes[k]->getCoords()));
+		delete nodes[k];
+	}
+	std::vector<GeoLib::Surface*> *surfaces = new std::vector<GeoLib::Surface*>;
+	if (!parseFacets(poly_stream, *surfaces, *points))
+	{
+		// remove surfaces read until now but keep the points
+		for (std::size_t k=0; k<surfaces->size(); k++)
+			delete (*surfaces)[k];
+		delete surfaces;
+		surfaces = nullptr;
+	}
+
+	std::string geo_name (BaseLib::extractBaseNameWithoutExtension(poly_fname));
+	geo_objects.addPointVec(points, geo_name);
+	if (surfaces)
+		geo_objects.addSurfaceVec(surfaces, geo_name);
+	return true;
+}
+
+std::size_t TetGenInterface::getNFacets(std::ifstream &input) const
+{
+	std::string line;
+	while (!input.fail())
+	{
+		getline (input, line);
+		if (input.fail())
+		{
+			ERR("TetGenInterface::getNFacets(): Error reading number of facets.");
+			return false;
+		}
+		
+		BaseLib::simplify(line);
+		if (line.empty() || line.compare(0,1,"#") == 0)
+			continue;
+
+		const std::list<std::string> fields = BaseLib::splitString(line, ' ');
+		return BaseLib::str2number<size_t> (*fields.begin());
+		// here this line also includes a flag for boundary markers which we ignore for now
+	}
+	return false;
+}
+
+bool TetGenInterface::parseFacets(std::ifstream &input,
+                                  std::vector<GeoLib::Surface*> &surfaces,
+                                  std::vector<GeoLib::Point*> &points) const
+{
+	const std::size_t nFacets (this->getNFacets(input));
+	std::size_t nMultPolys (0);
+	std::string line;
+	surfaces.reserve(nFacets);
+	std::list<std::string>::const_iterator it;
+
+	const unsigned offset = (_zero_based_idx) ? 0 : 1;
+	for (std::size_t k(0); k<nFacets && !input.fail(); k++)
+	{
+		getline (input, line);
+		if (input.fail())
+		{
+			ERR("TetGenInterface::parseFacets(): Error reading facet %d.", k);
+			return false;
+		}
+
+		BaseLib::simplify(line);
+		if (line.empty() || line.compare(0,1,"#") == 0)
+		{
+			k--;
+			continue;
+		}
+		
+		// read facets
+		const std::list<std::string> poly_def_fields = BaseLib::splitString(line, ' ');
+		it = poly_def_fields.begin();
+		const std::size_t nPolys     = BaseLib::str2number<std::size_t>(*it);
+		const std::size_t nPolyHoles = (poly_def_fields.size()>1) ? BaseLib::str2number<std::size_t>(*(++it)) : 0;
+		// here this line also potentially includes a boundary marker which we ignore for now
+		nMultPolys += (nPolys-1);
+
+		// read polys
+		for (std::size_t i(0); i<nPolys && !input.fail(); ++i)
+		{
+			getline (input, line);
+			BaseLib::simplify(line);
+			if (line.empty() || line.compare(0,1,"#") == 0)
+			{
+				i--;
+				continue;
+			}
+
+			const std::list<std::string> point_fields = BaseLib::splitString(line, ' ');
+			it = point_fields.begin();
+			const std::size_t nPoints = BaseLib::str2number<std::size_t>(*it);
+			if (point_fields.size() > nPoints)
+			{
+				GeoLib::Polyline polyline(points);
+				for (std::size_t j(0); j<nPoints; ++j)
+					polyline.addPoint(BaseLib::str2number<std::size_t>(*(++it))-offset);
+				
+				polyline.closePolyline();
+				surfaces.push_back(GeoLib::Surface::createSurface(polyline));
+			}
+			else
+			{
+				ERR("TetGenInterface::parseFacets(): Error reading points for polygon %d of facet %d.", i, k);
+				return false;
+			}
+		}
+		for (std::size_t j(0); j<nPolyHoles && !input.fail(); ++j)
+			getline(input, line);
+			// Here are points defined which are located in holes within the surface. We ignore these as they are not part of the actual geometry.
+	}
+	// here the poly-file potentially defines a number of points to mark holes within the volumes defined by the facets, these are ignored for now
+	// here the poly-file potentially defines a number of region attributes, these are ignored for now
+
+	if (surfaces.size() == nFacets+nMultPolys)
+		return true;
+
+	ERR ("TetGenInterface::parseFacets(): Number of expected surfaces (%d) does not match number of found surfaces (%d).", nFacets+nMultPolys, surfaces.size());
+	return false;
+}
+
 MeshLib::Mesh* TetGenInterface::readTetGenMesh (std::string const& nodes_fname,
-                                                   std::string const& ele_fname)
+                                                std::string const& ele_fname)
 {
 	std::ifstream ins_nodes (nodes_fname.c_str());
 	std::ifstream ins_ele (ele_fname.c_str());
@@ -53,42 +200,45 @@ MeshLib::Mesh* TetGenInterface::readTetGenMesh (std::string const& nodes_fname,
 			ERR ("TetGenInterface::readTetGenMesh failed to open %s", nodes_fname.c_str());
 		if (!ins_ele)
 			ERR ("TetGenInterface::readTetGenMesh failed to open %s", ele_fname.c_str());
-		return NULL;
+		return nullptr;
 	}
 
-	if (!readNodesFromStream (ins_nodes)) {
+	std::vector<MeshLib::Node*> nodes;
+	if (!readNodesFromStream (ins_nodes, nodes)) {
 		// remove nodes read until now
-		for (std::size_t k(0); k<_nodes.size(); k++) {
-			delete _nodes[k];
+		for (std::size_t k(0); k<nodes.size(); k++) {
+			delete nodes[k];
 		}
-		return NULL;
+		return nullptr;
 	}
 
-	if (!readElementsFromStream (ins_ele)) {
+	std::vector<MeshLib::Element*> elements;
+	if (!readElementsFromStream (ins_ele, elements, nodes)) {
 		// remove elements read until now
-		for (std::size_t k(0); k<_elements.size(); k++) {
-			delete _elements[k];
+		for (std::size_t k(0); k<elements.size(); k++) {
+			delete elements[k];
 		}
 		// remove nodes
-		for (std::size_t k(0); k<_nodes.size(); k++) {
-			delete _nodes[k];
+		for (std::size_t k(0); k<nodes.size(); k++) {
+			delete nodes[k];
 		}
-		return NULL;
+		return nullptr;
 	}
 
-	return new MeshLib::Mesh(nodes_fname, _nodes, _elements);
+	const std::string mesh_name (BaseLib::extractBaseNameWithoutExtension(nodes_fname));
+	return new MeshLib::Mesh(mesh_name, nodes, elements);
 }
 
-bool TetGenInterface::readNodesFromStream (std::ifstream &ins)
+bool TetGenInterface::readNodesFromStream (std::ifstream &ins,
+                                           std::vector<MeshLib::Node*> &nodes)
 {
 	std::string line;
 	getline (ins, line);
 	size_t pos_beg (line.find_first_not_of(" "));
 	size_t n_nodes, dim, n_attributes;
 	bool boundary_markers;
-	bool not_read_header (true);
 
-	while (!ins.fail() && not_read_header)
+	while (!ins.fail())
 	{
 		line = line.substr(pos_beg);
 		if (line.compare(0,1,"#") == 0)
@@ -96,30 +246,26 @@ bool TetGenInterface::readNodesFromStream (std::ifstream &ins)
 			// this line is a comment - skip
 			getline (ins, line);
 			pos_beg = line.find_first_not_of(" ");
+			continue;
 		}
-		else
-			// read header line
-			not_read_header = !parseNodesFileHeader(line,
-			                                        n_nodes,
-			                                        dim,
-			                                        n_attributes,
-			                                        boundary_markers);
+		// read header line
+		bool header_okay = parseNodesFileHeader(line, n_nodes, dim, n_attributes, boundary_markers);
+		if (!header_okay)
+			return false;
+		if (!parseNodes(ins, nodes, n_nodes, dim))
+			return false;
+		return true;
 	}
-	if (not_read_header)
-		return false;
-	if (!parseNodes(ins, n_nodes, dim))
-		return false;
-
-	return true;
+	return false;	
 }
 
 bool TetGenInterface::parseNodesFileHeader(std::string &line,
-                                           size_t& n_nodes,
-                                           size_t& dim,
-                                           size_t& n_attributes,
-                                           bool& boundary_markers) const
+                                           std::size_t &n_nodes,
+                                           std::size_t &dim,
+                                           std::size_t &n_attributes,
+                                           bool &boundary_markers) const
 {
-	size_t pos_beg, pos_end;
+	std::size_t pos_beg, pos_end;
 
 	// number of nodes
 	pos_beg = line.find_first_not_of (" ");
@@ -128,7 +274,7 @@ bool TetGenInterface::parseNodesFileHeader(std::string &line,
 		n_nodes = BaseLib::str2number<size_t> (line.substr(pos_beg, pos_end - pos_beg));
 	else
 	{
-		ERR("TetGenInterface::parseNodesFileHeader(): could not correct read TetGen mesh header - number of nodes");
+		ERR("TetGenInterface::parseNodesFileHeader(): could not read number of nodes specified in header.");
 		return false;
 	}
 	// dimension
@@ -152,66 +298,78 @@ bool TetGenInterface::parseNodesFileHeader(std::string &line,
 	return true;
 }
 
-bool TetGenInterface::parseNodes(std::ifstream& ins, size_t n_nodes, size_t dim)
+bool TetGenInterface::parseNodes(std::ifstream &ins,
+                                 std::vector<MeshLib::Node*> &nodes,
+                                 std::size_t n_nodes,
+                                 std::size_t dim)
 {
-	std::size_t pos_beg, pos_end;
 	std::string line;
-	double* coordinates (static_cast<double*> (alloca (sizeof(double) * dim)));
+	double* coordinates (new double[dim]);
+	nodes.reserve(n_nodes);
 
-	for (std::size_t k(0); k < n_nodes && !ins.fail(); k++) {
+	for (std::size_t k(0); k < n_nodes && !ins.fail(); k++)
+	{
 		getline(ins, line);
-		if (!ins.fail()) {
-			if (!line.empty()) {
-				pos_end = 0;
-				// read id
-				size_t id;
-				pos_beg = line.find_first_not_of(" ", pos_end);
-				pos_end = line.find_first_of(" \n", pos_beg);
-				if (pos_beg != std::string::npos && pos_end != std::string::npos) {
-					id = BaseLib::str2number<size_t> (line.substr(pos_beg, pos_end - pos_beg));
-					if (k == 0 && id == 0)
-						_zero_based_idx = true;
-				} else {
-					ERR("TetGenInterface::parseNodes(): error reading id of node %d", k);
-					return false;
-				}
-				// read coordinates
-				for (size_t i(0); i < dim; i++) {
-					pos_beg = line.find_first_not_of(" ", pos_end);
-					pos_end = line.find_first_of(" \n", pos_beg);
-					if (pos_end == std::string::npos) pos_end = line.size();
-					if (pos_beg != std::string::npos)
-						coordinates[i] = BaseLib::str2number<double> (
-										line.substr(pos_beg, pos_end - pos_beg));
-					else {
-						ERR("TetGenInterface::parseNodes(): error reading coordinate %d of node %d", i, k);
-						return false;
-					}
-				}
-				if (!_zero_based_idx) id--;
-				// since CFEMesh is our friend we can access private data of mesh
-				_nodes.push_back(new MeshLib::Node(coordinates, id));
-				// read attributes and boundary markers ... - at the moment we do not use this information
-			}
+		if (ins.fail())
+		{
+			ERR("TetGenInterface::parseNodes(): Error reading node %d.", k);
+			return false;
+		}
+
+		std::size_t id;
+		std::size_t pos_end = 0;
+		std::size_t pos_beg = line.find_first_not_of(" ", pos_end);
+		pos_end = line.find_first_of(" \n", pos_beg);
+
+		if (line.empty() || pos_beg==pos_end || line.compare(pos_beg,1,"#") == 0)
+		{
+			k--;
+			continue;
+		}
+
+		if (pos_beg != std::string::npos && pos_end != std::string::npos) {
+			id = BaseLib::str2number<size_t> (line.substr(pos_beg, pos_end - pos_beg));
+			if (k == 0 && id == 0)
+				_zero_based_idx = true;
 		} else {
-			ERR("TetGenInterface::parseNodes(): error reading node %d, stream error", k);
+			ERR("TetGenInterface::parseNodes(): Error reading ID of node %d.", k);
+			delete [] coordinates;
 			return false;
 		}
+		// read coordinates
+		const unsigned offset = (_zero_based_idx) ? 0 : 1;
+		for (std::size_t i(0); i < dim; i++) {
+			pos_beg = line.find_first_not_of(" ", pos_end);
+			pos_end = line.find_first_of(" \n", pos_beg);
+			if (pos_end == std::string::npos) pos_end = line.size();
+			if (pos_beg != std::string::npos)
+				coordinates[i] = BaseLib::str2number<double>(line.substr(pos_beg, pos_end-pos_beg));
+			else {
+				ERR("TetGenInterface::parseNodes(): error reading coordinate %d of node %d.", i, k);
+				delete [] coordinates;
+				return false;
+			}
+		}
+
+		nodes.push_back(new MeshLib::Node(coordinates, id-offset));
+		// read attributes and boundary markers ... - at the moment we do not use this information
 	}
 
+	delete [] coordinates;
 	return true;
 }
 
-bool TetGenInterface::readElementsFromStream(std::ifstream &ins)
+bool TetGenInterface::readElementsFromStream(std::ifstream &ins,
+                                             std::vector<MeshLib::Element*> &elements,
+                                             const std::vector<MeshLib::Node*> &nodes) const
 {
 	std::string line;
 	getline (ins, line);
-	size_t pos_beg (line.find_first_not_of(" "));
-	size_t n_tets, n_nodes_per_tet;
+	std::size_t pos_beg (line.find_first_not_of(" "));
+	std::size_t n_tets, n_nodes_per_tet;
 	bool region_attributes;
-	bool not_read_header (true);
 
-	while (!ins.fail() && not_read_header)
+	while (!ins.fail())
 	{
 		line = line.substr(pos_beg);
 		if (line.compare(0,1,"#") == 0)
@@ -219,28 +377,26 @@ bool TetGenInterface::readElementsFromStream(std::ifstream &ins)
 			// this line is a comment - skip
 			getline (ins, line);
 			pos_beg = line.find_first_not_of(" ");
+			continue;
 		}
-		else
-			// read header line
-			not_read_header = !parseElementsFileHeader(line,
-			                                           n_tets,
-			                                           n_nodes_per_tet,
-			                                           region_attributes);
+		
+		// read header line
+		bool header_okay = parseElementsFileHeader(line, n_tets, n_nodes_per_tet, region_attributes);
+		if (!header_okay)
+			return false;
+		if (!parseElements(ins, elements, nodes, n_tets, n_nodes_per_tet, region_attributes))
+			return false;
+		return true;
 	}
-	if (not_read_header)
-		return false;
-	if (!parseElements(ins, n_tets, n_nodes_per_tet, region_attributes))
-		return false;
-
-	return true;
+	return false;
 }
 
 bool TetGenInterface::parseElementsFileHeader(std::string &line,
-                                              size_t& n_tets,
-                                              size_t& n_nodes_per_tet,
+                                              std::size_t& n_tets,
+                                              std::size_t& n_nodes_per_tet,
                                               bool& region_attribute) const
 {
-	size_t pos_beg, pos_end;
+	std::size_t pos_beg, pos_end;
 
 	// number of tetrahedras
 	pos_beg = line.find_first_not_of (" ");
@@ -248,7 +404,7 @@ bool TetGenInterface::parseElementsFileHeader(std::string &line,
 	if (pos_beg != std::string::npos && pos_end != std::string::npos)
 		n_tets = BaseLib::str2number<size_t> (line.substr(pos_beg, pos_end - pos_beg));
 	else {
-		ERR("TetGenInterface::parseElementsFileHeader(): could not correct read TetGen mesh header - number of tetrahedras");
+		ERR("TetGenInterface::parseElementsFileHeader(): Could not read number of tetrahedra specified in header.");
 		return false;
 	}
 	// nodes per tet - either 4 or 10
@@ -268,81 +424,124 @@ bool TetGenInterface::parseElementsFileHeader(std::string &line,
 	return true;
 }
 
-bool TetGenInterface::parseElements(std::ifstream& ins, size_t n_tets, size_t n_nodes_per_tet,
-                                    bool region_attribute)
+bool TetGenInterface::parseElements(std::ifstream& ins,
+                                    std::vector<MeshLib::Element*> &elements,
+                                    const std::vector<MeshLib::Node*> &nodes,
+                                    std::size_t n_tets,
+                                    std::size_t n_nodes_per_tet,
+                                    bool region_attribute) const
 {
-	size_t pos_beg, pos_end;
 	std::string line;
-	size_t* ids (static_cast<size_t*>(alloca (sizeof (size_t) * n_nodes_per_tet)));
+	std::size_t* ids (static_cast<size_t*>(alloca (sizeof (size_t) * n_nodes_per_tet)));
+	elements.reserve(n_tets);
 
-	for (size_t k(0); k < n_tets && !ins.fail(); k++)
+	const unsigned offset = (_zero_based_idx) ? 0 : 1;
+	for (std::size_t k(0); k < n_tets && !ins.fail(); k++)
 	{
 		getline (ins, line);
-		if (!ins.fail())
+		if (ins.fail())
 		{
-			if (!line.empty())
+			ERR("TetGenInterface::parseElements(): Error reading tetrahedron %d.", k);
+			return false;
+		}
+
+		std::size_t pos_end = 0;
+		std::size_t pos_beg = line.find_first_not_of(" ", pos_end);
+		pos_end = line.find_first_of(" \n", pos_beg);
+
+		if (line.empty() || pos_beg==pos_end || line.compare(pos_beg,1,"#") == 0)
+		{
+			k--;
+			continue;
+		}
+
+		if (pos_beg == std::string::npos || pos_end == std::string::npos)
+		{
+			ERR("TetGenInterface::parseElements(): Error reading id of tetrahedron %d.", k);
+			return false;
+		}
+
+		// read node ids
+		for (std::size_t i(0); i < n_nodes_per_tet; i++)
+		{
+			pos_beg = line.find_first_not_of(" ", pos_end);
+			pos_end = line.find_first_of(" ", pos_beg);
+			if (pos_end == std::string::npos)
+				pos_end = line.size();
+			if (pos_beg != std::string::npos && pos_end != std::string::npos)
+				ids[i] = BaseLib::str2number<std::size_t>(line.substr(pos_beg, pos_end - pos_beg)) - offset;
+			else
 			{
-				pos_end = 0;
-				// read id
-				size_t id;
-				pos_beg = line.find_first_not_of(" ", pos_end);
-				pos_end = line.find_first_of(" \n", pos_beg);
-				if (pos_beg != std::string::npos && pos_end != std::string::npos)
-					id = BaseLib::str2number<size_t>(line.substr(pos_beg, pos_end - pos_beg));
-				else {
-					ERR("TetGenInterface::parseElements(): error reading id of tetrahedra %d", k);
-					return false;
-				}
-				// read node ids
-				for (size_t i(0); i < n_nodes_per_tet; i++)
-				{
-					pos_beg = line.find_first_not_of(" ", pos_end);
-					pos_end = line.find_first_of(" ", pos_beg);
-					if (pos_end == std::string::npos)
-						pos_end = line.size();
-					if (pos_beg != std::string::npos && pos_end !=
-					    std::string::npos)
-						ids[i] = BaseLib::str2number<std::size_t>(line.substr(pos_beg, pos_end - pos_beg));
-					else
-					{
-						ERR("TetGenInterface::parseElements(): error reading node %d of tetrahedra %d", i, k);
-						return false;
-					}
-				}
-				if (!_zero_based_idx) {
-					id--;
-					for (size_t i(0); i < n_nodes_per_tet; i++)
-						ids[i]--;
-				}
-
-				// read region attribute - this is something like material group
-				unsigned region (0);
-				if (region_attribute) {
-					pos_beg = line.find_first_not_of(" ", pos_end);
-					pos_end = line.find_first_of(" ", pos_beg);
-					if (pos_end == std::string::npos) pos_end = line.size();
-					if (pos_beg != std::string::npos && pos_end != std::string::npos)
-						region = BaseLib::str2number<unsigned> (line.substr(pos_beg, pos_end - pos_beg));
-					else {
-						ERR("TetGenInterface::parseElements(): error reading region attribute of tetrahedra %d", k);
-						return false;
-					}
-				}
-				// insert new element into vector
-				MeshLib::Node** tet_nodes = new MeshLib::Node*[4];
-				for (unsigned k(0); k<4; k++) {
-					tet_nodes[k] = _nodes[ids[k]];
-				}
-				_elements.push_back (new MeshLib::Tet(tet_nodes, region));
+				ERR("TetGenInterface::parseElements(): Error reading node %d of tetrahedron %d.", i, k);
+				return false;
+			}
+		}
 
+		// read region attribute - this is something like material group
+		unsigned region (0);
+		if (region_attribute) {
+			pos_beg = line.find_first_not_of(" ", pos_end);
+			pos_end = line.find_first_of(" ", pos_beg);
+			if (pos_end == std::string::npos) pos_end = line.size();
+			if (pos_beg != std::string::npos && pos_end != std::string::npos)
+				region = BaseLib::str2number<unsigned> (line.substr(pos_beg, pos_end - pos_beg));
+			else {
+				ERR("TetGenInterface::parseElements(): Error reading region attribute of tetrahedron %d.", k);
+				return false;
 			}
 		}
-		else
+		// insert new element into vector
+		MeshLib::Node** tet_nodes = new MeshLib::Node*[4];
+		for (unsigned k(0); k<4; k++) {
+			tet_nodes[k] = nodes[ids[k]];
+		}
+		elements.push_back (new MeshLib::Tet(tet_nodes, region));
+	}
+	return true;
+}
+
+bool TetGenInterface::writeTetGenPoly(const std::string &file_name,
+                                      const GeoLib::GEOObjects &geo_objects,
+                                      const std::string &geo_name) const
+{
+	std::vector<GeoLib::Point*> const*const points = geo_objects.getPointVec(geo_name);
+	std::vector<GeoLib::Surface*> const*const surfaces = geo_objects.getSurfaceVec(geo_name);
+
+	if (points==nullptr)
+	{
+		ERR ("Geometry %s not found.", geo_name.c_str());
+		return false;
+	}
+	if (surfaces==nullptr)
+		WARN ("No surfaces found for geometry %s. Writing points only.", geo_name.c_str());
+
+	std::ofstream out( file_name.c_str(), std::ios::out );
+	// the points header
+	const std::size_t nPoints (points->size());
+	out << nPoints << " 3 0 0\n";
+	// the point list
+	for (std::size_t i=0; i<nPoints; ++i)
+		out << i << "  " << (*(*points)[i])[0] << " " << (*(*points)[i])[1] << " " << (*(*points)[i])[2] << "\n";
+	// the surfaces header
+	const std::size_t nSurfaces = (surfaces) ? surfaces->size() : 0;
+	out << nSurfaces << " 0\n";
+	// the facets list
+	for (std::size_t i=0; i<nSurfaces; ++i)
+	{
+		// the number of polys per facet
+		const std::size_t nTriangles ((*surfaces)[i]->getNTriangles());
+		out << nTriangles << "\n";
+		// the poly list
+		for (std::size_t j=0; j<nTriangles; ++j)
 		{
-			ERR("TetGenInterface::parseElements(): error reading node %d", k);
-			return false;
+			const GeoLib::Triangle &tri = *(*(*surfaces)[i])[j];
+			out << "3  " << tri[0] << " " << tri[1] << " " << tri[2] << "\n";
 		}
 	}
+	out << "0\n"; // the polygon holes list
+	out << "0\n"; // the region attribues list
+	INFO ("TetGenInterface::writeTetGenPoly() - %d points and %d surfaces successfully written.", nPoints, nSurfaces);
+	out.close();
 	return true;
 }
 
diff --git a/FileIO/TetGenInterface.h b/FileIO/TetGenInterface.h
index 4535d956c2b79bbe051da28abfd6433eb143b369..72ca2c04618a2dabfe7e2134e9633a2879395eea 100644
--- a/FileIO/TetGenInterface.h
+++ b/FileIO/TetGenInterface.h
@@ -17,6 +17,8 @@
 
 #include <vector>
 
+#include "GEOObjects.h"
+
 // forward declaration of class Node and Element
 namespace MeshLib
 {
@@ -28,7 +30,11 @@ namespace MeshLib
 namespace FileIO
 {
 /**
- * class TetGenInterface is used to read meshes created by <a href="http://tetgen.berlios.de/">TetGen</a>
+ * class TetGenInterface is used to read file formats used by <a href="http://tetgen.berlios.de/">TetGen</a>.
+ * Currently supported formats are:
+ *   poly - Geometric point and surface definition
+ *   node - mesh node / geometric point definition
+ *   ele  - mesh element definition
  */
 class TetGenInterface
 {
@@ -38,82 +44,124 @@ public:
 
 	/**
 	 * Method reads the TetGen mesh from node file and element file.
-	 * @param nodes_fname file name of the nodes file
-	 * @param ele_fname file name of the elements file
-	 * @return on success the method returns a (pointer to a) CFEMesh, else the method returns NULL
+	 * @param poly_fname   file name of the poly file
+	 * @param geo_objects  where the geometry is written to
+	 * @return on success  the method returns true, otherwise it returns false
+	 */
+	bool readTetGenPoly (std::string const& poly_fname,
+	                     GeoLib::GEOObjects &geo_objects);
+
+	/**
+	 * Method reads the TetGen mesh from node file and element file.
+	 * @param nodes_fname  file name of the nodes file
+	 * @param ele_fname    file name of the elements file
+	 * @return on success  the method returns a (pointer to a) CFEMesh, else the method returns nullptr
 	 */
 	MeshLib::Mesh* readTetGenMesh (std::string const& nodes_fname,
 	                               std::string const& ele_fname);
-	/** in order to have a direct access to the
-	 * data structures for nodes and elements we make
-	 * class TetGenInterface a friend of the mesh class
+
+	/**
+	 * Writes the geometry of a given name to TetGen poly-file.
+	 * @param file_name    file name of the new poly file
+	 * @param geo_objects  the container for the geometry.
+	 * @param geo_name     the name for the geometry.
+	 * @return returns true on success and false otherwise.
 	 */
-	friend class MeshLib::Mesh;
+	bool writeTetGenPoly(const std::string &file_name,
+	                     const GeoLib::GEOObjects &geo_objects,
+	                     const std::string &geo_name) const;
 
 private:
+	/// Returns the declared number of facets in the poly file.
+	std::size_t getNFacets(std::ifstream &input) const;
+
 	/**
-	 * Method reads the nodes from stream and stores them in the node vector of the mesh class.
+	 * Method parses the lines reading the facets from TetGen poly file
+	 * @param input     the input stream (input)
+	 * @param surfaces  the vector of surfaces to be filled (output)
+	 * @param points    the point vector needed for creating surfaces (input)
+	 * @return true, if the facets have been read correctly, false if the method detects an error
+	 */
+	bool parseFacets(std::ifstream &input,
+	                 std::vector<GeoLib::Surface*> &surfaces,
+	                 std::vector<GeoLib::Point*> &points) const;
+
+	/**
+	 * Method reads the nodes from stream and stores them in a node vector.
 	 * For this purpose it uses methods parseNodesFileHeader() and parseNodes().
-	 * @param input the input stream
+	 * @param input  the input stream
 	 * @return true, if all information is read, false if the method detects an error
 	 */
-	bool readNodesFromStream(std::ifstream &input);
+	bool readNodesFromStream(std::ifstream &input,
+	                         std::vector<MeshLib::Node*> &nodes);
+
 	/**
 	 * Method parses the header of the nodes file created by TetGen
-	 * @param line the header is in this string (input)
-	 * @param n_nodes number of nodes in the file (output)
-	 * @param dim the spatial dimension of the node (output)
-	 * @param n_attributes the number of attributes for each node (output)
-	 * @param boundary_markers have the nodes boundary information (output)
+	 * @param line              the header is in this string (input)
+	 * @param n_nodes           number of nodes in the file (output)
+	 * @param dim               the spatial dimension of the node (output)
+	 * @param n_attributes      the number of attributes for each node (output)
+	 * @param boundary_markers  have the nodes boundary information (output)
 	 * @return true, if the file header is read, false if the method detects an error
 	 */
-	bool parseNodesFileHeader(std::string &line, std::size_t& n_nodes, std::size_t& dim,
-	                          std::size_t& n_attributes, bool& boundary_markers) const;
+	bool parseNodesFileHeader(std::string &line,
+	                          std::size_t &n_nodes,
+	                          std::size_t &dim,
+	                          std::size_t &n_attributes,
+	                          bool &boundary_markers) const;
 	/**
 	 * method parses the lines reading the nodes from TetGen nodes file
-	 * @param ins the input stream (input)
-	 * @param n_nodes the number of nodes to read (input)
-	 * @param dim the spatial dimension of the node (input)
+	 * @param ins      the input stream (input)
+	 * @param nodes    the nodes vector to be filled (input)
+	 * @param n_nodes  the number of nodes to read (input)
+	 * @param dim      the spatial dimension of the node (input)
 	 * @return true, if the nodes are read, false if the method detects an error
 	 */
-	bool parseNodes(std::ifstream& ins, std::size_t n_nodes, std::size_t dim);
+	bool parseNodes(std::ifstream &ins,
+	                std::vector<MeshLib::Node*> &nodes,
+	                std::size_t n_nodes,
+	                std::size_t dim);
 
 	/**
-	 * Method reads the elements from stream and stores them in the element vector of the mesh class.
+	 * Method reads the elements from stream and stores them in an element vector.
 	 * For this purpose it uses methods parseElementsFileHeader() and parseElements().
-	 * @param input the input stream
+	 * @param input     the input stream
+	 * @param elements  the elements vector to be filled
+	 * @param nodes     the node information needed for creating elements
 	 * @return true, if all information is read, false if the method detects an error
 	 */
-	bool readElementsFromStream(std::ifstream &input);
+	bool readElementsFromStream(std::ifstream &input,
+	                            std::vector<MeshLib::Element*> &elements,
+	                            const std::vector<MeshLib::Node*> &nodes) const;
 	/**
 	 * Method parses the header of the elements file created by TetGen
-	 * @param line
-	 * @param n_tets
-	 * @param n_nodes_per_tet
-	 * @param region_attribute is on output true, if there
+	 * @param line              the header is in this string (input)
+	 * @param n_tets            the number of tets to read (input)
+	 * @param n_nodes_per_tet   the number of nodes per tets (input)
+	 * @param region_attribute  is on output true, if there
 	 * @return
 	 */
-	bool parseElementsFileHeader(std::string &line, std::size_t& n_tets, std::size_t& n_nodes_per_tet,
-	                             bool& region_attribute) const;
+	bool parseElementsFileHeader(std::string &line,
+	                             std::size_t &n_tets,
+	                             std::size_t &n_nodes_per_tet,
+	                             bool &region_attribute) const;
 	/**
 	 * Method parses the tetrahedras and put them in the element vector of the mesh class.
 	 * @param ins the input stream
-	 * @param n_tets the number of tetrahedras that should be read
-	 * @param n_nodes_per_tet the number of nodes per tetrahedron
-	 * @param region_attribute if region attribute is true, region information is read
+	 * @param elements          the elements vector to be filled
+	 * @param nodes             the node information needed for creating elements
+	 * @param n_tets            the number of tetrahedras that should be read
+	 * @param n_nodes_per_tet   the number of nodes per tetrahedron
+	 * @param region_attribute  if region attribute is true, region information is read
 	 * @return true, if the tetrahedras are read, false if the method detects an error
 	 */
-	bool parseElements(std::ifstream& ins, std::size_t n_tets, std::size_t n_nodes_per_tet,
-	                   bool region_attribute);
+	bool parseElements(std::ifstream& ins,
+	                   std::vector<MeshLib::Element*> &elements,
+	                   const std::vector<MeshLib::Node*> &nodes,
+	                   std::size_t n_tets,
+	                   std::size_t n_nodes_per_tet,
+	                   bool region_attribute) const;
 
-	/**
-	 * the nodes later on handed over to the mesh are stored in this vector
-	 */
-	std::vector<MeshLib::Node*> _nodes;
-	/**
-	 * the elements (tetrahedrons) later on handed over to the mesh are stored in this vector
-	 */
-	std::vector<MeshLib::Element*> _elements;
 	/**
 	 * the value is true if the indexing is zero based, else false
 	 */
diff --git a/Gui/mainwindow.cpp b/Gui/mainwindow.cpp
index 33a9dba8cd96cf5aeb3e2ca7be998759ca614644..8dade0950b9306867d5d61e43af2aeaba4364ea4 100644
--- a/Gui/mainwindow.cpp
+++ b/Gui/mainwindow.cpp
@@ -446,8 +446,7 @@ void MainWindow::open(int file_type)
 	QSettings settings;
 	ImportFileType::type t = static_cast<ImportFileType::type>(file_type);
 	QString type_str = QString::fromStdString((ImportFileType::convertImportFileTypeToString(t)));
-	QString fileName = QFileDialog::getOpenFileName(this,
-	                                                "Select " + type_str + " file to import",
+	QString fileName = QFileDialog::getOpenFileName(this, "Select " + type_str + " file to import",
 													settings.value("lastOpenedFileDirectory").toString(),
 	                                                QString::fromStdString(ImportFileType::getFileSuffixString(t)));
 	if (!fileName.isEmpty())
@@ -688,20 +687,25 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName)
 	}
 	else if (t == ImportFileType::TETGEN)
 	{
-		QString element_fname = QFileDialog::getOpenFileName(this, "Select TetGen element file",
-						                                     settings.value("lastOpenedTetgenFileDirectory").toString(),
-						                                     "TetGen element files (*.ele);;");
-
-		if (!fileName.isEmpty() && !element_fname.isEmpty()) {
+		if (fi.suffix().toLower().compare("poly") == 0)
+		{
 			FileIO::TetGenInterface tetgen;
-			MeshLib::Mesh* msh (tetgen.readTetGenMesh(fileName.toStdString(), element_fname.toStdString()));
-			if (msh) {
-				std::string name(fileName.toStdString());
-				msh->setName(name);
-				_meshModels->addMesh(msh);
-			} else
-				OGSError::box("Failed to load a TetGen mesh.");
-			settings.setValue("lastOpenedFileDirectory", QDir(fileName).absolutePath());
+			tetgen.readTetGenPoly(fileName.toStdString(), *(_project.getGEOObjects()));
+		}
+		else {
+			settings.setValue("lastOpenedTetgenFileDirectory", QFileInfo(fileName).absolutePath());
+			QString element_fname = QFileDialog::getOpenFileName(this, "Select TetGen element file",
+			                                                     settings.value("lastOpenedTetgenFileDirectory").toString(),
+			                                                     "TetGen element files (*.ele);;");
+
+			if (!fileName.isEmpty() && !element_fname.isEmpty()) {
+				FileIO::TetGenInterface tetgen;
+				MeshLib::Mesh* mesh (tetgen.readTetGenMesh(fileName.toStdString(), element_fname.toStdString()));
+				if (mesh)
+					_meshModels->addMesh(mesh);
+				else
+					OGSError::box("Failed to load a TetGen mesh.");
+			}
 		}
 	}
 	else if (t == ImportFileType::VTK)