Пример #1
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;
        }
Пример #2
0
        public static void Remove(VpNode node)
        {
            Check.Assert(node.IsLeaf, "Узел не лист");

            var parent = node.Parent;
            if (parent == null)
                return;

            if (parent.Insade == node)
            {
                var anotherNode = parent.Outsade;

                parent.Insade = anotherNode.Insade;
                parent.Outsade = anotherNode.Outsade;
                parent.IsLeaf = anotherNode.IsLeaf;
                parent.Value = anotherNode.Value;
                parent.Radius = anotherNode.Radius;

                if (parent.Insade != null)
                    parent.Insade.Parent = parent;
                if (parent.Outsade != null)
                    parent.Outsade.Parent = parent;
                return;
            }

            if (parent.Outsade == node)
            {
                var anotherNode = parent.Insade;

                parent.Insade = anotherNode.Insade;
                parent.Outsade = anotherNode.Outsade;
                parent.IsLeaf = anotherNode.IsLeaf;
                parent.Value = anotherNode.Value;
                parent.Radius = anotherNode.Radius;

                if (parent.Insade != null)
                    parent.Insade.Parent = parent;
                if (parent.Outsade != null)
                    parent.Outsade.Parent = parent;

                return;
            }

            throw new Exception("Не правильный родитель");
        }
Пример #3
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;
        }