[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 ...
随机推荐
- 制作一款3D炸弹超人游戏
说起炸弹超人,相信很多朋友都玩过类似的游戏,其中最为人熟知的莫过于<泡泡堂>.该类型游戏需要玩家在地图中一边跑动一边放置炸弹,同时还要躲避敌方炸弹保护自己.最初的炸弹超人游戏都是2D的,今 ...
- mysql中什么是逻辑备份
需求描述: mysql中,或者说关系型数据库中逻辑备份到底指的是什么呢,主要还是对于 概念的理解,在此记录下. 概念解释: 逻辑备份:主要指的是保存数据库的逻辑结构(比如:create dattaba ...
- [extjs] extjs 5.1 API 开发 文档
官方博客发布了这个新版本说明,英文文章请戳下面 http://www.sencha.com/blog/announcing-sencha-ext-js-5.1/ 翻译版本请戳下面: http://ex ...
- 解决Qt程序在Linux下无法输入中文的办法(与下文连接)
在安装QT集成开发工具包之前需要先安装build-essential和libncurses5-dev这两个开发工具和库,libncurses5-dev库是一个在Linux/Unix下广泛应用的图形函数 ...
- easyui —— footer
前言: 使用easyui的datagrid,在最后一行加上“总计”字样,效果如下: 过程: ... <table id="dg" title="xx管理" ...
- Extjs6 Sdk中常用文件的作用
一.框架文件 ext.js: 压缩版. 动态加载扩展类的基础框架. ext-all.js: 压缩版. 包含框架全部类. ext-all-debug.js: 未压缩版. 包含框架全部类 ext-debu ...
- Sql Server 关于SET IDENTITY_INSERT的问题
想要将值插入到自动编号(或者说是标识列,IDENTITY)中去,需要设定 SET IDENTITY_INSERT 示例: 1.首先建立一个有标识列的表: CREATE TABLE products ( ...
- jfinal关联查询给dto添加表结构以外的字段并返回的处理方式
官网栗子: http://www.jfinal.com/doc/5-10 5.10 表关联操作 JFinal ActiveRecord 天然支持表关联操作,并不需要学习新的东西,此为无招胜有招.表关联 ...
- Thrift Expected protocol id ffffff82 but got 0
如果服务端配的也是noblock=false;客户端不能改成noblock=true;
- 安装 sql server 2008出现重启电脑,另在server 2012 r2安装sql server 2008 安装不上
时即使是进行电脑重启,也会报这个错误,那么就不是电脑的问题了,其实是系统注册表在作怪,解决方法如下: 1.开始-->运行,输入regedit,打开注册表管理器: 2. 找到 HKEY_LOCAL ...