Exemplo n.º 1
0
        /// <summary>
        /// Reads and parses the geometry with ID 'oid' from the ShapeFile
        /// </summary>
        /// <remarks><see cref="FilterDelegate">Filtering</see> is not applied to this method</remarks>
        /// <param name="oid">Object ID</param>
        /// <returns>geometry</returns>
        private unsafe IGeometry ReadGeometry(int oid)
        {
            if (_ShapeType == ShapeType.Polygon || _ShapeType == ShapeType.PolygonM || _ShapeType == ShapeType.PolygonZ)
            {
                return(ReadPolygon(oid));
            }

            var dataPtr = zeroPtr + recordHeaders[oid].Offset + 8;
            var type    = *((ShapeType *)dataPtr);

            if (type == ShapeType.Null)
            {
                return(null);
            }

            dataPtr += 4;

            if (IsPoint)
            {
                var x = *((double *)dataPtr); dataPtr += 8;
                var y = *((double *)dataPtr);

                return(GeometryFactory.CreatePoint(x, y));
            }

            if (_ShapeType == ShapeType.Multipoint || _ShapeType == ShapeType.MultiPointM || _ShapeType == ShapeType.MultiPointZ)
            {
                dataPtr += 32; // min/max box

                var points  = new List <IPoint>();
                var nPoints = *(int *)dataPtr; // get the number of points
                dataPtr += 4;

                if (nPoints == 0)
                {
                    return(null);
                }

                for (var i = 0; i < nPoints; i++)
                {
                    var x = *((double *)dataPtr); dataPtr += 8;
                    var y = *((double *)dataPtr); dataPtr += 8;

                    points.Add(GeometryFactory.CreatePoint(x, y));
                }


                return(GeometryFactory.CreateMultiPoint(points.ToArray()));
            }

            if (_ShapeType == ShapeType.PolyLine || _ShapeType == ShapeType.Polygon ||
                _ShapeType == ShapeType.PolyLineM || _ShapeType == ShapeType.PolygonM ||
                _ShapeType == ShapeType.PolyLineZ || _ShapeType == ShapeType.PolygonZ)
            {
                dataPtr += 32;                // min/max

                int nParts = *(int *)dataPtr; // get number of parts (segments)
                dataPtr += 4;

                if (nParts == 0)
                {
                    return(null);
                }

                int nPoints = *((int *)dataPtr); // get number of points
                dataPtr += 4;

                var segments = new int[nParts + 1];

                //Read in the segment indexes
                for (int b = 0; b < nParts; b++)
                {
                    segments[b] = *((int *)dataPtr);
                    dataPtr    += 4;
                }

                //add end point
                segments[nParts] = nPoints;

                if ((int)_ShapeType % 10 == 3)
                {
                    var mline = new List <ILineString>();
                    for (var lineId = 0; lineId < nParts; lineId++)
                    {
                        var line = new List <Coordinate>();
                        for (var i = segments[lineId]; i < segments[lineId + 1]; i++)
                        {
                            var x = *((double *)dataPtr); dataPtr += 8;
                            var y = *((double *)dataPtr); dataPtr += 8;
                            line.Add(GeometryFactoryEx.CreateCoordinate(x, y));
                        }

                        //line.Vertices.Add(new SharpMap.Geometries.Point(
                        mline.Add(GeometryFactory.CreateLineString(line.ToArray()));
                    }

                    if (mline.Count == 1)
                    {
                        return(mline[0]);
                    }

                    return(GeometryFactory.CreateMultiLineString(mline.ToArray()));
                }

                // TODO: check it!
                //(_ShapeType == ShapeType.Polygon etc...)
                {
                    //First read all the rings
                    //List<SharpMap.Geometries.LinearRing> rings = new List<SharpMap.Geometries.LinearRing>();
                    var rings = new List <ILinearRing>();
                    for (int RingID = 0; RingID < nParts; RingID++)
                    {
                        //SharpMap.Geometries.LinearRing ring = new SharpMap.Geometries.LinearRing();
                        var ring = new List <Coordinate>();
                        for (int i = segments[RingID]; i < segments[RingID + 1]; i++)
                        {
                            ring.Add(GeometryFactoryEx.CreateCoordinate(brShapeFile.ReadDouble(), brShapeFile.ReadDouble()));
                        }

                        // polygon should be closed, try to fix
                        if (!ring[ring.Count - 1].Equals2D(ring[0]))
                        {
                            ring.Add(GeometryFactoryEx.CreateCoordinate(ring[0].X, ring[0].Y));
                        }

                        //ring.Vertices.Add(new SharpMap.Geometries.Point
                        rings.Add(GeometryFactory.CreateLinearRing(ring.ToArray()));
                    }
                    var IsCounterClockWise = new bool[rings.Count];
                    int PolygonCount       = 0;
                    for (int i = 0; i < rings.Count; i++)
                    {
                        IsCounterClockWise[i] = GeometryFactory.IsCCW(rings[i].Coordinates);
                        if (!IsCounterClockWise[i])
                        {
                            PolygonCount++;
                        }
                    }
                    if (PolygonCount == 1) //We only have one polygon
                    {
                        ILinearRing shell = rings[0];
                        var         holes = new List <ILinearRing>();
                        if (rings.Count > 1)
                        {
                            for (int i = 1; i < rings.Count; i++)
                            {
                                holes.Add(rings[i]);
                            }
                        }
                        return(GeometryFactory.CreatePolygon(shell, holes.ToArray()));
                    }
                    else
                    {
                        var         polys = new List <IPolygon>();
                        ILinearRing shell = rings[0];
                        var         holes = new List <ILinearRing>();
                        for (int i = 1; i < rings.Count; i++)
                        {
                            if (!IsCounterClockWise[i])
                            {
                                polys.Add(GeometryFactory.CreatePolygon(shell, null));
                                shell = rings[i];
                            }
                            else
                            {
                                holes.Add(rings[i]);
                            }
                        }
                        polys.Add(GeometryFactory.CreatePolygon(shell, holes.ToArray()));
                        return(GeometryFactory.CreateMultiPolygon(polys.ToArray()));
                    }
                }
            }
            else
            {
                throw (new ApplicationException("Shapefile type " + _ShapeType.ToString() + " not supported"));
            }
        }