Пример #1
0
        /// <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}");
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        // 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.");
        }