/// <summary> /// Initializes a new instance of the <see cref= "T:WorldWind.Renderable.QuadTile"/> class. /// </summary> /// <param name="south"></param> /// <param name="north"></param> /// <param name="west"></param> /// <param name="east"></param> /// <param name="level"></param> /// <param name="quadTileSet"></param> public QuadTile(double south, double north, double west, double east, int level, QuadTileSet quadTileSet) { this.South = south; this.North = north; this.West = west; this.East = east; CenterLatitude = Angle.FromDegrees(0.5f * (North + South)); CenterLongitude = Angle.FromDegrees(0.5f * (West + East)); LatitudeSpan = Math.Abs(North - South); LongitudeSpan = Math.Abs(East - West); this.Level = level; this.QuadTileSet = quadTileSet; BoundingBox = new BoundingBox((float)south, (float)north, (float)west, (float)east, (float)quadTileSet.LayerRadius, (float)quadTileSet.LayerRadius + 300000f); //localOrigin = BoundingBox.CalculateCenter(); localOrigin = MathEngine.SphericalToCartesianD(CenterLatitude, CenterLongitude, quadTileSet.LayerRadius); // To avoid gaps between neighbouring tiles truncate the origin to // a number that doesn't get rounded. (nearest 10km) localOrigin.X = (float)(Math.Round(localOrigin.X / 10000) * 10000); localOrigin.Y = (float)(Math.Round(localOrigin.Y / 10000) * 10000); localOrigin.Z = (float)(Math.Round(localOrigin.Z / 10000) * 10000); Row = MathEngine.GetRowFromLatitude(South, North - South); Col = MathEngine.GetColFromLongitude(West, North - South); }
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 { 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) { 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; 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; } qt = new QuadTile(south, north, west, east, 0, this); if (DrawArgs.Camera.ViewFrustum.Intersects(qt.BoundingBox)) { lock (m_topmostTiles.SyncRoot) m_topmostTiles.Add(key, qt); qt.Update(drawArgs); } } } } } catch (System.Threading.ThreadAbortException) { } catch (Exception caught) { Log.Write(caught); } }
/// <summary> /// 更新瓦片数据集 /// </summary> /// <param name="drawArgs"></param> public override void Update(DrawArgs drawArgs) { if (!IsInitialized) { Initialize(drawArgs); } #region 暂时没有使用 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; } } #endregion 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 { 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); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // WorldWind瓦片更新渲染方式:以当前可视区域中心位置所在瓦片向周围扩散一定半径,然后更新加载 // 此范围内的所有瓦片,每次更新加载都从0级开始向下进行递归搜索可视区域包含的瓦片,直到找到满足 // 可视高度层级的瓦片。 // 这种渲染方式存在如下问题: // 1. 瓦片拓展搜索的方式存在重复性,中心区域随着拓展半径的增加重复更新了若干次,耗费系统资源; // 2. 每次都从0级向下进行递归搜索加载瓦片的方式,虽然可以解决当某一层级缺少数据时的显示问题, // 但是也造成了系统资源的浪费,每一层级瓦片的渲染都需要将该瓦片层级之上的所有层级数据都加载, // 数据量大时影像视觉效果。 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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) { 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; 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; } qt = new QuadTile(south, north, west, east, 0, this); if (DrawArgs.Camera.ViewFrustum.Intersects(qt.BoundingBox)) { lock (m_topmostTiles.SyncRoot) m_topmostTiles.Add(key, qt); qt.Update(drawArgs); } } } } } catch (System.Threading.ThreadAbortException) { } catch (Exception caught) { Log.Write(caught); } }