VelocityDb.Collection.Spatial.NodeLeaf.pickSeeds C# (CSharp) Method

pickSeeds() private method

private pickSeeds ( VelocityDb.Collection.Spatial.RTree rTree, Rectangle &r, NodeLeaf newNode ) : void
rTree VelocityDb.Collection.Spatial.RTree
r Rectangle
newNode NodeLeaf
return void
    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;
    }