/// <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); }