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); }
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); }
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); } }