示例#1
0
文件: KDTree.cs 项目: psyinf/KDTree
        /// <summary>
        /// Recursive splitting procedure
        /// </summary>
        /// <param name="parent">This is where root node goes</param>
        /// <param name="depth"></param>
        ///
        void SplitNode(KDNode parent)
        {
            // center of bounding box
            KDBounds parentBounds     = parent.bounds;
            Vector3  parentBoundsSize = parentBounds.size;

            // Find axis where bounds are largest
            int   splitAxis = 0;
            float axisSize  = parentBoundsSize.x;

            if (axisSize < parentBoundsSize.y)
            {
                splitAxis = 1;
                axisSize  = parentBoundsSize.y;
            }

            if (axisSize < parentBoundsSize.z)
            {
                splitAxis = 2;
            }

            // Our axis min-max bounds
            float boundsStart = parentBounds.min[splitAxis];
            float boundsEnd   = parentBounds.max[splitAxis];

            // Calculate the spliting coords
            float splitPivot = CalculatePivot(parent.start, parent.end, boundsStart, boundsEnd, splitAxis);

            parent.partitionAxis       = splitAxis;
            parent.partitionCoordinate = splitPivot;

            // 'Spliting' array to two subarrays
            int splittingIndex = Partition(parent.start, parent.end, splitPivot, splitAxis);

            // Negative / Left node
            Vector3 negMax = parentBounds.max;

            negMax[splitAxis] = splitPivot;

            KDNode negNode = GetKDNode();

            negNode.bounds       = parentBounds;
            negNode.bounds.max   = negMax;
            negNode.start        = parent.start;
            negNode.end          = splittingIndex;
            parent.negativeChild = negNode;

            // Positive / Right node
            Vector3 posMin = parentBounds.min;

            posMin[splitAxis] = splitPivot;

            KDNode posNode = GetKDNode();

            posNode.bounds       = parentBounds;
            posNode.bounds.min   = posMin;
            posNode.start        = splittingIndex;
            posNode.end          = parent.end;
            parent.positiveChild = posNode;

            // check if we are actually splitting it anything
            // this if check enables duplicate coordinates, but makes construction a bit slower
#if KDTREE_DUPLICATES
            if (negNode.Count != 0 && posNode.Count != 0)
            {
            #endif
            // Constraint function deciding if split should be continued
            if (ContinueSplit(negNode))
            {
                SplitNode(negNode);
            }


            if (ContinueSplit(posNode))
            {
                SplitNode(posNode);
            }

#if KDTREE_DUPLICATES
        }
#endif
        }
示例#2
0
文件: KDTree.cs 项目: psyinf/KDTree
        /// <summary>
        /// For calculating root node bounds
        /// </summary>
        /// <returns>Boundary of all Vector3 points</returns>
        KDBounds MakeBounds()
        {
            Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
            Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);

            int even = Count & ~1; // calculate even Length

            // min, max calculations
            // 3n/2 calculations instead of 2n
            for (int i0 = 0; i0 < even; i0 += 2)
            {
                int i1 = i0 + 1;

                // X Coords
                if (points[i0].x > points[i1].x)
                {
                    // i0 is bigger, i1 is smaller
                    if (points[i1].x < min.x)
                    {
                        min.x = points[i1].x;
                    }

                    if (points[i0].x > max.x)
                    {
                        max.x = points[i0].x;
                    }
                }
                else
                {
                    // i1 is smaller, i0 is bigger
                    if (points[i0].x < min.x)
                    {
                        min.x = points[i0].x;
                    }

                    if (points[i1].x > max.x)
                    {
                        max.x = points[i1].x;
                    }
                }

                // Y Coords
                if (points[i0].y > points[i1].y)
                {
                    // i0 is bigger, i1 is smaller
                    if (points[i1].y < min.y)
                    {
                        min.y = points[i1].y;
                    }

                    if (points[i0].y > max.y)
                    {
                        max.y = points[i0].y;
                    }
                }
                else
                {
                    // i1 is smaller, i0 is bigger
                    if (points[i0].y < min.y)
                    {
                        min.y = points[i0].y;
                    }

                    if (points[i1].y > max.y)
                    {
                        max.y = points[i1].y;
                    }
                }

                // Z Coords
                if (points[i0].z > points[i1].z)
                {
                    // i0 is bigger, i1 is smaller
                    if (points[i1].z < min.z)
                    {
                        min.z = points[i1].z;
                    }

                    if (points[i0].z > max.z)
                    {
                        max.z = points[i0].z;
                    }
                }
                else
                {
                    // i1 is smaller, i0 is bigger
                    if (points[i0].z < min.z)
                    {
                        min.z = points[i0].z;
                    }

                    if (points[i1].z > max.z)
                    {
                        max.z = points[i1].z;
                    }
                }
            }

            // if array was odd, calculate also min/max for the last element
            if (even != Count)
            {
                // X
                if (min.x > points[even].x)
                {
                    min.x = points[even].x;
                }

                if (max.x < points[even].x)
                {
                    max.x = points[even].x;
                }
                // Y
                if (min.y > points[even].y)
                {
                    min.y = points[even].y;
                }

                if (max.y < points[even].y)
                {
                    max.y = points[even].y;
                }
                // Z
                if (min.z > points[even].z)
                {
                    min.z = points[even].z;
                }

                if (max.z < points[even].z)
                {
                    max.z = points[even].z;
                }
            }

            KDBounds b = new KDBounds();

            b.min = min;
            b.max = max;

            return(b);
        }