/// <summary> /// Creates a new updatable R-Tree instance. /// </summary> /// <param name="geoFactory"> /// An <see cref="IGeometryFactory"/> for creating extent instances. /// </param> /// <param name="insertStrategy"> /// Strategy used to insert new entries into the index. /// </param> /// <param name="nodeSplitStrategy"> /// Strategy used to split nodes when they are full. /// </param> /// <param name="heuristic"> /// Heuristics used to build the index and keep it balanced. /// </param> public DynamicRTree( IGeometryFactory geoFactory, IItemInsertStrategy <IExtents, TItem> insertStrategy, INodeSplitStrategy <IExtents, TItem> nodeSplitStrategy, DynamicRTreeBalanceHeuristic heuristic) : base(geoFactory) { if (insertStrategy == null) { throw new ArgumentNullException("insertStrategy"); } if (nodeSplitStrategy == null) { throw new ArgumentNullException("nodeSplitStrategy"); } if (heuristic == null) { throw new ArgumentNullException("heuristic"); } _insertStrategy = insertStrategy; _nodeSplitStrategy = nodeSplitStrategy; _heuristic = heuristic; }
public ISpatialIndexNode <IExtents, TItem> SplitNode( ISpatialIndexNode <IExtents, TItem> node, IndexBalanceHeuristic heuristic) { if (node == null) { throw new ArgumentNullException("node"); } RTreeNode <TItem> rTreeNode = node as RTreeNode <TItem>; Debug.Assert(rTreeNode != null); DynamicRTreeBalanceHeuristic rTreeHueristic = heuristic as DynamicRTreeBalanceHeuristic; return(doSplit(rTreeNode, rTreeHueristic)); }
/// <summary> /// Creates a new SelfOptimizingDynamicSpatialIndex. /// </summary> /// <param name="geoFactory">An <see cref="IGeometryFactory"/> instance.</param> /// <param name="restructureStrategy">The strategy used to restructure the index.</param> /// <param name="restructureHeuristic">The heuristic to control when the index is restructured.</param> /// <param name="insertStrategy">The strategy used to insert entries into the index.</param> /// <param name="nodeSplitStrategy">The strategy used to split index nodes.</param> /// <param name="indexHeuristic">A heuristic used to balance the index for optimum efficiency.</param> /// <param name="idleMonitor">A monitor to determine idle conditions on the executing machine.</param> public SelfOptimizingDynamicSpatialIndex(IGeometryFactory geoFactory, IIndexRestructureStrategy <IExtents, TItem> restructureStrategy, RestructuringHuristic restructureHeuristic, IItemInsertStrategy <IExtents, TItem> insertStrategy, INodeSplitStrategy <IExtents, TItem> nodeSplitStrategy, DynamicRTreeBalanceHeuristic indexHeuristic, IdleMonitor idleMonitor) : base(geoFactory, insertStrategy, nodeSplitStrategy, indexHeuristic) { _periodMilliseconds = restructureHeuristic.WhenToRestructure == RestructureOpportunity.Periodic ? (Int32)(restructureHeuristic.Period / 1000.0) : -1; _restructureStrategy = restructureStrategy; _restructuringHeuristic = restructureHeuristic; _idleMonitor = idleMonitor; _userIdleEvent = new AutoResetEvent(false); _machineIdleEvent = new AutoResetEvent(false); _terminateEvent = new ManualResetEvent(false); if (restructureHeuristic.WhenToRestructure != RestructureOpportunity.None) { _restructureThread = new Thread(doRestructure); _restructureThread.Start(); } RestructureOpportunity idle = RestructureOpportunity.OnMachineIdle | RestructureOpportunity.OnUserIdle; if (((Int32)(restructureHeuristic.WhenToRestructure & idle)) > 0) { if (_idleMonitor == null) { throw new ArgumentNullException("idleMonitor", "If the restructuring heuristic has a value of anything but " + "None for WhenToRestructure, the idleMonitor cannot be null."); } _idleMonitor.UserIdle += _idleMonitor_UserIdle; _idleMonitor.UserBusy += _idleMonitor_UserBusy; _idleMonitor.MachineIdle += _idleMonitor_MachineIdle; _idleMonitor.MachineBusy += _idleMonitor_MachineBusy; } }
private RTreeNode <TItem> doSplit(RTreeNode <TItem> node, DynamicRTreeBalanceHeuristic heuristic) { Boolean isLeaf = node.IsLeaf; IEnumerable <IBoundable <IExtents> > boundables; Int32 boundablesCount; if (isLeaf) { boundables = Caster.Upcast <IBoundable <IExtents>, TItem>(node.Items); boundablesCount = node.ItemCount; } else { boundables = Caster.Upcast <IBoundable <IExtents>, ISpatialIndexNode <IExtents, TItem> >(node.SubNodes); boundablesCount = node.SubNodeCount; } List <IBoundable <IExtents> > entries = new List <IBoundable <IExtents> >(boundablesCount); entries.AddRange(boundables); IBoundable <IExtents>[] group1 = new IBoundable <IExtents> [heuristic.NodeItemMaximumCount]; IBoundable <IExtents>[] group2 = new IBoundable <IExtents> [heuristic.NodeItemMaximumCount]; pickSeeds(entries, group1, group2); Int32 group1Count = 1, group2Count = 1; distribute(entries, group1, group2, heuristic, ref group1Count, ref group2Count); if (entries.Count > 0) { if (group1Count < group2Count) { fillShortGroup(entries, group1, ref group1Count); } else // group2Count < heuristic.NodeItemMinimumCount { fillShortGroup(entries, group2, ref group2Count); } } node.Clear(); RTreeNode <TItem> sibling = (node.Index as RTree <TItem>).CreateNode(node.Level); IEnumerable <IBoundable <IExtents> > g1Sized = Enumerable.Take(group1, group1Count); IEnumerable <IBoundable <IExtents> > g2Sized = Enumerable.Take(group2, group2Count); if (isLeaf) { IEnumerable <TItem> g1Cast = Caster.Downcast <TItem, IBoundable <IExtents> >(g1Sized); node.InsertRange(g1Cast); //IEnumerable<TItem> g2Cast = Caster.Downcast<TItem, IBoundable<IExtents>>(g2Sized); sibling.AddRange(g2Sized); } else { //IEnumerable<ISpatialIndexNode<IExtents, TItem>> g1Cast // = Caster.Downcast<ISpatialIndexNode<IExtents, TItem>, IBoundable<IExtents>>(g1Sized); node.AddRange(g1Sized); //IEnumerable<ISpatialIndexNode<IExtents, TItem>> g2Cast // = Caster.Downcast<ISpatialIndexNode<IExtents, TItem>, IBoundable<IExtents>>(g2Sized); sibling.AddRange(g2Sized); } return(sibling); }