[World Wind学习]22.相机高度和瓦片等级计算
|
在这里我们看到判断Lod的级别主要有三个条件: |
1.采用dstile制作WW瓦片,需要传人参数Level0的大小和建立金字塔的等级,这是一种自顶向下的方法。顶是指金字塔的顶部。
创建瓦片的通用命令行格式如下:
dstile.exe tile --lztsd tile_size --wwcache --overviews output_directory georeferenced_image_file(s)
参数如下:
tile_size - 0图层瓦片大小,十进制数,能被180正常(最好为180/(2^N))。
output_directory - 瓦片金字塔的输出路径。(如何没有盘符只要文件夹名,是在FWTool安装目录下)
georeferenced_image_file(s) - 影像数据的完整路径(如果影像数据在FWTool安装目录下的文件夹下,可以使用相对路径).一系列的多重影像可以自动组合成单一的瓦片金字塔。( A list of multiple image files can be supplied and will be automatically combined into a single set of tiles.)
举例:确定金字塔的顶部大小比如2.25度,确定了0级的瓦片数量160*160,根据地球的周长,确定了每个瓦片的长度范围,对于了256pixels的瓦片,则每个像素的分辨率可知。
确定了level0的tileSize,也就间接确定了Level0显示的相机(CameraBase)高度(_altitude),通过viewRange可视范围、视域体和相机中心与瓦片球面夹角确定。
制作WW瓦片时,确定了levlZeroTileSizeDegrees后,瓦片分多少级合适应该由影像的最高精度决定。 同样的相机高度,对于不同的瓦片数据集的levelZeroTileSizeDegrees是不一样的,所以在同样的高度存在多个瓦片等级,没有一个统一的值。
CameraBase的Update()方法中计算可视范围:
// Old view range (used in quadtile logic)
double factor = (this._altitude) / this._worldRadius;
if(factor > )
viewRange = Angle.FromRadians(Math.PI);
else
viewRange = Angle.FromRadians(Math.Abs(Math.Asin((this._altitude) / this._worldRadius))*);
在QuadTile和SurfaceTile的Update()方法中,一项任务就是:初始化可见瓦片的瓦片;将视点中心部分瓦片细化,外围不细化。首先初始化瓦片,
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)
{
if (DrawArgs.Camera.ViewRange < Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize)
&& MathEngine.SphericalDistance(CenterLatitude, CenterLongitude,
DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) < Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize)
&& DrawArgs.Camera.ViewFrustum.Intersects(BoundingBox)
)
{
if (northEastChild == null || northWestChild == null || southEastChild == null || southWestChild == null)
{
ComputeChildren(drawArgs);
} if (northEastChild != null)
{
northEastChild.Update(drawArgs);
} if (northWestChild != null)
{
northWestChild.Update(drawArgs);
} if (southEastChild != null)
{
southEastChild.Update(drawArgs);
} if (southWestChild != null)
{
southWestChild.Update(drawArgs);
}
}
else
{
if (northWestChild != null)
{
northWestChild.Dispose();
northWestChild = null;
} if (northEastChild != null)
{
northEastChild.Dispose();
northEastChild = null;
} if (southEastChild != null)
{
southEastChild.Dispose();
southEastChild = null;
} if (southWestChild != null)
{
southWestChild.Dispose();
southWestChild = null;
}
}
} if (isInitialized)
{
if (DrawArgs.Camera.ViewRange / > Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize * 1.5f)
|| MathEngine.SphericalDistance(CenterLatitude, CenterLongitude, DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) > Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize * 1.5f))
{
if (Level != || (Level == && !QuadTileSet.AlwaysRenderBaseTiles))
this.Dispose();
}
}
2.Globe Mapper中默认采用的方法是根据最高精度建立ww瓦片金字塔。另外一个选项就是传人Level0参数。
WW适用SurfaceTile、QuadTile,VirtualEarth Tile,可以加载多个不同的瓦片集合QuadTileSet。而不同的QuadTileSet有不同的levelZeroTileSizeDegrees。
BingMap的瓦片体系只是一种固定的瓦片层级。由于Bing地图是正射地图,所以根据屏幕像素可以计算比例尺。但是放在球上显示,需要经过纹理映射,世界坐标转换到屏幕坐标,因此与比例尺对应似乎存在问题。
3.WW中几个参数理解尝试:
如图:AB为相机海拔高度,令AB=BC做B点切线,作CE//AB交地球与E,作EG垂直AB于G,则EG=BC=AB,若认为弧BE长度等于EG,则α的弧度值=viewRange/2。事实上α的弧度值是大于viewRange/2的。
β为相机的FOV/2,β=22.5度。α对应弧BE,包括多少个瓦片?假设β只能看到 1个(对称分布)1/2个瓦片,则弧BE大概包括tan(PI/4)/tan(PI/8)=1/tan(PI/8)=1/0.392699=2.414个。
所以QuadTileSet.TileDrawDistance=3.5 ,每个Level等级加载大约5或者(3+3)个瓦片。QuadTileSet.TileDrawSpread=2.9。
初始化时候的范围α<QuadTileSet.TileDrawDistance*tileSize,QuadTileSet.TileDrawSpread*1.25=3.625。比细化的范围大,
细化范围 2α<QuadTileSet.TileDrawDistance*tileSize,细化了(1+1)或者3个瓦片;
超过某个范围是剔除,剔除的临界范围更大些α>QuadTileSet.TileDrawDistance*tileSize*1.5=5.25*tileSize,QuadTileSet.TileDrawSpread*1.5=4.35。
回到原来的问题,通过高度如何确定显示范围的金字塔等级Level。首先需要明确当前显示的范围内金字塔等级有多个,我要中心的那个。
我想大概中心瓦片大小sizeTileCenter=AB*tan(PI/8)/R,再根据levelZeroTileSizeDegrees求出Level。
--------------------------------------------------------------------------------------------------------------------------------
WW支持改变视域体,相当于改变了Frustrm。
R*sin(α)=Altitude
临界条件:ViewRange=2*α=2*3.5*TileSize;
| 地球半径R(m) | 6378137 | |
| 赤道周长 =2*PI*R(m) | 40075016.69 | |
| Level 0瓦片 Tile0(度) | 2.25 | 36 |
| 瓦片纹理大小(像素) | 512 | 512 |
| Level 0 Tile赤道分辨率(m) =2*PI*R/360*Tile0/512 | 489.196981 | 7827.152 |
以上不知道分析的对不对!
[World Wind学习]22.相机高度和瓦片等级计算的更多相关文章
- [转]World Wind学习总结一
WW的纹理,DEM数据,及LOD模型 以earth为例 1. 地形数据: 默认浏览器纹理数据存放在/Cache/Earth/Images/NASA Landsat Imagery/NLT Landsa ...
- 从零开始一起学习SLAM | 相机成像模型
上一篇文章<从零开始一起学习SLAM | 为啥需要李群与李代数?>以小白和师兄的对话展开,受到了很多读者的好评.本文继续采用对话的方式来学习一下相机成像模型,这个是SLAM中极其重要的内容 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader)
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader) 代码工程 ...
- 人工智能范畴及深度学习主流框架,IBM Watson认知计算领域IntelligentBehavior介绍
人工智能范畴及深度学习主流框架,IBM Watson认知计算领域IntelligentBehavior介绍 工业机器人,家用机器人这些只是人工智能的一个细分应用而已.图像识别,语音识别,推荐算法,NL ...
- Three.js学习(相机,场景,渲染,形状)
相机分为透视相机和正交相机(还有第三人称相机不介绍). var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window. ...
- Python学习--22 异步I/O
在同步IO中,线程启动一个IO操作然后就立即进入等待状态,直到IO操作完成后才醒来继续执行.而异步IO方式中,线程发送一个IO请求到内核,然后继续处理其他的事情,内核完成IO请求后,将会通知线程IO操 ...
- swift学习 - tableView自适应高度1(xib autoLayout)
tableView自适应高度 效果图: 源码: class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSo ...
- python学习(22) 访问数据库
原文链接:http://www.limerence2017.com/2018/01/11/python22/ 本文介绍python如何使用数据库方面的知识. SQLite SQLite是一种嵌入式数据 ...
- OpenCV学习(22) opencv中使用kmeans算法
kmeans算法的原理参考:http://www.cnblogs.com/mikewolf2002/p/3368118.html 下面学习一下opencv中kmeans函数的使用. 首先我们 ...
随机推荐
- SQLite学习手册
在实际的应用中,SQLite作为目前最为流行的开源嵌入式关系型数据库,在系统的架构设计中正在扮演着越来越为重要的角色.和很多其它嵌入式NoSQL数据库不同的是,SQLite支持很多关系型数据库的基本特 ...
- MathType中公式不对齐怎么办
MathType是一款专门用来编辑数学公式的数学公式编辑器,利用它可以在文档中快速编辑公式,与文字完美结合,可以编辑出各种各样的数学符号与公式,省下你不少的时间. 一.对齐上标与下标 MathType ...
- 放在github pages上的静态网站怎么取消绑定自定义域名?
使用GitHub Pages搭建的静态网站绑定了自定义域名操作,但是想反悔怎么办? 删除CNAME文件,重新删除仓库,新建后均不行~ 解决办法:清除一下浏览器缓存,或者用别的浏览器打开就好了,因为之前 ...
- 【ExtJs】 ExtJs4.2 基本表单组件的使用
包含ExtJs 基本的组件radioGroup,ComboBox,File,NumberField... <%-- Created by IntelliJ IDEA. User: Adminis ...
- Don‘t talk.Just do it.
对于算法,自己掌握的还是不多.并且我发现对于一个算法的理解非常重要.也许你会发现你貌似会用某总算法但是,他一旦变形,自己就无从下手. 还有就是对于算法.最好每次都自己敲,这样不仅能添加对于算法的熟度. ...
- 【RF库Collections测试】Count Values In List
Name:Count Values In ListSource:Collections <test library>Arguments:[ list_ | value | start=0 ...
- 【RF库Collections测试】Dictionary Should Not Contain Value
Name:Dictionary Should Not Contain ValueSource:Collections <test library>Arguments:[ dictionar ...
- (使用lua++)Lua脚本和C++交互(三)
前两篇文章中介绍了C++调用lua.lua栈操作的一些相关知识. 下面说一下Lua的工具.我们下一步要用到其中的一个帮助我们的开发,其实,Lua里面有很多简化开发的工具,你可以去www.sourcef ...
- C#文件下载的几种方式
第一种:最简单的超链接方法,<a>标签的href直接指向目标文件地址,这样容易暴露地址造成盗链,这里就不说了 1.<a>标签 <a href="~/Home/d ...
- go练习4--json 序列号反序列化
//定义结构体 //首字母大写 , json:"msg_id" 是 tag type Message struct { MsgId string `json:"msg_i ...