Example #1
0
        private static ISpatialIndexNode <IExtents, TItem> findLeastExpandedChild(
            IEnumerable <ISpatialIndexNode <IExtents, TItem> > children,
            ComputationExtents currentBounds,
            Double leastExpandedArea,
            Double leastExpandedChildArea)
        {
            ISpatialIndexNode <IExtents, TItem> leastExpandedChild = null;

            foreach (ISpatialIndexNode <IExtents, TItem> child in children)
            {
                ComputationExtents childBounds = child.Bounds != null
                                                        ? new ComputationExtents(child.Bounds)
                                                        : new ComputationExtents();
                ComputationExtents candidateRegion = childBounds.Union(currentBounds);

                Double candidateRegionArea = candidateRegion.Area;
                Double childArea           = childBounds.Area;
                Double expandedArea        = candidateRegionArea - childArea;

                if (expandedArea < leastExpandedArea)
                {
                    leastExpandedChild     = child;
                    leastExpandedChildArea = childArea;
                    leastExpandedArea      = expandedArea;
                }
                else if (expandedArea == leastExpandedArea &&
                         childArea < leastExpandedChildArea)
                {
                    leastExpandedChild     = child;
                    leastExpandedChildArea = childArea;
                }
            }

            return(leastExpandedChild);
        }
        public ComputationExtents Intersection(ComputationExtents other)
        {
            if (XMin > other.XMax || XMax < other.XMin
                || YMin > other.YMax || YMax < other.YMin)
            {
                return new ComputationExtents();
            }

            return new ComputationExtents(
                Math.Max(XMin, other.XMin),
                Math.Max(YMin, other.YMin),
                Math.Min(XMax, other.XMax),
                Math.Min(YMax, other.YMax));
        }
Example #3
0
        public ComputationExtents Intersection(ComputationExtents other)
        {
            if (XMin > other.XMax || XMax < other.XMin ||
                YMin > other.YMax || YMax < other.YMin)
            {
                return(new ComputationExtents());
            }

            return(new ComputationExtents(
                       Math.Max(XMin, other.XMin),
                       Math.Max(YMin, other.YMin),
                       Math.Min(XMax, other.XMax),
                       Math.Min(YMax, other.YMax)));
        }
Example #4
0
        private ComputationExtents computeBounds(IBoundable <IExtents>[] entries, Int32 count)
        {
            ComputationExtents bounds = new ComputationExtents();

            for (Int32 i = 0; i < count; i++)
            {
                if (bounds.IsEmpty)
                {
                    bounds = new ComputationExtents(entries[i].Bounds);
                }
                else
                {
                    bounds = bounds.Union(new ComputationExtents(entries[i].Bounds));
                }
            }

            return(bounds);
        }
        public ComputationExtents Union(ComputationExtents other)
        {
            if (other.IsEmpty)
            {
                return this;
            }

            if (IsEmpty)
            {
                return other;
            }

            return new ComputationExtents(
                Math.Min(XMin, other.XMin),
                Math.Min(YMin, other.YMin),
                Math.Max(XMax, other.XMax),
                Math.Max(YMax, other.YMax));
        }
Example #6
0
        public ComputationExtents Union(ComputationExtents other)
        {
            if (other.IsEmpty)
            {
                return(this);
            }

            if (IsEmpty)
            {
                return(other);
            }

            return(new ComputationExtents(
                       Math.Min(XMin, other.XMin),
                       Math.Min(YMin, other.YMin),
                       Math.Max(XMax, other.XMax),
                       Math.Max(YMax, other.YMax)));
        }
Example #7
0
        private GroupBoundsLeastEnlarged pickNext(IList <IBoundable <IExtents> > entries,
                                                  ComputationExtents group1Bounds,
                                                  ComputationExtents group2Bounds,
                                                  out IBoundable <IExtents> entry)
        {
            Double maxArealDifference          = -1;
            GroupBoundsLeastEnlarged group     = GroupBoundsLeastEnlarged.Tie;
            IBoundable <IExtents>    nextEntry = null;

            foreach (IBoundable <IExtents> e in entries)
            {
                ComputationExtents bounds     = new ComputationExtents(e.Bounds);
                ComputationExtents group1Join = bounds.Union(group1Bounds);
                ComputationExtents group2Join = bounds.Union(group2Bounds);

                Double arealDifferenceGroup1 = Math.Abs(
                    group1Join.Area - group1Bounds.Area);

                Double arealDifferenceGroup2 = Math.Abs(
                    group2Join.Area - group2Bounds.Area);

                Double differenceInAreas = Math.Abs(arealDifferenceGroup1 - arealDifferenceGroup2);

                if (differenceInAreas > maxArealDifference)
                {
                    maxArealDifference = differenceInAreas;
                    nextEntry          = e;

                    if (arealDifferenceGroup1 < arealDifferenceGroup2)
                    {
                        group = GroupBoundsLeastEnlarged.Group1;
                    }
                    else if (arealDifferenceGroup2 < arealDifferenceGroup1)
                    {
                        group = GroupBoundsLeastEnlarged.Group2;
                    }
                }
            }

            entries.Remove(nextEntry);
            entry = nextEntry;
            return(group);
        }
Example #8
0
        private void distribute(IList <IBoundable <IExtents> > entries,
                                IBoundable <IExtents>[] group1,
                                IBoundable <IExtents>[] group2,
                                IndexBalanceHeuristic heuristic,
                                ref Int32 group1Count,
                                ref Int32 group2Count)
        {
            // recursion halting case #1
            if (entries.Count == 0)
            {
                return;
            }

            // recursion halting case #2
            if (group1Count == heuristic.TargetNodeCount ||
                group2Count == heuristic.TargetNodeCount)
            {
                return;
            }

            IBoundable <IExtents> entry;
            ComputationExtents    group1Bounds = computeBounds(group1, group1Count);
            ComputationExtents    group2Bounds = computeBounds(group2, group2Count);

            GroupBoundsLeastEnlarged group = pickNext(entries, group1Bounds,
                                                      group2Bounds, out entry);

            switch (group)
            {
            case GroupBoundsLeastEnlarged.Group1:
                group1[group1Count++] = entry;
                break;

            case GroupBoundsLeastEnlarged.Group2:
                group2[group2Count++] = entry;
                break;

            case GroupBoundsLeastEnlarged.Tie:
                Double group1BoundsArea = group1Bounds.Area;
                Double group2BoundsArea = group2Bounds.Area;

                if (group1BoundsArea < group2BoundsArea)
                {
                    group1[group1Count++] = entry;
                }
                else if (group2BoundsArea < group1BoundsArea)
                {
                    group2[group2Count++] = entry;
                }
                else if (group1Count < group2Count)
                {
                    group1[group1Count++] = entry;
                }
                else if (group2Count < group1Count)
                {
                    group2[group2Count++] = entry;
                }
                else if (_random.Next(0, 2) == 0)     // generates 0 or 1 randomly
                {
                    group1[group1Count++] = entry;
                }
                else
                {
                    group2[group2Count++] = entry;
                }

                break;

            default:
                throw new InvalidOperationException("Unknown group.");
            }

            distribute(entries, group1, group2, heuristic, ref group1Count, ref group2Count);
        }
Example #9
0
        private static void pickSeeds(IList <IBoundable <IExtents> > items,
                                      IBoundable <IExtents>[] group1,
                                      IBoundable <IExtents>[] group2)
        {
            Int32  group1Count = 0, group2Count = 0;
            Double largestWaste = -1;

            ComputationExtents[] allExtents = new ComputationExtents[items.Count];

            Int32 itemCount = items.Count;

            // read the bounds into local structures only once
            // for speed
            for (Int32 i = 0; i < itemCount; i++)
            {
                allExtents[i] = new ComputationExtents(items[i].Bounds);
            }

            Int32 seed1Index = -1, seed2Index = -1;

            for (Int32 i = 0; i < itemCount; i++)
            {
                for (int j = 0; j < itemCount; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }

                    ComputationExtents e1 = allExtents[i];
                    ComputationExtents e2 = allExtents[j];
                    ComputationExtents minBoundingRectangle = e1.Union(e2);
                    ComputationExtents intersection         = e1.Intersection(e2);

                    Double minBoundingArea = minBoundingRectangle.Area;
                    Double entry1Area      = e1.Area;
                    Double entry2Area      = e2.Area;

                    Double waste = (minBoundingArea - entry1Area - entry2Area)
                                   + intersection.Area;

                    if (group1Count == 0 && group2Count == 0)
                    {
                        group1[group1Count++] = items[i];
                        group2[group2Count++] = items[j];
                        seed1Index            = i;
                        seed2Index            = j;
                        largestWaste          = waste;
                        continue;
                    }

                    if (waste > largestWaste)
                    {
                        group1[0]    = items[i];
                        group2[0]    = items[j];
                        seed1Index   = i;
                        seed2Index   = j;
                        largestWaste = waste;
                    }
                }
            }

            if (seed1Index > seed2Index)
            {
                items.RemoveAt(seed1Index);
                items.RemoveAt(seed2Index);
            }
            else
            {
                items.RemoveAt(seed2Index);
                items.RemoveAt(seed1Index);
            }
        }
Example #10
0
        //private Int32 _tempSplitCount = 0;
        public void Insert(IExtents bounds,
                           TItem entry,
                           ISpatialIndexNode <IExtents, TItem> node,
                           INodeSplitStrategy <IExtents, TItem> nodeSplitStrategy,
                           IndexBalanceHeuristic heuristic,
                           out ISpatialIndexNode <IExtents, TItem> newSiblingFromSplit)
        {
            newSiblingFromSplit = null;

            // Terminating case
            if (node.IsLeaf)
            {
                node.Add(entry);

                // Handle node overflow
                if (node.ItemCount > heuristic.NodeItemMaximumCount)
                {
                    // Split the node using the given strategy
                    newSiblingFromSplit = nodeSplitStrategy.SplitNode(node, heuristic);

                    //if (++_tempSplitCount % 100 == 0)
                    //{
                    //    Debug.Print("Node split # {0}", _tempSplitCount);
                    //}
                }
            }
            else
            {
                // NOTE: Descending the tree recursively here
                // can make for a very expensive build of a tree,
                // even for moderate amounts of data.

                Double leastExpandedArea      = Double.MaxValue;
                Double leastExpandedChildArea = Double.MaxValue;

                ComputationExtents currentBounds = new ComputationExtents(bounds);

                ISpatialIndexNode <IExtents, TItem> leastExpandedChild;
                leastExpandedChild = findLeastExpandedChild(node.SubNodes,
                                                            currentBounds,
                                                            leastExpandedArea,
                                                            leastExpandedChildArea);

                Debug.Assert(leastExpandedChild != null);

                // Found least expanded child node - insert into it
                Insert(bounds, entry, leastExpandedChild, nodeSplitStrategy,
                       heuristic, out newSiblingFromSplit);

                RTreeNode <TItem> rNode = node as RTreeNode <TItem>;

                // Adjust this node...
                rNode.Bounds.ExpandToInclude(bounds);

                // Check for overflow and add to current node if it occured
                if (newSiblingFromSplit != null)
                {
                    // Add new sibling node to the current node
                    node.Add(newSiblingFromSplit);
                    newSiblingFromSplit = null;

                    // Split the current node, since the child count is too high,
                    // and return the split to the caller
                    if (node.SubNodeCount > heuristic.NodeItemMaximumCount)
                    {
                        newSiblingFromSplit = nodeSplitStrategy.SplitNode(node, heuristic);
                    }
                }
            }
        }