Beispiel #1
0
        public static Image GenerateWaypointGraphImage(ITierInfo tier, Transformation2D transformer, double strokeThickness)
        {
            // Init image
            Image image = new Image();

            image.Stretch             = Stretch.Fill;
            image.SnapsToDevicePixels = true;
            RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.NearestNeighbor);
            WriteableBitmap writeableBitmap = BitmapFactory.New((int)transformer.ProjectionXLength, (int)transformer.ProjectionYLength);
            // Create complete waypoint graph
            SymmetricKeyDictionary <IWaypointInfo, bool> connections = new SymmetricKeyDictionary <IWaypointInfo, bool>();

            foreach (var waypoint in tier.GetInfoWaypoints())
            {
                // Create and remember connections (while doing so bidirectional connections are implicitly combined to one)
                foreach (var otherWP in waypoint.GetInfoConnectedWaypoints())
                {
                    connections[waypoint, otherWP] = true;
                }
            }
            // Create connections
            foreach (var connection in connections.KeysCombined)
            {
                writeableBitmap.DrawLineAa(
                    (int)transformer.ProjectX(connection.Item1.GetInfoCenterX()),
                    (int)transformer.ProjectY(connection.Item1.GetInfoCenterY()),
                    (int)transformer.ProjectX(connection.Item2.GetInfoCenterX()),
                    (int)transformer.ProjectY(connection.Item2.GetInfoCenterY()),
                    Colors.Black,
                    (int)Math.Ceiling(strokeThickness * 3));
            }
            // Return it
            image.Source = writeableBitmap;
            return(image);
        }
Beispiel #2
0
        /// <summary>
        /// Builds and renders the heatmap.
        /// </summary>
        private void BuildHeatmap()
        {
            // Prepare datapoints for a bit more efficient calculation
            _logger("Preparing dataset ...");
            HashSet <HeatDatapoint>[,] datapointMap = new HashSet <HeatDatapoint> [_heatmap.GetLength(0), _heatmap.GetLength(1)];
            foreach (var datapoint in _dataPoints)
            {
                int xIndex = (int)(datapoint.X / _tier.GetInfoLength() * _heatmap.GetLength(0));
                int yIndex = (int)(datapoint.Y / _tier.GetInfoWidth() * _heatmap.GetLength(1));
                if (datapointMap[xIndex, yIndex] == null)
                {
                    datapointMap[xIndex, yIndex] = new HashSet <HeatDatapoint>();
                }
                datapointMap[xIndex, yIndex].Add(datapoint);
            }
            // Actually calculate all the heat information
            _logger("Calculating heatmap ...");
            DateTime lastLog = DateTime.MinValue; TimeSpan minLogInterval = TimeSpan.FromSeconds(3);
            int      counter = 0; int overallCount = _heatmap.GetLength(0) * _heatmap.GetLength(1);

            Parallel.For(0, _heatmap.GetLength(0), (int x) => // Calculate heat values in parallel across the rows
            {
                for (int y = 0; y < _heatmap.GetLength(1); y++)
                {
                    _heatmap[x, y] = GetHeatValue(datapointMap, x, y);
                    counter++;
                    if (DateTime.Now - lastLog > minLogInterval)
                    {
                        _logger(counter + " / " + overallCount);
                        lastLog = DateTime.Now;
                    }
                }
            });
            _logger(overallCount + " / " + overallCount);
            // Handle logarithmic transformation, if desired
            if (_config.Logarithmic)
            {
                // If logarithmic values are desired, shift all values to numbers greater or equal to 1 first
                double minValue     = _heatmap.Cast <double>().Min(v => v);
                double offsetForLog = minValue < 1 ? 1 - minValue : 0;
                if (_config.Logarithmic && offsetForLog > 0)
                {
                    for (int x = 0; x < _heatmap.GetLength(0); x++)
                    {
                        for (int y = 0; y < _heatmap.GetLength(1); y++)
                        {
                            _heatmap[x, y] += offsetForLog;
                        }
                    }
                }
                // Transform to logarithmic values if desired
                for (int x = 0; x < _heatmap.GetLength(0); x++)
                {
                    for (int y = 0; y < _heatmap.GetLength(1); y++)
                    {
                        _heatmap[x, y] = _heatmap[x, y] <= 0 ? 0 : Math.Log10(_heatmap[x, y]);
                    }
                }
            }
            // Normalize the heat to [0,1]
            _logger("Normalizing heatmap ...");
            double maxHeat = double.MinValue;

            for (int x = 0; x < _heatmap.GetLength(0); x++)
            {
                for (int y = 0; y < _heatmap.GetLength(1); y++)
                {
                    maxHeat = Math.Max(maxHeat, _heatmap[x, y]);
                }
            }
            for (int x = 0; x < _heatmap.GetLength(0); x++)
            {
                for (int y = 0; y < _heatmap.GetLength(1); y++)
                {
                    _heatmap[x, y] /= maxHeat;
                }
            }
            // Render the heat overlay
            _logger("Rendering heatmap ...");
            _contentControl.Dispatcher.Invoke(() =>
            {
                // Init image
                Image image = new Image();
                RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.NearestNeighbor);
                image.Opacity    = 0.7;
                int bitmapWidth  = (int)_transformer.ProjectXLength(_heatmap.GetLength(0));
                int bitmapHeight = (int)_transformer.ProjectYLength(_heatmap.GetLength(1));
                WriteableBitmap writeableBitmap = BitmapFactory.New(bitmapWidth + 1, bitmapHeight + 1); // TODO hotfixing the missing 1-pixel column and row by increasing the size of the bitmap by 1 in each direction
                // Draw all tiles
                for (int x = 0; x < _heatmap.GetLength(0); x++)
                {
                    for (int y = 0; y < _heatmap.GetLength(1); y++)
                    {
                        int x1      = (int)_transformer.ProjectX(x);
                        int y1      = (int)_transformer.ProjectY(y + 1.0);
                        int x2      = (int)_transformer.ProjectX(x + 1.0);
                        int y2      = (int)_transformer.ProjectY(y);
                        Color color = _config.BichromaticColoring ?
                                      HeatVisualizer.GenerateBiChromaticHeatColor(_config.BichromaticColorOne, _config.BichromaticColorTwo, _heatmap[x, y]) :
                                      HeatVisualizer.GenerateHeatColor(_heatmap[x, y]);
                        writeableBitmap.FillRectangle(x1, y1, x2, y2, color);
                    }
                }
                image.Source = writeableBitmap;
                ResultImage  = image;
                // Add the image to the canvas (in background, if desired)
                if (_config.DrawInBackground)
                {
                    _contentControl.Children.Insert(0, image);
                }
                else
                {
                    _contentControl.Children.Add(image);
                }
            });
            // Finished
            _logger("Heatmap done!");
        }