public void init() { GeoCoord topLeft = m_topLeft.Clone(); topLeft.Normalize(); GeoCoord bottomRight = m_bottomRight.Clone(); bottomRight.Normalize(); int iLat = (int)Math.Ceiling(topLeft.Lat); int iLng = (int)Math.Floor(topLeft.Lng); m_siLng = iLng; m_siLat = iLat; if(m_tileScale.Equals("z")) { // HACK: // compensate for the shift in z-level tiles // (their names point to the center, not the top left corner: iLat -= 2; iLng += 2; } string latDir = iLat < 0 ? "s" : "n"; string lngDir = iLng < 0 ? "w" : "e"; iLat = Math.Abs(iLat); iLng = Math.Abs(iLng); switch(m_tileScale) { case "w": m_level = 0; m_baseName = "world_good"; break; case "y": m_level = 1; if(iLat == 60 && latDir.Equals("s")) { m_tileBackdrop = null; return; } else { string sLng = ("" + iLng).PadLeft(3,'0'); string sLat = "" + iLat; m_baseName = m_tileScale + sLng + lngDir + sLat + latDir; } break; case "x": m_level = 2; m_baseName = m_tileScale + iLng + lngDir + iLat + latDir; break; case "z": m_level = 3; m_baseName = m_tileScale + iLng + lngDir + iLat + latDir; break; default: m_level = 4; iLat = (int)Math.Floor(bottomRight.Lat); iLng = (int)Math.Ceiling(bottomRight.Lng); if(iLng == -180) { // edge correction needed around Lng=180 iLng = 180; } latDir = iLat < 0 ? "s" : "n"; lngDir = iLng <= 0 ? "w" : "e"; m_siLng = iLng; m_siLat = iLat; iLat = Math.Abs(iLat); iLng = Math.Abs(iLng); m_baseName = m_tileScale + iLng + lngDir + iLat + latDir; break; case "a": m_level = 5; iLat = (int)Math.Floor(bottomRight.Lat); iLng = (int)Math.Ceiling(bottomRight.Lng); if(iLng == -180) { // edge correction needed around Lng=180 iLng = 180; } latDir = iLat < 0 ? "s" : "n"; lngDir = iLng <= 0 ? "w" : "e"; m_siLng = iLng; m_siLat = iLat; iLat = Math.Abs(iLat); iLng = Math.Abs(iLng); // figure out quadrant and correct the tile scale letter: double ty = topLeft.Lat - Math.Floor(topLeft.Lat); double tx = topLeft.Lng - Math.Floor(topLeft.Lng); if(ty > 0.01d && tx > 0.01d) { m_tileScale = "d"; m_aShiftX = 1; m_aShiftY = 1; } else if(tx > 0.01d) { m_tileScale = "b"; m_aShiftX = 1; } else if(ty > 0.01d) { m_tileScale = "c"; m_aShiftY = 1; } m_baseName = m_tileScale + iLng + lngDir + iLat + latDir; break; } if(MayUseSubstitute) { // calculate substitute backdrop parameters, just in case real backdrop will be missing: int substLat = (int)Math.Floor(bottomRight.Lat); if(substLat >= 0) { substLat = substLat / 10 + 1; } else if(substLat < 0 && substLat >= -10) { substLat = 0; latDir = "n"; } else { substLat = (int)Math.Ceiling(bottomRight.Lat + 0.0001d); substLat = substLat / 10; } substLat = substLat * 10; int substLng = (int)Math.Ceiling(bottomRight.Lng); if(substLng > 0) { substLng = (int)Math.Floor(topLeft.Lng); substLng = substLng / 10; } else if(substLng == 0) { // edge correction needed around Lng=0 substLng = 1; } else if(substLng == -180) { // edge correction needed around Lng=180 substLng = 17; } else { substLng = substLng / 10 - 1; } substLng = substLng * 10; m_substLng = substLng; m_substLat = substLat; substLat = Math.Abs(substLat); substLng = Math.Abs(substLng); m_substituteName = "x" + substLng + lngDir + substLat + latDir; #if DEBUG LibSys.StatusBar.Trace("Tile::init() m_substituteName=" + m_substituteName); LibSys.StatusBar.Trace("siLng=" + m_siLng + " m_substLng=" + m_substLng + " siLat=" + m_siLat + " m_substLat=" + m_substLat); #endif } //LibSys.StatusBar.Trace("Tile:init() baseName=" + m_baseName); m_tileBackdrop = TileCache.getBackdrop(this, m_baseName); // may be Empty, never null if(m_tileBackdrop.IsEmpty) { // unlikely, but we may know immediately that we need to use substitute, if feasible: if(MayUseSubstitute) { // get substitute backdrop: m_useSubstitute = true; //LibSys.StatusBar.Trace("Tile::init() - requesting backdrop substitute " + m_substituteName); m_tileBackdrop = TileCache.getBackdrop(this, m_substituteName); // may be Empty, never null if(m_tileBackdrop.IsEmpty) { m_isEmpty = true; } else if(m_tileBackdrop.HasImage) { CalculateSubstituteRectangle(); // may instead set IsEmpty } // else wait for arrival... } else { m_isEmpty = true; } } m_tileFeatures = TileCache.getFeatures(this, m_baseName); // may be Empty, never null if(m_tileFeatures.IsEmpty) { // unlikely, but we may know immediately that we need to use substitute, if feasible: if(MayUseSubstitute) { // get substitute features: #if DEBUG LibSys.StatusBar.Trace("Tile::init() - requesting features substitute " + m_substituteName); #endif m_tileFeatures = TileCache.getFeatures(this, m_substituteName); // may be Empty, never null if(m_tileFeatures.HasLoaded) { CreateFeaturesSubset(); ProvokeFeaturesPutOnMap(); // provoke PutOnMap on the next Tile_Paint() } else { #if DEBUG LibSys.StatusBar.Trace("Tile::init() - " + m_baseName + " - features hasn't loaded - nothing to copy..."); #endif } // wait for arrival... } } else { ProvokeFeaturesPutOnMap(); // provoke PutOnMap on the next Tile_Paint() } }
public void featuresArrived(Features features) { // the Features may arrive when this tile has been phased out due to TileSet.ReTile() // this tile then hangs around as a means to pass Features to TileSet, which is supposed // to find appropriate location for the Features. #if DEBUG LibSys.StatusBar.Trace("featuresArrived() - features=" + features); #endif m_tileFeatures = features; if(m_tileFeatures.IsEmpty) { // more likely, need to use substitute is discovered here. if(MayUseSubstitute) { // get substitute features: #if DEBUG LibSys.StatusBar.Trace("Tile::featuresArrived() - requesting substitute " + m_substituteName); #endif m_tileFeatures = TileCache.getFeatures(this, m_substituteName); // may be Empty, never null if(m_tileFeatures.IsEmpty) { #if DEBUG LibSys.StatusBar.Trace("Tile::featuresArrived() - got empty substitute " + m_substituteName); #endif } else { #if DEBUG LibSys.StatusBar.Trace("Tile::featuresArrived() - copying relevant features"); #endif CreateFeaturesSubset(); ProvokeFeaturesPutOnMap(); // provoke PutOnMap on the next Tile_Paint() } } } else { ProvokeFeaturesPutOnMap(); // provoke PutOnMap on the next Tile_Paint() } m_tileSet.tileFeaturesArrived(this); }
public void Dispose() { //LibSys.StatusBar.Trace("Tile:Dispose() baseName=" + m_baseName); if(m_tileBackdrop != null) { TileCache.BackdropMarkUnused(m_baseName); m_tileBackdrop = null; } if(m_tileFeatures != null) { TileCache.FeaturesMarkUnused(m_baseName); m_tileFeatures = null; } }
/// <summary> /// for substitute tiles - /// makes a subset of features out of existing features, adds it to cache (under this tile name), /// so the next time this tile is called a cache-resident subset is ready for use /// </summary> public void CreateFeaturesSubset() { Features tileFeatures = TileCache.getFeatures(this, m_baseName); if(!m_tileFeatures.HasLoaded) { #if DEBUG LibSys.StatusBar.Trace("IP: Tile::CreateFeaturesSubset() - " + m_baseName + " - not loaded yet " + m_tileFeatures); #endif return; } if(tileFeatures.HasLoaded) { #if DEBUG LibSys.StatusBar.Trace("IP: Tile::CreateFeaturesSubset() - " + m_baseName + " - found in cache " + tileFeatures); #endif } else { GeoCoord bottomRight = m_bottomRight.Clone(); bottomRight.Normalize(); GeoCoord topLeft = m_topLeft.Clone(); topLeft.Normalize(); double rightLng = bottomRight.Lng; double leftLng = topLeft.Lng; if(rightLng <= -180.0d) { rightLng += 360.0d; } double bottomLat = bottomRight.Lat; double topLat = topLeft.Lat; //LibSys.StatusBar.Trace("IP: Tile::CreateFeaturesSubset() - " + m_baseName + " - copying features related to lng:" + leftLng + "<" + rightLng + " lat:" + bottomLat + "<" + topLat + " from " + m_tileFeatures.BaseName); // we are not cloning the lo assuming that lo's belonging to a tile are not reappearing // in any other tile. That also means that we need to cut selection rectangles correctly. foreach(LiveObject lo in m_tileFeatures.List) { if(lo.Location.Lat <= topLat && lo.Location.Lat >= bottomLat && lo.Location.Lng >= leftLng && lo.Location.Lng <= rightLng) { try { //LibSys.StatusBar.WriteLine(" --- " + lo); tileFeatures.Add(lo); } catch (Exception e) { } } } tileFeatures.HasLoaded = true; tileFeatures.IsEmpty = false; } m_tileFeatures = tileFeatures; //LibSys.StatusBar.Trace("OK: Tile::CreateFeaturesSubset() - " + m_baseName + " result: " + m_tileFeatures); //TileCache.ListFeaturesCache(); }
public static void AddFeatures(string baseName, Features f) { try { m_featuresCache.Add(baseName, f); } catch (Exception e) { } }
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; }