Example #1
0
        /// <summary>
        /// Initializes a new instance of the ShapefileHeader class with values read in from the stream.
        /// </summary>
        /// <remarks>Reads the header information from the stream.</remarks>
        /// <param name="shpBinaryReader">BigEndianBinaryReader stream to the shapefile.</param>
        public ShapefileHeader(BigEndianBinaryReader shpBinaryReader)
        {
            if (shpBinaryReader == null)
                throw new ArgumentNullException("shpBinaryReader");

            _fileCode = shpBinaryReader.ReadInt32BE();
            if (_fileCode != Shapefile.ShapefileId)
                throw new ShapefileException("The first four bytes of this file indicate this is not a shape file.");

            // skip 5 unsed bytes
            shpBinaryReader.ReadInt32BE();
            shpBinaryReader.ReadInt32BE();
            shpBinaryReader.ReadInt32BE();
            shpBinaryReader.ReadInt32BE();
            shpBinaryReader.ReadInt32BE();

            _fileLength = shpBinaryReader.ReadInt32BE();

            _version = shpBinaryReader.ReadInt32();
            Debug.Assert(_version == 1000, "Shapefile version", String.Format("Expecting only one version (1000), but got {0}",_version));
            int shapeType = shpBinaryReader.ReadInt32();
            _shapeType = (ShapeGeometryTypes) Enum.Parse(typeof(ShapeGeometryTypes), shapeType.ToString());

            //read in and store the bounding box
            double[] coords = new double[4];
            for (int i = 0; i < 4; i++)
                coords[i] = shpBinaryReader.ReadDouble();
            _bounds = new Envelope(coords[0], coords[2], coords[1], coords[3]);

            // skip z and m bounding boxes.
            for (int i = 0; i < 4; i++)
                shpBinaryReader.ReadDouble();
        }
Example #2
0
        /// <summary>
        /// Initializes a new instance of the ShapefileHeader class with values read in from the stream.
        /// </summary>
        /// <remarks>Reads the header information from the stream.</remarks>
        /// <param name="shpBinaryReader">BigEndianBinaryReader stream to the shapefile.</param>
        public ShapefileHeader(BigEndianBinaryReader shpBinaryReader)
        {
            if (shpBinaryReader == null)
            {
                throw new ArgumentNullException("shpBinaryReader");
            }

            _fileCode = shpBinaryReader.ReadInt32BE();
            if (_fileCode != Shapefile.ShapefileId)
            {
                throw new ShapefileException("The first four bytes of this file indicate this is not a shape file.");
            }

            // skip 5 unsed bytes
            shpBinaryReader.ReadInt32BE();
            shpBinaryReader.ReadInt32BE();
            shpBinaryReader.ReadInt32BE();
            shpBinaryReader.ReadInt32BE();
            shpBinaryReader.ReadInt32BE();

            _fileLength = shpBinaryReader.ReadInt32BE();

            _version = shpBinaryReader.ReadInt32();
            Debug.Assert(_version == 1000, "Shapefile version", String.Format("Expecting only one version (1000), but got {0}", _version));
            int shapeType = shpBinaryReader.ReadInt32();

            _shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeType.ToString());

            //read in and store the bounding box
            double[] coords = new double[4];
            for (int i = 0; i < 4; i++)
            {
                coords[i] = shpBinaryReader.ReadDouble();
            }
            _bounds = new Envelope(coords[0], coords[2], coords[1], coords[3]);

            // skip z and m bounding boxes.
            for (int i = 0; i < 4; i++)
            {
                shpBinaryReader.ReadDouble();
            }
        }
Example #3
0
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivant geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="geometryFactory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
        {
            int shapeTypeNum = file.ReadInt32();
            ShapeGeometryTypes shapeType = (ShapeGeometryTypes) Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString());
            if (shapeType == ShapeGeometryTypes.NullShape)
                return null;

            if ( ! ( shapeType == ShapeGeometryTypes.MultiPoint  || shapeType == ShapeGeometryTypes.MultiPointM ||
                     shapeType == ShapeGeometryTypes.MultiPointZ || shapeType == ShapeGeometryTypes.MultiPointZM))
                throw new ShapefileException("Attempting to load a non-multipoint as multipoint.");

            // Read and for now ignore bounds.
            double[] box = new double[4];
            for (int i = 0; i < 4; i++)
                box[i] = file.ReadDouble();

            // Read points
            int numPoints = file.ReadInt32();
            IPoint[] points = new IPoint[numPoints];
            for (int i = 0; i < numPoints; i++)
                points[i] = geometryFactory.CreatePoint(new Coordinate(file.ReadDouble(), file.ReadDouble()));
            return geometryFactory.CreateMultiPoint(points);
        }
Example #4
0
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="geometryFactory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
        {
            int shapeTypeNum = file.ReadInt32();
            ShapeGeometryTypes shapeType = (ShapeGeometryTypes) Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString());
            if (shapeType == ShapeGeometryTypes.NullShape)
                return null;

            if ( ! ( shapeType == ShapeGeometryTypes.Point  || shapeType == ShapeGeometryTypes.PointM   ||
                     shapeType == ShapeGeometryTypes.PointZ || shapeType == ShapeGeometryTypes.PointZM  ))
                throw new ShapefileException("Attempting to load a point as point.");
            double x= file.ReadDouble();
            double y= file.ReadDouble();
            ICoordinate external = new Coordinate(x,y);
            geometryFactory.PrecisionModel.MakePrecise( external);
            return geometryFactory.CreatePoint(external);
        }
Example #5
0
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="geometryFactory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
        {
            int shapeTypeNum             = file.ReadInt32();
            ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString());

            if (shapeType == ShapeGeometryTypes.NullShape)
            {
                return(null);
            }

            if (!(shapeType == ShapeGeometryTypes.Point || shapeType == ShapeGeometryTypes.PointM ||
                  shapeType == ShapeGeometryTypes.PointZ || shapeType == ShapeGeometryTypes.PointZM))
            {
                throw new ShapefileException("Attempting to load a point as point.");
            }
            double      x        = file.ReadDouble();
            double      y        = file.ReadDouble();
            ICoordinate external = new Coordinate(x, y);

            geometryFactory.PrecisionModel.MakePrecise(external);
            return(geometryFactory.CreatePoint(external));
        }
Example #6
0
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="geometryFactory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
        {
            int shapeTypeNum = file.ReadInt32();
            ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString());

            if (shapeType == ShapeGeometryTypes.NullShape)
                return null;

            if( ! ( shapeType == ShapeGeometryTypes.LineString  || shapeType == ShapeGeometryTypes.LineStringM   ||
                    shapeType == ShapeGeometryTypes.LineStringZ || shapeType == ShapeGeometryTypes.LineStringZM  ))
                throw new ShapefileException("Attempting to load a non-arc as arc.");

            //read and for now ignore bounds.
            double[] box = new double[4];
            for (int i = 0; i < 4; i++)
            {
                double d= file.ReadDouble();
                box[i] =d;
            }

            int numParts = file.ReadInt32();
            int numPoints = file.ReadInt32();
            int[] partOffsets = new int[numParts];
            for (int i = 0; i < numParts; i++)
                partOffsets[i] = file.ReadInt32();

            ILineString[] lines = new ILineString[numParts];
            int start, finish, length;
            for (int part = 0; part < numParts; part++)
            {
                start = partOffsets[part];
                if (part == numParts - 1)
                     finish = numPoints;
                else finish = partOffsets[part + 1];
                length = finish - start;
                CoordinateList points = new CoordinateList();
                points.Capacity=length;
                ICoordinate external;
                for (int i = 0; i < length; i++)
                {
                    external = new Coordinate(file.ReadDouble(),file.ReadDouble());
                    geometryFactory.PrecisionModel.MakePrecise( external);
                    points.Add(external);
                }
                if (numPoints < 2)
                    lines[part] = geometryFactory.CreateLineString(null as Topology.Geometries.ICoordinate[]);
                else
                    lines[part] = geometryFactory.CreateLineString(points.ToArray());
            }

            //If we have Z-coordinates, read them..
            if (shapeType == ShapeGeometryTypes.LineStringZ || shapeType == ShapeGeometryTypes.LineStringZM)
            {
                //z-Bounds
                double zMin = file.ReadDouble();
                double zMax = file.ReadDouble();
                for (int part = 0; part < numParts; part++)
                {
                    start = partOffsets[part];
                    if (part == numParts - 1)
                        finish = numPoints;
                    else finish = partOffsets[part + 1];
                    length = finish - start;
                    for (int i = 0; i < length; i++)
                    {
                        double val = file.ReadDouble();
                        if (numPoints > 1)
                        {

                            lines[part].Coordinates[i].Z = val;
                        }
                    }

                }
            }

            //If we have M-coordinates, read them..
            if (shapeType == ShapeGeometryTypes.LineStringM || shapeType == ShapeGeometryTypes.LineStringZM)
            {
                //m-Bounds
                double mMin = file.ReadDouble();
                double mMax = file.ReadDouble();
                for (int part = 0; part < numParts; part++)
                {
                    start = partOffsets[part];
                    if (part == numParts - 1)
                        finish = numPoints;
                    else finish = partOffsets[part + 1];
                    length = finish - start;
                    for (int i = 0; i < length; i++)
                    {
                        double val = file.ReadDouble();
                        //dont store..
                    }

                }
            }

            return geometryFactory.CreateMultiLineString(lines);
        }
Example #7
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="beReader"></param>
 private void ReadFeatureHeader(BigEndianBinaryReader beReader)
 {
     int recordNumber = beReader.ReadInt32BE();
     int contentLength = beReader.ReadInt32BE();
     int shapeType = beReader.ReadInt32();
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="beReader"></param>
 private void ReadFeatureHeader(BigEndianBinaryReader beReader)
 {
     int recordNumber  = beReader.ReadInt32BE();
     int contentLength = beReader.ReadInt32BE();
     int shapeType     = beReader.ReadInt32();
 }
Example #9
0
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="geometryFactory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
        {
            int shapeTypeNum             = file.ReadInt32();
            ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString());

            if (shapeType == ShapeGeometryTypes.NullShape)
            {
                return(null);
            }

            if (!(shapeType == ShapeGeometryTypes.LineString || shapeType == ShapeGeometryTypes.LineStringM ||
                  shapeType == ShapeGeometryTypes.LineStringZ || shapeType == ShapeGeometryTypes.LineStringZM))
            {
                throw new ShapefileException("Attempting to load a non-arc as arc.");
            }

            //read and for now ignore bounds.
            double[] box = new double[4];
            for (int i = 0; i < 4; i++)
            {
                double d = file.ReadDouble();
                box[i] = d;
            }

            int numParts  = file.ReadInt32();
            int numPoints = file.ReadInt32();

            int[] partOffsets = new int[numParts];
            for (int i = 0; i < numParts; i++)
            {
                partOffsets[i] = file.ReadInt32();
            }

            ILineString[] lines = new ILineString[numParts];
            int           start, finish, length;

            for (int part = 0; part < numParts; part++)
            {
                start = partOffsets[part];
                if (part == numParts - 1)
                {
                    finish = numPoints;
                }
                else
                {
                    finish = partOffsets[part + 1];
                }
                length = finish - start;
                CoordinateList points = new CoordinateList();
                points.Capacity = length;
                ICoordinate external;
                for (int i = 0; i < length; i++)
                {
                    external = new Coordinate(file.ReadDouble(), file.ReadDouble());
                    geometryFactory.PrecisionModel.MakePrecise(external);
                    points.Add(external);
                }
                if (numPoints < 2)
                {
                    lines[part] = geometryFactory.CreateLineString(null as Topology.Geometries.ICoordinate[]);
                }
                else
                {
                    lines[part] = geometryFactory.CreateLineString(points.ToArray());
                }
            }

            //If we have Z-coordinates, read them..
            if (shapeType == ShapeGeometryTypes.LineStringZ || shapeType == ShapeGeometryTypes.LineStringZM)
            {
                //z-Bounds
                double zMin = file.ReadDouble();
                double zMax = file.ReadDouble();
                for (int part = 0; part < numParts; part++)
                {
                    start = partOffsets[part];
                    if (part == numParts - 1)
                    {
                        finish = numPoints;
                    }
                    else
                    {
                        finish = partOffsets[part + 1];
                    }
                    length = finish - start;
                    for (int i = 0; i < length; i++)
                    {
                        double val = file.ReadDouble();
                        if (numPoints > 1)
                        {
                            lines[part].Coordinates[i].Z = val;
                        }
                    }
                }
            }

            //If we have M-coordinates, read them..
            if (shapeType == ShapeGeometryTypes.LineStringM || shapeType == ShapeGeometryTypes.LineStringZM)
            {
                //m-Bounds
                double mMin = file.ReadDouble();
                double mMax = file.ReadDouble();
                for (int part = 0; part < numParts; part++)
                {
                    start = partOffsets[part];
                    if (part == numParts - 1)
                    {
                        finish = numPoints;
                    }
                    else
                    {
                        finish = partOffsets[part + 1];
                    }
                    length = finish - start;
                    for (int i = 0; i < length; i++)
                    {
                        double val = file.ReadDouble();
                        //dont store..
                    }
                }
            }

            return(geometryFactory.CreateMultiLineString(lines));
        }
Example #10
0
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="geometryFactory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
        {
            int shapeTypeNum = file.ReadInt32();
            ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString());
            if (shapeType == ShapeGeometryTypes.NullShape)
                return null;

            if ( ! ( shapeType == ShapeGeometryTypes.Polygon  || shapeType == ShapeGeometryTypes.PolygonM ||
                     shapeType == ShapeGeometryTypes.PolygonZ || shapeType == ShapeGeometryTypes.PolygonZM))
                throw new ShapefileException("Attempting to load a non-polygon as polygon.");

            // Read and for now ignore bounds.
            double[] box = new double[4];
            for (int i = 0; i < 4; i++)
                box[i] = file.ReadDouble();

            int[] partOffsets;
            int numParts = file.ReadInt32();
            int numPoints = file.ReadInt32();
            partOffsets = new int[numParts];
            for (int i = 0; i < numParts; i++)
                partOffsets[i] = file.ReadInt32();

            ArrayList shells = new ArrayList();
            ArrayList holes = new ArrayList();

            int start, finish, length;
            for (int part = 0; part < numParts; part++)
            {
                start = partOffsets[part];
                if (part == numParts - 1)
                     finish = numPoints;
                else finish = partOffsets[part + 1];
                length = finish - start;
                CoordinateList points = new CoordinateList();
                points.Capacity = length;
                for (int i = 0; i < length; i++)
                {
                    ICoordinate external = new Coordinate(file.ReadDouble(), file.ReadDouble() );
                    geometryFactory.PrecisionModel.MakePrecise( external);
                    ICoordinate internalCoord = external;

                    // Thanks to Abhay Menon!
                    if (!Double.IsNaN(internalCoord.Y) && !Double.IsNaN(internalCoord.X))
                       points.Add(internalCoord);
             				}

                if (points.Count > 0) // Thanks to Abhay Menon!
                {
                    ILinearRing ring = geometryFactory.CreateLinearRing(points.ToArray());

                    // If shape have only a part, jump orientation check and add to shells
                    if (numParts == 1)
                        shells.Add(ring);
                    else
                    {
                        // Orientation check
                        if (CGAlgorithms.IsCCW(points.ToArray()))
                             holes.Add(ring);
                        else shells.Add(ring);
                    }
                }
            }

            // Now we have a list of all shells and all holes
            ArrayList holesForShells = new ArrayList(shells.Count);
            for (int i = 0; i < shells.Count; i++)
                holesForShells.Add(new ArrayList());
            // Find holes
            for (int i = 0; i < holes.Count; i++)
            {
                ILinearRing testRing = (ILinearRing) holes[i];
                ILinearRing minShell = null;
                IEnvelope minEnv = null;
                IEnvelope testEnv = testRing.EnvelopeInternal;
                ICoordinate testPt = testRing.GetCoordinateN(0);
                ILinearRing tryRing;
                for (int j = 0; j < shells.Count; j++)
                {
                    tryRing = (ILinearRing) shells[j];
                    IEnvelope tryEnv = tryRing.EnvelopeInternal;
                    if (minShell != null)
                        minEnv = minShell.EnvelopeInternal;
                    bool isContained = false;
                    CoordinateList coordList = new CoordinateList(tryRing.Coordinates);
                    if (tryEnv.Contains(testEnv)
                        && (CGAlgorithms.IsPointInRing(testPt, coordList.ToArray())
                        || (PointInList(testPt, coordList))))
                        isContained = true;

                    // Check if this new containing ring is smaller than the current minimum ring
                    if (isContained)
                    {
                        if (minShell == null || minEnv.Contains(tryEnv))
                            minShell = tryRing;

                        // Suggested by Brian Macomber and added 3/28/2006:
                        // holes were being found but never added to the holesForShells array
                        // so when converted to geometry by the factory, the inner rings were never created.
                        ArrayList holesForThisShell = (ArrayList) holesForShells[j];
                        holesForThisShell.Add(testRing);
                    }
                }
            }

            //If we have Z-coordinates, read them..
            if (shapeType == ShapeGeometryTypes.PolygonZ || shapeType == ShapeGeometryTypes.PolygonZM)
            {
                //z-Bounds
                double zMin = file.ReadDouble();
                double zMax = file.ReadDouble();
                for (int part = 0; part < numParts; part++)
                {
                    start = partOffsets[part];
                    if (part == numParts - 1)
                        finish = numPoints;
                    else finish = partOffsets[part + 1];
                    length = finish - start;
                    for (int i = 0; i < length; i++)
                    {
                        double val = file.ReadDouble();
                        //lines[part].Coordinates[i].Z = val;
                    }

                }
            }

            //If we have M-coordinates, read them..
            if (shapeType == ShapeGeometryTypes.PolygonM || shapeType == ShapeGeometryTypes.PolygonZM)
            {
                //m-Bounds
                double mMin = file.ReadDouble();
                double mMax = file.ReadDouble();
                for (int part = 0; part < numParts; part++)
                {
                    start = partOffsets[part];
                    if (part == numParts - 1)
                        finish = numPoints;
                    else finish = partOffsets[part + 1];
                    length = finish - start;
                    for (int i = 0; i < length; i++)
                    {
                        double val = file.ReadDouble();
                        //dont store..
                    }

                }
            }

            IPolygon[] polygons = new IPolygon[shells.Count];
            for (int i = 0; i < shells.Count; i++)
                polygons[i] = (geometryFactory.CreatePolygon((ILinearRing) shells[i],
                    (ILinearRing[]) ((ArrayList)holesForShells[i]).ToArray(typeof(ILinearRing))));

            if (polygons.Length == 1)
                return polygons[0];
            // It's a multi part
            return geometryFactory.CreateMultiPolygon(polygons);
        }
Example #11
0
        /// <summary>
        /// Reads a stream and converts the shapefile record to an equilivent geometry object.
        /// </summary>
        /// <param name="file">The stream to read.</param>
        /// <param name="geometryFactory">The geometry factory to use when making the object.</param>
        /// <returns>The Geometry object that represents the shape file record.</returns>
        public override IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory)
        {
            int shapeTypeNum             = file.ReadInt32();
            ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString());

            if (shapeType == ShapeGeometryTypes.NullShape)
            {
                return(null);
            }

            if (!(shapeType == ShapeGeometryTypes.Polygon || shapeType == ShapeGeometryTypes.PolygonM ||
                  shapeType == ShapeGeometryTypes.PolygonZ || shapeType == ShapeGeometryTypes.PolygonZM))
            {
                throw new ShapefileException("Attempting to load a non-polygon as polygon.");
            }

            // Read and for now ignore bounds.
            double[] box = new double[4];
            for (int i = 0; i < 4; i++)
            {
                box[i] = file.ReadDouble();
            }

            int[] partOffsets;
            int   numParts  = file.ReadInt32();
            int   numPoints = file.ReadInt32();

            partOffsets = new int[numParts];
            for (int i = 0; i < numParts; i++)
            {
                partOffsets[i] = file.ReadInt32();
            }

            ArrayList shells = new ArrayList();
            ArrayList holes  = new ArrayList();

            int start, finish, length;

            for (int part = 0; part < numParts; part++)
            {
                start = partOffsets[part];
                if (part == numParts - 1)
                {
                    finish = numPoints;
                }
                else
                {
                    finish = partOffsets[part + 1];
                }
                length = finish - start;
                CoordinateList points = new CoordinateList();
                points.Capacity = length;
                for (int i = 0; i < length; i++)
                {
                    ICoordinate external = new Coordinate(file.ReadDouble(), file.ReadDouble());
                    geometryFactory.PrecisionModel.MakePrecise(external);
                    ICoordinate internalCoord = external;

                    // Thanks to Abhay Menon!
                    if (!Double.IsNaN(internalCoord.Y) && !Double.IsNaN(internalCoord.X))
                    {
                        points.Add(internalCoord);
                    }
                }

                if (points.Count > 0) // Thanks to Abhay Menon!
                {
                    ILinearRing ring = geometryFactory.CreateLinearRing(points.ToArray());

                    // If shape have only a part, jump orientation check and add to shells
                    if (numParts == 1)
                    {
                        shells.Add(ring);
                    }
                    else
                    {
                        // Orientation check
                        if (CGAlgorithms.IsCCW(points.ToArray()))
                        {
                            holes.Add(ring);
                        }
                        else
                        {
                            shells.Add(ring);
                        }
                    }
                }
            }

            // Now we have a list of all shells and all holes
            ArrayList holesForShells = new ArrayList(shells.Count);

            for (int i = 0; i < shells.Count; i++)
            {
                holesForShells.Add(new ArrayList());
            }
            // Find holes
            for (int i = 0; i < holes.Count; i++)
            {
                ILinearRing testRing = (ILinearRing)holes[i];
                ILinearRing minShell = null;
                IEnvelope   minEnv   = null;
                IEnvelope   testEnv  = testRing.EnvelopeInternal;
                ICoordinate testPt   = testRing.GetCoordinateN(0);
                ILinearRing tryRing;
                for (int j = 0; j < shells.Count; j++)
                {
                    tryRing = (ILinearRing)shells[j];
                    IEnvelope tryEnv = tryRing.EnvelopeInternal;
                    if (minShell != null)
                    {
                        minEnv = minShell.EnvelopeInternal;
                    }
                    bool           isContained = false;
                    CoordinateList coordList   = new CoordinateList(tryRing.Coordinates);
                    if (tryEnv.Contains(testEnv) &&
                        (CGAlgorithms.IsPointInRing(testPt, coordList.ToArray()) ||
                         (PointInList(testPt, coordList))))
                    {
                        isContained = true;
                    }

                    // Check if this new containing ring is smaller than the current minimum ring
                    if (isContained)
                    {
                        if (minShell == null || minEnv.Contains(tryEnv))
                        {
                            minShell = tryRing;
                        }

                        // Suggested by Brian Macomber and added 3/28/2006:
                        // holes were being found but never added to the holesForShells array
                        // so when converted to geometry by the factory, the inner rings were never created.
                        ArrayList holesForThisShell = (ArrayList)holesForShells[j];
                        holesForThisShell.Add(testRing);
                    }
                }
            }

            //If we have Z-coordinates, read them..
            if (shapeType == ShapeGeometryTypes.PolygonZ || shapeType == ShapeGeometryTypes.PolygonZM)
            {
                //z-Bounds
                double zMin = file.ReadDouble();
                double zMax = file.ReadDouble();
                for (int part = 0; part < numParts; part++)
                {
                    start = partOffsets[part];
                    if (part == numParts - 1)
                    {
                        finish = numPoints;
                    }
                    else
                    {
                        finish = partOffsets[part + 1];
                    }
                    length = finish - start;
                    for (int i = 0; i < length; i++)
                    {
                        double val = file.ReadDouble();
                        //lines[part].Coordinates[i].Z = val;
                    }
                }
            }

            //If we have M-coordinates, read them..
            if (shapeType == ShapeGeometryTypes.PolygonM || shapeType == ShapeGeometryTypes.PolygonZM)
            {
                //m-Bounds
                double mMin = file.ReadDouble();
                double mMax = file.ReadDouble();
                for (int part = 0; part < numParts; part++)
                {
                    start = partOffsets[part];
                    if (part == numParts - 1)
                    {
                        finish = numPoints;
                    }
                    else
                    {
                        finish = partOffsets[part + 1];
                    }
                    length = finish - start;
                    for (int i = 0; i < length; i++)
                    {
                        double val = file.ReadDouble();
                        //dont store..
                    }
                }
            }



            IPolygon[] polygons = new IPolygon[shells.Count];
            for (int i = 0; i < shells.Count; i++)
            {
                polygons[i] = (geometryFactory.CreatePolygon((ILinearRing)shells[i],
                                                             (ILinearRing[])((ArrayList)holesForShells[i]).ToArray(typeof(ILinearRing))));
            }

            if (polygons.Length == 1)
            {
                return(polygons[0]);
            }
            // It's a multi part
            return(geometryFactory.CreateMultiPolygon(polygons));
        }