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>
        /// 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 #3
0
        /// <summary>
        /// Initializes a new instance of the Shapefile class with the given parameters.
        /// </summary>
        /// <param name="filename">The filename of the shape file to read (with .shp).</param>
        /// <param name="geometryFactory">The GeometryFactory to use when creating Geometry objects.</param>
        public ShapefileReader(string filename, IGeometryFactory geometryFactory)
        {
            if (filename == null)
                throw new ArgumentNullException("filename");
            if (geometryFactory == null)
                throw new ArgumentNullException("geometryFactory");

            _filename = filename;
            _geometryFactory = geometryFactory;

            // read header information. note, we open the file, read the header information and then
            // close the file. This means the file is not opened again until GetEnumerator() is requested.
            // For each call to GetEnumerator() a new BinaryReader is created.
            FileStream stream = new FileStream(filename, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read);
            BigEndianBinaryReader shpBinaryReader = new BigEndianBinaryReader(stream);
            _mainHeader = new ShapefileHeader(shpBinaryReader);
            shpBinaryReader.Close();
        }
        /// <summary>
        /// Reads Polygon shapefile
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        protected IList ReadPolygonData(Stream stream)
        {
            IList list = new ArrayList();

            // Jump to first header
            stream.Seek(100, SeekOrigin.Begin);

            // Read big endian informations
            using (BigEndianBinaryReader beReader = new BigEndianBinaryReader(stream))
            {
                // Read little endian informations
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    // For each header
                    while (stream.Position < stream.Length)
                    {
                        ReadFeatureHeader(beReader);
                        shapeReader.ReadBoundingBox(reader);

                        int[] indexParts = null;
                        int   numParts   = shapeReader.ReadNumParts(reader);
                        int   numPoints  = shapeReader.ReadNumPoints(reader);

                        indexParts = shapeReader.ReadIndexParts(reader, numParts);
                        ICoordinate[] coordinates = shapeReader.ReadCoordinates(reader, numPoints);

                        if (numParts == 1)
                        {
                            list.Add(shapeReader.CreateSimpleSinglePolygon(coordinates));
                        }
                        else
                        {
                            list.Add(shapeReader.CreateSingleOrMultiPolygon(numPoints, indexParts, coordinates));
                        }
                    }
                }
            }
            return(list);
        }
Example #5
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 #6
0
        /// <summary>
        /// Initializes a new instance of the Shapefile class with the given parameters.
        /// </summary>
        /// <param name="filename">The filename of the shape file to read (with .shp).</param>
        /// <param name="geometryFactory">The GeometryFactory to use when creating Geometry objects.</param>
        public ShapefileReader(string filename, IGeometryFactory geometryFactory)
        {
            if (filename == null)
            {
                throw new ArgumentNullException("filename");
            }
            if (geometryFactory == null)
            {
                throw new ArgumentNullException("geometryFactory");
            }

            _filename        = filename;
            _geometryFactory = geometryFactory;

            // read header information. note, we open the file, read the header information and then
            // close the file. This means the file is not opened again until GetEnumerator() is requested.
            // For each call to GetEnumerator() a new BinaryReader is created.
            FileStream            stream          = new FileStream(filename, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read);
            BigEndianBinaryReader shpBinaryReader = new BigEndianBinaryReader(stream);

            _mainHeader = new ShapefileHeader(shpBinaryReader);
            shpBinaryReader.Close();
        }
Example #7
0
        /// <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;
                }
            }
        }
Example #8
0
 /// <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 Polygon shapefile
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        protected IList ReadPolygonData(Stream stream)
        {
            IList list = new ArrayList();

            // Jump to first header
            stream.Seek(100, SeekOrigin.Begin);

            // Read big endian informations
            using (BigEndianBinaryReader beReader = new BigEndianBinaryReader(stream))
            {
                // Read little endian informations
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    // For each header
                    while (stream.Position < stream.Length)
                    {
                        ReadFeatureHeader(beReader);
                        shapeReader.ReadBoundingBox(reader);

                        int[] indexParts = null;
                        int numParts = shapeReader.ReadNumParts(reader);
                        int numPoints = shapeReader.ReadNumPoints(reader);

                        indexParts = shapeReader.ReadIndexParts(reader, numParts);
                        ICoordinate[] coordinates = shapeReader.ReadCoordinates(reader, numPoints);

                        if (numParts == 1)
                             list.Add(shapeReader.CreateSimpleSinglePolygon(coordinates));
                        else list.Add(shapeReader.CreateSingleOrMultiPolygon(numPoints, indexParts, coordinates));
                    }
                }
            }
            return list;
        }
Example #10
0
        /// <summary>
        /// Reads Point shapefile
        /// </summary>
        /// <param name="stream"></param>
        protected IList ReadPointData(Stream stream)
        {
            IList list = new ArrayList();

            // Jump to first header
            stream.Seek(100, SeekOrigin.Begin);

            // Read big endian informations
            using (BigEndianBinaryReader beReader = new BigEndianBinaryReader(stream))
            {
                // Read little endian informations
                using (BinaryReader leReader = new BinaryReader(stream))
                {
                    // For each header
                    while (stream.Position < stream.Length)
                    {
                        ReadFeatureHeader(beReader);

                        ICoordinate coordinate = shapeReader.ReadCoordinate(leReader);
                        IGeometry point = shapeReader.CreatePoint(coordinate);
                        list.Add(point);
                    }
                }
            }
            return list;
        }
Example #11
0
        /// <summary>
        /// Reads MultiPoint shapefile
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        protected IList ReadMultiPointData(Stream stream)
        {
            IList list = new ArrayList();

            // Jump to first header
            stream.Seek(100, SeekOrigin.Begin);

            // Read big endian informations
            using (BigEndianBinaryReader beReader = new BigEndianBinaryReader(stream))
            {
                // Read little endian informations
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    // For each header
                    while (stream.Position < stream.Length)
                    {
                        ReadFeatureHeader(beReader);
                        shapeReader.ReadBoundingBox(reader);

                        int numPoints = shapeReader.ReadNumPoints(reader);
                        ICoordinate[] coords = new ICoordinate[numPoints];
                        for (int i = 0; i < numPoints; i++)
                            coords[i] = shapeReader.ReadCoordinate(reader);
                        list.Add(shapeReader.CreateMultiPoint(coords));
                    }

                }
            }
            return list;
        }
Example #12
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 abstract IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory);
Example #13
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 #14
0
 public void Dispose()
 {
     if (_shpBinaryReader != null)
     {
         _shpBinaryReader.Close();
         _shpBinaryReader = null;
     }
 }
Example #15
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="beReader"></param>
 private void ReadFeatureHeader(BigEndianBinaryReader beReader)
 {
     int recordNumber  = beReader.ReadInt32BE();
     int contentLength = beReader.ReadInt32BE();
     int shapeType     = beReader.ReadInt32();
 }
Example #16
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 #17
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 abstract IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory);
Example #18
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 #19
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 #20
0
        /// <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);
                }
            }
        }
Example #21
0
            /// <summary>
            /// Initializes a new instance of the ShapefileEnumerator class.
            /// </summary>
            /// <param name="shapefile"></param>
            public ShapefileEnumerator(ShapefileReader shapefile)
            {
                _parent = shapefile;

                // create a file stream for each enumerator that is given out. This allows the same file
                // to have one or more enumerator. If we used the parents stream - than only one IEnumerator
                // could be given out.
                FileStream stream = new FileStream(_parent._filename, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read);
                _shpBinaryReader = new BigEndianBinaryReader(stream);

                // skip header - since parent has already read this.
                _shpBinaryReader.ReadBytes(100);
                ShapeGeometryTypes type = _parent._mainHeader.ShapeType;
                _handler = Shapefile.GetShapeHandler(type);
                if (_handler == null)
                    throw new NotSupportedException("Unsuported shape type:" + type);
            }