• [WorldWind学习]23.TerrainAccessor


    QuadTile的CreateElevatedMesh()方法中:

    1  //获取地形瓦片
    2 TerrainTile tile = QuadTileSet.World.TerrainAccessor.GetElevationArray(North + degreePerSample, South - degreePerSample, West - degreePerSample, East + degreePerSample, vertexCountElevated + 3);
    3 float[,] heightData = tile.ElevationData;

    调用了World的TerrainAccessor属性的GetElevationArray()方法。

    实际调用的是TerrainAccessor子类NltTerrainAccessor的GetElevationArray方法。

    GetElevationArray对高清影像进行递归调用。如下是NltTerrainAccessor的GetElevationArray方法。

      1                                 /// <summary>
      2         /// Builds a terrain array with specified boundaries
      3         /// </summary>
      4         /// <param name="north">North edge in decimal degrees.</param>
      5         /// <param name="south">South edge in decimal degrees.</param>
      6         /// <param name="west">West edge in decimal degrees.</param>
      7         /// <param name="east">East edge in decimal degrees.</param>
      8         /// <param name="samples"></param>
      9         public override TerrainTile GetElevationArray(double north, double south, double west, double east,
     10             int samples)
     11         {
     12             TerrainTile res = null;
     13             
     14             if (m_higherResolutionSubsets != null)
     15             {
     16                 // TODO: Support more than 1 level of higher resolution sets and allow user selections
     17                 foreach (TerrainAccessor higherResSub in m_higherResolutionSubsets)
     18                 {
     19                     if (north <= higherResSub.North && south >= higherResSub.South &&
     20                         west >= higherResSub.West && east <= higherResSub.East)
     21                     {
     22                         res = higherResSub.GetElevationArray(north, south, west, east, samples);
     23                         return res;
     24                     }
     25                 }
     26             }
     27 
     28             res = new TerrainTile(m_terrainTileService);
     29             res.North = north;
     30             res.South = south;
     31             res.West = west;
     32             res.East = east;
     33             res.SamplesPerTile = samples;
     34             res.IsInitialized = true;
     35             res.IsValid = true;
     36 
     37             double samplesPerDegree = (double)samples / (double)(north - south);
     38             double latrange = Math.Abs(north - south);
     39             double lonrange = Math.Abs(east - west);
     40             TerrainTileCacheEntry ttce = null;
     41 
     42             float[,] data = new float[samples, samples];
     43 
     44             if(samplesPerDegree < World.Settings.MinSamplesPerDegree)
     45             {
     46                 res.ElevationData = data;
     47                 return res;
     48             }
     49 
     50             double scaleFactor = (double)1 / (samples - 1);
     51             for (int x = 0; x < samples; x++)
     52             {
     53                 for (int y = 0; y < samples; y++)
     54                 {
     55                     double curLat = north - scaleFactor * latrange * x;
     56                     double curLon = west + scaleFactor * lonrange * y;
     57 
     58                     // Wrap lat/lon to fit range 90/-90 and -180/180 (PM 2006-11-17)
     59                     if (curLat > 90)
     60                     {
     61                         curLat = 90 - (curLat - 90);
     62                         curLon += 180;
     63                     }
     64                     if (curLat < -90)
     65                     {
     66                         curLat = -90 - (curLat + 90);
     67                         curLon += 180;
     68                     }
     69                     if (curLon > 180)
     70                     {
     71                         curLon -= 360;
     72                     }
     73                     if (curLon < -180)
     74                     {
     75                         curLon += 360;
     76                     }
     77 
     78                     if (ttce == null ||
     79                         curLat < ttce.TerrainTile.South ||
     80                         curLat > ttce.TerrainTile.North ||
     81                         curLon < ttce.TerrainTile.West ||
     82                         curLon > ttce.TerrainTile.East)
     83                     {
     84                         TerrainTile tt = m_terrainTileService.GetTerrainTile(curLat, curLon, samplesPerDegree);
     85                         ttce = (TerrainTileCacheEntry)m_tileCache[tt.TerrainTileFilePath];
     86                         if (ttce == null)
     87                         {
     88                             ttce = new TerrainTileCacheEntry(tt);
     89                             AddToCache(ttce);
     90                         }
     91                         if (!ttce.TerrainTile.IsInitialized)
     92                             ttce.TerrainTile.Initialize();
     93                         ttce.LastAccess = DateTime.Now;
     94                         if (!tt.IsValid)
     95                             res.IsValid = false;
     96                     }
     97 
     98                     data[x, y] = ttce.TerrainTile.GetElevationAt(curLat, curLon);
     99                 }
    100             }
    101             res.ElevationData = data;
    102 
    103             return res;
    104         }
    GetElevationArray

    最后查看TerrainTile类的GetElevationAt方法获取了高程数据。

      1 public class TerrainTile : IDisposable
      2     {
      3         public string TerrainTileFilePath;
      4         public double TileSizeDegrees;
      5         public int SamplesPerTile;
      6         public double South;
      7         public double North;
      8         public double West;
      9         public double East;
     10         public int Row;
     11         public int Col;
     12         public int TargetLevel;
     13         public TerrainTileService m_owner;
     14         public bool IsInitialized;
     15         public bool IsValid;
     16 
     17         public float[,] ElevationData;
     18         protected TerrainDownloadRequest request;
     19 
     20         public TerrainTile( TerrainTileService owner )
     21         {
     22             m_owner = owner;
     23         }
     24         /// <summary>
     25         /// This method initializes the terrain tile add switches to
     26         /// Initialize floating point/int 16 tiles
     27         /// </summary>
     28         public void Initialize()
     29         {
     30             if(IsInitialized)
     31                 return;
     32 
     33             if(!File.Exists(TerrainTileFilePath))
     34             {
     35                 // Download elevation
     36                 if(request==null)
     37                 {
     38                     using( request = new TerrainDownloadRequest(this, m_owner, Row, Col, TargetLevel) )
     39                     {
     40                         request.SaveFilePath = TerrainTileFilePath;
     41                         request.DownloadInForeground();
     42                     }
     43                 }
     44             }
     45 
     46             if(ElevationData==null)
     47                 ElevationData = new float[SamplesPerTile, SamplesPerTile];
     48 
     49             if(File.Exists(TerrainTileFilePath))
     50             {
     51                 // Load elevation file
     52                 try
     53                 {
     54                     // TerrainDownloadRequest's FlagBadTile() creates empty files
     55                     // as a way to flag "bad" terrain tiles.
     56                     // Remove the empty 'flag' files after preset time.
     57                     try
     58                     {
     59                         FileInfo tileInfo = new FileInfo(TerrainTileFilePath);
     60                         if(tileInfo.Length == 0)
     61                         {
     62                             TimeSpan age = DateTime.Now.Subtract( tileInfo.LastWriteTime );
     63                             if(age < m_owner.TerrainTileRetryInterval)
     64                             {
     65                                 // This tile is still flagged bad
     66                                 IsInitialized = true;
     67                             }
     68                             else
     69                             {
     70                                 // remove the empty 'flag' file
     71                                 File.Delete(TerrainTileFilePath);
     72                             }
     73                             return;
     74                         }
     75                     }
     76                     catch
     77                     {
     78                         // Ignore any errors in the above block, and continue.
     79                         // For example, if someone had the empty 'flag' file
     80                         // open, the delete would fail.
     81                     }
     82     
     83                     using( Stream s = File.OpenRead(TerrainTileFilePath))
     84                     {
     85                         BinaryReader reader = new BinaryReader(s);
     86                         if(m_owner.DataType=="Int16")
     87                         {
     88                             /*
     89                             byte[] tfBuffer = new byte[SamplesPerTile*SamplesPerTile*2];
     90                             if (s.Read(tfBuffer,0,tfBuffer.Length) < tfBuffer.Length)
     91                                 throw new IOException(string.Format("End of file error while reading terrain file '{0}'.", TerrainTileFilePath) );
     92 
     93                             int offset = 0;
     94                             for(int y = 0; y < SamplesPerTile; y++)
     95                                 for(int x = 0; x < SamplesPerTile; x++)
     96                                     ElevationData[x,y] = tfBuffer[offset++] + (short)(tfBuffer[offset++]<<8);
     97                             */
     98                             for(int y = 0; y < SamplesPerTile; y++)
     99                                 for(int x = 0; x < SamplesPerTile; x++)
    100                                     ElevationData[x,y] = reader.ReadInt16();
    101                         }
    102                         if(m_owner.DataType=="Float32")
    103                         {
    104                             /*
    105                             byte[] tfBuffer = new byte[SamplesPerTile*SamplesPerTile*4];
    106                             if (s.Read(tfBuffer,0,tfBuffer.Length) < tfBuffer.Length)
    107                                     throw new IOException(string.Format("End of file error while reading terrain file '{0}'.", TerrainTileFilePath) );
    108                             */
    109                             for(int y = 0; y < SamplesPerTile; y++)
    110                                 for(int x = 0; x < SamplesPerTile; x++)
    111                                 {
    112                                     ElevationData[x,y] = reader.ReadSingle();
    113                                 }
    114                         }
    115                         IsInitialized = true;
    116                         IsValid = true;
    117                     }
    118                     return;
    119                 }
    120                 catch(IOException)
    121                 {
    122                     // If there is an IO exception when reading the terrain tile,
    123                     // then either something is wrong with the file, or with
    124                     // access to the file, so try and remove it.
    125                     try
    126                     {
    127                         File.Delete(TerrainTileFilePath);
    128                     }
    129                     catch(Exception ex)
    130                     {
    131                         throw new ApplicationException(String.Format("Error while trying to delete corrupt terrain tile {0}", TerrainTileFilePath), ex);
    132                     }
    133                 }
    134                 catch(Exception ex)
    135                 {
    136                     // Some other type of error when reading the terrain tile.
    137                     throw new ApplicationException(String.Format("Error while trying to read terrain tile {0}", TerrainTileFilePath), ex);
    138                 }
    139             }
    140         }
    141         //根据经纬度从DEM瓦片中获取高程
    142         public float GetElevationAt(double latitude, double longitude)
    143         {
    144             try
    145             {
    146                 double deltaLat = North - latitude;
    147                 double deltaLon = longitude - West;
    148 
    149                 double df2 = (SamplesPerTile-1) / TileSizeDegrees;
    150                 float lat_pixel = (float)(deltaLat * df2);
    151                 float lon_pixel = (float)(deltaLon * df2);
    152 
    153                 int lat_min = (int)lat_pixel;
    154                 int lat_max = (int)Math.Ceiling(lat_pixel);
    155                 int lon_min = (int)lon_pixel;
    156                 int lon_max = (int)Math.Ceiling(lon_pixel);
    157 
    158                 if(lat_min >= SamplesPerTile)
    159                     lat_min = SamplesPerTile - 1;
    160                 if(lat_max >= SamplesPerTile)
    161                     lat_max = SamplesPerTile - 1;
    162                 if(lon_min >= SamplesPerTile)
    163                     lon_min = SamplesPerTile - 1;
    164                 if(lon_max >= SamplesPerTile)
    165                     lon_max = SamplesPerTile - 1;
    166 
    167                 if(lat_min < 0)
    168                     lat_min = 0;
    169                 if(lat_max < 0)
    170                     lat_max = 0;
    171                 if(lon_min < 0)
    172                     lon_min = 0;
    173                 if(lon_max < 0)
    174                     lon_max = 0;
    175 
    176                 float delta = lat_pixel - lat_min;
    177                 float westElevation = 
    178                     ElevationData[lon_min, lat_min]*(1-delta) + 
    179                     ElevationData[lon_min, lat_max]*delta;
    180             
    181                 float eastElevation = 
    182                     ElevationData[lon_max, lat_min]*(1-delta) + 
    183                     ElevationData[lon_max, lat_max]*delta;
    184             
    185                 delta = lon_pixel - lon_min;
    186                 float interpolatedElevation = 
    187                     westElevation*(1-delta) + 
    188                     eastElevation*delta;
    189 
    190                 return interpolatedElevation;
    191             }
    192             catch
    193             {
    194             }
    195             return 0;
    196         }
    197         #region IDisposable Members
    198 
    199         public void Dispose()
    200         {
    201             if(request != null)
    202             {
    203                 request.Dispose();
    204                 request = null;
    205             }
    206             
    207             GC.SuppressFinalize(this);
    208         }
    209 
    210         #endregion
    211     }
    TerrainTile

    TerrainAccessor在ConfigLoader中构建,赋值给World。

  • 相关阅读:
    .Net Core使用Options模式来使用配置项
    git忽略已经提交的文件(git忽略文件不起作用)
    AirTest
    VSCode搭建rust开发环境
    动态编译和加载java代码
    JavaScript动态应用代码(有点像Java里的drools)
    Win10 Rust 编译报错: linking with `link.exe` failed: exit code: 1181
    git 拉取仓库的单个目录
    dart里实现类似Java里的--classpath的功能
    Rust离线安装
  • 原文地址:https://www.cnblogs.com/yhlx125/p/3557425.html
Copyright © 2020-2023  润新知