Exemplo n.º 1
0
        /// <summary>
        /// 中心地(経緯度)と中心地からの範囲(経緯度差)による矩形領域について
        /// DEM を切り出し・合成して取得する
        /// </summary>
        /// <param name="z">Z</param>
        /// <param name="center">中心地</param>
        /// <param name="delta">中心地からの範囲(経緯度差)</param>
        /// <param name="dem_type">対象とするDEM群</param>
        /// <returns>標高群</returns>
        public static double[,] LoadDEM
            (byte z
            , ILonLatGettable center
            , ILonLatGettable delta
            , DEMType dem_type = DEMType.DEM_5A_5B_10B
            )
        {
            // 緯度軸方向の北端と南端を確定
            var dlatabs     = delta.Latitude.Abs();
            var north_angle = (center.Latitude + dlatabs).Normalize180();
            var south_angle = (center.Latitude - dlatabs).Normalize180();

            // 経度軸方向の西端と東端を確定
            var dlonabs    = delta.Longitude.Abs();
            var east_angle = (center.Longitude + dlonabs).Normalize360();
            var west_angle = (center.Longitude - dlonabs).Normalize360();

            //Console.WriteLine( $"e={east_angle}" );
            //Console.WriteLine( $"w={west_angle}" );
            //Console.WriteLine( $"n={north_angle}" );
            //Console.WriteLine( $"s={south_angle}" );

            // 東端・北端のピクセルを確定
            var north_east_pixel = WebMercator.AngleToPixel(new LonLat(east_angle, north_angle), z);
            // 西端・南端のピクセルを確定
            var south_west_pixel = WebMercator.AngleToPixel(new LonLat(west_angle, south_angle), z);

            //Console.WriteLine( $"N-E px = {north_east_pixel}" );
            //Console.WriteLine( $"S-W px = {south_west_pixel}" );

            // 東端・北端のタイルを確定
            var north_east_tile = WebMercator.PixelToTile(north_east_pixel);
            // 西端・南端のタイルを確定
            var south_west_tile = WebMercator.PixelToTile(south_west_pixel);

            //Console.WriteLine( $"N-E tile = {north_east_tile}" );
            //Console.WriteLine( $"S-W tile = {south_west_tile}" );

            // 最終的に必要なピクセル群のX軸サイズ; 区間 [ west ... east ] なのでサイズは +1
            // west < east
            var target_pixel_size_x = ( int )(north_east_pixel.X - south_west_pixel.X + 1);
            // 最終的に必要なピクセル群のY軸サイズ; 区間 [ north ... south ] なのでサイズは +1
            // north < south
            var target_pixel_size_y = ( int )(south_west_pixel.Y - north_east_pixel.Y + 1);

            // 出力用のバッファー
            var r = new double[target_pixel_size_x, target_pixel_size_y];

            // 北西から南東へ
            {
                // r 開始地点と data 開始地点のずれを計算
                const int tile_pixel_shift = 8;
                const int data_arris_size  = 1 << tile_pixel_shift;
                var       dpx = (int)(south_west_tile.X << tile_pixel_shift) - (int)south_west_pixel.X;
                var       dpy = (int)(north_east_tile.Y << tile_pixel_shift) - (int)north_east_pixel.Y;
                var       t   = new TileLocation(0, 0, z);
                // data ごとの r 開始位置を dp だけずらしておく
                var rx_begin = dpx;
                var ry_begin = dpy;
                for
                (t.Y = north_east_tile.Y
                 ; t.Y <= south_west_tile.Y
                 ; ++t.Y, ry_begin += data_arris_size, rx_begin = dpx
                )
                {
                    for
                    (t.X = south_west_tile.X
                     ; t.X <= north_east_tile.X
                     ; ++t.X, rx_begin += data_arris_size
                    )
                    {
                        // デコードして
                        var data = LoadDEM(t, dem_type);

                        //using ( var i = SavePNGNumberTileS( data, 1.0e-2, 0, Color.FromArgb( 255, 128, 0, 0 ) ) )
                        //  i.Save( System.IO.Path.Combine( System.Environment.GetFolderPath( System.Environment.SpecialFolder.DesktopDirectory ), $"GK/tmp/gyoe-{t.X}-{t.Y}-{t.Z}.png" ), System.Drawing.Imaging.ImageFormat.Png );

                        Func <int, int, double> sampler = (dx, dy) => data[dx, dy];
                        if (data == null)
                        {
                            sampler = (dx, dy) => double.NaN;
                        }

                        // r の適切な領域へ data をコピー
                        var rx = rx_begin;
                        var ry = ry_begin;
                        //Console.WriteLine( $"t={t} rx_begin={rx_begin} ry_begin={ry_begin}" );
                        for (var dy = 0; dy < data_arris_size; ++dy, ++ry, rx = rx_begin)
                        {
                            if (ry < 0 || ry >= r.GetLength(1))
                            {
                                continue;
                            }
                            else
                            {
                                for (var dx = 0; dx < data_arris_size; ++dx, ++rx)
                                {
                                    if (rx < 0 || rx >= r.GetLength(0))
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        //{
                                        r[rx, ry] = sampler(dx, dy);
                                    }
                                }
                            }
                        }
                        //Console.WriteLine( $"rx={rx} ry={ry} dx={dx} dy={dy} value={data[ dx, dy ]}" );
                        //}
                    }
                }
            }

            return(r);
        }