Exemple #1
0
        public static Mesh Compute(RectangleD rectangle, int numberOfPartitionsX, int numberOfPartitionsY)
        {
            if (numberOfPartitionsX < 0)
            {
                throw new ArgumentOutOfRangeException("numberOfPartitionsX");
            }

            if (numberOfPartitionsY < 0)
            {
                throw new ArgumentOutOfRangeException("numberOfPartitionsY");
            }

            Mesh mesh = new Mesh();

            mesh.PrimitiveType         = PrimitiveType.Triangles;
            mesh.FrontFaceWindingOrder = WindingOrder.Counterclockwise;

            int numberOfPositions = (numberOfPartitionsX + 1) * (numberOfPartitionsY + 1);
            VertexAttributeFloatVector2 positionsAttribute = new VertexAttributeFloatVector2("position", numberOfPositions);
            IList <Vector2F>            positions          = positionsAttribute.Values;

            mesh.Attributes.Add(positionsAttribute);

            int numberOfIndices        = (numberOfPartitionsX * numberOfPartitionsY) * 6;
            IndicesUnsignedInt indices = new IndicesUnsignedInt(numberOfIndices);

            mesh.Indices = indices;

            //
            // Positions
            //
            Vector2D lowerLeft    = rectangle.LowerLeft;
            Vector2D toUpperRight = rectangle.UpperRight - lowerLeft;

            for (int y = 0; y <= numberOfPartitionsY; ++y)
            {
                double deltaY   = y / (double)numberOfPartitionsY;
                double currentY = lowerLeft.Y + (deltaY * toUpperRight.Y);

                for (int x = 0; x <= numberOfPartitionsX; ++x)
                {
                    double deltaX   = x / (double)numberOfPartitionsX;
                    double currentX = lowerLeft.X + (deltaX * toUpperRight.X);
                    positions.Add(new Vector2D(currentX, currentY).ToVector2F());
                }
            }

            //
            // Indices
            //
            int rowDelta = numberOfPartitionsX + 1;
            int i        = 0;

            for (int y = 0; y < numberOfPartitionsY; ++y)
            {
                for (int x = 0; x < numberOfPartitionsX; ++x)
                {
                    indices.AddTriangle(new TriangleIndicesUnsignedInt(i, i + 1, rowDelta + (i + 1)));
                    indices.AddTriangle(new TriangleIndicesUnsignedInt(i, rowDelta + (i + 1), rowDelta + i));
                    i += 1;
                }
                i += 1;
            }

            return(mesh);
        }
Exemple #2
0
        public Shapefile(string filename)
        {
            //
            // ESRI Shapefile Technical Description:
            //    http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf
            //
            using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                //
                // File Header:
                //
                // Position  Field         Value        Type     Byte Order
                // --------  -----         -----        ----     ----------
                // Byte 0    File Code     9994         Integer  Big
                // Byte 4    Unused        0            Integer  Big
                // Byte 8    Unused        0            Integer  Big
                // Byte 12   Unused        0            Integer  Big
                // Byte 16   Unused        0            Integer  Big
                // Byte 20   Unused        0            Integer  Big
                // Byte 24   File Length   File Length  Integer  Big
                // Byte 28   Version       1000         Integer  Little
                // Byte 32   Shape Type    Shape Type   Integer  Little
                // Byte 36   Bounding Box  Xmin         Double   Little
                // Byte 44   Bounding Box  Ymin         Double   Little
                // Byte 52   Bounding Box  Xmax         Double   Little
                // Byte 60   Bounding Box  Ymax         Double   Little
                // Byte 68*  Bounding Box  Zmin         Double   Little
                // Byte 76*  Bounding Box  Zmax         Double   Little
                // Byte 84*  Bounding Box  Mmin         Double   Little
                // Byte 92*  Bounding Box  Mmax         Double   Little
                //
                // * Unused, with value 0.0, if not Measured or Z type
                //
                byte[] fileHeader = Read(fs, _fileHeaderLength);
                if (fileHeader == null)
                {
                    throw new InvalidDataException("Could not read shapefile header.");
                }

                int fileCode = ToInteger(fileHeader, 0, ByteOrder.BigEndian);
                if (fileCode != _fileCode)
                {
                    //
                    // Swap byte order and try again.
                    //
                    _byteOrder = ByteOrder.BigEndian;

                    fileCode = ToInteger(fileHeader, 0, ByteOrder.BigEndian);

                    if (fileCode != _fileCode)
                    {
                        throw new InvalidDataException("Could not read shapefile file code.  Is this a valid shapefile?");
                    }
                }

                int fileLengthInBytes = ToInteger(fileHeader, 24, ByteOrder.BigEndian) * 2;

                int version = ToInteger(fileHeader, 28, ByteOrder.LittleEndian);
                if (version != _version)
                {
                    throw new InvalidDataException("Shapefile version " + version + " is not supported.  Only version " + _version + " is supported.");
                }

                _shapeType = (ShapeType)ToInteger(fileHeader, 32, ByteOrder.LittleEndian);

                double xMin = ToDouble(fileHeader, 36, ByteOrder.LittleEndian);
                double yMin = ToDouble(fileHeader, 44, ByteOrder.LittleEndian);
                double xMax = ToDouble(fileHeader, 52, ByteOrder.LittleEndian);
                double yMax = ToDouble(fileHeader, 60, ByteOrder.LittleEndian);

                // TODO: Publicly expose these
                //double zMin = NoDataToZero(ToDouble(fileHeader, 68, ByteOrder.LittleEndian));
                //double zMax = NoDataToZero(ToDouble(fileHeader, 76, ByteOrder.LittleEndian));
                //double mMin = NoDataToZero(ToDouble(fileHeader, 84, ByteOrder.LittleEndian));
                //double mMax = NoDataToZero(ToDouble(fileHeader, 92, ByteOrder.LittleEndian));

                if (fileLengthInBytes == _fileHeaderLength)
                {
                    //
                    // If the shapefile is empty (that is, has no records),
                    // the values for xMin, yMin, xMax, and yMax are unspecified.
                    //
                    // I like zero better.
                    //
                    xMin = 0.0;
                    yMin = 0.0;
                    xMax = 0.0;
                    yMax = 0.0;
                }

                _extent = new RectangleD(new Vector2D(xMin, yMin), new Vector2D(xMax, yMax));

                //
                // Read each header...
                //

                //
                // Record Header:
                //
                // Position  Field           Value           Type     Byte Order
                // --------  -----           -----           ----     ----------
                // Byte 0    Record Number   Record Number   Integer  Big
                // Byte 4    Content Length  Content Length  Integer  Big
                //
                _shapes = new List <Shape>();
                byte[] recordHeader;

                while ((recordHeader = Read(fs, _recordHeaderLength)) != null)
                {
                    int    recordNumber         = ToInteger(recordHeader, 0, ByteOrder.BigEndian);
                    int    contextLengthInBytes = ToInteger(recordHeader, 4, ByteOrder.BigEndian) * 2;
                    byte[] record = Read(fs, contextLengthInBytes);

                    ShapeType recordShapeType = (ShapeType)ToInteger(record, 0, ByteOrder.LittleEndian);
                    switch (recordShapeType)
                    {
                    case ShapeType.NullShape:
                        //
                        // Filter out null shapes.  Otherwise, every client
                        // would have to deal with them.
                        //
                        break;

                    case ShapeType.Point:
                        _shapes.Add(new PointShape(recordNumber,
                                                   new Vector2D(
                                                       ToDouble(record, 4, ByteOrder.LittleEndian),
                                                       ToDouble(record, 12, ByteOrder.LittleEndian))));
                        break;

                    case ShapeType.Polyline:
                    case ShapeType.Polygon:
                        RectangleD extent = new RectangleD(
                            new Vector2D(
                                ToDouble(record, 4, ByteOrder.LittleEndian),
                                ToDouble(record, 12, ByteOrder.LittleEndian)),
                            new Vector2D(
                                ToDouble(record, 20, ByteOrder.LittleEndian),
                                ToDouble(record, 28, ByteOrder.LittleEndian)));
                        int numberOfParts  = ToInteger(record, 36, ByteOrder.LittleEndian);
                        int numberOfPoints = ToInteger(record, 40, ByteOrder.LittleEndian);

                        int[]      parts  = new int[numberOfParts];
                        Vector2D[] points = new Vector2D[numberOfPoints];

                        //
                        // These two loops can be optimized if the machine is little endian.
                        //
                        for (int i = 0; i < numberOfParts; ++i)
                        {
                            parts[i] = ToInteger(record, 44 + (4 * i), ByteOrder.LittleEndian);
                        }

                        int pointsOffset = 44 + (4 * numberOfParts);
                        for (int i = 0; i < numberOfPoints; ++i)
                        {
                            points[i] = new Vector2D(
                                ToDouble(record, pointsOffset + (16 * i), ByteOrder.LittleEndian),
                                ToDouble(record, pointsOffset + (16 * i) + 8, ByteOrder.LittleEndian));
                        }

                        if (recordShapeType == ShapeType.Polyline)
                        {
                            _shapes.Add(new PolylineShape(recordNumber, extent, parts, points));
                        }
                        else
                        {
                            _shapes.Add(new PolygonShape(recordNumber, extent, parts, points));
                        }

                        break;

                    default:
                        throw new NotImplementedException("The shapefile type is not supported.  Only null, point, polyline, and polygon are supported.");
                    }
                }
            }
        }