Beispiel #1
0
 public int QDist(Rgb color)
 {
     return Math.Abs(color.R - R) + Math.Abs(color.G - G) + Math.Abs(color.B - B);
 }
Beispiel #2
0
        public static VpNode CreateTree(Rgb[] colors)
        {
            var root = new VpNode();

            var candidats = new Stack<Tuple<VpNode, Rgb[]>>();
            candidats.Push(Tuple.Create(root, colors));
            while (candidats.Count > 0)
            {
                var candidat = candidats.Pop();
                var node = candidat.Item1;
                var allColors = candidat.Item2;
                var color = allColors[0];

                if (allColors.Length == 1)
                {
                    node.Value = color;
                    node.IsLeaf = true;
                    continue;
                }

                var sorted = allColors.OrderBy(x => color.QDist(x)).ToArray();
                var medianIndex = (sorted.Length - 1) / 2; //2 - 0, 3 - 1, 4 - 1, 5 - 2

                var inside = new VpNode { Parent = node };
                var insideColors = new Rgb[medianIndex + 1];
                Array.Copy(sorted, insideColors, medianIndex + 1);
                candidats.Push(Tuple.Create(inside, insideColors));

                var outside = new VpNode { Parent = node };
                var outsideColors = new Rgb[sorted.Length - (medianIndex + 1)];
                Array.Copy(sorted, medianIndex + 1, outsideColors, 0, sorted.Length - (medianIndex + 1));
                candidats.Push(Tuple.Create(outside, outsideColors));

                node.Value = color;
                node.Radius = sorted[medianIndex].QDist(color);
                node.Insade = inside;
                node.Outsade = outside;
            }

            return root;
        }
Beispiel #3
0
        public static VpNode Near(VpNode root, Rgb target)
        {
            long bestQDist = uint.MaxValue;
            VpNode bestCandidat = null;

            int i=0;
            var candidats = new Stack<VpNode>();
            candidats.Push(root);

            while (candidats.Count > 0)
            {
                i++;
                var node = candidats.Pop();

                long dist = node.Value.QDist(target);
                if(!node.IsLeaf)
                    dist = dist + node.Radius;

                Check.Assert(dist >= 0);

                if (dist <= bestQDist) // = чтобы добраться до листьев
                {
                    bestQDist = dist;
                    bestCandidat = node;
                }

                dist = node.Value.QDist(target);

                if (node.Outsade != null && !(dist < node.Radius - bestQDist))
                    candidats.Push(node.Outsade);

                if (node.Insade != null && !(dist > bestQDist + node.Radius))
                    candidats.Push(node.Insade);
            }
            //Console.WriteLine(i);
            Check.Assert(bestCandidat.IsLeaf, "Узел не лист");

            return bestCandidat;
        }
Beispiel #4
0
        static void Main(string[] args)
        {
            //2-8
            const int colorBits = 8;
            const int colorCount = 1 << (colorBits);
            const int width = 4096;
            const int height = colorCount * colorCount * colorCount / width;

            var allColors = new List<Rgb>();
            for (int r = 0; r < colorCount; ++r)
                for (int g = 0; g < colorCount; ++g)
                    for (int b = 0; b < colorCount; ++b)
                        allColors.Add(new Rgb((byte)(r * 256 / colorCount), (byte)(g * 256 / colorCount), (byte)(b * 256 / colorCount)));

            //var tree = VpTree.CreateTree(allColors.ToArray());

            var rnd = new Random();
            for(int i=allColors.Count - 1; i > 0; --i )
            {
                var rand = rnd.Next(i);
                var t = allColors[i];
                allColors[i] = allColors[rand];
                allColors[rand] = t;
            }

            var front = new List<YX>();
            //front.Add(new YX((ushort)rnd.Next(height), (ushort)rnd.Next(width)));
            //front.Add(new YX((ushort)rnd.Next(height), (ushort)rnd.Next(width)));
            //front.Add(new YX((ushort)rnd.Next(height), (ushort)rnd.Next(width)));
            //front.Add(new YX((ushort)rnd.Next(height), (ushort)rnd.Next(width)));
            //front.Add(new YX((ushort)rnd.Next(height), (ushort)rnd.Next(width)));
            //front.Add(new YX((ushort)rnd.Next(height), (ushort)rnd.Next(width)));
            front.Add(new YX((ushort)(height/2), (ushort)(width/2)));

            Func<YX> ololo = () =>
            {
                var rndIndex = rnd.Next(front.Count);
                var lastIndex = front.Count - 1;
                var result = front[rndIndex];
                front[rndIndex] = front[lastIndex];
                front.RemoveAt(lastIndex);
                return result;
            };

            var neighbors = new YX[8];
            var canvas = new Rgb[height, width];
            while (front.Count > 0)
            {
                var f = ololo();
                if(canvas[f.Y, f.X].isAssigned)
                    continue;

                double r = 0, g = 0, b = 0, count = 0;
                neighbors[0] = new YX((ushort)(f.Y - 1), (ushort)(f.X - 1));
                neighbors[1] = new YX((ushort)(f.Y - 1), (ushort)(f.X + 0));
                neighbors[2] = new YX((ushort)(f.Y - 1), (ushort)(f.X + 1));
                neighbors[3] = new YX((ushort)(f.Y + 0), (ushort)(f.X - 1));
                neighbors[4] = new YX((ushort)(f.Y + 0), (ushort)(f.X + 1));
                neighbors[5] = new YX((ushort)(f.Y + 1), (ushort)(f.X - 1));
                neighbors[6] = new YX((ushort)(f.Y + 1), (ushort)(f.X + 0));
                neighbors[7] = new YX((ushort)(f.Y + 1), (ushort)(f.X + 1));

                Rgb qwe = new Rgb();
                int randIndex = 1;
                foreach (var n in neighbors)
                {
                    if (n.X < 0 || n.Y < 0 || n.X >= width || n.Y >= height)
                        continue;

                    var c = canvas[n.Y, n.X];
                    if (!c.isAssigned)
                    {
                        front.Add(n);
                        continue;
                    }

                    if (rnd.Next(randIndex) == 0)
                    {
                        r = c.R;
                        g = c.G;
                        b = c.B;
                    }
                    randIndex++;

                    count++;
                }
                if (count > 0)
                {
                    //r /= count;
                    //g /= count;
                    //b /= count;
                }
                else
                {
                    r = rnd.Next(256);
                    g = rnd.Next(256);
                    b = rnd.Next(256);
                }

                r = (int)Math.Round(r + (rnd.Next(5) - 2));
                g = (int)Math.Round(g + (rnd.Next(5) - 2));
                b = (int)Math.Round(b + (rnd.Next(5) - 2));
                if (r < 0)
                    r = 0;
                if (g < 0)
                    g = 0;
                if (b < 0)
                    b = 0;

                if (r > 255)
                    r = 255;
                if (g > 255)
                    g = 255;
                if (b > 255)
                    b = 255;

                int minLen = int.MaxValue;
                //int randIndex = 1;
                int bestIndex = 0;
                //for (int i = 0; i < allColors.Count; ++i)
                //{
                //    var color = allColors[i];
                //    var len = Math.Abs(color.R - r) + Math.Abs(color.G - g) + Math.Abs(color.B - b);
                //    if(len < minLen)
                //    {
                //        randIndex = 1;
                //        minLen = len;
                //        bestIndex = i;
                //    }
                //    else if(len == minLen)
                //    {
                //        randIndex++;
                //        if (rnd.Next(randIndex) == 0)
                //            bestIndex = i;
                //    }
                //}
                canvas[f.Y, f.X] = new Rgb((byte)r, (byte)g, (byte)b);// allColors[bestIndex];

                allColors[bestIndex] = allColors[allColors.Count-1];
                allColors.RemoveAt(allColors.Count-1);

                if (allColors.Count % 10000 == 0)
                    Console.WriteLine(allColors.Count);
            }

            using (var bitmap = new Bitmap(width, height))
            {
                for (int y = 0; y < height; ++y)
                    for (int x = 0; x < width; ++x)
                    {
                        var c = canvas[y, x];
                        bitmap.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B));
                    }

                Directory.CreateDirectory("Out");
                bitmap.Save("Out\\Image_" + DateTime.Now.Ticks + ".png");
            }
        }