/// <summary> /// Chooses which node should we enlarge with the new envelope to minimalize the overlap between the nodes /// </summary> /// <param name="entries">The nodes from we want to choose.</param> /// <param name="newEnvelope">The new envelope.</param> /// <returns></returns> private RTreeNode ChooseNode(List <RTreeNode> entries, Envelope newEnvelope) { RTreeNode minimalEntry = entries[0]; Envelope enlargedEnvelope = Envelope.FromEnvelopes(minimalEntry.Envelope, newEnvelope); Double minimalOverlap = entries.Sum(x => x != entries[0] ? ComputeOverlap(enlargedEnvelope, x.Envelope) : 0); for (Int32 i = 1; i < entries.Count; i++) { enlargedEnvelope = Envelope.FromEnvelopes(entries[i].Envelope, newEnvelope); Double overlap = entries.Sum(x => x != entries[i] ? ComputeOverlap(enlargedEnvelope, x.Envelope) : 0); if (overlap < minimalOverlap) { minimalOverlap = overlap; minimalEntry = entries[i]; } else if (overlap == minimalOverlap) { if (entries[i].ComputeEnlargement(newEnvelope) < minimalEntry.ComputeEnlargement(newEnvelope)) { minimalEntry = entries[i]; } } } return(minimalEntry); }
/// <summary> /// Splits a node into two nodes. /// </summary> /// <param name="overflownNode">The overflown node.</param> /// <param name="firstNode">The first produced node.</param> /// <param name="secondNode">The second produced node.</param> protected virtual void SplitNode(RTreeNode overflownNode, out RTreeNode firstNode, out RTreeNode secondNode) { RTreeNode firstSeed, secondSeed; PickSeeds(overflownNode.Children, out firstSeed, out secondSeed); firstNode = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren); secondNode = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren); firstNode.AddChild(firstSeed); secondNode.AddChild(secondSeed); overflownNode.Children.Remove(firstSeed); overflownNode.Children.Remove(secondSeed); while (overflownNode.ChildrenCount > 0) { RTreeNode node = PickNext(overflownNode.Children); if (firstNode.ChildrenCount + overflownNode.ChildrenCount <= MinChildren) { firstNode.AddChild(node); } else if (secondNode.ChildrenCount + overflownNode.ChildrenCount <= MinChildren) { secondNode.AddChild(node); } else { Double firstEnlargement = firstNode.ComputeEnlargement(node.Envelope); Double secondEnlargement = secondNode.ComputeEnlargement(node.Envelope); if (firstEnlargement < secondEnlargement) { firstNode.AddChild(node); } else if (firstEnlargement > secondEnlargement) { secondNode.AddChild(node); } else { if (firstNode.Envelope.Surface < secondNode.Envelope.Surface) { firstNode.AddChild(node); } else { secondNode.AddChild(node); } } } } }