在这里我们看到判断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()方法中计算可视范围:
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 }
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 |
以上不知道分析的对不对!