/// <summary> /// helps when image file was corrupted, arranges reload. /// </summary> /// <param name="tile"></param> /// <param name="baseName"></param> public static void resetBackdrop(Tile tile, string baseName) { string imageFileName = Path.Combine(m_mapsPath, baseName + imageExt); try { if(Project.serverAvailable) { string imageUrl = getFileUrl(tile, baseName, imageFileName); DownloadThread dt = new DownloadThread(); dt.DownloadUrl = imageUrl; dt.tile = tile; dt.baseName = baseName; dt.fileName = imageFileName; dt.CompleteCallback += new DownloadCompleteHandler( imageDownloadCompleteCallback ); dt.ProgressCallback += new DownloadProgressHandler( imageDownloadProgressCallback ); dt.addMonitoredMethod = new AddMonitoredMethod(ProgressMonitor.addMonitored); //add dt worker method to the thread pool / queue a task //Project.threadPool.PostRequest (new WorkRequestDelegate (dt.Download), baseName); ThreadPool2.QueueUserWorkItem (new WaitCallback (dt.Download), baseName); #if DEBUG LibSys.StatusBar.Trace("OK: TileCache:resetBackdrop() - tile '" + baseName + "' - loading remote from " + imageUrl); #endif } } catch (Exception e) { LibSys.StatusBar.Error("file '" + imageFileName + "' failed to load on reset: " + e.Message); } }
private static string getFileUrl(Tile tile, string baseName, string fileName) { string fileUrl = null; foreach(MappingServer ms in m_mappingServers) { #if DEBUG LibSys.StatusBar.Trace("IP: ms=" + ms); #endif if(ms.isLevelSupported(tile.Level)) { fileUrl = ms.Url + "/" + Project.mapsQuality + "/" + baseName + ms.getRightExtention(fileName); #if DEBUG LibSys.StatusBar.Trace("IP: fileUrl=" + fileUrl); #endif break; } } return fileUrl; }
public static Backdrop getBackdrop(Tile tile, string baseName) { string imageFileName = Path.Combine(m_mapsPath, baseName + imageExt); Backdrop ret = null; try { if(m_backdropCache.ContainsKey(baseName)) { ret = (Backdrop)m_backdropCache[baseName]; // may be IsEmpty, if proven that can't download ret.MarkUsed(); #if DEBUG LibSys.StatusBar.Trace("OK: TileCache:getBackdrop() - tile '" + baseName + "' - found in cache - " + ret); #endif return ret; } bool loadedFromFile = false; if(!Project.reloadRefresh && File.Exists(imageFileName)) { try { ret = new Backdrop(imageFileName, baseName, true); #if DEBUG LibSys.StatusBar.Trace("OK: TileCache:getBackdrop() - tile '" + baseName + "' - loaded from file"); #endif AddBackdrop(baseName, ret); loadedFromFile = true; } catch {} } if(!loadedFromFile && m_mappingServers.Count > 0) { string imageUrl = getFileUrl(tile, baseName, imageFileName); if(imageUrl == null) { ret = new Backdrop(null, baseName, true); // doFill with null name makes it Empty AddBackdrop(baseName, ret); return ret; } if(!m_backdropCache.ContainsKey(baseName)) { ret = new Backdrop(imageFileName, baseName, false); // fill later AddBackdrop(baseName, ret); DownloadThread dt = new DownloadThread(); dt.DownloadUrl = imageUrl; dt.tile = tile; dt.baseName = baseName; dt.fileName = imageFileName; dt.CompleteCallback += new DownloadCompleteHandler( imageDownloadCompleteCallback ); dt.ProgressCallback += new DownloadProgressHandler( imageDownloadProgressCallback ); dt.addMonitoredMethod = new AddMonitoredMethod(ProgressMonitor.addMonitored); //add dt worker method to the thread pool / queue a task //Project.threadPool.PostRequest (new WorkRequestDelegate (dt.Download)); ThreadPool2.QueueUserWorkItem (new WaitCallback (dt.Download), baseName); #if DEBUG LibSys.StatusBar.Trace("OK: TileCache:getBackdrop() - tile '" + baseName + "' - loading remote from " + imageUrl); #endif } #if DEBUG else { LibSys.StatusBar.Trace("OK: TileCache:getBackdrop() - tile '" + baseName + "' - already in cache"); } #endif } } catch (Exception e) { LibSys.StatusBar.Error("file '" + imageFileName + "' failed to load: " + e.Message); } // whatever happened before, returning null is not an option. if(ret == null) { ret = new Backdrop(null, baseName, true); // doFill with null name makes it Empty AddBackdrop(baseName, ret); } return ret; }
public static Features getFeatures(Tile tile, string baseName) { string featuresFileName = Path.Combine(m_mapsPath, baseName + featuresExt); Features ret = null; try { if(m_featuresCache.ContainsKey(baseName)) { ret = (Features)m_featuresCache[baseName]; // may be still downloading if(ret != null) { ret.MarkUsed(); } #if DEBUG LibSys.StatusBar.Trace("OK: TileCache:getFeatures() - tile '" + baseName + "' - found in cache - " + ret); #endif return ret; } bool loadedFromFile = false; if(!Project.reloadRefresh && File.Exists(featuresFileName)) { try { ret = new Features(featuresFileName, baseName, true); #if DEBUG LibSys.StatusBar.Trace("OK: TileCache:getFeatures() - tile '" + baseName + "' - loaded local"); #endif AddFeatures(baseName, ret); loadedFromFile = true; } catch {} } if(!loadedFromFile && m_mappingServers.Count > 0) { string featuresUrl = getFileUrl(tile, baseName, featuresFileName); if(featuresUrl == null) { ret = new Features(null, baseName, true); // doFill with null name makes it Empty AddFeatures(baseName, ret); return ret; } if(!m_featuresCache.ContainsKey(baseName)) { ret = new Features(featuresFileName, baseName, false); // fill later AddFeatures(baseName, ret); DownloadThread dt = new DownloadThread(); dt.DownloadUrl = featuresUrl; dt.tile = tile; dt.baseName = baseName; dt.fileName = featuresFileName; dt.CompleteCallback += new DownloadCompleteHandler( featuresDownloadCompleteCallback ); dt.ProgressCallback += new DownloadProgressHandler( featuresDownloadProgressCallback ); dt.addMonitoredMethod = new AddMonitoredMethod(ProgressMonitor.addMonitored); //add this to the thread pool / queue a task //Project.threadPool.PostRequest (new WorkRequestDelegate (dt.Download)); ThreadPool2.QueueUserWorkItem (new WaitCallback (dt.Download), baseName); #if DEBUG LibSys.StatusBar.Trace("OK: TileCache:getFeatures() - tile '" + baseName + "' - loading remote from " + featuresUrl); #endif } } } catch (Exception e) { LibSys.StatusBar.Error("file '" + featuresFileName + "' failed to load: " + e.Message); } // whatever happened before, returning null is not an option. if(ret == null) { ret = new Features(null, baseName, true); // doFill with null name makes it Empty AddFeatures(baseName, ret); } return ret; }
private void ReTile() { //LibSys.StatusBar.Trace("IP: ReTile() drawableReady=" + Project.drawableReady); if(!Project.drawableReady) // when starting, we get several resize events with different sizes, as // layout settles. We want to ignore these and retile after the first paint. { return; } // what is the picture area in degrees? // use CameraManager.m_coverageXDegrees, m_coverageYDegrees for span in degrees // what is appropriate tile resolution? double cameraHeightKm = (m_cameraManager.Location.Elev) / 1000.0d; // km string tileScale; // each tile scale has it's threshold, after which the next tile scale is used. // the idea is to use the tile while it maps closely to 1:1 in pixels, and when // the mapping requires magnification (i.e. x tile 1200x1200 --> 1300x1300 on the picture), // then use the next level if(cameraHeightKm > 5000.0d) { m_tileResolutionDegreesH = 360.0d; // degrees per tile m_tileResolutionDegreesV = 180.0d; // degrees per tile tileScale = "w"; } else if(cameraHeightKm > 2000.0d) { m_tileResolutionDegreesH = 40.0d; // degrees per tile m_tileResolutionDegreesV = 50.0d; // degrees per tile tileScale = "y"; } //else if(cameraHeightKm > 900.0d) else if(cameraHeightKm > 370.0d) { m_tileResolutionDegreesH = 10.0d; // degrees per tile m_tileResolutionDegreesV = 10.0d; // degrees per tile tileScale = "x"; } /* else if(cameraHeightKm > 370.0d) { m_tileResolutionDegreesH = 4.0d; // degrees per tile m_tileResolutionDegreesV = 4.0d; // degrees per tile tileScale = "z"; } */ else if(cameraHeightKm > 100.0d) { m_tileResolutionDegreesH = 1.0d; // degrees per tile m_tileResolutionDegreesV = 1.0d; // degrees per tile tileScale = ""; } else { m_tileResolutionDegreesH = 0.5d; // degrees per tile m_tileResolutionDegreesV = 0.5d; // degrees per tile tileScale = "a"; } // how many tiles v*h do we need to cover the picture area? GeoCoord topLeftTileCorner = getTopLeftTileCorner(m_cameraManager.CoverageTopLeft, tileScale, m_tileResolutionDegreesH, m_tileResolutionDegreesV); GeoCoord bottomRightTileCorner = getBottomRightTileCorner(m_cameraManager.CoverageBottomRight, tileScale, m_tileResolutionDegreesH, m_tileResolutionDegreesV); #if DEBUG LibSys.StatusBar.Trace("TileSet:ReTile() topLeftTileCorner=" + topLeftTileCorner + " bottomRightTileCorner=" + bottomRightTileCorner); #endif m_hCount = (int)((bottomRightTileCorner.Lng - topLeftTileCorner.Lng) / m_tileResolutionDegreesH); m_vCount = (int)((topLeftTileCorner.Lat - bottomRightTileCorner.Lat) / m_tileResolutionDegreesV); // world tile is replicated, if 180 meridian is in the picture: bool doWorldOffset = false; switch(tileScale) { case "w": if(m_cameraManager.CoverageBottomRight.Lng > 180.0d) { m_hCount++; doWorldOffset = true; } else if(m_cameraManager.CoverageTopLeft.Lng < -180.0d) { topLeftTileCorner.Lng -= 360.0d; // left tile starts there m_hCount++; doWorldOffset = true; } break; } #if DEBUG LibSys.StatusBar.Trace("TileSet:ReTile() m_vCount=" + m_vCount + " m_hCount=" + m_hCount + " doWorldOffset=" + doWorldOffset); #endif // calculate meters per pixel for selected tile scale: m_xMetersPerPixel = m_cameraManager.MetersPerPixelX(); m_yMetersPerPixel = m_cameraManager.MetersPerPixelY(); #if DEBUG LibSys.StatusBar.Trace("TileSet:ReTile() m_xMetersPerPixel=" + m_xMetersPerPixel + " m_yMetersPerPixel=" + m_yMetersPerPixel); LibSys.StatusBar.Trace("TileSet:ReTile() ----------------- before " + TileCache.ToString()); #endif double topLeftLat = topLeftTileCorner.Lat; cleanTiles(); lock(tilesLock) { m_tiles = new Tile[m_vCount, m_hCount]; for(int vv=0; vv < m_vCount ;vv++) { double topLeftLng = topLeftTileCorner.Lng; for(int hh=0; hh < m_hCount ;hh++) { GeoCoord topLeft = new GeoCoord(topLeftLng, topLeftLat, 0.0d); GeoCoord bottomRight = new GeoCoord(topLeftLng + m_tileResolutionDegreesH, topLeftLat - m_tileResolutionDegreesV, 0.0d); m_tiles[vv, hh] = new Tile(this, tileScale, topLeft, bottomRight); m_tiles[vv, hh].init(); switch(tileScale) { case "w": // world tiles use doWorldOffset around 180 meridian: if(doWorldOffset && hh > 0) { int offsetX = m_tiles[vv, hh].getFrameRectangle().Width; m_tiles[vv, hh].Offset = new Point(offsetX, 0); } break; default: m_tiles[vv, hh].Offset = new Point(0, 0); break; } #if DEBUG LibSys.StatusBar.Trace(" hh=" + hh + " ---- offset=" + m_tiles[vv, hh].getOffset()); #endif topLeftLng += m_tileResolutionDegreesH; } topLeftLat -= m_tileResolutionDegreesV; } } // lock #if DEBUG LibSys.StatusBar.Trace("TileSet:ReTile() ----------------- after " + TileCache.ToString()); #endif TileCache.purge(); double safeHeight = ((double)Project.CAMERA_HEIGHT_SAFE) * 1000.0d; if(m_cameraManager.Elev < safeHeight && (!Project.allowUnreasonableZoom && IsAllSubstitutes || IsEmpty)) { // we get here if all tiles are already in cache, and all are empty. LibSys.StatusBar.Trace("TileSet:ReTile() - all tiles empty - repositioning"); m_cameraManager.Elev = safeHeight; } }
public void tileFeaturesArrived(Tile tile) { // the features may arrive when the tile has been phased out due to TileSet.ReTile() // the tile then hangs around as a means to pass features to TileSet, which is supposed // to find appropriate location for the features. bool found = false; Features features = tile.features; lock(tilesLock) { for(int vv=0; vv < m_vCount ;vv++) { for(int hh=0; hh < m_hCount ;hh++) { Tile tt = m_tiles[vv, hh]; if(tt == tile) { // tile still in the array. // a tile with full substitute features will have same features name: if(tt.UseSubstitute && tt.features.BaseName.Equals(features.BaseName)) { tt.CreateFeaturesSubset(); tt.ProvokeFeaturesPutOnMap(); // provoke PutOnMap on the next Tile_Paint() } ArrangeFeaturesRedraw(tt); found = true; } else if((!tt.UseSubstitute && tt.baseName.Equals(tile.baseName)) || (tt.UseSubstitute && tile.UseSubstitute && tt.SubstituteName.Equals(tile.SubstituteName))) { // tile has been replaced by a similar tile if(!tt.UseSubstitute) { tt.features = features; } else if(tt.features.BaseName.Equals(features.BaseName)) { // for tiles using substitutes and not having own features subset: #if DEBUG LibSys.StatusBar.Trace(" - " + tt.baseName + " - copying features from " + features.BaseName); #endif tt.features = features; tt.CreateFeaturesSubset(); tt.ProvokeFeaturesPutOnMap(); // provoke PutOnMap on the next Tile_Paint() } ArrangeFeaturesRedraw(tt); found = true; } if(found && !tt.MayUseSubstitute) { goto endLoop; } } } endLoop: ; } // lock // tile not found - features stay in file system and cache for the future. }
public void tileBackdropArrived(Tile tile) { // the backdrop may arrive when the tile has been phased out due to TileSet.ReTile() // the tile then hangs around as a means to pass backdrop to TileSet, which is supposed // to find appropriate location for the backdrop. bool found = false; #if DEBUG LibSys.StatusBar.Trace("TileSet::tileBackdropArrived() - " + tile.ToString()); #endif lock(tilesLock) { for(int vv=0; vv < m_vCount ;vv++) { for(int hh=0; hh < m_hCount ;hh++) { Tile tt = m_tiles[vv, hh]; //LibSys.StatusBar.Trace(" = " + tt.baseName + " UseSubstitute=" + tt.UseSubstitute + " SubstituteName=" + tt.SubstituteName); if(tt == tile) { // tile still in the array #if DEBUG LibSys.StatusBar.Trace(" - still in array : " + tt.baseName); #endif if(tt.UseSubstitute && tile.backdrop.HasImage && tt.SubstituteRectangle.IsEmpty) { tt.CalculateSubstituteRectangle(); } ArrangeBackdropRedraw(tt); found = true; } else if((!tt.UseSubstitute && tt.baseName.Equals(tile.baseName)) || (tt.UseSubstitute && tile.UseSubstitute && tt.SubstituteName.Equals(tile.SubstituteName))) { // tile has been replaced by another tile with the same base name (due to ReTile()) #if DEBUG LibSys.StatusBar.Trace(" - " + tt.baseName + " - replaced by " + tile.baseName + " " + tile.backdrop); #endif tt.backdrop = tile.backdrop; if(!tt.baseName.Equals(tile.baseName)) { //tt.backdrop.MarkUsed(); tt.CalculateSubstituteRectangle(); } ArrangeBackdropRedraw(tt); found = true; } if(found && !tt.MayUseSubstitute) { goto endLoop; } } } endLoop: ; } // lock // tile not found - bitmap/backdrop stays in file system and cache for the future. }
public void ArrangeFeaturesRedraw(Tile tile) { //Point topLeft = tile.pixelTopLeft(); //Point bottomRight = tile.pixelBottomRight(); //Size size = new Size(bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); Rectangle tileRect = tile.getFrameRectangle(); //new Rectangle(topLeft, size); //LibSys.StatusBar.Trace("tileFeaturesArrived() - tileRect " + tileRect); Rectangle toDrawRect = m_pictureManager.PictureBox.Bounds; //LibSys.StatusBar.Trace("tileFeaturesArrived() - pbRect " + toDrawRect); if(m_cameraManager.Elev < 5000000.0d) // world map may span 180, redraw whole thing { toDrawRect.Intersect(tileRect); } #if DEBUG LibSys.StatusBar.Trace("tileFeaturesArrived() - tile " + tile.ToString() + " invalidating " + toDrawRect); #endif m_pictureManager.Invalidate(toDrawRect); }
public void ArrangeBackdropRedraw(Tile tile) { double safeHeight = ((double)Project.CAMERA_HEIGHT_SAFE) * 1000.0d; if(m_cameraManager.Elev < safeHeight && (!Project.allowUnreasonableZoom && IsAllSubstitutes || IsEmpty)) { // we get here if the last tile arrived empty. and whole tile set is empty. #if DEBUG LibSys.StatusBar.Trace("TileSet:tileBackdropArrived() - all tiles empty - repositioning"); #endif m_cameraManager.Elev = safeHeight; return; } if(m_cameraManager.Elev >= 5000000.0d) // world map may span 180, redraw whole thing { Rectangle toDrawRect = m_pictureManager.PictureBox.Bounds; m_pictureManager.Invalidate(toDrawRect); } else { //LibSys.StatusBar.Trace("TileSet::tileBackdropArrived() - " + tile.ToString()); //Point topLeft = tile.pixelTopLeft(); //Point bottomRight = tile.pixelBottomRight(); //Size size = new Size(bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); //Rectangle tileRect = new Rectangle(topLeft, size); Rectangle tileRect = tile.getFrameRectangle(); //new Rectangle(topLeft, size); //LibSys.StatusBar.Trace(" - tileRect " + tileRect); Rectangle toDrawRect = m_pictureManager.PictureBox.Bounds; //LibSys.StatusBar.Trace(" - pbRect " + toDrawRect); toDrawRect.Intersect(tileRect); //LibSys.StatusBar.Trace(" - " + tile.ToString() + " invalidating " + toDrawRect); m_pictureManager.Invalidate(toDrawRect); } }