当前位置: 首页 > news >正文

[World Wind学习]22.相机高度和瓦片等级计算

在这里我们看到判断Lod的级别主要有三个条件:
 * 1、相机视角范围,视角范围越大,所包含的tileSize就越大
 * 2、相机与瓦片距离,距离越远,所包含的tileSize也就越大
 * 3、相机视锥与瓦片是否相交
 相对应我们可以把视角剔除方法理解成以下三步:
 * 1、根据视角范围,画个大圈,把大圈里的大瓦片全加进来
 * 2、根据相机与瓦片的距离进行细化瓦片,如果太远的瓦片仍然保持很大,而近处的瓦片需要进一步更新,计算子瓦片。
 * 3、每计算一个瓦片都需要判断它是否在视锥里,否则剔除身后看不到的瓦片
 在理解以上三个条件的前提下,需要理解的是视角、距离到底与tileSize有什么关系。
 对于不同级别影像或地形,ww中设置了相应的大小,根据一定的比例系数和经验参数寻找与距离和视角的关系。即通过调整参数可控制在怎样的距离下可以看到怎样级别的地形或影像。例如在地形中设置为3.0 2.9等常数,在影像中设置为TileDrawDistance和TileDrawSpread 等常数。只是反映了一定的经验参数而已。

http://blog.csdn.net/jk276993857/article/details/5937941

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()方法中计算可视范围:

1 // Old view range (used in quadtile logic)
2    double factor = (this._altitude) / this._worldRadius;
3    if(factor > 1)
4     viewRange = Angle.FromRadians(Math.PI);
5    else
6     viewRange = Angle.FromRadians(Math.Abs(Math.Asin((this._altitude) / this._worldRadius))*2);

  在QuadTile和SurfaceTile的Update()方法中,一项任务就是:初始化可见瓦片的瓦片;将视点中心部分瓦片细化,外围不细化。首先初始化瓦片,

1 if (!isInitialized)
2     {
3         if (DrawArgs.Camera.ViewRange * 0.5f < Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize)&&
4             MathEngine.SphericalDistance(CenterLatitude, CenterLongitude, DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) < Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize * 1.25f) && DrawArgs.Camera.ViewFrustum.Intersects(BoundingBox)
7            )
8            Initialize();
9      }

  接着细化,对于超出可视范围的剔除:

 1 if (isInitialized && World.Settings.VerticalExaggeration != verticalExaggeration || m_CurrentOpacity != QuadTileSet.Opacity ||
 2                     QuadTileSet.RenderStruts != renderStruts)
 3                 {
 4                     CreateTileMesh();
 5                 }
 6 
 7                 if (isInitialized)
 8                 {
 9                     if (DrawArgs.Camera.ViewRange < Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize)
10     && MathEngine.SphericalDistance(CenterLatitude, CenterLongitude,
11                             DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) < Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize)
12     && DrawArgs.Camera.ViewFrustum.Intersects(BoundingBox)
13                         )
14                     {
15                         if (northEastChild == null || northWestChild == null || southEastChild == null || southWestChild == null)
16                         {
17                             ComputeChildren(drawArgs);
18                         }
19 
20                         if (northEastChild != null)
21                         {
22                             northEastChild.Update(drawArgs);
23                         }
24 
25                         if (northWestChild != null)
26                         {
27                             northWestChild.Update(drawArgs);
28                         }
29 
30                         if (southEastChild != null)
31                         {
32                             southEastChild.Update(drawArgs);
33                         }
34 
35                         if (southWestChild != null)
36                         {
37                             southWestChild.Update(drawArgs);
38                         }
39                     }
40                     else
41                     {
42                         if (northWestChild != null)
43                         {
44                             northWestChild.Dispose();
45                             northWestChild = null;
46                         }
47 
48                         if (northEastChild != null)
49                         {
50                             northEastChild.Dispose();
51                             northEastChild = null;
52                         }
53 
54                         if (southEastChild != null)
55                         {
56                             southEastChild.Dispose();
57                             southEastChild = null;
58                         }
59 
60                         if (southWestChild != null)
61                         {
62                             southWestChild.Dispose();
63                             southWestChild = null;
64                         }
65                     }
66                 }
67 
68                 if (isInitialized)
69                 {
70                     if (DrawArgs.Camera.ViewRange / 2 > Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize * 1.5f)
71                             || MathEngine.SphericalDistance(CenterLatitude, CenterLongitude, DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) > Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize * 1.5f))
72                     {
73                         if (Level != 0 || (Level == 0 && !QuadTileSet.AlwaysRenderBaseTiles))
74                             this.Dispose();
75                     }
76                 }
View Code

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.2536
瓦片纹理大小(像素)512512
Level 0 Tile赤道分辨率(m) =2*PI*R/360*Tile0/512489.1969817827.152

  以上不知道分析的对不对!

相关文章:

  • 修改apache+php上传文件大小限制
  • paip.mysql 性能测试 报告 home right
  • 我的2013校招总结
  • C语言函数可变长度参数剖析
  • 当本机通过代理服务器上网时,本机无法打开在本机上的虚拟机(oracle vm)linux系统上的网站,但是局域网里的其他机器却可以打开...
  • API编程基本控件使用
  • SCOM 常识概念—图标状态/维护模式
  • 学习电商路线
  • SDL2.0上手试用
  • static 与 extern 关键字描述说明
  • Java对象引用处理机制
  • HTML5 UI框架Kendo UI Web中如何创建自定义组件(二)
  • WIKI系统及MysQL数据库宕机恢复文档
  • Intellij IDEA快捷键
  • OpenCV学习(38) 人脸识别(3)
  • @jsonView过滤属性
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • express如何解决request entity too large问题
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • unity如何实现一个固定宽度的orthagraphic相机
  • Xmanager 远程桌面 CentOS 7
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 仿天猫超市收藏抛物线动画工具库
  • 构建二叉树进行数值数组的去重及优化
  • 关于字符编码你应该知道的事情
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 前端知识点整理(待续)
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 白色的风信子
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • ionic入门之数据绑定显示-1
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • 阿里云ACE认证之理解CDN技术
  • 进程与线程(三)——进程/线程间通信
  • #if #elif #endif
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (ros//EnvironmentVariables)ros环境变量
  • (动态规划)5. 最长回文子串 java解决
  • (二)springcloud实战之config配置中心
  • (六)Hibernate的二级缓存
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (十三)Maven插件解析运行机制
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (原)本想说脏话,奈何已放下
  • (转)shell中括号的特殊用法 linux if多条件判断
  • (转)程序员疫苗:代码注入
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • . Flume面试题
  • .Net - 类的介绍
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)