WorldWind系列十四DEM数据加载和应用以SRTM为例.docx
- 文档编号:20147993
- 上传时间:2023-04-25
- 格式:DOCX
- 页数:27
- 大小:47.25KB
WorldWind系列十四DEM数据加载和应用以SRTM为例.docx
《WorldWind系列十四DEM数据加载和应用以SRTM为例.docx》由会员分享,可在线阅读,更多相关《WorldWind系列十四DEM数据加载和应用以SRTM为例.docx(27页珍藏版)》请在冰豆网上搜索。
WorldWind系列十四DEM数据加载和应用以SRTM为例
WorldWind系列十四:
DEM数据加载和应用——以SRTM为例
来源:
博客园 作者:
无痕客
DEM应用在WW的三维表现中占有很重要的位置,跟影像数据同等重要!
幸好影像和DEM的加载和处理原理上几乎一致,对基于WW搞GIS三维开发来说是件好事,理解好任何一种,另一种触类旁通!
前一篇,主要从功能上做了简单入门介绍,该篇将从代码级别分析WW内置的SRTM的DEM数据加载和应用,下一篇讲从二次开发角度上讲解如何处理、配置自己的影像和DEM数据。
呵呵,因为DEM部分很重要,且是放假期间我也有时间,争取篇篇精彩!
两个缩写词介绍:
因为这两个缩写词常出现,知道是什么缩写,就不觉得神秘啦!
SRTM:
The ShuttleRadarTopographyMission (SRTM)obtainedelevationdataonanear-globalscaletogeneratethemostcompletehigh-resolutiondigitaltopographicdatabaseofEarth.SRTMconsistedofaspeciallymodifiedradarsystemthatflewonboardtheSpaceShuttleEndeavourduringan11-daymissioninFebruaryof2000.
NLT:
NASALearningTechnologies.
我从BMNG.cs为例入手研究DEM的使用,当然研究瓦片影像也该从此入手,但,今天影像不是我们关注的重点。
现在正式步入主题,跟我一起分析和学习代码吧!
BMNG.cs类144行构造函数中代码,
WorldWind.NltImageStore imageStore = new WorldWind.NltImageStore(String.Format("bmng.topo.2004{0:
D2}", i + 1), "http:
//worldwind25.arc.nasa.gov/tile/tile.aspx");
imageStore.DataDirectory = null;
imageStore.LevelZeroTileSizeDegrees = 36.0;
imageStore.LevelCount = 5;
imageStore.ImageExtension = "jpg";
imageStore.CacheDirectory = String.Format("{0}\\BMNG\\{1}", m_WorldWindow.Cache.CacheDirectory, String.Format("BMNG (Shaded) Tiled - {0}.2004", i + 1));
ias = new WorldWind.ImageStore[1];
ias[0] = imageStore;
m_QuadTileLayers[0, i] = new WorldWind.Renderable.QuadTileSet(
String.Format("Tiled - {0}.2004", i + 1),
m_WorldWindow.CurrentWorld,
0,
90, -90, -180, 180,
true,
ias);
BMNG中的NltImageStore.cs、QuadTileSet类。
这是我们关注的对象。
QuadTileSet继承自RenderableObject,是要绘制渲染的对象类。
关注它的562行Update()方法、517行Initialize()方法、701行Render()方法。
Update()方法
QuadTileSet的Update()方法
public override void Update(DrawArgs drawArgs)
{
if (!
isInitialized)
Initialize(drawArgs);
if (m_effectPath !
= null && m_effect == null)
{
string errs = string.Empty;
m_effect = Effect.FromFile(DrawArgs.Device, m_effectPath, null, "", ShaderFlags.None, m_effectPool, out errs);
if (errs !
= null && errs !
= string.Empty)
{
Log.Write(Log.Levels.Warning, "Could not load effect " + m_effectPath + ":
" + errs);
Log.Write(Log.Levels.Warning, "Effect has been disabled.");
m_effectPath = null;
m_effect = null;
}
}
if (ImageStores[0].LevelZeroTileSizeDegrees < 180)
{
// Check for layer outside view
double vrd = DrawArgs.Camera.ViewRange.Degrees;
double latitudeMax = DrawArgs.Camera.Latitude.Degrees + vrd;
double latitudeMin = DrawArgs.Camera.Latitude.Degrees - vrd;
double longitudeMax = DrawArgs.Camera.Longitude.Degrees + vrd;
double longitudeMin = DrawArgs.Camera.Longitude.Degrees - vrd;
if (latitudeMax < m_south || latitudeMin > m_north || longitudeMax < m_west || longitudeMin > m_east)
return;
}
if (DrawArgs.Camera.ViewRange * 0.5f >
Angle.FromDegrees(TileDrawDistance * ImageStores[0].LevelZeroTileSizeDegrees))
{
lock (m_topmostTiles.SyncRoot)
{
foreach (QuadTile qt in m_topmostTiles.Values)
qt.Dispose();
m_topmostTiles.Clear();
ClearDownloadRequests();
}
return;
}
//知识点,可以看看,如何计算不可见瓦片的算法。
RemoveInvisibleTiles(DrawArgs.Camera);
下面主要是如何计算和加载瓦片式影像的,是重点,但不是这次的重点。
try
{
//根据Camera所对的中心经纬度,计算中心点的行列号
int middleRow = MathEngine.GetRowFromLatitude(DrawArgs.Camera.Latitude, ImageStores[0].LevelZeroTileSizeDegrees);
int middleCol = MathEngine.GetColFromLongitude(DrawArgs.Camera.Longitude, ImageStores[0].LevelZeroTileSizeDegrees);
//根据行列号,反推瓦片的四点对应的经度或纬度
double middleSouth = -90.0f + middleRow * ImageStores[0].LevelZeroTileSizeDegrees;
double middleNorth = -90.0f + middleRow * ImageStores[0].LevelZeroTileSizeDegrees + ImageStores[0].LevelZeroTileSizeDegrees;
double middleWest = -180.0f + middleCol * ImageStores[0].LevelZeroTileSizeDegrees;
double middleEast = -180.0f + middleCol * ImageStores[0].LevelZeroTileSizeDegrees + ImageStores[0].LevelZeroTileSizeDegrees;
double middleCenterLat = 0.5f * (middleNorth + middleSouth);
double middleCenterLon = 0.5f * (middleWest + middleEast);
//这里存在一个算法,由中心瓦片框,向四周扩散地找相邻的瓦片矩形框。
//有兴趣的网友可以看一下,根据算法画出图来就好理解啦。
(我感觉该算法对以后开发会有用的)
int tileSpread = 4;
for (int i = 0; i < tileSpread; i++)
{
for (double j = middleCenterLat - i * ImageStores[0].LevelZeroTileSizeDegrees; j < middleCenterLat + i * ImageStores[0].LevelZeroTileSizeDegrees; j += ImageStores[0].LevelZeroTileSizeDegrees)
{
for (double k = middleCenterLon - i * ImageStores[0].LevelZeroTileSizeDegrees; k < middleCenterLon + i * ImageStores[0].LevelZeroTileSizeDegrees; k += ImageStores[0].LevelZeroTileSizeDegrees)
{
//根据经\纬度和tileSize来计算行列号,这里LevelZeroTileSizeDegrees为第0层的瓦片大小为36度,瓦片总个数为50片
int curRow = MathEngine.GetRowFromLatitude(Angle.FromDegrees(j), ImageStores[0].LevelZeroTileSizeDegrees);
int curCol = MathEngine.GetColFromLongitude(Angle.FromDegrees(k), ImageStores[0].LevelZeroTileSizeDegrees);
long key = ((long)curRow << 32) + curCol;
//如果集合m_topmostTiles已经存在QuadTile,则更新QuadTile
QuadTile qt = (QuadTile)m_topmostTiles[key];
if (qt !
= null)
{
qt.Update(drawArgs);
continue;
}
// Check for tile outside layer boundaries,获取外边框四点经度或纬度坐标
double west = -180.0f + curCol * ImageStores[0].LevelZeroTileSizeDegrees;
if (west > m_east)
continue;
double east = west + ImageStores[0].LevelZeroTileSizeDegrees;
if (east < m_west)
continue;
double south = -90.0f + curRow * ImageStores[0].LevelZeroTileSizeDegrees;
if (south > m_north)
continue;
double north = south + ImageStores[0].LevelZeroTileSizeDegrees;
if (north < m_south)
continue;
//结合中不存在,创建新的QuadTile
qt = new QuadTile(south, north, west, east, 0, this);
//判断新的QuadTile是否在可视区域中。
(可以关注一下:
Intersects()方法判断矩形框相交)
if (DrawArgs.Camera.ViewFrustum.Intersects(qt.BoundingBox))
{
lock (m_topmostTiles.SyncRoot)
m_topmostTiles.Add(key, qt);
//调用QuadTile的Update()方法
qt.Update(drawArgs);
}
}
}
}
}
catch (System.Threading.ThreadAbortException)
{
}
catch (Exception caught)
{
Log.Write(caught);
}
}
Render()方法的关键代码为:
device.VertexFormat=CustomVertex.PositionNormalTextured.Format;
foreach(QuadTileqtinm_topmostTiles.Values)
qt.Render(drawArgs);
从上面可以看出,QuadTileSet可看作是QuadTile的集合,真正实现更新和渲染的是QuadTile对象。
里面有影像的加载和渲染绘制,也有DEM的渲染绘制。
我们先看看QuadTile.cs中Update()方法:
QuadTile的Update()代码
public virtual void Update(DrawArgs drawArgs)
{
if (m_isResetingCache)
return;
try
{
double tileSize = North - South;
if (!
isInitialized)
{
if (DrawArgs.Camera.ViewRange * 0.5f < Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize)
&& MathEngine.SphericalDistance(CenterLatitude, CenterLongitude,
DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) < Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize * 1.25f)
&& DrawArgs.Camera.ViewFrustum.Intersects(BoundingBox)
)
Initialize();
}
if (isInitialized && World.Settings.VerticalExaggeration !
= verticalExaggeration || m_CurrentOpacity !
= QuadTileSet.Opacity ||
QuadTileSet.RenderStruts !
= renderStruts)
{
//创建瓦片网格(重点)
CreateTileMesh();
}
if (isInitialized)
{
//判断进入下一层的条件(ViewRange角度、球面距离、可视区域)
if (DrawArgs.Camera.ViewRange < Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize)
&& MathEngine.SphericalDistance(CenterLatitude, CenterLongitude,
DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) < Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- WorldWind 系列 十四 DEM 数据 加载 应用 SRTM