QuadTile的CreateElevatedMesh()方法中:

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

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

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

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

                                 /// <summary>
/// Builds a terrain array with specified boundaries
/// </summary>
/// <param name="north">North edge in decimal degrees.</param>
/// <param name="south">South edge in decimal degrees.</param>
/// <param name="west">West edge in decimal degrees.</param>
/// <param name="east">East edge in decimal degrees.</param>
/// <param name="samples"></param>
public override TerrainTile GetElevationArray(double north, double south, double west, double east,
int samples)
{
TerrainTile res = null; if (m_higherResolutionSubsets != null)
{
// TODO: Support more than 1 level of higher resolution sets and allow user selections
foreach (TerrainAccessor higherResSub in m_higherResolutionSubsets)
{
if (north <= higherResSub.North && south >= higherResSub.South &&
west >= higherResSub.West && east <= higherResSub.East)
{
res = higherResSub.GetElevationArray(north, south, west, east, samples);
return res;
}
}
} res = new TerrainTile(m_terrainTileService);
res.North = north;
res.South = south;
res.West = west;
res.East = east;
res.SamplesPerTile = samples;
res.IsInitialized = true;
res.IsValid = true; double samplesPerDegree = (double)samples / (double)(north - south);
double latrange = Math.Abs(north - south);
double lonrange = Math.Abs(east - west);
TerrainTileCacheEntry ttce = null; float[,] data = new float[samples, samples]; if(samplesPerDegree < World.Settings.MinSamplesPerDegree)
{
res.ElevationData = data;
return res;
} double scaleFactor = (double) / (samples - );
for (int x = ; x < samples; x++)
{
for (int y = ; y < samples; y++)
{
double curLat = north - scaleFactor * latrange * x;
double curLon = west + scaleFactor * lonrange * y; // Wrap lat/lon to fit range 90/-90 and -180/180 (PM 2006-11-17)
if (curLat > )
{
curLat = - (curLat - );
curLon += ;
}
if (curLat < -)
{
curLat = - - (curLat + );
curLon += ;
}
if (curLon > )
{
curLon -= ;
}
if (curLon < -)
{
curLon += ;
} if (ttce == null ||
curLat < ttce.TerrainTile.South ||
curLat > ttce.TerrainTile.North ||
curLon < ttce.TerrainTile.West ||
curLon > ttce.TerrainTile.East)
{
TerrainTile tt = m_terrainTileService.GetTerrainTile(curLat, curLon, samplesPerDegree);
ttce = (TerrainTileCacheEntry)m_tileCache[tt.TerrainTileFilePath];
if (ttce == null)
{
ttce = new TerrainTileCacheEntry(tt);
AddToCache(ttce);
}
if (!ttce.TerrainTile.IsInitialized)
ttce.TerrainTile.Initialize();
ttce.LastAccess = DateTime.Now;
if (!tt.IsValid)
res.IsValid = false;
} data[x, y] = ttce.TerrainTile.GetElevationAt(curLat, curLon);
}
}
res.ElevationData = data; return res;
}

GetElevationArray

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

 public class TerrainTile : IDisposable
{
public string TerrainTileFilePath;
public double TileSizeDegrees;
public int SamplesPerTile;
public double South;
public double North;
public double West;
public double East;
public int Row;
public int Col;
public int TargetLevel;
public TerrainTileService m_owner;
public bool IsInitialized;
public bool IsValid; public float[,] ElevationData;
protected TerrainDownloadRequest request; public TerrainTile( TerrainTileService owner )
{
m_owner = owner;
}
/// <summary>
/// This method initializes the terrain tile add switches to
/// Initialize floating point/int 16 tiles
/// </summary>
public void Initialize()
{
if(IsInitialized)
return; if(!File.Exists(TerrainTileFilePath))
{
// Download elevation
if(request==null)
{
using( request = new TerrainDownloadRequest(this, m_owner, Row, Col, TargetLevel) )
{
request.SaveFilePath = TerrainTileFilePath;
request.DownloadInForeground();
}
}
} if(ElevationData==null)
ElevationData = new float[SamplesPerTile, SamplesPerTile]; if(File.Exists(TerrainTileFilePath))
{
// Load elevation file
try
{
// TerrainDownloadRequest's FlagBadTile() creates empty files
// as a way to flag "bad" terrain tiles.
// Remove the empty 'flag' files after preset time.
try
{
FileInfo tileInfo = new FileInfo(TerrainTileFilePath);
if(tileInfo.Length == )
{
TimeSpan age = DateTime.Now.Subtract( tileInfo.LastWriteTime );
if(age < m_owner.TerrainTileRetryInterval)
{
// This tile is still flagged bad
IsInitialized = true;
}
else
{
// remove the empty 'flag' file
File.Delete(TerrainTileFilePath);
}
return;
}
}
catch
{
// Ignore any errors in the above block, and continue.
// For example, if someone had the empty 'flag' file
// open, the delete would fail.
} using( Stream s = File.OpenRead(TerrainTileFilePath))
{
BinaryReader reader = new BinaryReader(s);
if(m_owner.DataType=="Int16")
{
/*
byte[] tfBuffer = new byte[SamplesPerTile*SamplesPerTile*2];
if (s.Read(tfBuffer,0,tfBuffer.Length) < tfBuffer.Length)
throw new IOException(string.Format("End of file error while reading terrain file '{0}'.", TerrainTileFilePath) ); int offset = 0;
for(int y = 0; y < SamplesPerTile; y++)
for(int x = 0; x < SamplesPerTile; x++)
ElevationData[x,y] = tfBuffer[offset++] + (short)(tfBuffer[offset++]<<8);
*/
for(int y = ; y < SamplesPerTile; y++)
for(int x = ; x < SamplesPerTile; x++)
ElevationData[x,y] = reader.ReadInt16();
}
if(m_owner.DataType=="Float32")
{
/*
byte[] tfBuffer = new byte[SamplesPerTile*SamplesPerTile*4];
if (s.Read(tfBuffer,0,tfBuffer.Length) < tfBuffer.Length)
throw new IOException(string.Format("End of file error while reading terrain file '{0}'.", TerrainTileFilePath) );
*/
for(int y = ; y < SamplesPerTile; y++)
for(int x = ; x < SamplesPerTile; x++)
{
ElevationData[x,y] = reader.ReadSingle();
}
}
IsInitialized = true;
IsValid = true;
}
return;
}
catch(IOException)
{
// If there is an IO exception when reading the terrain tile,
// then either something is wrong with the file, or with
// access to the file, so try and remove it.
try
{
File.Delete(TerrainTileFilePath);
}
catch(Exception ex)
{
throw new ApplicationException(String.Format("Error while trying to delete corrupt terrain tile {0}", TerrainTileFilePath), ex);
}
}
catch(Exception ex)
{
// Some other type of error when reading the terrain tile.
throw new ApplicationException(String.Format("Error while trying to read terrain tile {0}", TerrainTileFilePath), ex);
}
}
}
//根据经纬度从DEM瓦片中获取高程
public float GetElevationAt(double latitude, double longitude)
{
try
{
double deltaLat = North - latitude;
double deltaLon = longitude - West; double df2 = (SamplesPerTile-) / TileSizeDegrees;
float lat_pixel = (float)(deltaLat * df2);
float lon_pixel = (float)(deltaLon * df2); int lat_min = (int)lat_pixel;
int lat_max = (int)Math.Ceiling(lat_pixel);
int lon_min = (int)lon_pixel;
int lon_max = (int)Math.Ceiling(lon_pixel); if(lat_min >= SamplesPerTile)
lat_min = SamplesPerTile - ;
if(lat_max >= SamplesPerTile)
lat_max = SamplesPerTile - ;
if(lon_min >= SamplesPerTile)
lon_min = SamplesPerTile - ;
if(lon_max >= SamplesPerTile)
lon_max = SamplesPerTile - ; if(lat_min < )
lat_min = ;
if(lat_max < )
lat_max = ;
if(lon_min < )
lon_min = ;
if(lon_max < )
lon_max = ; float delta = lat_pixel - lat_min;
float westElevation =
ElevationData[lon_min, lat_min]*(-delta) +
ElevationData[lon_min, lat_max]*delta; float eastElevation =
ElevationData[lon_max, lat_min]*(-delta) +
ElevationData[lon_max, lat_max]*delta; delta = lon_pixel - lon_min;
float interpolatedElevation =
westElevation*(-delta) +
eastElevation*delta; return interpolatedElevation;
}
catch
{
}
return ;
}
#region IDisposable Members public void Dispose()
{
if(request != null)
{
request.Dispose();
request = null;
} GC.SuppressFinalize(this);
} #endregion
}

TerrainTile

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

[WorldWind学习]23.TerrainAccessor的更多相关文章

  1. Python学习--23 第三方库

    本文将介绍python里常用的模块.如未特殊说明,所有示例均以python3.4为例: $ python -V Python 3.4.3 网络请求 urllib urllib提供了一系列用于操作URL ...

  2. Python学习--23 内建模块及第三方库

    本文将介绍python里常用的模块.如未特殊说明,所有示例均以python3.4为例: $ python -V Python 3.4.3 网络请求 urllib urllib提供了一系列用于操作URL ...

  3. [WorldWind学习]19.WebDownload

    using System; using System.Diagnostics; using System.Globalization; using System.Net; using System.I ...

  4. [WorldWind学习]18.High-Performance Timer in C#

    In some applications exact time measurement methods are very important. 一些应用程序中精确的时间测量是非常重要的. The of ...

  5. msp430入门学习23

    msp430的ADC(模数转换) msp430入门学习

  6. iOS 学习 - 23 加载本地 txt 文件, NSMutableParagraphStyle 段落格式,缩放动画,字体间距

    思路: 1.new 一个 Empty 后缀为 .txt 文件,内容随笔拷贝一段 2.用 NSString 接收本地文件,再用一个标题拼接字符串 3.创建一个 NSMutableParagraphSty ...

  7. 【Java EE 学习 23】【log4j的使用】【ant的使用】【内省】

    一.ant下载地址:http://ant.apache.org/bindownload.cgi  二.log4j下载地址:http://logging.apache.org/log4j/2.x/dow ...

  8. iOS学习23之事件处理

    1. 事件的基本概念 1> 概述 事件是当用户手指触击屏幕及在屏幕上移动时,系统不断发送给应用程序的对象. 系统将事件按照特定的路径传递给可以对其进行处理的对象 在iOS中,一个UITouch对 ...

  9. [游戏学习23] MFC 画尺子

    >_<:这是个简单的MFC程序,有利于了解MFC的框架结构 >_<:Ruler.h #include<afxwin.h> class CMyApp:public C ...

随机推荐

  1. HttpClient三种不同的服务器认证客户端方案

    http://blog.csdn.net/i_lovefish/article/details/9816783 HttpClient三种不同的认证方案: Basic, Digest and NTLM. ...

  2. ASP.NET MVC自定义验证Authorize Attribute(包含cookie helper)

    前几天Insus.NET有在数据库实现过对某一字段进行加密码与解密<使用EncryptByPassPhrase和DecryptByPassPhrase对MS SQLServer某一字段时行加密和 ...

  3. js中数组作为参数传递的定义

    下面的函数实现了一个我们想要的最基本的图片预加载效果 function preloadimages(arr){    var newimages=[]    var arr=(typeof arr!= ...

  4. 详解JQuery Ajax 在asp.net中使用总结

    自从有了JQuery,Ajax的使用变的越来越方便了,但是使用中还是会或多或少的出现一些让人短时间内痛苦的问题.本文暂时总结一些在使用JQuery Ajax中应该注意的问题,如有不恰当或者不完善的地方 ...

  5. [Scikit-learn] *Dynamic Bayesian Network - Partical Filter

    涉及的一些知识: 机器人的自我定位 Sequential Importance Sampling Ref: http://scipy-cookbook.readthedocs.io/items/Par ...

  6. python2.0_s12_day13_javascript&Dom&jQuery

    今天主要内容:JavaScriptDomjQuery http://www.cnblogs.com/wupeiqi/articles/5369773.html 今天主要内容大致了解:javascrip ...

  7. nohub和重定向文件

    1.如果使用远程连接的Linux的方式并想后台运行执行如下命令: 格式:nohup <程序名> & 比如:nohup /usr/local/collection/bin/start ...

  8. Serlvet学习笔记之四—对文件的操作

    1.读文件 package com.demo; import java.io.BufferedReader; import java.io.FileReader; import java.io.Pri ...

  9. C++说明符和限定符

    有些被称为存储说明符(storage class specifier)或cv-限定符(cv-qualifier)的C++关键字提供了一些有关存储的信息.下面是存储所说明符:* auto (在C++11 ...

  10. 【IOS6.0 自学瞎折腾】(四)Xib可视化编程

    其实在Interface Builder中,要把xib中的控件与代码联系起来用鼠标拖拉连线是非常方便的一件事,有的教程写的非常复杂要先点这后点那的. 一:IBOutlet,IB说明是Interface ...