Пример #1
0
        public bool Build(PointCloud pcTarget)
        {
            this.targetTreee = pcTarget;

            this.TreeVectors = pcTarget.VectorsWithIndex;


            this.sort_results = false;
            this.root         = null;

            this.Indices = new uint[pcTarget.Vectors.Length];

            this.TreeVectors = pcTarget.VectorsWithIndex;

            for (uint i = 0; i < this.TreeVectors.Count; i++)
            {
                Indices[i] = i;
            }
            root = new KDTreeNodeKennell(this);
            root = root.build_tree_for_range(0, TreeVectors.Count - 1, null);

            return(true);
        }
Пример #2
0
        // utility



        //public static void swap(ref uint a, ref uint b)
        //{
        //    uint tmp;
        //    tmp = a;
        //    a = b;
        //    b = tmp;
        //}

        //public static void swap(ref float a, ref float b)
        //{
        //    float tmp;
        //    tmp = a;
        //    a = b;
        //    b = tmp;
        //}



        #endregion

        #region base implementation

        public void Dispose()
        {
            root = null;
        }
Пример #3
0
        public KDTreeNodeKennell build_tree_for_range(int startIndex, int endIndex, KDTreeNodeKennell parent)
        {
            // recursive function to build
            KDTreeNodeKennell node = new KDTreeNodeKennell(this.Parent);

            // the newly created node.
            if (endIndex < startIndex)
            {
                return(null);  // no data in this node.
            }
            if ((endIndex - startIndex) <= thresholdForApproximateTree)
            {
                // create a leaf node.
                // always compute true bounding box for leaf node.
                for (int i = 0; i < 3; i++)
                {
                    node.box[i] = spread_in_coordinate(i, startIndex, endIndex);
                }
                node.cutAxis         = 0;
                node.cut_val         = 0f;
                node.IndexLeafVector = startIndex;
                node.endIndex        = endIndex;
                node.ChildLeft       = node.ChildRight = null;
            }
            else
            {
                //
                // Compute an APPROXIMATE bounding box for this node.
                // if parent == NULL, then this is the root node, and
                // we compute for all dimensions.
                // Otherwise, we copy the bounding box from the parent for
                // all coordinates except for the parent's cut dimension.
                // That, we recompute ourself.
                //
                int c = -1;
                //int c = 0;

                float maxspread = 0.0F;
                int   mEndIndexToBuild;
                for (int i = 0; i < 3; i++)
                {
                    if ((parent == null) || (parent.cutAxis == i))
                    {
                        node.box[i] = spread_in_coordinate(i, startIndex, endIndex);
                    }
                    else
                    {
                        node.box[i] = parent.box[i];
                    }
                    float spread = node.box[i].upper - node.box[i].lower;
                    if (spread > maxspread)
                    {
                        maxspread = spread;
                        c         = i;
                    }
                }

                if (c == -1)
                {
                    System.Windows.Forms.MessageBox.Show("Error in building the tree: The point cloud contains duplicates. Please remove the duplicates (see help)");
                    return(null);
                }
                float sum;
                float average;


                sum = 0.0F;
                for (int k = startIndex; k <= endIndex; k++)
                {
                    sum += this.Parent.TreeVectors[Convert.ToInt32(this.Parent.Indices[k])].Vector[c];
                }
                average = sum / (float)(endIndex - startIndex + 1);


                mEndIndexToBuild = select_on_coordinate_value(c, average, startIndex, endIndex);

                // move the indices around to cut on dim 'c'.
                node.cutAxis         = c;
                node.IndexLeafVector = startIndex;
                node.endIndex        = endIndex;
                node.ChildLeft       = build_tree_for_range(startIndex, mEndIndexToBuild, node);
                node.ChildRight      = build_tree_for_range(mEndIndexToBuild + 1, endIndex, node);
                if (node.ChildRight == null && node.ChildLeft == null)
                {
                    System.Windows.Forms.MessageBox.Show("Error in building tree");
                }
                if (node.ChildRight == null)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        node.box[i] = node.ChildLeft.box[i];
                    }
                    node.cut_val      = node.ChildLeft.box[c].upper;
                    node.cut_val_left = node.cut_val_right = node.cut_val;
                }
                else if (node.ChildLeft == null)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        node.box[i] = node.ChildRight.box[i];
                    }
                    node.cut_val      = node.ChildRight.box[c].upper;
                    node.cut_val_left = node.cut_val_right = node.cut_val;
                }
                else
                {
                    node.cut_val_right = node.ChildRight.box[c].lower;
                    node.cut_val_left  = node.ChildLeft.box[c].upper;
                    node.cut_val       = (node.cut_val_left + node.cut_val_right) / 2f;
                    //
                    // now recompute true bounding box as union of subtree boxes.
                    // This is now faster having built the tree, being logarithmic in
                    // N, not linear as would be from naive method.
                    //
                    for (int i = 0; i < 3; i++)
                    {
                        interval intv = new interval(
                            Math.Min(node.ChildLeft.box[i].lower, node.ChildRight.box[i].lower),
                            Math.Max(node.ChildLeft.box[i].upper, node.ChildRight.box[i].upper)
                            );
                        node.box[i] = intv;
                    }
                }
            }
            return(node);
        }