/// <summary>
        /// Reads a generic stream containing geographic data saved as shapefile structure,
        /// and returns a collection of all the features contained.
        /// Since NTS Geometry Model not support Z and M data, those informations are ignored if presents in shapefile.
        /// </summary>
        /// <param name="stream">Shapefile data stream.</param>
        /// <returns><c>GeometryCollection</c> containing all geometries in shapefile.</returns>
        protected IGeometryCollection Read(Stream stream)
        {
            // Read big endian values
            using (BigEndianBinaryReader beReader = new BigEndianBinaryReader(stream))
            {
                // Verify File Code
                int fileCode = beReader.ReadInt32BE();
                Debug.Assert(fileCode == 9994);

                stream.Seek(20, SeekOrigin.Current);
                length = beReader.ReadInt32BE();

                // Read little endian values
                using (BinaryReader leReader = new BinaryReader(stream))
                {
                    ArrayList list = null;

                    // Verify Version
                    int version = leReader.ReadInt32();
                    Debug.Assert(version == 1000);

                    // ShapeTypes
                    int shapeType = leReader.ReadInt32();

                    switch ((ShapeGeometryTypes)shapeType)
                    {
                    case ShapeGeometryTypes.Point:
                    case ShapeGeometryTypes.PointZ:
                    case ShapeGeometryTypes.PointM:
                    case ShapeGeometryTypes.PointZM:
                        list = new ArrayList(ReadPointData(stream));
                        break;

                    case ShapeGeometryTypes.LineString:
                    case ShapeGeometryTypes.LineStringZ:
                    case ShapeGeometryTypes.LineStringM:
                    case ShapeGeometryTypes.LineStringZM:
                        list = new ArrayList(ReadLineStringData(stream));
                        break;

                    case ShapeGeometryTypes.Polygon:
                    case ShapeGeometryTypes.PolygonZ:
                    case ShapeGeometryTypes.PolygonM:
                    case ShapeGeometryTypes.PolygonZM:
                        list = new ArrayList(ReadPolygonData(stream));
                        break;

                    case ShapeGeometryTypes.MultiPoint:
                    case ShapeGeometryTypes.MultiPointZ:
                    case ShapeGeometryTypes.MultiPointM:
                    case ShapeGeometryTypes.MultiPointZM:
                        list = new ArrayList(ReadMultiPointData(stream));
                        break;

                    case ShapeGeometryTypes.MultiPatch:
                        throw new NotImplementedException("FeatureType " + shapeType + " not supported.");

                    default:
                        throw new ArgumentOutOfRangeException("FeatureType " + shapeType + " not recognized by the system");
                    }
                    IGeometryCollection collection = shapeReader.CreateGeometryCollection(list);
                    return(collection);
                }
            }
        }