Ejemplo n.º 1
0
        private KdTreeNode <TValue> Build(TValue[] elementsArray, int startIndex, int endIndex, int depth)
        {
            var length = endIndex - startIndex + 1;

            if (length == 0)
            {
                return(null);
            }

            // Sort array of elements by component of chosen dimension, in ascending magnitude.
            _valueComparer.Dimension = depth % _nrOfDimensions;

            Array.Sort(elementsArray, startIndex, length, _valueComparer);

            // Select median element as pivot.
            var medianIndex   = startIndex + length / 2;
            var medianElement = elementsArray[medianIndex];

            // Create node and construct sub-trees around pivot element.
            var node = new KdTreeNode <TValue>(medianElement);

            node.LeftChild  = Build(elementsArray, startIndex, medianIndex - 1, depth + 1);
            node.RightChild = Build(elementsArray, medianIndex + 1, endIndex, depth + 1);

            return(node);
        }
Ejemplo n.º 2
0
        public KdTree(IEnumerable <TValue> elements, params Func <TValue, double>[] valueSelectors)
        {
            _nrOfDimensions = valueSelectors.Length;
            _valueSelectors = valueSelectors;
            _valueComparer  = new ValueLocationComparer(_valueSelectors);

            var elementsArray = elements.ToArray();

            _root = Build(elementsArray, 0, elementsArray.Length - 1, 0);
        }
Ejemplo n.º 3
0
        private void FindInRange(KdTreeNode <TValue> node, Vector location, double range, IList <TValue> valuesList, int depth)
        {
            if (node == null)
            {
                return;
            }

            var dimension = depth % _nrOfDimensions;

            var nodeLocation = CreateVector(node.Value);

            var distance = (nodeLocation - location).Abs();

            // add to list if its in range
            if (distance < range)
            {
                valuesList.Add(node.Value);
            }

            var nearChildNode = location[dimension] < nodeLocation[dimension] ? node.LeftChild : node.RightChild;

            if (nearChildNode != null)
            {
                FindInRange(nearChildNode, location, range, valuesList, depth + 1);
            }

            // also other half needs to be checked?
            if (range > Math.Abs(nodeLocation[dimension] - location[dimension]))
            {
                // Check for nodes in sub-tree of far child.
                var farChildNode = nearChildNode == node.LeftChild ? node.RightChild : node.LeftChild;

                if (farChildNode != null)
                {
                    FindInRange(farChildNode, location, range, valuesList, depth + 1);
                }
            }
        }