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