[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。

[WorldWind学习]23.TerrainAccessor_第1张图片

 

你可能感兴趣的:(Access)