diff --git a/DDCore/include/DD4hep/Primitives.h b/DDCore/include/DD4hep/Primitives.h
index 239b7a7a34a499d9b8f907bf7b870d50c64e7ad3..518580a62ddf4f7247e293c057917164a2c59fc7 100644
--- a/DDCore/include/DD4hep/Primitives.h
+++ b/DDCore/include/DD4hep/Primitives.h
@@ -9,6 +9,8 @@
 #ifndef DD4HEP_DD4HEP_PRIMITIVES_H
 #define DD4HEP_DD4HEP_PRIMITIVES_H
 
+#include "DDSegmentation/Segmentation.h"
+
 // C/C++ include files
 #include <algorithm>
 
@@ -18,7 +20,8 @@
 namespace DD4hep {
 
   // Put here global basic type definitions derived from primitive types of the DD4hep namespace
-  typedef unsigned long long int VolumeID;
+  typedef DDSegmentation::CellID CellID;
+  typedef DDSegmentation::VolumeID VolumeID;
 
   /// Helper to delete objects from heap and reset the pointer. Saves many many lines of code
   template <typename T> inline void deletePtr(T*& p) {
diff --git a/DDCore/include/DD4hep/Segmentations.h b/DDCore/include/DD4hep/Segmentations.h
index ccc86f11093118118adb4563cdec8488ceb9d020..ecc7f3dd92e42f1ce0925745cc2d410cd1f84314 100644
--- a/DDCore/include/DD4hep/Segmentations.h
+++ b/DDCore/include/DD4hep/Segmentations.h
@@ -54,9 +54,9 @@ namespace DD4hep {
         /// Flag to use segmentation for hit positioning
         unsigned char useForHitPosition;
         /// determine the local position based on the cell ID
-        DDSegmentation::Position position(const long64& cellID) const;
+        DDSegmentation::Vector3D position(const long64& cellID) const;
         /// determine the cell ID based on the local position
-        long64 cellID(const DDSegmentation::Position& localPosition, const DDSegmentation::Position& globalPosition, const long64& volumeID) const;
+        long64 cellID(const DDSegmentation::Vector3D& localPosition, const DDSegmentation::Vector3D& globalPosition, const long64& volumeID) const;
         /// Standard constructor
         Object(BaseSegmentation* s = 0);
         /// Default destructor
diff --git a/DDCore/src/Segmentations.cpp b/DDCore/src/Segmentations.cpp
index 7f390ccf389de51a99bbe8fbd9db48f251b4753d..962e5c7cfc57e51aee6cd7568fb73403becbe144 100644
--- a/DDCore/src/Segmentations.cpp
+++ b/DDCore/src/Segmentations.cpp
@@ -34,12 +34,12 @@ Segmentation::Object::~Object() {
 }
 
 /// determine the local position based on the cell ID
-DDSegmentation::Position Segmentation::Object::position(const long64& cellID) const {
+DDSegmentation::Vector3D Segmentation::Object::position(const long64& cellID) const {
   return segmentation->position(cellID);
 }
 
 /// determine the cell ID based on the local position
-long64 Segmentation::Object::cellID(const DDSegmentation::Position& localPosition, const DDSegmentation::Position& globalPosition, const long64& volumeID) const {
+long64 Segmentation::Object::cellID(const DDSegmentation::Vector3D& localPosition, const DDSegmentation::Vector3D& globalPosition, const long64& volumeID) const {
   return segmentation->cellID(localPosition, globalPosition, volumeID);
 }
 
diff --git a/DDSegmentation/include/DDSegmentation/CartesianGridXY.h b/DDSegmentation/include/DDSegmentation/CartesianGridXY.h
index 5e470e1165f76876b348bd0683b71e1a9efa4adc..e8adf981b7be38e939e732bf930a612495c0d8b9 100644
--- a/DDSegmentation/include/DDSegmentation/CartesianGridXY.h
+++ b/DDSegmentation/include/DDSegmentation/CartesianGridXY.h
@@ -21,9 +21,9 @@ public:
 	virtual ~CartesianGridXY();
 
 	/// determine the position based on the cell ID
-	virtual Position position(const CellID& cellID) const;
+	virtual Vector3D position(const CellID& cellID) const;
 	/// determine the cell ID based on the position
-	virtual CellID cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const;
+	virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const;
 	/// access the grid size in X
 	double gridSizeX() const {
 		return _gridSizeX;
diff --git a/DDSegmentation/include/DDSegmentation/CartesianGridXYZ.h b/DDSegmentation/include/DDSegmentation/CartesianGridXYZ.h
index b28840df31811be5dc1cccf31d4caed6e8f3ce89..2365dd4ec22e5f2c3266228e56613fb1f788bedb 100644
--- a/DDSegmentation/include/DDSegmentation/CartesianGridXYZ.h
+++ b/DDSegmentation/include/DDSegmentation/CartesianGridXYZ.h
@@ -21,9 +21,9 @@ public:
 	virtual ~CartesianGridXYZ();
 
 	/// determine the position based on the cell ID
-	virtual Position position(const CellID& cellID) const;
+	virtual Vector3D position(const CellID& cellID) const;
 	/// determine the cell ID based on the position
-	virtual CellID cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const;
+	virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const;
 	/// access the grid size in Z
 	double gridSizeZ() const {
 		return _gridSizeZ;
diff --git a/DDSegmentation/include/DDSegmentation/CartesianGridXZ.h b/DDSegmentation/include/DDSegmentation/CartesianGridXZ.h
index 02ab684ef5e1857804198c9d382b4117dcfcd417..d0febe4e59004873b194cf926fd1350d93989414 100644
--- a/DDSegmentation/include/DDSegmentation/CartesianGridXZ.h
+++ b/DDSegmentation/include/DDSegmentation/CartesianGridXZ.h
@@ -21,9 +21,9 @@ public:
 	virtual ~CartesianGridXZ();
 
 	/// determine the local based on the cell ID
-	virtual Position position(const CellID& cellID) const;
+	virtual Vector3D position(const CellID& cellID) const;
 	/// determine the cell ID based on the position
-	virtual CellID cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const;
+	virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const;
 	/// access the grid size in X
 	double gridSizeX() const {
 		return _gridSizeX;
diff --git a/DDSegmentation/include/DDSegmentation/ProjectiveCylinder.h b/DDSegmentation/include/DDSegmentation/ProjectiveCylinder.h
index f2c61bae838f27bb04b8324870becacc03e9bcbb..56e5447efb3b2bc3311e27f4af913e791d3ea5ac 100644
--- a/DDSegmentation/include/DDSegmentation/ProjectiveCylinder.h
+++ b/DDSegmentation/include/DDSegmentation/ProjectiveCylinder.h
@@ -21,9 +21,9 @@ public:
 	virtual ~ProjectiveCylinder();
 
 	/// determine the position based on the cell ID
-	virtual Position position(const CellID& cellID) const;
+	virtual Vector3D position(const CellID& cellID) const;
 	/// determine the cell ID based on the position
-	virtual CellID cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const;
+	virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const;
 	/// determine the polar angle theta based on the cell ID
 	double theta(const long64& cellID) const;
 	/// determine the azimuthal angle phi based on the cell ID
diff --git a/DDSegmentation/include/DDSegmentation/Segmentation.h b/DDSegmentation/include/DDSegmentation/Segmentation.h
index 84f477bb156c5f19115f336c8fc4b20b83c1c325..08fade05ab99c365a5e9b5b081b373a38753e96e 100644
--- a/DDSegmentation/include/DDSegmentation/Segmentation.h
+++ b/DDSegmentation/include/DDSegmentation/Segmentation.h
@@ -27,6 +27,10 @@ typedef TypedSegmentationParameter<int>* IntParameter;
 typedef TypedSegmentationParameter<float>* FloatParameter;
 typedef TypedSegmentationParameter<double>* DoubleParameter;
 typedef TypedSegmentationParameter<std::string>* StringParameter;
+typedef TypedSegmentationParameter<std::vector<int> >* IntVecParameter;
+typedef TypedSegmentationParameter<std::vector<float> >* FloatVecParameter;
+typedef TypedSegmentationParameter<std::vector<double> >* DoubleVecParameter;
+typedef TypedSegmentationParameter<std::vector<std::string> >* StringVecParameter;
 typedef SegmentationParameter::UnitType UnitType;
 
 /// Useful typedefs to differentiate cell IDs and volume IDs
@@ -34,13 +38,13 @@ typedef long long int CellID;
 typedef long long int VolumeID;
 
 /// Simple container for a physics vector
-struct Position {
+struct Vector3D {
 	/// Default constructor
-	Position(double x = 0., double y = 0., double z = 0.) :
+	Vector3D(double x = 0., double y = 0., double z = 0.) :
 			X(x), Y(y), Z(z) {
 	}
 	/// Constructor using a foreign vector class. Requires methods x(), y() and z()
-	template<typename T> Position(const T& v) {
+	template<typename T> Vector3D(const T& v) {
 		X = v.x();
 		Y = v.y();
 		Z = v.Z();
@@ -67,9 +71,9 @@ public:
 	virtual ~Segmentation();
 
 	/// Determine the local position based on the cell ID
-	virtual Position position(const CellID& cellID) const = 0;
+	virtual Vector3D position(const CellID& cellID) const = 0;
 	/// Determine the cell ID based on the position
-	virtual CellID cellID(const Position& localPosition, const Position& globalPosition,
+	virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition,
 			const VolumeID& volumeID) const = 0;
 	/// Determine the volume ID from the full cell ID by removing all local fields
 	virtual VolumeID volumeID(const CellID& cellID) const;
@@ -116,8 +120,10 @@ protected:
 
 	/// Add a parameter to this segmentation. Used by derived classes to define their parameters
 	template<typename TYPE> void registerParameter(const std::string& name, const std::string& description,
-			TYPE& parameter, const TYPE& defaultValue, UnitType unitType = SegmentationParameter::NoUnit, bool isOptional = false) {
-		_parameters[name] = new TypedSegmentationParameter<TYPE>(name, description, parameter, defaultValue, unitType, isOptional);
+			TYPE& parameter, const TYPE& defaultValue, UnitType unitType = SegmentationParameter::NoUnit,
+			bool isOptional = false) {
+		_parameters[name] = new TypedSegmentationParameter<TYPE>(name, description, parameter, defaultValue, unitType,
+				isOptional);
 	}
 	/// Add a cell identifier to this segmentation. Used by derived classes to define their required identifiers
 	void registerIdentifier(const std::string& name, const std::string& description, std::string& identifier,
diff --git a/DDSegmentation/include/DDSegmentation/SegmentationParameter.h b/DDSegmentation/include/DDSegmentation/SegmentationParameter.h
index 099fbdf9269047d2805743b171a6e51cab20d25e..d435ecb02ae0939db924c7b5be79eaf99173a280 100644
--- a/DDSegmentation/include/DDSegmentation/SegmentationParameter.h
+++ b/DDSegmentation/include/DDSegmentation/SegmentationParameter.h
@@ -13,50 +13,81 @@
 #include <sstream>
 #include <string>
 #include <typeinfo>
+#include <vector>
 
 namespace DD4hep {
 namespace DDSegmentation {
 
 /// Helper class to extract type names
-template <typename TYPE> struct TypeName {
+template<typename TYPE> struct TypeName {
 	static const char* name() {
 		return typeid(TYPE).name();
 	}
 };
 
 /// Specialization for int type
-template <> struct TypeName<int> {
+template<> struct TypeName<int> {
 	static const char* name() {
 		return "int";
 	}
 };
 
 /// Specialization for float type
-template <> struct TypeName<float> {
+template<> struct TypeName<float> {
 	static const char* name() {
 		return "float";
 	}
 };
 
 /// Specialization for double type
-template <> struct TypeName<double> {
+template<> struct TypeName<double> {
 	static const char* name() {
 		return "double";
 	}
 };
 
 /// Specialization for string type
-template <> struct TypeName<std::string> {
+template<> struct TypeName<std::string> {
 	static const char* name() {
 		return "string";
 	}
 };
 
+/// Specialization for int vector type
+template<> struct TypeName<std::vector<int> > {
+	static const char* name() {
+		return "intvec";
+	}
+};
+
+/// Specialization for float vector type
+template<> struct TypeName<std::vector<float> > {
+	static const char* name() {
+		return "floatvec";
+	}
+};
+
+/// Specialization for double vector type
+template<> struct TypeName<std::vector<double> > {
+	static const char* name() {
+		return "doublevec";
+	}
+};
+
+/// Specialization for string vector type
+template<> struct TypeName<std::vector<std::string> > {
+	static const char* name() {
+		return "stringvec";
+	}
+};
+
 /// Class to hold a segmentation parameter with its description
 class SegmentationParameter {
 public:
 	/// Defines the parameter unit type (useful to convert to default set of units)
-	enum UnitType {NoUnit, LengthUnit, AngleUnit};
+	enum UnitType {
+		NoUnit, LengthUnit, AngleUnit
+	};
 	/// Destructor
 	virtual ~SegmentationParameter() {
 	}
@@ -95,7 +126,8 @@ public:
 	}
 protected:
 	/// Default constructor used by derived classes
-	SegmentationParameter(const std::string& name, const std::string& description, UnitType unitType = NoUnit, bool isOptional = false) :
+	SegmentationParameter(const std::string& name, const std::string& description, UnitType unitType = NoUnit,
+			bool isOptional = false) :
 			_name(name), _description(description), _unitType(unitType), _isOptional(isOptional) {
 	}
 	/// The parameter name
@@ -112,7 +144,8 @@ template<typename TYPE> class TypedSegmentationParameter: public SegmentationPar
 public:
 	/// Default constructor
 	TypedSegmentationParameter(const std::string& name, const std::string& description, TYPE& value,
-			const TYPE& defaultValue, SegmentationParameter::UnitType unitType = SegmentationParameter::NoUnit, bool isOptional = false) :
+			const TYPE& defaultValue, SegmentationParameter::UnitType unitType = SegmentationParameter::NoUnit,
+			bool isOptional = false) :
 			SegmentationParameter(name, description, unitType, isOptional), _value(value), _defaultValue(defaultValue) {
 		_value = defaultValue;
 	}
@@ -163,6 +196,91 @@ protected:
 	TYPE _defaultValue;
 };
 
+template<typename TYPE> class TypedSegmentationParameter<std::vector<TYPE> > : public SegmentationParameter {
+public:
+	/// Default constructor
+	TypedSegmentationParameter(const std::string& name, const std::string& description, std::vector<TYPE>& value,
+			const std::vector<TYPE>& defaultValue, SegmentationParameter::UnitType unitType =
+					SegmentationParameter::NoUnit, bool isOptional = false) :
+			SegmentationParameter(name, description, unitType, isOptional), _value(value), _defaultValue(defaultValue) {
+		_value = defaultValue;
+	}
+
+	/// Access to the parameter value
+	const std::vector<TYPE>& typedValue() const {
+		return _value;
+	}
+
+	/// Set the parameter value
+	void setTypedValue(const std::vector<TYPE>& value) {
+		_value = value;
+	}
+
+	/// Access to the parameter default value
+	const std::vector<TYPE>& typedDefaultValue() const {
+		return _defaultValue;
+	}
+
+	/// Access to the parameter type
+	std::string type() const {
+		std::stringstream s;
+		s << TypeName<TYPE>::name() << "Vec";
+		return s.str() ;
+	}
+
+	/// Access to the parameter value in string representation
+	std::string value() const {
+		std::stringstream s;
+		typename std::vector<TYPE>::const_iterator it = _value.begin();
+		for (; it != _value.end(); ++it) {
+			s << *it;
+			s << " ";
+		}
+		return s.str();
+	}
+
+	/// Set the parameter value in string representation
+	void setValue(const std::string& value) {
+		std::vector<std::string> elements = splitString(value);
+		_value.clear();
+		for (std::vector<std::string>::const_iterator it = elements.begin(); it != elements.end(); ++it) {
+			if (not it->empty()) {
+				TYPE entry;
+				std::stringstream s;
+				s << *it;
+				s >> entry;
+				_value.push_back(entry);
+			}
+		}
+	}
+
+	/// Access to the parameter default value in string representation
+	std::string defaultValue() const {
+		std::stringstream s;
+		typename std::vector<TYPE>::const_iterator it = _defaultValue.begin();
+		for (; it != _defaultValue.end(); ++it) {
+			s << *it;
+			s << " ";
+		}
+		return s.str();
+	}
+
+protected:
+	std::vector<TYPE>& _value;
+	std::vector<TYPE> _defaultValue;
+
+	/// Helper method to split string into tokens
+	std::vector<std::string> splitString(const std::string& s, char delimiter = ' ') {
+		std::vector<std::string> elements;
+		std::stringstream ss(s);
+		std::string item;
+		while (std::getline(ss, item, delimiter)) {
+			elements.push_back(item);
+		}
+		return elements;
+	}
+};
+
 } /* namespace DDSegmentation */
 } /* namespace DD4hep */
 #endif /* DDSegmentation_SEGMENTATIONPARAMETER_H_ */
diff --git a/DDSegmentation/include/DDSegmentation/SegmentationUtil.h b/DDSegmentation/include/DDSegmentation/SegmentationUtil.h
index a310a7f449a39d0522dcd61053919ad319e33aa1..5f8798b2c0cfd1d9eb9d47031ebcaf072c3ba903 100644
--- a/DDSegmentation/include/DDSegmentation/SegmentationUtil.h
+++ b/DDSegmentation/include/DDSegmentation/SegmentationUtil.h
@@ -29,22 +29,22 @@ namespace Util {
 
 
 /// calculates the radius in xyz from Cartesian coordinates
-double magFromXYZ(const Position& position) {
+double magFromXYZ(const Vector3D& position) {
 	return std::sqrt(position.X * position.X + position.Y * position.Y + position.Z * position.Z);
 }
 
 /// calculates the radius in the xy-plane from Cartesian coordinates
-double radiusFromXYZ(const Position& position) {
+double radiusFromXYZ(const Vector3D& position) {
 	return std::sqrt(position.X * position.X + position.Y * position.Y);
 }
 
 /// calculates the polar angle theta from Cartesian coordinates
-double thetaFromXYZ(const Position& position) {
+double thetaFromXYZ(const Vector3D& position) {
 	return std::acos(position.Z / radiusFromXYZ(position));
 }
 
 /// calculates the azimuthal angle phi from Cartesian coordinates
-double phiFromXYZ(const Position& position) {
+double phiFromXYZ(const Vector3D& position) {
 	return std::atan2(position.Y, position.X);
 }
 
@@ -53,8 +53,8 @@ double phiFromXYZ(const Position& position) {
 /////////////////////////////////////////////////////////////
 
 /// calculates the Cartesian position from cylindrical coordinates
-Position positionFromRPhiZ(double r, double phi, double z) {
-	return Position(r * std::cos(phi), r * std::sin(phi), z);
+Vector3D positionFromRPhiZ(double r, double phi, double z) {
+	return Vector3D(r * std::cos(phi), r * std::sin(phi), z);
 }
 
 /// calculates the radius in xyz from cylindrical coordinates
@@ -82,14 +82,14 @@ double thetaFromRPhiZ(double r, double phi, double z) {
 /////////////////////////////////////////////////////////////
 
 /// calculates the Cartesian position from spherical coordinates
-Position positionFromRThetaPhi(double r, double theta, double phi) {
-	return Position(r * std::cos(phi), r * std::sin(phi), r * std::tan(theta));
+Vector3D positionFromRThetaPhi(double r, double theta, double phi) {
+	return Vector3D(r * std::cos(phi), r * std::sin(phi), r * std::tan(theta));
 }
 
 /// calculates the Cartesian position from spherical coordinates
-Position positionFromMagThetaPhi(double mag, double theta, double phi) {
+Vector3D positionFromMagThetaPhi(double mag, double theta, double phi) {
 	double r = mag * sin(theta);
-	return Position(r * std::cos(phi), r * std::sin(phi), mag * std::cos(theta));
+	return Vector3D(r * std::cos(phi), r * std::sin(phi), mag * std::cos(theta));
 }
 
 } /* namespace Util */
diff --git a/DDSegmentation/include/DDSegmentation/TiledLayerSegmentation.h b/DDSegmentation/include/DDSegmentation/TiledLayerSegmentation.h
new file mode 100644
index 0000000000000000000000000000000000000000..94aed501b04ac7775d291ba218cd1a5710b26d21
--- /dev/null
+++ b/DDSegmentation/include/DDSegmentation/TiledLayerSegmentation.h
@@ -0,0 +1,116 @@
+/*
+ * TiledLayerSegmentation.h
+ *
+ *  Created on: Mar 10, 2014
+ *      Author: cgrefe
+ */
+
+#ifndef DDSegmentation_TILEDLAYERSEGMENTATION_H_
+#define DDSegmentation_TILEDLAYERSEGMENTATION_H_
+
+#include "DDSegmentation/Segmentation.h"
+
+// C/C++ includes
+#include <string>
+#include <vector>
+
+namespace DD4hep {
+namespace DDSegmentation {
+
+class TiledLayerSegmentation: public Segmentation {
+public:
+	/// Helper class to store x and y dimensions of a layer
+	struct LayerDimensions {
+		LayerDimensions(double x = 1., double y = 1.) :
+			x(x), y(y) {}
+		double x, y;
+	};
+
+	/// Default constructor passing the encoding string
+	TiledLayerSegmentation(const std::string& cellEncoding = "");
+	/// destructor
+	virtual ~TiledLayerSegmentation();
+
+	/// determine the position based on the cell ID
+	virtual Vector3D position(const CellID& cellID) const;
+	/// determine the cell ID based on the position
+	virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition,
+			const VolumeID& volumeID) const;
+
+	/// access the default grid size in X
+	double gridSizeX() const {
+		return _gridSizeX;
+	}
+	/// access the default grid size in Y
+	double gridSizeY() const {
+		return _gridSizeY;
+	}
+
+	/// access the actual grid size in X for a given layer
+	double layerGridSizeX(int layerIndex) const;
+	/// access the actual grid size in Y for a given layer
+	double layerGridSizeY(int layerIndex) const;
+
+	/// access the encoding field name used for X
+	const std::string& identifierX() const {
+		return _identifierX;
+	}
+	/// access the encoding field name used for Y
+	const std::string& identifierY() const {
+		return _identifierY;
+	}
+	/// access the encoding field name used for Y
+	const std::string& identifierLayer() const {
+		return _identifierLayer;
+	}
+
+	/// access to the dimensions of the given layer
+	LayerDimensions layerDimensions(int layerIndex) const;
+
+	/// set the default grid size in X
+	void setGridSizeX(double cellSize) {
+		_gridSizeX = cellSize;
+	}
+	/// set the default grid size in Y
+	void setGridSizeY(double cellSize) {
+		_gridSizeY = cellSize;
+	}
+
+	/// set the encoding field name used for X
+	void setIdentifierX(const std::string& name) {
+		_identifierX = name;
+	}
+	/// set the encoding field name used for Y
+	void setIdentifierY(const std::string& name) {
+		_identifierY = name;
+	}
+	/// set the encoding field name used for layer
+	void setIdentifierLayer(const std::string& name) {
+		_identifierLayer = name;
+	}
+
+	/// set the dimensions of the given layer
+	void setLayerDimensions(int layerIndex, double x, double y);
+
+
+
+protected:
+	double _gridSizeX; /// default grid size in X
+	double _gridSizeY; /// default grid size in Y
+	std::string _identifierX; /// encoding field used for X
+	std::string _identifierY; /// encoding field used for Y
+	std::string _identifierLayer; /// encoding field used for the layer
+	std::vector<int> _layerIndices; /// list of valid layer identifiers
+	std::vector<double> _layerDimensionsX; /// list of layer x dimensions
+	std::vector<double> _layerDimensionsY; /// list of layer y dimensions
+
+	/// helper method to calculate optimal cell size based on total size
+	static double calculateOptimalCellSize(double nominalCellSize, double totalSize);
+	/// helper method to calculate offset of bin 0 based on the total size
+	static double calculateOffset(double cellSize, double totalSize);
+};
+
+} /* namespace DDSegmentation */
+} /* namespace DD4hep */
+
+#endif /* TILEDLAYERSEGMENTATION_H_ */
diff --git a/DDSegmentation/src/CartesianGridXY.cpp b/DDSegmentation/src/CartesianGridXY.cpp
index fef07f52e5349b17b248ae54c265475f6312521d..d8e5c3b0b0e4d084ea46563670cba33979f5d873 100644
--- a/DDSegmentation/src/CartesianGridXY.cpp
+++ b/DDSegmentation/src/CartesianGridXY.cpp
@@ -34,16 +34,16 @@ CartesianGridXY::~CartesianGridXY() {
 }
 
 /// determine the position based on the cell ID
-Position CartesianGridXY::position(const CellID& cellID) const {
+Vector3D CartesianGridXY::position(const CellID& cellID) const {
 	_decoder->setValue(cellID);
-	Position position;
+	Vector3D position;
 	position.X = binToPosition((*_decoder)[_xId].value(), _gridSizeX, _offsetX);
 	position.Y = binToPosition((*_decoder)[_yId].value(), _gridSizeY, _offsetY);
 	return position;
 }
 
 /// determine the cell ID based on the position
-CellID CartesianGridXY::cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const {
+CellID CartesianGridXY::cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const {
 	_decoder->setValue(volumeID);
 	(*_decoder)[_xId] = positionToBin(localPosition.X, _gridSizeX, _offsetX);
 	(*_decoder)[_yId] = positionToBin(localPosition.Y, _gridSizeY, _offsetY);
diff --git a/DDSegmentation/src/CartesianGridXYZ.cpp b/DDSegmentation/src/CartesianGridXYZ.cpp
index 85b20c709c5d49bdc80be800641d416a7844c3c8..6ce8c65b9aa32a0e2d4010071aa4016b651f10a8 100644
--- a/DDSegmentation/src/CartesianGridXYZ.cpp
+++ b/DDSegmentation/src/CartesianGridXYZ.cpp
@@ -31,9 +31,9 @@ CartesianGridXYZ::~CartesianGridXYZ() {
 }
 
 /// determine the position based on the cell ID
-Position CartesianGridXYZ::position(const CellID& cellID) const {
+Vector3D CartesianGridXYZ::position(const CellID& cellID) const {
 	_decoder->setValue(cellID);
-	Position position;
+	Vector3D position;
 	position.X = binToPosition((*_decoder)[_xId].value(), _gridSizeX, _offsetX);
 	position.Y = binToPosition((*_decoder)[_yId].value(), _gridSizeY, _offsetY);
 	position.Z = binToPosition((*_decoder)[_zId].value(), _gridSizeZ, _offsetZ);
@@ -41,7 +41,7 @@ Position CartesianGridXYZ::position(const CellID& cellID) const {
 }
 
 /// determine the cell ID based on the position
-CellID CartesianGridXYZ::cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const {
+CellID CartesianGridXYZ::cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const {
 	_decoder->setValue(volumeID);
 	(*_decoder)[_xId] = positionToBin(localPosition.X, _gridSizeX, _offsetX);
 	(*_decoder)[_yId] = positionToBin(localPosition.Y, _gridSizeY, _offsetY);
diff --git a/DDSegmentation/src/CartesianGridXZ.cpp b/DDSegmentation/src/CartesianGridXZ.cpp
index 4a5ef64f8f4e96c69fa8bd25c18534c158ee7ced..e5f599695258feb097f31ed1417581350bde05c5 100644
--- a/DDSegmentation/src/CartesianGridXZ.cpp
+++ b/DDSegmentation/src/CartesianGridXZ.cpp
@@ -36,17 +36,17 @@ CartesianGridXZ::~CartesianGridXZ() {
 }
 
 /// determine the position based on the cell ID
-Position CartesianGridXZ::position(const CellID& cellID) const {
+Vector3D CartesianGridXZ::position(const CellID& cellID) const {
 	_decoder->setValue(cellID);
 	vector<double> localPosition(3);
-	Position position;
+	Vector3D position;
 	position.X = binToPosition((*_decoder)[_xId].value(), _gridSizeX, _offsetX);
 	position.Z = binToPosition((*_decoder)[_zId].value(), _gridSizeZ, _offsetZ);
 	return position;
 }
 
 /// determine the cell ID based on the position
-CellID CartesianGridXZ::cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const {
+CellID CartesianGridXZ::cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const {
 	_decoder->setValue(volumeID);
 	(*_decoder)[_xId] = positionToBin(localPosition.X, _gridSizeX, _offsetX);
 	(*_decoder)[_zId] = positionToBin(localPosition.Z, _gridSizeZ, _offsetZ);
diff --git a/DDSegmentation/src/ProjectiveCylinder.cpp b/DDSegmentation/src/ProjectiveCylinder.cpp
index e06f6ee0bc9960d652a3bd3298b16370d31fcd2c..cdbf281cc83cb1cc94f148c03e97a82bd0c956a0 100644
--- a/DDSegmentation/src/ProjectiveCylinder.cpp
+++ b/DDSegmentation/src/ProjectiveCylinder.cpp
@@ -40,12 +40,12 @@ ProjectiveCylinder::~ProjectiveCylinder() {
 }
 
 /// determine the local based on the cell ID
-Position ProjectiveCylinder::position(const long64& cellID) const {
+Vector3D ProjectiveCylinder::position(const long64& cellID) const {
 	return Util::positionFromRThetaPhi(1.0, theta(cellID), phi(cellID));
 }
 
 /// determine the cell ID based on the position
-CellID ProjectiveCylinder::cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const {
+CellID ProjectiveCylinder::cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const {
 	_decoder->setValue(volumeID);
 	double theta = thetaFromXYZ(globalPosition);
 	double phi = phiFromXYZ(globalPosition);
diff --git a/DDSegmentation/src/TiledLayerSegmentation.cpp b/DDSegmentation/src/TiledLayerSegmentation.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..567f9571d099a4a7e9363b10956d83539763adf3
--- /dev/null
+++ b/DDSegmentation/src/TiledLayerSegmentation.cpp
@@ -0,0 +1,138 @@
+/*
+ * TiledLayerSegmentation.cpp
+ *
+ *  Created on: Mar 10, 2014
+ *      Author: cgrefe
+ */
+
+#include "DDSegmentation/TiledLayerSegmentation.h"
+
+// C/C++ includes
+#include <algorithm>
+#include <sstream>
+#include <stdexcept>
+
+namespace DD4hep {
+namespace DDSegmentation {
+
+using std::find;
+using std::runtime_error;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+TiledLayerSegmentation::TiledLayerSegmentation(const string& cellEncoding) :
+		Segmentation(cellEncoding) {
+	_type = "TiledLayerSegmentation";
+	_description = "Cartesian segmentation using optimal tiling depending on the layer dimensions";
+
+	// register all necessary parameters
+	registerParameter("grid_size_x", "Default cell size in X", _gridSizeX, 1., SegmentationParameter::LengthUnit);
+	registerParameter("grid_size_y", "Default cell size in Y", _gridSizeY, 1., SegmentationParameter::LengthUnit);
+	registerIdentifier("identifier_x", "Cell encoding identifier for X", _identifierX, "x");
+	registerIdentifier("identifier_y", "Cell encoding identifier for Y", _identifierY, "y");
+	registerParameter("identifier_layer", "Cell encoding identifier for layer", _identifierLayer, string("layer"),
+			SegmentationParameter::NoUnit, true);
+	registerParameter("layer_identifiers", "List of valid layer identifiers", _layerIndices, vector<int>(),
+			SegmentationParameter::NoUnit, true);
+	registerParameter("x_dimensions", "List of layer x dimensions", _layerDimensionsX, vector<double>(),
+			SegmentationParameter::NoUnit, true);
+	registerParameter("y_dimensions", "List of layer y dimensions", _layerDimensionsY, vector<double>(),
+			SegmentationParameter::NoUnit, true);
+
+}
+
+TiledLayerSegmentation::~TiledLayerSegmentation() {
+}
+
+/// access the actual grid size in X for a given layer
+double TiledLayerSegmentation::layerGridSizeX(int layerIndex) const {
+	// should be cached in a map if calculateOptimalCellSize is expensive
+	return calculateOptimalCellSize(_gridSizeX, layerDimensions(layerIndex).x);
+}
+
+/// access the actual grid size in Y for a given layer
+double TiledLayerSegmentation::layerGridSizeY(int layerIndex) const {
+	// should be cached in a map if calculateOptimalCellSize is expensive
+	return calculateOptimalCellSize(_gridSizeY, layerDimensions(layerIndex).y);
+}
+
+/// set the dimensions of the given layer
+void TiledLayerSegmentation::setLayerDimensions(int layerIndex, double x, double y) {
+	// a bit clumsy since we use three vectors instead of a map<int, LayerDimensions>
+	if (_layerIndices.size() != _layerDimensionsX.size() or _layerIndices.size() != _layerDimensionsY.size()) {
+		throw runtime_error(
+				"TiledLayerSegmentation::setLayerDimensions: inconsistent size of layer parameter vectors.");
+	}
+	vector<int>::iterator it = find(_layerIndices.begin(), _layerIndices.end(), layerIndex);
+	if (it == _layerIndices.end()) {
+		_layerIndices.push_back(layerIndex);
+		_layerDimensionsX.push_back(x);
+		_layerDimensionsY.push_back(y);
+	} else {
+		size_t index = it - _layerIndices.begin();
+		_layerDimensionsX[index] = x;
+		_layerDimensionsY[index] = y;
+	}
+}
+
+/// access to the dimensions of the given layer
+TiledLayerSegmentation::LayerDimensions TiledLayerSegmentation::layerDimensions(int layerIndex) const {
+	// a bit clumsy since we use three vectors instead of a map<int, LayerDimensions>
+	if (_layerIndices.size() != _layerDimensionsX.size() or _layerIndices.size() != _layerDimensionsY.size()) {
+		throw runtime_error(
+				"TiledLayerSegmentation::layerDimensions: inconsistent size of layer parameter vectors.");
+	}
+	vector<int>::const_iterator it = find(_layerIndices.begin(), _layerIndices.end(), layerIndex);
+	if (it == _layerIndices.end()) {
+		stringstream message;
+		message << "TiledLayerSegmentation::layerDimensions: invalid layer index " << layerIndex;
+		throw runtime_error(message.str());
+	} else {
+		size_t index = it - _layerIndices.begin();
+		return LayerDimensions(_layerDimensionsX[index], _layerDimensionsY[index]);
+	}
+}
+
+/// determine the position based on the cell ID
+Vector3D TiledLayerSegmentation::position(const CellID& cellID) const {
+	_decoder->setValue(cellID);
+	int layerIndex = (*_decoder)[_identifierLayer];
+	double cellSizeX = layerGridSizeX(layerIndex);
+	double cellSizeY = layerGridSizeY(layerIndex);
+	LayerDimensions dimensions = layerDimensions(layerIndex);
+	double offsetX = calculateOffset(cellSizeX, dimensions.x);
+	double offsetY = calculateOffset(cellSizeY, dimensions.y);
+	double localX = binToPosition((*_decoder)[_identifierX], cellSizeX, offsetX);
+	double localY = binToPosition((*_decoder)[_identifierY], cellSizeY, offsetY);
+	return Vector3D(localX, localY, 0.);
+}
+/// determine the cell ID based on the position
+CellID TiledLayerSegmentation::cellID(const Vector3D& localPosition, const Vector3D& globalPosition,
+		const VolumeID& volumeID) const {
+	_decoder->setValue(volumeID);
+	int layerIndex = (*_decoder)[_identifierLayer];
+	double cellSizeX = layerGridSizeX(layerIndex);
+	double cellSizeY = layerGridSizeY(layerIndex);
+	LayerDimensions dimensions = layerDimensions(layerIndex);
+	double offsetX = calculateOffset(cellSizeX, dimensions.x);
+	double offsetY = calculateOffset(cellSizeY, dimensions.y);
+	(*_decoder)[_identifierX] = positionToBin(localPosition.x(), cellSizeX, offsetX);
+	(*_decoder)[_identifierY] = positionToBin(localPosition.y(), cellSizeY, offsetY);
+	return _decoder->getValue();
+}
+
+/// helper method to calculate optimal cell size based on total size
+double TiledLayerSegmentation::calculateOptimalCellSize(double nominalCellSize, double totalSize) {
+	// TODO: implement algorithm to calculate optimal cell size
+	return 1.;
+}
+
+/// helper method to calculate offset of bin 0 based on the total size
+double TiledLayerSegmentation::calculateOffset(double cellSize, double totalSize) {
+	// TODO: implement algorithm to calculate placement of bin 0
+	return 0.;
+}
+
+} /* namespace DDSegmentation */
+} /* namespace DD4hep */