Пример #1
0
        /// calculate the surface area of a pixel given its height value, the height of the 8 neigboring pixels, and the cellsize
        /// the algorithm is based on http://www.jennessent.com/downloads/WSB_32_3_Jenness.pdf
        private static float CalculateSurfaceArea(float[] heights, float cellsize)
        {
            // values in the height array [0..8]: own height / north/east/west/south/ NE/NW/SE/SW
            // step 1: calculate length on 3d surface between all edges
            //   8(A) * 1(B) * 5(C)       <- 0: center cell, indices in the "heights" grid, A..I: codes used by Jenness
            //   4(D) * 0(E) * 2(F)
            //   7(G) * 3(H) * 6(I)

            float[] slen = new float[16]; // surface lengths (divided by 2)
                                          // horizontal
            slen[0] = RumpleIndex.SurfaceLength(heights[8], heights[1], cellsize) / 2.0F;
            slen[1] = RumpleIndex.SurfaceLength(heights[1], heights[5], cellsize) / 2.0F;
            slen[2] = RumpleIndex.SurfaceLength(heights[4], heights[0], cellsize) / 2.0F;
            slen[3] = RumpleIndex.SurfaceLength(heights[0], heights[2], cellsize) / 2.0F;
            slen[4] = RumpleIndex.SurfaceLength(heights[7], heights[3], cellsize) / 2.0F;
            slen[5] = RumpleIndex.SurfaceLength(heights[3], heights[6], cellsize) / 2.0F;
            // vertical
            slen[6]  = RumpleIndex.SurfaceLength(heights[8], heights[4], cellsize) / 2.0F;
            slen[7]  = RumpleIndex.SurfaceLength(heights[1], heights[0], cellsize) / 2.0F;
            slen[8]  = RumpleIndex.SurfaceLength(heights[5], heights[2], cellsize) / 2.0F;
            slen[9]  = RumpleIndex.SurfaceLength(heights[4], heights[7], cellsize) / 2.0F;
            slen[10] = RumpleIndex.SurfaceLength(heights[0], heights[3], cellsize) / 2.0F;
            slen[11] = RumpleIndex.SurfaceLength(heights[2], heights[6], cellsize) / 2.0F;
            // diagonal
            float cellsize_diag = Constant.Sqrt2 * cellsize;

            slen[12] = RumpleIndex.SurfaceLength(heights[0], heights[8], cellsize_diag) / 2.0F;
            slen[13] = RumpleIndex.SurfaceLength(heights[0], heights[5], cellsize_diag) / 2.0F;
            slen[14] = RumpleIndex.SurfaceLength(heights[0], heights[7], cellsize_diag) / 2.0F;
            slen[15] = RumpleIndex.SurfaceLength(heights[0], heights[6], cellsize_diag) / 2.0F;

            // step 2: combine the three sides of all the 8 sub triangles using Heron's formula
            float surface_area = 0.0F;

            surface_area += RumpleIndex.HeronTriangleArea(slen[12], slen[0], slen[7]);  // i
            surface_area += RumpleIndex.HeronTriangleArea(slen[7], slen[1], slen[13]);  // ii
            surface_area += RumpleIndex.HeronTriangleArea(slen[6], slen[2], slen[12]);  // iii
            surface_area += RumpleIndex.HeronTriangleArea(slen[13], slen[8], slen[3]);  // iv
            surface_area += RumpleIndex.HeronTriangleArea(slen[2], slen[9], slen[14]);  // v
            surface_area += RumpleIndex.HeronTriangleArea(slen[3], slen[11], slen[15]); // vi
            surface_area += RumpleIndex.HeronTriangleArea(slen[14], slen[10], slen[4]); // vii
            surface_area += RumpleIndex.HeronTriangleArea(slen[10], slen[15], slen[5]); // viii

            return(surface_area);
        }
Пример #2
0
        public void Calculate(Model model)
        {
            if (this.mRumpleGrid.IsNotSetup())
            {
                this.Setup(model);
            }

            this.mRumpleGrid.Fill(0.0F);
            Grid <HeightCell> heightGrid = model.Landscape.HeightGrid;

            // iterate over the resource units and calculate the rumple index / surface area for each resource unit
            HeightCell[] neighboringHeightCells = new HeightCell[8]; // array holding pointers to height grid values (neighborhood)
            float[]      heights          = new float[9];            // array holding heights (8er neighborhood + center pixel)
            int          totalValidPixels = 0;
            float        totalSurfaceArea = 0.0F;

            for (int rumpleGridIndex = 0; rumpleGridIndex != mRumpleGrid.Count; ++rumpleGridIndex)
            {
                int   validPixels    = 0;
                float surfaceAreaSum = 0.0F;
                GridWindowEnumerator <HeightCell> runner = new(heightGrid, mRumpleGrid.GetCellExtent(mRumpleGrid.GetCellPosition(rumpleGridIndex)));
                while (runner.MoveNext())
                {
                    if (runner.Current.IsOnLandscape())
                    {
                        runner.GetNeighbors8(neighboringHeightCells);
                        bool valid = true;
                        int  hp    = 0;
                        heights[hp++] = runner.Current.Height;
                        // retrieve height values from the grid
                        for (int i = 0; i < 8; ++i)
                        {
                            heights[hp++] = neighboringHeightCells[i] != null ? neighboringHeightCells[i].Height : 0;
                            if (neighboringHeightCells[i] != null && !neighboringHeightCells[i].IsOnLandscape())
                            {
                                valid = false;
                            }
                            if (neighboringHeightCells[i] != null)
                            {
                                valid = false;
                            }
                        }
                        // calculate surface area only for cells which are (a) within the project area, and (b) all neighboring pixels are inside the forest area
                        if (valid)
                        {
                            validPixels++;
                            float surface_area = RumpleIndex.CalculateSurfaceArea(heights, heightGrid.CellSize);
                            surfaceAreaSum += surface_area;
                        }
                    }
                }
                if (validPixels > 0)
                {
                    float rumpleIndex = surfaceAreaSum / (validPixels * heightGrid.CellSize * heightGrid.CellSize);
                    this.mRumpleGrid[rumpleGridIndex] = rumpleIndex;
                    totalValidPixels += validPixels;
                    totalSurfaceArea += surfaceAreaSum;
                }
            }
            this.mRumpleIndex = 0.0F;
            if (totalValidPixels > 0)
            {
                float rumpleIndex = totalSurfaceArea / (totalValidPixels * heightGrid.CellSize * heightGrid.CellSize);
                this.mRumpleIndex = rumpleIndex;
            }
            this.mLastYear = model.CurrentYear;
        }