/// <summary> /// Writes an uncompressed raw format in a "raw" folder under the config-file specified folder for later recall during super tile regeneration. /// </summary> /// <param name="locationX">Region location x.</param> /// <param name="locationY">Region location y.</param> /// <param name="locationZ">Region location z.</param> /// <param name="bitmap">Bitmap of the region.</param> public void WriteRawTile(int locationX, int locationY, int locationZ, Bitmap bitmap) { var filename = $"{TileTreeNode.MakeId(locationX, locationY, locationZ)}.tiff"; LOG.Debug($"Writing raw image file {filename} for later use."); try { bitmap.Save(Path.Combine(_rawImageFolder.FullName, filename), ImageFormat.Tiff); } catch (Exception e) { LOG.Error($"Error writing map image tile to disk: {e}"); } }
public Bitmap LoadRawTile(int locationX, int locationY, int locationZ) { var image_path = Path.Combine(_rawImageFolder.FullName, $"{TileTreeNode.MakeId(locationX, locationY, locationZ)}.tiff"); try { return(new Bitmap(Image.FromFile(image_path))); } catch (Exception e) { LOG.Warn($"Error reading raw image tile from disk: {e}"); } return(null); }
// This really doesn't belong here, but where should it be? public void RemoveDeadTiles(DataReader.RDBMap rdbMap, IEnumerable <string> superTiles) { LOG.Info("Checking for base region tiles that need to be removed."); var files = Directory.EnumerateFiles(_tileFolder.FullName); var order = string.Join(string.Empty, _tileNameFormat.Split('{') .Where(str => str.Contains("}")) .Select(str => str[0]) ); var region_tile_regex = new Regex("/" + PrepareTileFilename(Regex.Replace(_tileNameFormat, "{[XYZ]}", "([0-9]+)")) + "$"); var counter = 0; Parallel.ForEach(files, PARALLELISM_OPTIONS, (filename) => { var oldPriority = Thread.CurrentThread.Priority; Thread.CurrentThread.Priority = ThreadPriority.BelowNormal; var match = region_tile_regex.Match(filename); if (!match.Success) { return; } int x, y, z; switch (order) { case "XYZ": x = int.Parse(match.Groups[1].Value); y = int.Parse(match.Groups[2].Value); z = int.Parse(match.Groups[3].Value); break; case "XZY": x = int.Parse(match.Groups[1].Value); z = int.Parse(match.Groups[2].Value); y = int.Parse(match.Groups[3].Value); break; case "YXZ": y = int.Parse(match.Groups[1].Value); x = int.Parse(match.Groups[2].Value); z = int.Parse(match.Groups[3].Value); break; case "YZX": y = int.Parse(match.Groups[1].Value); z = int.Parse(match.Groups[2].Value); x = int.Parse(match.Groups[3].Value); break; case "ZXY": z = int.Parse(match.Groups[1].Value); x = int.Parse(match.Groups[2].Value); y = int.Parse(match.Groups[3].Value); break; //case "ZYX": default: z = int.Parse(match.Groups[1].Value); y = int.Parse(match.Groups[2].Value); x = int.Parse(match.Groups[3].Value); break; } // Delete all region tiles for regions that have been explicitly removed from the DB. For the new guy: this does not remove regions that are simply just offline. if (z == 1) { DataReader.Region region = null; try { region = rdbMap.GetRegionByLocation(x, y); } catch (KeyNotFoundException) { // Don't care } if (region == null) { // Remove the region tile. try { File.Delete(filename); counter++; } catch (IOException) { // File was in use. Skip for now. LOG.Warn($"Attempted removal of {filename} failed as file was in-use."); } } } else { // Check the super tiles for posible removals. Not a high likelyhood on a growing grid, but will happen in all other cases. var key = TileTreeNode.MakeId(x, y, z); if (!superTiles.Contains(key)) { try { File.Delete(filename); counter++; } catch (IOException) { // File was in use. Skip for now. LOG.Warn($"Attempted removal of {filename} failed as file was in-use."); } } } Thread.CurrentThread.Priority = oldPriority; }); if (counter > 0) { LOG.Info($"Deleted {counter} region tiles for removed regions and consequent super tiles."); } // Go clean up the uuid reverse lookup folder. if (_reverseLookupFolder != null) { counter = 0; var uuid_regex = new Regex("/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"); files = Directory.EnumerateFiles(_reverseLookupFolder.FullName); Parallel.ForEach(files, PARALLELISM_OPTIONS, (filename) => { var match = uuid_regex.Match(filename); if (!match.Success) { return; } // Delete all uuid lookup files for regions that have been explicitly removed from the DB. For the new guy: this does not remove regions that are simply just offline. var uuid = Guid.Parse(match.Value.Substring(1)); if (!rdbMap.GetRegionUUIDs().Contains(uuid)) { // Remove the file. try { File.Delete(filename); counter++; } catch (IOException) { // File was in use. Skip for now. LOG.Warn($"Attempted removal of {filename} failed as file was in-use."); } } }); if (counter > 0) { LOG.Info($"Deleted {counter} uuid lookup files for removed regions."); } } // Go clean up the raw image folder. if (_rawImageFolder != null) { counter = 0; var raw_image_regex = new Regex("/[^/]+.tiff$"); files = Directory.EnumerateFiles(_rawImageFolder.FullName); Parallel.ForEach(files, PARALLELISM_OPTIONS, (filename) => { var match = raw_image_regex.Match(filename); if (!match.Success) { return; } // Delete all uuid lookup files for regions that have been explicitly removed from the DB. For the new guy: this does not remove regions that are simply just offline. var key = match.Value.Substring(1, match.Value.Length - 6); if (!superTiles.Contains(key)) { // Remove the file. try { File.Delete(filename); counter++; } catch (IOException) { // File was in use. Skip for now. LOG.Warn($"Attempted removal of {filename} failed as file was in-use."); } } }); if (counter > 0) { LOG.Info($"Deleted {counter} raw image files for removed super tiles."); } } }
public void PreloadTileTrees(IEnumerable <Guid> region_ids) { _rootNodeIds.Clear(); _allNodesById.Clear(); LOG.Debug($"Preparing tree: loading bottom layer of {region_ids?.Count()} tiles..."); // Preload the base layer as given. foreach (var region_id in region_ids) { var region = _rdbMap.GetRegionByUUID(region_id); if (!region.HasKnownCoordinates()) { continue; // Skip over the regions that have no known location. } // Add all regions that would show on the same super tile to make sure a full picture is generated. var super_x = ((int)region.Location?.X >> 1) << 1; var super_y = ((int)region.Location?.Y >> 1) << 1; if (_rdbMap.GetRegionByLocation(super_x, super_y) != null) { var node = new TileTreeNode(super_x, super_y, 1); try { // Might already be added. _allNodesById.Add(node.Id, node); _rootNodeIds.Add(node.Id); } catch (ArgumentException) { // Don't care. } } if (_rdbMap.GetRegionByLocation(super_x + 1, super_y) != null) { var node = new TileTreeNode(super_x + 1, super_y, 1); try { // Might already be added. _allNodesById.Add(node.Id, node); _rootNodeIds.Add(node.Id); } catch (ArgumentException) { // Don't care. } } if (_rdbMap.GetRegionByLocation(super_x, super_y + 1) != null) { var node = new TileTreeNode(super_x, super_y + 1, 1); try { // Might already be added. _allNodesById.Add(node.Id, node); _rootNodeIds.Add(node.Id); } catch (ArgumentException) { // Don't care. } } if (_rdbMap.GetRegionByLocation(super_x + 1, super_y + 1) != null) { var node = new TileTreeNode(super_x + 1, super_y + 1, 1); try { // Might already be added. _allNodesById.Add(node.Id, node); _rootNodeIds.Add(node.Id); } catch (ArgumentException) { // Don't care. } } } // Generate tree of tiles using a bottom-up breadth-first algorithm. for (int zoom_level = 1; zoom_level < _maxZoomLevel; ++zoom_level) { LOG.Debug($"Preparing tree: loading zoom level {zoom_level + 1}..."); var current_layer_ids = new List <string>(); // Move the top layer into the current layer for the next pass. current_layer_ids.AddRange(_rootNodeIds); _rootNodeIds.Clear(); foreach (var node_id in current_layer_ids) { var branch = _allNodesById[node_id]; // Find super tile. var super_x = (branch.X >> zoom_level) << zoom_level; // = Math.floor(region.x / Math.pow(2, zoom_level)) * Math.pow(2, zoom_level) var super_y = (branch.Y >> zoom_level) << zoom_level; // = Math.floor(region.y / Math.pow(2, zoom_level)) * Math.pow(2, zoom_level) var super = new TileTreeNode(super_x, super_y, zoom_level + 1); try { // Super tile might not exist, so try adding it. _allNodesById.Add(super.Id, super); _rootNodeIds.Add(super.Id); } catch (ArgumentException) { // Tile exists, go get it using the already computed ID. super = _allNodesById[super.Id]; } // Graft the current branch onto the tree. branch.SetParent(super.Id); super.AddChild(node_id); } } LOG.Debug($"Preparing tree complete."); }