private int GetWidth()
        {
            if (!TrackResults)
            {
                return(0);
            }

            var visits = Visits.ToArray();

            int xMin = visits.OrderBy(kvp => kvp.Key.X).First().Key.X;
            int xMax = visits.OrderByDescending(kvp => kvp.Key.X).First().Key.X;
            int xd   = Math.Abs(xMax - xMin);

            return(xd + 1);
        }
        private int GetHeight()
        {
            if (!TrackResults)
            {
                return(0);
            }

            var visits = Visits.ToArray();

            int zMin = visits.OrderBy(kvp => kvp.Key.Z).First().Key.Z;
            int zMax = visits.OrderByDescending(kvp => kvp.Key.Z).First().Key.Z;
            int zd   = Math.Abs(zMax - zMin);

            return(zd + 1);
        }
        public void SnapshotVisits()
        {
            lock (_imageSync)
            {
                if (!TrackResults)
                {
                    return;
                }

                var visits1 = Visits.ToArray();

                if (visits1.Length == 0)
                {
                    return;
                }

                long time = Environment.TickCount;

                Task <Bitmap> t = new Task <Bitmap>(v =>
                {
                    var fileId = time;

                    try
                    {
                        var visits = v as KeyValuePair <BlockCoordinates, int>[];

                        int valMax = Visits.OrderByDescending(kvp => kvp.Value).First().Value;
                        int valMin = visits.OrderBy(kvp => kvp.Value).First().Value;

                        int xMin = visits.OrderBy(kvp => kvp.Key.X).First().Key.X;
                        int xMax = visits.OrderByDescending(kvp => kvp.Key.X).First().Key.X;
                        int xd   = Math.Abs(xMax - xMin);

                        int zMin = visits.OrderBy(kvp => kvp.Key.Z).First().Key.Z;
                        int zMax = visits.OrderByDescending(kvp => kvp.Key.Z).First().Key.Z;
                        int zd   = Math.Abs(zMax - zMin);

                        int zMov = zMin < 0 ? Math.Abs(zMin) : zMin * -1;
                        int xMov = xMin < 0 ? Math.Abs(xMin) : xMin * -1;

                        //Bitmap bitmap = new Bitmap(xd + 1, zd + 1, PixelFormat.Format32bppArgb);
                        Bitmap bitmap = new Bitmap(GetWidth(), GetHeight(), PixelFormat.Format32bppArgb);

                        foreach (var visit in visits)
                        {
                            try
                            {
                                double logBase = 4;
                                double min     = Math.Abs(Math.Ceiling(Math.Log(1, logBase)));
                                if (visit.Value == 0)
                                {
                                    continue;
                                }
                                //bitmap.SetPixel(visit.Key.X + xMov, visit.Key.Z + zMov, new ColorHeatMap().GetColorForValue(visit.Value, valMax));
                                bitmap.SetPixel(visit.Key.X + xMov, visit.Key.Z + zMov, new ColorHeatMap().GetColorForValue(Math.Log(visit.Value, logBase) + min, Math.Log(valMax, logBase) + min));
                                //bitmap.SetPixel(visit.Key.X + xMov, visit.Key.Z + zMov, CreateHeatColor(Math.Log(visit.Value, logBase) + min, Math.Log(valMax, logBase) + min));
                                //bitmap.SetPixel(visit.Key.X + xMov, visit.Key.Z + zMov, CreateHeatColor(Math.Log(visit.Value + 3), Math.Log(valMax + 3)));
                                //bitmap.SetPixel(visit.Key.X + xMov, visit.Key.Z + zMov, CreateHeatColor(Math.Pow(visit.Value, 10), Math.Pow(valMax, 10)));
                                //bitmap.SetPixel(visit.Key.X + xMov, visit.Key.Z + zMov, CreateHeatColor(visit.Value, valMax));
                            }
                            catch (Exception e)
                            {
                                Log.Error($"{xd}, {zd}, {xMin}, {zMin}, {xMax}, {zMax}, X={visit.Key.X}, Z={visit.Key.Z}, {xMov}, {zMov}", e);
                                break;
                            }
                        }
                        //byte[] bytes = new byte[xd*zd*4];
                        //int i = 0;
                        //for (int x = 0; x < xd; x++)
                        //{
                        //    for (int z = 0; z < zd; z++)
                        //    {
                        //        bytes[i++*4] = image[x, z];
                        //    }
                        //}


                        //var interval = valMax/zd;
                        //for (int i = 0; i < zd; i++)
                        //{
                        //    //var value = (i * interval) + 3;
                        //    //var max = valMax;
                        //    var value = Math.Log((i*interval) + 3);
                        //    var max = Math.Log(valMax);

                        //    bitmap.SetPixel(0, i, CreateHeatColor((int) value, (decimal) max));
                        //    bitmap.SetPixel(1, i, CreateHeatColor((int) value, (decimal) max));
                        //}


                        //using (Graphics g = Graphics.FromImage(bitmap))
                        //{
                        //    int tz = 0;
                        //    for (int i = 10 - 1; i >= 0; i--)
                        //    {
                        //        var d = i*(valMax/10);
                        //        g.DrawString($"{d}={Math.Log(d) :##.00}", new Font("Arial", 8), new SolidBrush(Color.White), 2, (tz++)*zd/10f); // requires font, brush etc
                        //    }
                        //}

                        using (Graphics g = Graphics.FromImage(bitmap))
                        {
                            g.DrawString($"MiNET skylight calculation\nTime (ms): {fileId - StartTimeInMilliseconds:N0}\n{_chunkCount:N0} chunks with {(_chunkCount*16*16*256):N0} blocks\n{visits.Sum(pair => pair.Value):N0} visits", new Font("Arial", 8), new SolidBrush(Color.White), 1, 0);                             // requires font, brush etc
                        }

                        //Directory.CreateDirectory(@"D:\Temp\Light\");

                        //lock (_imageSync)
                        //{
                        //	bitmap.Save(@"D:\Temp\Light\test-" + $"{fileId :00000}.bmp", ImageFormat.Bmp);
                        //}

                        //bitmap.Dispose();
                        //GC.Collect();

                        //foreach (var visit in visits)
                        //{
                        //	Log.Debug($"Visit {visit.Key} {visit.Value} times");
                        //}

                        Log.Debug($"Made a total of {visits.Sum(pair => pair.Value):N0} visits");
                        return(bitmap);
                    }
                    catch (Exception e)
                    {
                        Log.Error("Rendering", e);
                    }

                    return(null);
                }, visits1);
                RenderingTasks.Add(t);
            }
        }