private void pickSeeds(RTree rTree, ref Rectangle r, NodeLeaf newNode)
{
// Find extreme rectangles along all dimension. Along each dimension, find the entry whose rectangle has the highest low side, and the one
// with the lowest high side. Record the separation.
double maxNormalizedSeparation = -1; // initialize to -1 so that even overlapping rectangles will be considered for the seeds
int highestLowIndex = -1;
int lowestHighIndex = -1;
Update();
// for the purposes of picking seeds, take the MBR of the node to include the new rectangle aswell.
if (r.MinX < minimumBoundingRectangle.MinX)
minimumBoundingRectangle.MinX = r.MinX;
if (r.MinY < minimumBoundingRectangle.MinY)
minimumBoundingRectangle.MinY = r.MinY;
if (r.MaxX > minimumBoundingRectangle.MaxX)
minimumBoundingRectangle.MaxX = r.MaxX;
if (r.MaxY > minimumBoundingRectangle.MaxY)
minimumBoundingRectangle.MaxY = r.MaxY;
double mbrLenX = minimumBoundingRectangle.MaxX - minimumBoundingRectangle.MinX;
double mbrLenY = minimumBoundingRectangle.MaxY - minimumBoundingRectangle.MinY;
#if RtreeCheck
Console.WriteLine("pickSeeds(): Node = " + this);
#endif
double tempHighestLow = r.MinX;
int tempHighestLowIndex = -1; // -1 indicates the new rectangle is the seed
double tempLowestHigh = r.MaxX;
int tempLowestHighIndex = -1; // -1 indicates the new rectangle is the seed
for (int i = 0; i < entryCount; i++)
{
double tempLow = entries[i].Value.MinX;
if (tempLow >= tempHighestLow)
{
tempHighestLow = tempLow;
tempHighestLowIndex = i;
} // ensure that the same index cannot be both lowestHigh and highestLow
else
{
double tempHigh = entries[i].Value.MaxX;
if (tempHigh <= tempLowestHigh)
{
tempLowestHigh = tempHigh;
tempLowestHighIndex = i;
}
}
// PS2 [Adjust for shape of the rectangle cluster] Normalize the separations by dividing by the widths of the entire set along the corresponding dimension
double normalizedSeparation = mbrLenX == 0 ? 1 : (tempHighestLow - tempLowestHigh) / mbrLenX;
if (normalizedSeparation > 1 || normalizedSeparation < -1)
{
Console.WriteLine("Invalid normalized separation X");
}
#if RtreeCheck
Console.WriteLine("Entry " + i + ", dimension X: HighestLow = " + tempHighestLow + " (index " + tempHighestLowIndex + ")" + ", LowestHigh = " + tempLowestHigh + " (index " + tempLowestHighIndex + ", NormalizedSeparation = " + normalizedSeparation);
#endif
// PS3 [Select the most extreme pair] Choose the pair with the greatest normalized separation along any dimension.
// Note that if negative it means the rectangles overlapped. However still include overlapping rectangles if that is the only choice available.
if (normalizedSeparation >= maxNormalizedSeparation)
{
highestLowIndex = tempHighestLowIndex;
lowestHighIndex = tempLowestHighIndex;
maxNormalizedSeparation = normalizedSeparation;
}
}
// Repeat for the Y dimension
tempHighestLow = r.MinY;
tempHighestLowIndex = -1; // -1 indicates the new rectangle is the seed
tempLowestHigh = r.MaxY;
tempLowestHighIndex = -1; // -1 indicates the new rectangle is the seed
for (int i = 0; i < entryCount; i++)
{
double tempLow = entries[i].Value.MinY;
if (tempLow >= tempHighestLow)
{
tempHighestLow = tempLow;
tempHighestLowIndex = i;
} // ensure that the same index cannot be both lowestHigh and highestLow
else
{
double tempHigh = entries[i].Value.MaxY;
if (tempHigh <= tempLowestHigh)
{
tempLowestHigh = tempHigh;
tempLowestHighIndex = i;
}
}
// PS2 [Adjust for shape of the rectangle cluster] Normalize the separations by dividing by the widths of the entire set along the corresponding dimension
double normalizedSeparation = mbrLenY == 0 ? 1 : (tempHighestLow - tempLowestHigh) / mbrLenY;
if (normalizedSeparation > 1 || normalizedSeparation < -1)
{
throw new UnexpectedException("Invalid normalized separation Y");
}
#if RtreeCheck
Console.WriteLine("Entry " + i + ", dimension Y: HighestLow = " + tempHighestLow + " (index " + tempHighestLowIndex + ")" + ", LowestHigh = " + tempLowestHigh + " (index " + tempLowestHighIndex + ", NormalizedSeparation = " + normalizedSeparation);
#endif
// PS3 [Select the most extreme pair] Choose the pair with the greatest normalized separation along any dimension.
// Note that if negative it means the rectangles overlapped. However still include overlapping rectangles if that is the only choice available.
if (normalizedSeparation >= maxNormalizedSeparation)
{
highestLowIndex = tempHighestLowIndex;
lowestHighIndex = tempLowestHighIndex;
maxNormalizedSeparation = normalizedSeparation;
}
}
// At this point it is possible that the new rectangle is both highestLow and lowestHigh. This can happen if all rectangles in the node overlap the new rectangle.
// Resolve this by declaring that the highestLowIndex is the lowest Y and, the lowestHighIndex is the largest X (but always a different rectangle)
if (highestLowIndex == lowestHighIndex)
{
highestLowIndex = -1;
double tempMinY = r.MinY;
lowestHighIndex = 0;
double tempMaxX = entries[0].Value.MaxX;
for (int i = 1; i < entryCount; i++)
{
if (entries[i].Value.MinY < tempMinY)
{
tempMinY = entries[i].Value.MinY;
highestLowIndex = i;
}
else if (entries[i].Value.MaxX > tempMaxX)
{
tempMaxX = entries[i].Value.MaxX;
lowestHighIndex = i;
}
}
}
// highestLowIndex is the seed for the new node.
if (highestLowIndex == -1)
newNode.addEntry(ref r);
else
{
Rectangle entryRectangle = entries[highestLowIndex].Value;
newNode.addEntry(ref entryRectangle);
entries[highestLowIndex] = r; // move the new rectangle into the space vacated by the seed for the new node
}
// lowestHighIndex is the seed for the original node.
if (lowestHighIndex == -1)
lowestHighIndex = highestLowIndex;
rTree.entryStatus[lowestHighIndex] = ((byte)RTree.EntryStatus.assigned);
entryCount = 1;
minimumBoundingRectangle = entries[lowestHighIndex].Value;
}