// Can only remove overlapping pairs. // Sort edge down and remove pairs that are not overlapping anymore. // Needs to called after SortMinEdgeDown. private void SortMaxEdgeDown(List <Edge> edgeList, int axisIndex, int edgeIndex) { var edge = edgeList[edgeIndex]; var itemInfo = edge.Info; int previousEdgeIndex = edgeIndex - 1; var previousEdge = edgeList[previousEdgeIndex]; while (edge.Position < previousEdge.Position) { var previousItemInfo = previousEdge.Info; if (previousEdge.IsMax == false) { // Remove overlapping pair. var overlap = new Pair <T>(itemInfo.Item, previousItemInfo.Item); if (_broadPhase != null) { _broadPhase.Remove(overlap); } if (EnableSelfOverlaps) { SelfOverlaps.Remove(overlap); } previousItemInfo.MinEdgeIndices[axisIndex] = edgeIndex; // Min edge was swapped up. } else { previousItemInfo.MaxEdgeIndices[axisIndex] = edgeIndex; // Max edge was swapped up. } itemInfo.MaxEdgeIndices[axisIndex] = previousEdgeIndex; // Max edge was swapped down. // Swap edges in edge list. edgeList[edgeIndex] = previousEdge; edgeList[previousEdgeIndex] = edge; edgeIndex--; previousEdgeIndex--; previousEdge = edgeList[previousEdgeIndex]; } }
// Can only remove overlapping pairs. // Sort edge up and remove pairs that are not overlapping anymore. // Needs to be called after SortMaxEdgeUp. private void SortMinEdgeUp(List <Edge> edgeList, int axisIndex, int edgeIndex) { var edge = edgeList[edgeIndex]; var itemInfo = edge.Info; int nextEdgeIndex = edgeIndex + 1; var nextEdge = edgeList[nextEdgeIndex]; while (edge.Position > nextEdge.Position) { var nextItemInfo = nextEdge.Info; if (nextEdge.IsMax) { // Remove overlapping pair. var overlap = new Pair <T>(itemInfo.Item, nextItemInfo.Item); if (_broadPhase != null) { _broadPhase.Remove(overlap); } if (EnableSelfOverlaps) { SelfOverlaps.Remove(overlap); } nextItemInfo.MaxEdgeIndices[axisIndex] = edgeIndex; // Max edge was swapped down. } else { nextItemInfo.MinEdgeIndices[axisIndex] = edgeIndex; // Min edge was swapped down. } itemInfo.MinEdgeIndices[axisIndex] = nextEdgeIndex; // Min edge was swapped up. // Swap edges in edge list. edgeList[edgeIndex] = nextEdge; edgeList[nextEdgeIndex] = edge; edgeIndex++; nextEdgeIndex++; nextEdge = edgeList[nextEdgeIndex]; } }
private void UpdateSelfOverlaps(HashSet <T> addedItems, HashSet <T> removedItems, HashSet <T> invalidItems, List <Node> invalidNodes) { if (!EnableSelfOverlaps) { return; } // If the entire partition or a substantial amount of nodes is invalid use a tree vs. tree // checks. (Faster than leaf vs. tree checks. However, we need to determine the exact // threshold at which tree vs. tree is cheaper. The current threshold of Count / 2 is just // a guess.) if (invalidItems == null || addedItems.Count + invalidItems.Count > Count / 2) { // Recompute all self-overlaps by making a tree vs. tree test. SelfOverlaps.Clear(); if (_root != null) { // Important: Do not call GetOverlaps(this) because this would lead to recursive // Update() calls! // Note: Filtering is applied in GetOverlapsImpl(this). foreach (var overlap in GetOverlapsImpl(this)) { SelfOverlaps.Add(overlap); } } } else { // Merge invalid and removed items into single set. // Store result in invalidItems. if (invalidItems.Count > 0 && removedItems.Count > 0) { // Merge smaller set into larger set. if (invalidItems.Count < removedItems.Count) { MathHelper.Swap(ref invalidItems, ref removedItems); } foreach (var item in removedItems) { invalidItems.Add(item); } } else if (removedItems.Count > 0) { invalidItems = removedItems; } // Remove invalid entries from self-overlaps. if (invalidItems.Count > 0) { var invalidOverlaps = DigitalRune.ResourcePools <Pair <T> > .Lists.Obtain(); foreach (var overlap in SelfOverlaps) { if (invalidItems.Contains(overlap.First) || invalidItems.Contains(overlap.Second)) { invalidOverlaps.Add(overlap); } } foreach (var overlap in invalidOverlaps) { SelfOverlaps.Remove(overlap); } DigitalRune.ResourcePools <Pair <T> > .Lists.Recycle(invalidOverlaps); } // Compute new overlaps for all nodes that were updated in this frame. if (invalidNodes != null) { foreach (var node in invalidNodes) { foreach (var touchedItem in GetOverlapsImpl(node)) { var overlap = new Pair <T>(node.Item, touchedItem); if (Filter == null || Filter.Filter(overlap)) { SelfOverlaps.Add(overlap); } } } } } }