Index: src/com/iver/cit/gvsig/fmap/core/ShapeZMFactory.java
===================================================================
--- src/com/iver/cit/gvsig/fmap/core/ShapeZMFactory.java	(revision 0)
+++ src/com/iver/cit/gvsig/fmap/core/ShapeZMFactory.java	(revision 0)
@@ -0,0 +1,93 @@
+package com.iver.cit.gvsig.fmap.core;
+
+
+/**
+ * This factory is used to create geoemtries with the M and Z coordinates
+ * 
+ * @author Flavio Pompermaier (flavio.pompermaier@sinergis.it)
+ */
+public class ShapeZMFactory {
+	//TODO implement
+	//		public static IGeometry createPoint3DM(double x, double y,double z, double m) {
+	//			return new FGeometryM(new FPoint3DM(x, y, z, m));
+	//		}
+	
+	public static IGeometryM createPolyline3DM(FPolyline3DM polyline) {
+		return new FGeometryM(polyline);
+	}
+	
+	//TODO implement
+	//		public static IGeometry createPolyline3DM(ByteBuffer data) {
+	//
+	//			int count = data.getInt();
+	//			GeneralPathX gp = new GeneralPathX();
+	//			//double[] ms = new double[count - 1];
+	//			//ArrayList alMs = new ArrayList();
+	//
+	//			ArrayList<Double> ms = new ArrayList<Double>();
+	//			//		        ArrayList<Double> ms_aux = null;
+	//			//		        double[] ms = null;      //Intento de evitar el tener que encapsular las m's en
+	//			//		        double[] ms_aux = null;  //objetos Double y de tener que recorrer un ArrayList
+	//			int ms_lentgh = 0;
+	//
+	//			for (int i=0; i < count; i++) {
+	//				parseTypeAndSRID(data);
+	//				FPoint2DM[] points = parsePointArray(data);
+	//				//		            ms_aux = new double[ms_lentgh + points.length];
+	//
+	//				gp.moveTo(points[0].getX(), points[0].getY());
+	//				//alMs.add(new Double(points[0].getM()));
+	//				//		            ms_aux[ms_lentgh + 0] = points[0].getM();
+	//				ms.add(points[0].getM());
+	//
+	//				for (int j = 1; j< points.length; j++) {
+	//					ms.add(points[j].getM());
+	//					//		             ms_aux[ms_lentgh + j] = points[j].getM();
+	//					gp.lineTo(points[j].getX(), points[j].getY());
+	//				} 
+	//
+	//				//ms[i] = points[i].getM();
+	//				//		            if (ms != null) {
+	//				//		             System.arraycopy(ms, 0, ms_aux, ms.length, ms.length);
+	//				//		            }
+	//				//		            ms = ms_aux;
+	//				//		            ms_lentgh = ms.length;
+	//				//		            ms_aux = null;
+	//			}//for
+	//
+	//
+	//			// OJO: Para ahorrarme esto tendrķa que modificar la clase FPolyline2DM para
+	//			//      que las ms se almacenaran como objetos Double en lugar de usar el tipo
+	//			//      primitivo double.
+	//			double[] aMs = new double[ms.size()];
+	//			for (int i = 0; i < ms.size(); i++) {
+	//				aMs[i] = ((Double)ms.get(i)).doubleValue();
+	//			}
+	//
+	//			return new FGeometryM(new FPolyline3DM(gp, aMs));
+	//		}
+	
+	public static IGeometry createPolygon3DM(GeneralPathX shape, double[] pZ, double[] pM) {
+		throw new UnsupportedOperationException();
+	}
+	
+	public static IGeometry createMultipoint3DM(double[] x, double[] y, double[] z, double[] m) {
+		throw new UnsupportedOperationException();
+	}
+	
+	/**
+	 * Creates a Polyline in 3D with the Z and M coordinates.
+	 * 
+	 * @param shape
+	 *            Coordinates to create the polyline
+	 * @param pZ
+	 *            Vector de Z.
+	 * @param pM
+	 *            Vector de M.
+	 * @return Geometrķa.
+	 * @author Flavio Pompermaier
+	 */
+	public static IGeometry createPolyline3DM(GeneralPathX shape, double[] pZ, double[] pM) {
+		return new FGeometry(new FPolyline3DM(shape, pZ, pM));
+	}
+}
\ No newline at end of file
Index: src/com/iver/cit/gvsig/fmap/core/FPolyline3DM.java
===================================================================
--- src/com/iver/cit/gvsig/fmap/core/FPolyline3DM.java	(revision 0)
+++ src/com/iver/cit/gvsig/fmap/core/FPolyline3DM.java	(revision 0)
@@ -0,0 +1,166 @@
+package com.iver.cit.gvsig.fmap.core;
+
+import java.awt.geom.PathIterator;
+
+import com.iver.cit.gvsig.fmap.core.v02.FConverter;
+
+/**
+ * The Class FPolyline3DM that manages correctly (with Z and M) PolylineZs
+ * 
+ * @author Pompermaier Flavio
+ */
+public class FPolyline3DM extends FPolyline3D implements FShapeM {
+	
+	private static final long serialVersionUID = -4920745174292188836L;
+	private static final String NAME = "MULTILINESTRING_3DM";
+	double[] pM = null;
+	
+	/**
+	 * Crea un nuevo Polyline3DM.
+	 * 
+	 * @param gpx
+	 *            GeneralPathX
+	 * @param pZ
+	 *            Vector con la Z.
+	 * @param pM
+	 *            Vector con la M.
+	 */
+	public FPolyline3DM(GeneralPathX gpx, double[] pZ, double[] pM) {
+		super(gpx, pZ);
+		this.pM = pM;
+	}
+	
+	/**
+	 * @see com.iver.cit.gvsig.fmap.core.FShape#getShapeType()
+	 */
+	@Override
+	public int getShapeType() {
+		return FShape.LINE | FShape.Z;
+	}
+	
+	/**
+	 * Devuelve un Array con todos los valores de M.
+	 * 
+	 * @return Array de Ms.
+	 */
+	public double[] getMs() {
+		return pM;
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see com.iver.cit.gvsig.fmap.core.FShape#cloneFShape()
+	 */
+	@Override
+	public FShape cloneFShape() {
+		return new FPolyline3DM((GeneralPathX) gp.clone(), pZ, pM);
+	}
+	
+	
+	/*
+	 * (non-Javadoc)
+	 * @see com.iver.cit.gvsig.fmap.core.FShapeM#isDecreasing()
+	 */
+	public boolean isDecreasing() {
+		if (pM.length == 0)
+			return false;
+		return pM[0] > pM[pM.length - 1];
+	}
+	
+	
+	/*
+	 * (non-Javadoc)
+	 * @see com.iver.cit.gvsig.fmap.core.FShapeM#revertMs()
+	 */
+	public void revertMs() {
+		double totalDistance = Math.abs(pM[0] - pM[pM.length - 1]);
+		double[] percentages = new double[pM.length];
+		for (int i = 1; i < percentages.length; i++) {
+			percentages[i] = Math.abs(pM[i] - pM[i - 1]) / totalDistance;
+		}
+		//The first value
+		double pm0 = pM[0];
+		if (!isDecreasing()) {
+			pM[0] = pM[pM.length - 1];
+			for (int i = 1; i < pM.length - 1; i++) {
+				double increasing = percentages[i] * totalDistance;
+				pM[i] = pM[i - 1] - increasing;
+			}
+		}
+		else {
+			pM[0] = pM[pM.length - 1];
+			for (int i = 1; i < pM.length - 1; i++) {
+				double decreasing = percentages[i] * totalDistance;
+				pM[i] = pM[i - 1] + decreasing;
+			}
+		}
+		pM[pM.length - 1] = pm0;
+		
+	}
+	
+	
+	/*
+	 * (non-Javadoc)
+	 * @see com.iver.cit.gvsig.fmap.core.FShapeM#setMAt(int, double)
+	 */
+	public void setMAt(int i, double value) {
+		if (i < pM.length) {
+			pM[i] = value;
+		}
+		
+	}
+	
+	
+	/*
+	 * (non-Javadoc)
+	 * @see com.iver.cit.gvsig.fmap.core.FShapeM#toText()
+	 */
+	public String toText() {
+		StringBuffer str = new StringBuffer();
+		str.append(NAME);
+		str.append(" ((");
+		int theType;
+		double[] theData = new double[6];
+		
+		PathIterator theIterator = getPathIterator(null, FConverter.FLATNESS);
+		int i = 0;
+		
+		while (!theIterator.isDone()) {
+			//while not done
+			theType = theIterator.currentSegment(theData);
+			
+			double m = 0.0;
+			if (i < pM.length) {
+				m = pM[i];
+			}
+			
+			switch (theType) {
+				case PathIterator.SEG_MOVETO:
+					str.append(theData[0] + " " + theData[1] + " " + m + ",");
+					break;
+				
+				case PathIterator.SEG_LINETO:
+					str.append(theData[0] + " " + theData[1] + " " + m + ",");
+					
+					break;
+				
+				case PathIterator.SEG_QUADTO:
+					System.out.println("Not supported here");
+					
+					break;
+				
+				case PathIterator.SEG_CUBICTO:
+					System.out.println("Not supported here");
+					
+					break;
+				
+				case PathIterator.SEG_CLOSE:
+					break;
+			} //end switch
+			
+			theIterator.next();
+			i++;
+		} //end while loop		
+		return str.delete(str.length() - 1, str.length()) + "))";
+	}
+}
Index: src/com/iver/cit/gvsig/fmap/drivers/shp/IndexedShpDriver.java
===================================================================
--- src/com/iver/cit/gvsig/fmap/drivers/shp/IndexedShpDriver.java	(revision 31709)
+++ src/com/iver/cit/gvsig/fmap/drivers/shp/IndexedShpDriver.java	(working copy)
@@ -71,6 +71,7 @@
 import com.iver.cit.gvsig.fmap.core.IGeometry;
 import com.iver.cit.gvsig.fmap.core.ShapeFactory;
 import com.iver.cit.gvsig.fmap.core.ShapeMFactory;
+import com.iver.cit.gvsig.fmap.core.ShapeZMFactory;
 import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
 import com.iver.cit.gvsig.fmap.drivers.DriverAttributes;
 import com.iver.cit.gvsig.fmap.drivers.ExternalData;
@@ -355,19 +356,32 @@
 						elShape.lineTo(p.x, p.y);
 					}
 				}
-
+				// read zRange
 				double[] boxZ = new double[2];
 				boxZ[0] = bb.getDouble();
 				boxZ[1] = bb.getDouble();
-
+				
+				// read zArray
 				double[] pZ = new double[numPoints];
-
 				for (i = 0; i < numPoints; i++) {
 					pZ[i] = bb.getDouble();
 				}
-
-				return ShapeFactory.createPolyline3D(elShape, pZ);
-
+				//return ShapeFactory.createPolyline3D(elShape, pZ);
+				//------------ Piece modified -----------------
+				// read mRange
+				double[] boxM1 = new double[2];
+				boxM1[0] = bb.getDouble();//min
+				boxM1[1] = bb.getDouble();//max
+				
+				// read mArray
+				double[] pM1 = new double[numPoints];
+				for (i = 0; i < numPoints; i++) {
+					// m is optional. If "no data" --> (z < -10^-38)
+					pM1[i] = bb.getDouble();
+					//System.out.println("m: " + pM1[i]);
+				}
+				return ShapeZMFactory.createPolyline3DM(elShape, pZ, pM1);
+				//-------------------------------------
 			case (SHP.POLYLINEM):
 				bb.position(bb.position() + 32);
 				numParts = bb.getInt();
