[WorldWind学习]23.TerrainAccessor
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的更多相关文章
- Python学习--23 第三方库
本文将介绍python里常用的模块.如未特殊说明,所有示例均以python3.4为例: $ python -V Python 3.4.3 网络请求 urllib urllib提供了一系列用于操作URL ...
- Python学习--23 内建模块及第三方库
本文将介绍python里常用的模块.如未特殊说明,所有示例均以python3.4为例: $ python -V Python 3.4.3 网络请求 urllib urllib提供了一系列用于操作URL ...
- [WorldWind学习]19.WebDownload
using System; using System.Diagnostics; using System.Globalization; using System.Net; using System.I ...
- [WorldWind学习]18.High-Performance Timer in C#
In some applications exact time measurement methods are very important. 一些应用程序中精确的时间测量是非常重要的. The of ...
- msp430入门学习23
msp430的ADC(模数转换) msp430入门学习
- iOS 学习 - 23 加载本地 txt 文件, NSMutableParagraphStyle 段落格式,缩放动画,字体间距
思路: 1.new 一个 Empty 后缀为 .txt 文件,内容随笔拷贝一段 2.用 NSString 接收本地文件,再用一个标题拼接字符串 3.创建一个 NSMutableParagraphSty ...
- 【Java EE 学习 23】【log4j的使用】【ant的使用】【内省】
一.ant下载地址:http://ant.apache.org/bindownload.cgi 二.log4j下载地址:http://logging.apache.org/log4j/2.x/dow ...
- iOS学习23之事件处理
1. 事件的基本概念 1> 概述 事件是当用户手指触击屏幕及在屏幕上移动时,系统不断发送给应用程序的对象. 系统将事件按照特定的路径传递给可以对其进行处理的对象 在iOS中,一个UITouch对 ...
- [游戏学习23] MFC 画尺子
>_<:这是个简单的MFC程序,有利于了解MFC的框架结构 >_<:Ruler.h #include<afxwin.h> class CMyApp:public C ...
随机推荐
- 【算法】CRF
http://www.open-open.com/doc/view/7e983c0bf1594849bcd088dc212098c4 http://wenku.baidu.com/link?url=c ...
- DeDeCMS织梦的采集教程
http://www.tuicool.com/articles/VziaEz dede 第一步.我们打开织梦后台点击采集——采集节点管理——增加新节点 第二步.新增节点-配置网址索引 填写要采集 ...
- ubis文件系统的制作
在linux-2.6.27以前,谈到Flash文件系统,大家很多时候多会想到cramfs.jffs2.yaffs2等文件系统.它们也都是基于文件系统+mtd+flash设备的架构.linux-2.6. ...
- Tomcat之JSP运行原理之小试牛刀
最近空闲看了下JSP/Servlet,以前只知道用JSP,但是对其运行原理知之甚少,今在此做些笔记,以备查阅. 首先简要描述下其运行过程,然后结合Tomcat源码作简要分析. JSP运行过程: 第一步 ...
- GLSL/C++ 实现滤镜效果
入门效果之浮雕 "浮雕"图象效果是指图像的前景前向凸出背景.常见于一些纪念碑的雕刻上.要实现浮雕事实上很easy.我们把图象的一个象素和左上方的象素进行求差运算.并加上一个灰度.这 ...
- 工欲善其事 之 Web 前端调试工具格式化混淆过的 JS 代码
工欲善其事 之 Web 前端调试工具格式化混淆过的 JS 代码 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...
- POJ 1837 Balance(01背包变形, 枚举DP)
Q: dp 数组应该怎么设置? A: dp[i][j] 表示前 i 件物品放入天平后形成平衡度为 j 的方案数 题意: 有一个天平, 天平的两侧可以挂上重物, 给定 C 个钩子和G个秤砣. 2 4 - ...
- getViewTreeObserver
在项目中或多或少会遇一一些异步的操作,比如自定中不能马上获取到高度用测试可以得到.. final View headerView = View.inflate(this, R.layout.layou ...
- JS:“分享到”之类的悬浮框的运动原理(代码)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 【BZOJ1854】[Scoi2010]游戏 二分图最大匹配
[BZOJ1854][Scoi2010]游戏 Description lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当 ...