LCOV - code coverage report
Current view: top level - util/cgm - RTreeNode.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 318 364 87.4 %
Date: 2020-06-30 00:58:45 Functions: 52 220 23.6 %
Branches: 798 2484 32.1 %

           Branch data     Line data    Source code
       1                 :            : //---------------------------------------------------------------------------
       2                 :            : // Class Name:  RTreeNode
       3                 :            : // Description: Node of Rectangle tree.  Contians many of the
       4                 :            : //              required functions for building the tree and traversing it.
       5                 :            : // The algorithm was taken from the following paper:
       6                 :            : //            Guttman, A., "R-Trees: A Dynamic Index Structure for
       7                 :            : //              Spatial Searching", Proceedings of the SIGMOD
       8                 :            : //              Conference, Boston, June 1984, p. 47-57.
       9                 :            : // Creation Date: 3/13/02
      10                 :            : // Owner:  David R. White
      11                 :            : //---------------------------------------------------------------------------
      12                 :            : 
      13                 :            : //---------------------------------
      14                 :            : //Include Files
      15                 :            : //---------------------------------
      16                 :            : #include "RTreeNode.hpp"
      17                 :            : #include "DLIList.hpp"
      18                 :            : #include "CubitMessage.hpp"
      19                 :            : 
      20                 :            : //---------------------------
      21                 :            : //Initialize Static Members
      22                 :            : //---------------------------
      23                 :            : 
      24                 :            : #ifdef INLINE_TEMPLATES
      25                 :            : #define MY_INLINE inline
      26                 :            : #else
      27                 :            : #define MY_INLINE
      28                 :            : #endif
      29                 :            : 
      30                 :            : 
      31                 :       2974 : template <class Y> MY_INLINE RTreeNode<Y>::RTreeNode (Y data, double tol,
      32                 :            :                                                       int max_children,
      33                 :            :                                                       int min_children)
      34                 :            : {
      35                 :       2974 :   maxChildren = max_children;
      36                 :       2974 :   minChildren = min_children;
      37 [ +  - ][ +  - ]:       2974 :   myChildrenNodes = new RTreeNode<Y>* [maxChildren];
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
      38                 :            :   int ii;
      39 [ +  + ][ +  + ]:      26766 :   for ( ii = 0; ii < maxChildren; ii++ )
         [ #  # ][ +  + ]
      40                 :      23792 :     myChildrenNodes[ii] = (RTreeNode<Y>*) NULL;
      41 [ -  + ][ -  + ]:       2974 :   if ( data == NULL )
         [ #  # ][ -  + ]
      42                 :            :   {
      43 [ #  # ][ #  # ]:          0 :     PRINT_ERROR("Building RTree with null data is not allowed!\n");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
      44 [ #  # ][ #  # ]:          0 :     assert(data != NULL);
         [ #  # ][ #  # ]
      45                 :            :   }
      46                 :       2974 :   myData = data;
      47                 :       2974 :   myLevel = DATA_RNODE;
      48 [ +  - ][ +  - ]:       2974 :   CubitBox temp_box = data->bounding_box();
         [ #  # ][ +  - ]
                 [ #  # ]
      49                 :            :     //Check to see if any of the min/max pairs are less than the tolerance.
      50                 :            :     //make them bigger if they are...
      51 [ +  - ][ +  - ]:       2974 :   CubitVector min = temp_box.minimum();
         [ #  # ][ +  - ]
      52 [ +  - ][ +  - ]:       2974 :   CubitVector max = temp_box.maximum();
         [ #  # ][ +  - ]
      53 [ +  - ][ +  - ]:       2974 :   if ( max.x() - min.x() < tol )
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  + ]
      54                 :            :   {
      55 [ +  - ][ +  - ]:       2074 :     min.x(min.x()-.6*tol);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
      56 [ +  - ][ +  - ]:       2074 :     max.x(max.x()+.6*tol);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
      57                 :            :   }
      58 [ +  - ][ +  - ]:       2974 :   if ( max.y() - min.y() < tol )
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  + ]
      59                 :            :   {
      60 [ +  - ][ +  - ]:       1942 :     min.y(min.y()-.6*tol);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
      61 [ +  - ][ +  - ]:       1942 :     max.y(max.y()+.6*tol);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
      62                 :            :   }
      63 [ +  - ][ +  - ]:       2974 :   if ( max.z() - min.z() < tol )
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  + ]
      64                 :            :   {
      65 [ +  - ][ +  - ]:       2024 :     min.z(min.z()-.6*tol);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
      66 [ +  - ][ +  - ]:       2024 :     max.z(max.z()+.6*tol);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
      67                 :            :   }
      68 [ +  - ][ +  - ]:       2974 :   myBoundingBox = new CubitBox(min, max);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
      69                 :       2974 :   myParent = NULL;
      70                 :       2974 :   nextChildIndex = 0;
      71                 :       2974 :   markedFlag = 0;
      72                 :       2974 :   distIsBox = 1;
      73 [ +  - ][ +  - ]:       2974 :   myDist = CUBIT_DBL_MAX;
         [ #  # ][ +  - ]
      74                 :       2974 : }
      75                 :        715 : template <class Y> MY_INLINE RTreeNode<Y>::RTreeNode (CubitBox &bounding_box,
      76                 :            :                                                       int max_children,
      77                 :            :                                                       int min_children)
      78                 :            : {  
      79                 :        715 :   maxChildren = max_children;
      80                 :        715 :   minChildren = min_children;
      81 [ +  - ][ +  - ]:        715 :   myBoundingBox = new CubitBox(bounding_box);
         [ #  # ][ +  - ]
      82 [ +  - ][ +  - ]:        715 :   myChildrenNodes = new RTreeNode<Y>* [maxChildren];
         [ #  # ][ +  - ]
      83                 :            :   int ii;
      84 [ +  + ][ +  + ]:       6435 :   for ( ii = 0; ii < maxChildren; ii++ )
         [ #  # ][ +  + ]
      85                 :       5720 :     myChildrenNodes[ii] = (RTreeNode<Y>*) NULL;
      86                 :        715 :   myData = NULL;
      87                 :        715 :   myLevel = UNSET_RNODE;
      88                 :        715 :   myParent = NULL;
      89                 :        715 :   nextChildIndex = 0;
      90                 :        715 :   markedFlag = 0;
      91                 :        715 :   distIsBox = 1;
      92                 :        715 :   myDist = CUBIT_DBL_MAX;
      93                 :        715 : }
      94                 :            : //-----------------------------------------------------------
      95                 :            : // Destructor
      96                 :            : //-----------------------------------------------------------
      97                 :       3689 : template <class Y> MY_INLINE RTreeNode<Y>::~RTreeNode()
      98                 :            : {
      99 [ +  - ][ +  - ]:       3689 :   if ( myChildrenNodes )
         [ #  # ][ +  - ]
     100 [ +  - ][ +  - ]:       3689 :     delete [] myChildrenNodes;
         [ #  # ][ +  - ]
     101 [ +  - ][ +  - ]:       3689 :   if ( myBoundingBox )
         [ #  # ][ +  - ]
     102 [ +  - ][ +  - ]:       3689 :     delete myBoundingBox;
         [ #  # ][ +  - ]
     103                 :       3689 : }
     104                 :            : 
     105                 :            : //-----------------------------------------------------------
     106                 :            : // Algorithm: insert
     107                 :            : //  Insert a new index entry e into an R-Tree.
     108                 :            : //     I1. [Find postiion for new record] Invoke choose_leaf to select
     109                 :            : //        a leaf node in l, in which to place e.
     110                 :            : //     I2. [Add record to leaf node].a) If l has room for
     111                 :            : //        another entry, install E. b) Otherwise invoke split_node to
     112                 :            : //        obtain l and ll containing e and all the old entries of l.
     113                 :            : //     I3. [Propogate changes upward] Invoke adjust_tree on l, also passing ll
     114                 :            : //        if a split was performed.
     115                 :            : //     I4. [Grow Tree Taller] If node split propogation caused the root
     116                 :            : //         to split create a new root whose children are the two resulting
     117                 :            : //         nodes.
     118                 :            : //-----------------------------------------------------------
     119                 :       2974 : template <class Y> MY_INLINE CubitStatus RTreeNode<Y>::insert(RTreeNode<Y> *e, RTreeNode<Y> *&new_root)
     120                 :            : {
     121                 :            :   CubitStatus stat;
     122                 :       2974 :   new_root = NULL;//only set this if the root node changes.  Assume
     123                 :            :     //that this RTreeNode object is the root...
     124                 :            : 
     125                 :            :   
     126                 :            :     // I1. Invoke choose_leaf to select a leaf node l in which to place
     127                 :            :     //e
     128 [ +  - ][ +  - ]:       2974 :   RTreeNode<Y> *l = choose_leaf(this, e);
         [ #  # ][ +  - ]
     129                 :            :     //just test.
     130                 :            :     // make sure l is not null.
     131                 :            :     // make sure l is one level above e.
     132 [ +  - ][ +  - ]:       2974 :   if ( l ==  NULL || l->get_leaf_level() != (e->get_leaf_level() + 1) )
         [ +  - ][ -  + ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
     133                 :            :   {
     134 [ #  # ][ #  # ]:          0 :     PRINT_ERROR("Choosing leaf for inseartion into rtree failed.\n");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     135                 :          0 :     return CUBIT_FAILURE;
     136                 :            :   }
     137                 :       2974 :   RTreeNode<Y> *ll = NULL;
     138                 :            :     //I2 a) If l has room for another entry install e.
     139 [ +  - ][ +  + ]:       2974 :   if ( l->can_add() )
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ +  - ][ +  + ]
     140                 :            :   {
     141 [ +  - ][ +  - ]:       2501 :     l->add_child(e, CUBIT_TRUE);
         [ #  # ][ +  - ]
     142                 :            :   }
     143                 :            :   else
     144                 :            :   {
     145                 :            :       //I2 b)
     146                 :            :       //Otherwise invoke split_node to obtain l and ll containing e and
     147                 :            :       //all the old entries of l.
     148 [ +  - ][ +  - ]:        473 :     stat = quadratic_split_node(l,e,ll);
         [ #  # ][ +  - ]
     149 [ +  - ][ -  + ]:        473 :     if ( stat != CUBIT_SUCCESS || ll == NULL )
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     150                 :            :     {
     151 [ #  # ][ #  # ]:          0 :       PRINT_ERROR("Problems splitting node during insertion to RTree.\n");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     152                 :          0 :       return CUBIT_FAILURE;
     153                 :            :     }
     154                 :            :   }
     155                 :            :     //I3.  Propagate changes upward.
     156                 :            :     //I4, grow tree taller (do both inside adjust_tree...)
     157 [ +  - ][ +  - ]:       2974 :   stat = adjust_tree(l, ll, this, new_root);
         [ #  # ][ +  - ]
     158 [ -  + ][ -  + ]:       2974 :   if ( stat!= CUBIT_SUCCESS )
         [ #  # ][ -  + ]
     159                 :          0 :     return stat;
     160                 :       2974 :   return CUBIT_SUCCESS;
     161                 :            : }
     162                 :            : 
     163                 :            : //--------------------------------------------
     164                 :            : // Algorithm: ChooseLeaf: Select a leaf node in which to place
     165                 :            : // a new index entry e.  Recursive search the subtrees of n
     166                 :            : // until n is a leaf node.
     167                 :            : //----------------------------------------------
     168                 :       5262 : template <class Y> MY_INLINE RTreeNode<Y>* RTreeNode<Y>::choose_leaf( RTreeNode<Y>* n,
     169                 :            :                                                             RTreeNode<Y>* e )
     170                 :            : {   
     171                 :            :     //If n is a leaf node, or one level greater than e,
     172                 :            :     //we are done.
     173 [ +  + ][ +  + ]:       5262 :   if ( n->get_leaf_level() == (e->get_leaf_level() + 1) )
         [ #  # ][ +  + ]
     174                 :       2974 :     return n;
     175                 :            :     //Now choose the entry f in n (children of n that is)
     176                 :            :     //whose bounding box f_box needs
     177                 :            :     //least enlargement to include e_box. Resolve ties by
     178                 :            :     //choosing the entry with the bounding box of smallest volume.
     179                 :       2288 :   double min_enlargement = CUBIT_DBL_MAX, curr_enlargement;
     180                 :            :   RTreeNode<Y> *curr_node;
     181                 :       2288 :   int child_index = -1;
     182                 :            :   int ii;
     183 [ +  - ][ +  + ]:      11161 :   for(ii = 0; (ii < maxChildren) && (n->myChildrenNodes[ii] != NULL); ii++  )
         [ +  + ][ +  + ]
         [ #  # ][ #  # ]
         [ +  - ][ +  + ]
     184                 :            :   {
     185                 :            : 
     186                 :       8873 :     curr_node = n->myChildrenNodes[ii];
     187                 :       8873 :     curr_enlargement = calc_enlargement(curr_node, e);
     188   [ +  +  +  +  :       8873 :     if ( curr_enlargement <= min_enlargement )
             #  #  +  + ]
     189                 :            :     {
     190 [ -  + ][ #  # ]:       4950 :       if ( curr_enlargement == min_enlargement && child_index >= 0 )
         [ +  + ][ +  - ]
         [ #  # ][ #  # ]
         [ +  + ][ +  - ]
     191                 :            :       {
     192                 :            :           //only reset if the curr_node has a smaller volume.
     193                 :        188 :         double curr_vol = volume(curr_node);
     194                 :        188 :         double old_vol = volume(n->myChildrenNodes[child_index]);
     195   [ #  #  +  +  :        188 :         if ( old_vol < curr_vol )
             #  #  +  + ]
     196                 :        188 :           continue;
     197                 :            :       }
     198                 :       4909 :       child_index = ii;
     199                 :       4909 :       min_enlargement = curr_enlargement;
     200                 :            :     }  
     201                 :            :   }
     202                 :            :     //do error checking...
     203 [ +  - ][ -  + ]:       2288 :   if ( child_index == -1 || child_index >= maxChildren )
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     204                 :          0 :     return (RTreeNode<Y>*)NULL;
     205                 :       2288 :   RTreeNode<Y> *f = n->myChildrenNodes[child_index];
     206                 :            :     //Now continue on...
     207                 :       2288 :   curr_node = choose_leaf(f,e);
     208                 :       2288 :   return curr_node;
     209                 :            : }
     210                 :            : //----------------------------------------------------------------------
     211                 :            : // calc_enlargement:  Calculate the enlargement required for increasing
     212                 :            : // the bounding box of current so that it would encapsulate the bounding
     213                 :            : // box of add_to.  So to do that, create the union of the two bounding
     214                 :            : // boxes, then of that supper box subtrace the volume of the current.
     215                 :            : // The result should be the volumetric difference between how much
     216                 :            : // current has and how much it would need be or the enlargement.
     217                 :            : //----------------------------------------------------------------------
     218                 :       8873 : template <class Y> MY_INLINE double RTreeNode<Y>::calc_enlargement(RTreeNode<Y> *current, RTreeNode<Y> *add_to )
     219                 :            : {
     220                 :            :     //The enlargement area is the volume of the box that would
     221                 :            :     //be the union of current and add_to minus the volume of the current.
     222 [ +  - ][ +  - ]:       8873 :   CubitBox curr_box = current->bounding_box();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     223 [ +  - ][ +  - ]:      17746 :   CubitBox add_to_box = add_to->bounding_box();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
     224 [ +  - ][ +  - ]:      17746 :   CubitBox supper = curr_box;
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     225                 :            :     //Unite add_to_box to the curr_box.
     226 [ +  - ][ +  - ]:       8873 :   supper|= add_to_box;
         [ #  # ][ +  - ]
     227 [ +  - ][ +  - ]:       8873 :   double area_big = volume(supper);
         [ #  # ][ +  - ]
     228 [ +  - ][ +  - ]:      17746 :   return area_big - volume(current);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     229                 :            : }
     230                 :      28182 : template <class Y> MY_INLINE double RTreeNode<Y>::calc_enlargement(CubitBox &current, CubitBox &add_to )
     231                 :            : {
     232                 :            :     //The enlargement area is the volume of the box that would
     233                 :            :     //be the union of current and add_to minus the volume of the current.
     234 [ +  - ][ +  - ]:      28182 :   CubitBox supper = current;
         [ #  # ][ +  - ]
     235                 :            :     // unite the add_to box.
     236 [ +  - ][ +  - ]:      28182 :   supper |= add_to;
         [ #  # ][ +  - ]
     237 [ +  - ][ +  - ]:      28182 :   double area_big = volume(supper);
         [ #  # ][ +  - ]
     238 [ +  - ][ +  - ]:      28182 :   return area_big - volume(current);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     239                 :            : }
     240                 :            : //------------------------------------------------------------------
     241                 :            : // Algorithm: adjust_tree
     242                 :            : // Description:  Ascend from a leaf node L to the root, adjusting covering
     243                 :            : // bounding boxes and propagating nodes splits as necesary.
     244                 :            : //------------------------------------------------------------------
     245                 :       5262 : template <class Y> MY_INLINE CubitStatus RTreeNode<Y>::adjust_tree(RTreeNode<Y> *l, RTreeNode<Y> *ll,
     246                 :            :                                    RTreeNode<Y> *root_node,
     247                 :            :                                    RTreeNode<Y> *&new_root)
     248                 :            : {
     249                 :            :   CubitStatus stat;
     250                 :            :   //we need to move up the tree and correct things that have changed.
     251 [ +  + ][ +  + ]:       5262 :   if ( l == root_node )
         [ #  # ][ +  + ]
     252                 :            :   {
     253 [ +  + ][ +  + ]:       2974 :     if ( ll == NULL )
         [ #  # ][ +  + ]
     254                 :       2858 :       return CUBIT_SUCCESS;
     255                 :            :     else
     256                 :            :     {
     257                 :            :         //Create a new root node and store l and ll there
     258 [ +  - ][ +  - ]:        116 :           CubitBox root_box = l->bounding_box();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     259 [ +  - ][ +  - ]:        116 :       root_box |= ll->bounding_box();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     260 [ +  - ][ +  - ]:        116 :       new_root = new RTreeNode<Y>(root_box, maxChildren, minChildren);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     261 [ +  - ][ +  - ]:        116 :       int new_level = l->get_leaf_level() + 1;
         [ #  # ][ +  - ]
     262 [ +  - ][ +  - ]:        116 :       new_root->set_leaf_level(new_level);
         [ #  # ][ +  - ]
     263 [ +  - ][ +  - ]:        116 :       new_root->add_child(l, CUBIT_TRUE);
         [ #  # ][ +  - ]
     264 [ +  - ][ +  - ]:        116 :       new_root->add_child(ll, CUBIT_TRUE);
         [ #  # ][ +  - ]
     265 [ +  - ][ +  - ]:        116 :       return CUBIT_SUCCESS;
         [ #  # ][ +  - ]
     266                 :            :     }
     267                 :            :   }
     268 [ +  - ][ +  - ]:       2288 :   RTreeNode<Y> *parent_node = l->get_parent();
         [ #  # ][ +  - ]
     269                 :       2288 :   RTreeNode<Y> *new_group = NULL;
     270 [ +  + ][ +  + ]:       2288 :   if ( ll != NULL )
         [ #  # ][ +  + ]
     271                 :            :   {
     272                 :            :       //We need to add ll to the parent if we can,
     273                 :            :       //and then we need to update the parent's bounding box...
     274 [ +  - ][ +  - ]:        388 :     if ( parent_node->can_add() )
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     275                 :            :     {
     276 [ +  - ][ +  - ]:        357 :       parent_node->add_child(ll, CUBIT_FALSE);
         [ #  # ][ +  - ]
     277                 :            :         //we need to recalculate the bounding box for the
     278                 :            :         //entire set since both l and ll were modified...
     279 [ +  - ][ +  - ]:        357 :       parent_node->recalc_b_box();
         [ #  # ][ +  - ]
     280                 :            :     }
     281                 :            :     else
     282                 :            :     {
     283                 :            :         //Now we must split the children of the parent. l should
     284                 :            :         //already be in the chilren list of the paretn.  So send
     285                 :            :         //to split node the parent_node and ll.
     286                 :            :         //parent node during this process will have its b_box recalced.
     287 [ #  # ][ +  - ]:         31 :       stat = quadratic_split_node(parent_node, ll, new_group);
         [ #  # ][ #  # ]
     288 [ #  # ][ #  # ]:         31 :       if ( stat != CUBIT_SUCCESS || new_group == NULL )
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     289                 :            :       {
     290 [ #  # ][ #  # ]:          0 :         PRINT_ERROR("Problems splitting node during insertion to RTree.\n");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     291                 :          0 :         return CUBIT_FAILURE;
     292                 :            :       }
     293                 :            :     }
     294                 :            :   }
     295                 :            :   else
     296                 :            :   {
     297                 :            :       //just recalulate the b_box for the parent_node.
     298 [ +  - ][ +  - ]:       1900 :     parent_node->recalc_b_box();
         [ #  # ][ +  - ]
     299                 :            :   }
     300 [ +  - ][ +  - ]:       2288 :   stat = adjust_tree(parent_node, new_group, root_node, new_root);
         [ #  # ][ +  - ]
     301 [ -  + ][ -  + ]:       2288 :   if ( stat != CUBIT_SUCCESS )
         [ #  # ][ -  + ]
     302                 :          0 :     return CUBIT_FAILURE;
     303                 :       5262 :   return CUBIT_SUCCESS;
     304                 :            : }
     305                 :            : //------------------------------------------------------------------
     306                 :            : // Algorithm: quadratic_split_node
     307                 :            : //  Description:  For the RTree, this is where most of the variations
     308                 :            : //  on implementations have occured.  The best method proposed by Guttman
     309                 :            : //  was a quadratic split, which I'll implement here.  The Rstar tree
     310                 :            : //  did some slightly more complicated things which I might try later.
     311                 :            : // Description of function:
     312                 :            : //  e is the node to which we want to add l, but l's children's list
     313                 :            : //  is full.  Split the children of l and e up into two groups.  The
     314                 :            : //  groups are stored in l and ll.
     315                 :            : // Assume:  assume that l's myChildrenNodes are maxChildren in size.
     316                 :            : //
     317                 :            : //  Divide a set of maxChildren + 1 index entries into two groups.
     318                 :            : //  QS1  [Pick first entry for each group]  Apply algorithm pick_seeds,
     319                 :            : //       to choose two entries to be the first elements of the groups.
     320                 :            : //       Assign each to a group.
     321                 :            : //  QS2  [Check if done]  If all entries have been assigned, stop.
     322                 :            : //       If one group has so few entries that all the rest must
     323                 :            : //       be assigned to it in order for it to have the minimum number m,
     324                 :            : //       assign them and stop.
     325                 :            : //  QS3  [Select entry to assign]  Invoke Algorithm pick_next to choose
     326                 :            : //       the next entry to assign.  Add it to the group whose covering
     327                 :            : //       rectangle will have to be enlarged least to accommodate it.
     328                 :            : //       Resolve ties by adding the entry to the group with the smaller
     329                 :            : //       volume, then to the one with fewer entries, then to either. Repeat
     330                 :            : //       QS2.
     331                 :            : //
     332                 :            : //------------------------------------------------------------------
     333                 :        504 : template <class Y> MY_INLINE CubitStatus RTreeNode<Y>::quadratic_split_node( RTreeNode<Y> *l,
     334                 :            :                                              RTreeNode<Y> *e,
     335                 :            :                                              RTreeNode<Y> *&ll )
     336                 :            : {
     337                 :            :   int ii;
     338                 :            :     //create a new list containing all the nodes we want to split.
     339 [ +  - ][ +  - ]:        504 :   RTreeNode<Y> **input_list = new RTreeNode<Y>* [maxChildren + 1];
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     340 [ +  - ][ +  - ]:        504 :   DLIList <RTreeNode<Y>*> nodes_remaining;
         [ #  # ][ +  - ]
     341 [ +  + ][ +  + ]:       4536 :   for ( ii = 0; ii < maxChildren; ii++ )
         [ #  # ][ +  + ]
     342                 :            :   {
     343                 :       4032 :     input_list[ii] = l->myChildrenNodes[ii];
     344                 :            :   }
     345                 :        504 :   input_list[maxChildren] = e;
     346                 :            :   
     347                 :            :     //QS1, pick first entry for each group.
     348                 :            :   RTreeNode<Y> *seed_1, *seed_2;
     349                 :            :   CubitStatus stat = pick_seeds(input_list, maxChildren+1,seed_1,
     350 [ +  - ][ +  - ]:        504 :                                 seed_2);
         [ #  # ][ +  - ]
     351 [ -  + ][ -  + ]:        504 :   if ( stat != CUBIT_SUCCESS )
         [ #  # ][ -  + ]
     352                 :            :   {
     353 [ #  # ][ #  # ]:          0 :     delete [] input_list;
         [ #  # ][ #  # ]
     354                 :          0 :     return stat;
     355                 :            :   }
     356                 :            :     //now flush out l. This cleans out the bounding box and
     357                 :            :     //chindrenNodes and resets the bounding box.  Also
     358                 :            :     //create ll, make l and ll non-leaf nodes and add
     359                 :            :     //seed_1 and seed_2 to l and ll. (doesn't matter which...)
     360 [ +  - ][ +  - ]:        504 :   l->flush(seed_1->bounding_box());
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     361 [ +  - ][ +  - ]:        504 :   l->add_child(seed_1, CUBIT_FALSE);
         [ #  # ][ +  - ]
     362                 :            :     //this is still a leaf node.
     363                 :            :     //this will change if necessary the parent...
     364 [ +  - ][ +  - ]:        504 :   l->set_leaf_level(e->get_leaf_level() + 1);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     365 [ +  - ][ +  - ]:        504 :   ll = new RTreeNode<Y>(seed_2->bounding_box(), maxChildren, minChildren );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
     366 [ +  - ][ +  - ]:        504 :   ll->add_child(seed_2, CUBIT_FALSE);
         [ #  # ][ +  - ]
     367 [ +  - ][ +  - ]:        504 :   ll->set_leaf_level(l->get_leaf_level());
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     368                 :            :     //build the nodes remaining list...
     369 [ +  + ][ +  + ]:       5040 :   for ( ii = 0; ii < maxChildren+1; ii++ )
         [ #  # ][ +  + ]
     370                 :            :   {
     371 [ +  + ][ +  + ]:       4536 :     if ( input_list[ii] != seed_1 &&
         [ +  + ][ +  + ]
         [ #  # ][ #  # ]
         [ +  + ][ +  + ]
     372                 :       4032 :          input_list[ii] != seed_2 )
     373 [ +  - ][ +  - ]:       3528 :       nodes_remaining.append(input_list[ii]);
         [ #  # ][ +  - ]
     374                 :            :   }
     375 [ +  - ][ +  - ]:        504 :   delete [] input_list;
         [ #  # ][ +  - ]
     376                 :            :   RTreeNode<Y> *next_node;
     377                 :            :   CubitBoolean add_to_group_1;
     378                 :            :     //Q2
     379 [ +  - ][ +  + ]:       4011 :   while (nodes_remaining.size() > 0 )
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ +  - ][ +  + ]
     380                 :            :   {
     381                 :            :       //Q2 continued.
     382 [ +  - ][ -  + ]:       3539 :     if ( l->space_left() < minChildren &&
         [ #  # ][ -  + ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
         [ #  # ][ -  + ]
     383 [ #  # ][ #  # ]:         11 :          minChildren - l->space_left() >= nodes_remaining.size() )
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     384                 :            :     {
     385                 :            :         //just add the rest of the nodes to l.
     386 [ #  # ][ #  # ]:         22 :       for ( ii = nodes_remaining.size(); ii > 0; ii-- )
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     387 [ #  # ][ #  # ]:         11 :         l->add_child(nodes_remaining.get_and_step(), CUBIT_TRUE);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     388 [ #  # ][ +  - ]:         11 :       nodes_remaining.clean_out();
         [ #  # ][ #  # ]
     389                 :         11 :       break;
     390                 :            :     }
     391 [ +  - ][ -  + ]:       3527 :     else if ( ll->space_left() < minChildren &&
         [ #  # ][ -  + ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
         [ #  # ][ -  + ]
     392 [ #  # ][ #  # ]:         10 :          minChildren - ll->space_left() >= nodes_remaining.size() )
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     393                 :            :     {
     394                 :            :         //just add the rest of the nodes to l.
     395 [ #  # ][ #  # ]:         20 :       for ( ii = nodes_remaining.size(); ii > 0; ii-- )
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     396 [ #  # ][ #  # ]:         10 :         ll->add_child(nodes_remaining.get_and_step(), CUBIT_TRUE);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     397 [ #  # ][ +  - ]:         10 :       nodes_remaining.clean_out();
         [ #  # ][ #  # ]
     398                 :         10 :       break;
     399                 :            :     }
     400                 :            :       //Q3
     401                 :            :       //pick next selects the next node and the group to
     402                 :            :       //put it in.  It also removes the node from nodes remaining.
     403                 :            :       //Some of these steps were added to pick next for efficiency...
     404 [ +  - ][ +  - ]:       3507 :     stat = pick_next(nodes_remaining, l, ll, next_node,
         [ #  # ][ +  - ]
     405                 :       3507 :                      add_to_group_1 );
     406 [ -  + ][ -  + ]:       3507 :     if ( stat != CUBIT_SUCCESS )
         [ #  # ][ -  + ]
     407                 :          0 :       return stat;
     408 [ +  + ][ +  + ]:       3507 :     if ( add_to_group_1 )
         [ #  # ][ +  + ]
     409 [ +  - ][ +  - ]:       1806 :       l->add_child(next_node, CUBIT_TRUE);
         [ #  # ][ +  - ]
     410                 :            :     else
     411 [ +  - ][ +  - ]:       1701 :       ll->add_child(next_node, CUBIT_TRUE);
         [ #  # ][ +  - ]
     412                 :            :   }
     413 [ +  - ][ +  - ]:        504 :   return CUBIT_SUCCESS;
         [ #  # ][ +  - ]
     414                 :            : }
     415                 :        504 : template <class Y> MY_INLINE void RTreeNode<Y>::flush( CubitBox &new_box )
     416                 :            : {
     417                 :            :   int ii;
     418                 :        504 :   nextChildIndex = 0;
     419 [ +  + ][ +  + ]:       4536 :   for ( ii = 0; ii < maxChildren; ii++ )
         [ #  # ][ +  + ]
     420                 :       4032 :     myChildrenNodes[ii] = NULL;
     421 [ +  - ][ +  - ]:        504 :   delete myBoundingBox;
         [ #  # ][ +  - ]
     422 [ +  - ][ +  - ]:        504 :   myBoundingBox = new CubitBox(new_box);
         [ #  # ][ +  - ]
     423                 :        504 : }
     424                 :       7626 : template <class Y> MY_INLINE void RTreeNode<Y>::add_child(RTreeNode<Y> *child_node,
     425                 :            :                                                 CubitBoolean recalc_b_box)
     426                 :            : {
     427 [ +  - ][ -  + ]:       7626 :   assert(nextChildIndex < maxChildren && child_node != NULL );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     428                 :       7626 :   myChildrenNodes[nextChildIndex] = child_node;
     429                 :            :     //update the bounding box. by uniting with child node...
     430 [ +  + ][ +  + ]:       7626 :   if ( recalc_b_box )
         [ #  # ][ +  + ]
     431                 :            :   {
     432                 :       6261 :     CubitBox *old_box = myBoundingBox;
     433 [ +  - ][ +  - ]:       6261 :     myBoundingBox = new CubitBox( *old_box |= child_node->bounding_box());
         [ #  # ][ +  - ]
     434 [ +  - ][ +  - ]:       6261 :     delete old_box;
         [ #  # ][ +  - ]
     435                 :            :   }
     436                 :       7626 :   nextChildIndex++;
     437                 :       7626 :   child_node->set_parent(this);
     438                 :       7626 : }
     439                 :       3362 : template <class Y> MY_INLINE CubitBoolean RTreeNode<Y>::can_add()
     440                 :            : {
     441 [ +  + ][ +  + ]:       3362 :   if (nextChildIndex >= maxChildren )
         [ #  # ][ +  + ]
     442                 :        504 :     return CUBIT_FALSE;
     443                 :            :   else
     444                 :       2858 :     return CUBIT_TRUE;
     445                 :            : }
     446                 :       7352 : template <class Y> MY_INLINE int RTreeNode<Y>::space_left()
     447                 :            : {
     448                 :       7352 :   return maxChildren - nextChildIndex;
     449                 :            : }
     450                 :            : //------------------------------------------------------------------
     451                 :            : // Algorithm pick_seeds: 
     452                 :            : //  Select two entries to be the first elements of the groups.
     453                 :            : //  PS1 [Calculate inefficiency of grouping entries together] For
     454                 :            : //      each pair of entries, e1 and e2, compose a rectangle (bounding_box)
     455                 :            : //      j, including e1 and e2, calculate:
     456                 :            : //      d = volume(j) - volume(e1) - volume(e2)
     457                 :            : //  PS2 [Choose the most wasteful pair] Choose the pair with the largest
     458                 :            : //      d.
     459                 :            : //------------------------------------------------------------------
     460                 :        504 : template <class Y> MY_INLINE CubitStatus RTreeNode<Y>::pick_seeds(RTreeNode<Y> **input_list,
     461                 :            :                                                         const int input_list_size,
     462                 :            :                                                         RTreeNode<Y> *&seed_1,
     463                 :            :                                                         RTreeNode<Y> *&seed_2)
     464                 :            : {
     465                 :            :   int ii, jj;
     466                 :            :   RTreeNode<Y> *e_1, *e_2;
     467 [ +  - ][ +  - ]:       1008 :   CubitBox e_box_1, e_box_2, j;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     468                 :        504 :   double d, max_d = -CUBIT_DBL_MAX;
     469                 :        504 :   seed_1 = (RTreeNode<Y>*)NULL;
     470                 :        504 :   seed_2 = (RTreeNode<Y>*)NULL;
     471                 :            :   
     472 [ +  + ][ +  + ]:       5040 :   for(ii = 0; ii < input_list_size; ii++ )
         [ #  # ][ +  + ]
     473                 :            :   {
     474                 :       4536 :     e_1 = input_list[ii];
     475 [ +  - ][ +  - ]:       4536 :     e_box_1 = e_1->bounding_box();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     476 [ +  + ][ +  + ]:      22680 :     for ( jj = ii+1; jj < input_list_size; jj++ )
         [ #  # ][ +  + ]
     477                 :            :     {
     478                 :      18144 :       e_2 = input_list[jj];
     479 [ +  - ][ +  - ]:      18144 :       e_box_2 = e_2->bounding_box();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     480                 :            :         //unite the boxes.
     481 [ +  - ][ +  - ]:      18144 :           j = e_box_1;
         [ #  # ][ +  - ]
     482 [ +  - ][ +  - ]:      18144 :       j |= e_box_2;
         [ #  # ][ +  - ]
     483                 :            :         //find the most wastefull boxes to separate the groups.
     484 [ +  - ][ +  - ]:      18144 :       d = volume(j) - volume(e_box_1) - volume(e_box_2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
     485 [ +  + ][ +  + ]:      18144 :       if ( d > max_d )
         [ #  # ][ +  + ]
     486                 :            :       {
     487                 :       1966 :         seed_1 = e_1;
     488                 :       1966 :         seed_2 = e_2;
     489                 :       1966 :         max_d = d;
     490                 :            :       }
     491                 :            :     }
     492                 :            :   }
     493 [ +  - ][ +  - ]:        504 :   return CUBIT_SUCCESS;
         [ #  # ][ +  - ]
     494                 :            : }
     495                 :            : //------------------------------------------------------------------
     496                 :            : // Algorithm pick_next: 
     497                 :            : //  Select one remaining entry for classification in a group.
     498                 :            : //  PN1 [Determine cost of putting each entry in group] For each entry
     499                 :            : //      e not yet in a group, calculate d1 = area increase required in the
     500                 :            : //      covering rectangle of group_1 to include E.  Calculate d2 similarly
     501                 :            : //      for group_2
     502                 :            : //  PN2 [Find entry with greatest preference for one group]  Choose
     503                 :            : //      any entry with the maximum difference between d1 and d2.
     504                 :            : //------------------------------------------------------------------
     505                 :       3507 : template <class Y> MY_INLINE CubitStatus RTreeNode<Y>::pick_next(DLIList <RTreeNode<Y>*> &remaining_nodes,
     506                 :            :                                                        RTreeNode<Y>* group_1,
     507                 :            :                                                        RTreeNode<Y>* group_2,
     508                 :            :                                                        RTreeNode<Y>*& next,
     509                 :            :                                                        CubitBoolean &add_to_group_1)
     510                 :            : {
     511                 :       3507 :   int ii, next_index = 0;
     512                 :       3507 :   double d1, d2, max_diff = -CUBIT_DBL_MAX;
     513                 :       3507 :   add_to_group_1 = CUBIT_TRUE;
     514                 :       3507 :   RTreeNode<Y> *max_diff_node = (RTreeNode<Y>*)NULL;
     515                 :            :   RTreeNode<Y> *curr_node;
     516 [ +  - ][ +  - ]:       3507 :   CubitBox group_1_box = group_1->bounding_box();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     517 [ +  - ][ +  - ]:       7014 :   CubitBox group_2_box = group_2->bounding_box();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
     518 [ +  - ][ +  - ]:       7014 :   CubitBox curr_box;
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     519 [ +  - ][ +  - ]:       3507 :   double v1 = volume(group_1_box);
         [ #  # ][ +  - ]
     520 [ +  - ][ +  - ]:       3507 :   double v2 = volume(group_2_box);
         [ #  # ][ +  - ]
     521 [ +  - ][ +  - ]:       3507 :   remaining_nodes.reset();
         [ #  # ][ +  - ]
     522 [ +  - ][ +  + ]:      17598 :   for ( ii = 0; ii < remaining_nodes.size(); ii++ )
         [ +  - ][ +  + ]
         [ #  # ][ #  # ]
         [ +  - ][ +  + ]
     523                 :            :   {
     524 [ +  - ][ +  - ]:      14091 :     curr_node = remaining_nodes.get_and_step();
         [ #  # ][ +  - ]
     525 [ +  - ][ +  - ]:      14091 :     curr_box = curr_node->bounding_box();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     526 [ +  - ][ +  - ]:      14091 :     d1 = calc_enlargement(group_1_box, curr_box);
         [ #  # ][ +  - ]
     527 [ +  - ][ +  - ]:      14091 :     d2 = calc_enlargement(group_2_box, curr_box);
         [ #  # ][ +  - ]
     528 [ +  + ][ +  + ]:      14091 :     if ( d1 > d2 )
         [ #  # ][ +  + ]
     529                 :            :     {
     530 [ +  + ][ +  + ]:       6443 :       if ( max_diff < d1 - d2 )
         [ #  # ][ +  + ]
     531                 :            :       {
     532                 :            :         //add to group whose covering area would have
     533                 :            :         //to be enlarged least.
     534                 :       2822 :         add_to_group_1 = CUBIT_FALSE;
     535                 :       2822 :         max_diff = d1 - d2;
     536                 :       2822 :         max_diff_node = curr_node;
     537                 :       2822 :         next_index = ii;
     538                 :            :       }
     539                 :            :     }
     540 [ +  + ][ +  + ]:       7648 :     else if ( d2 > d1 )
         [ #  # ][ +  + ]
     541                 :            :     {
     542 [ +  + ][ +  + ]:       7031 :       if ( max_diff < d2 - d1 )
         [ #  # ][ +  + ]
     543                 :            :       {
     544                 :            :         //add to group whose covering area would have
     545                 :            :         //to be enlarged least.
     546                 :       3614 :         add_to_group_1 = CUBIT_TRUE;
     547                 :       3614 :         max_diff = d2 - d1;
     548                 :       3614 :         max_diff_node = curr_node;
     549                 :       3614 :         next_index = ii;
     550                 :            :       }
     551                 :            :     }
     552                 :            :     else {
     553 [ +  + ][ +  + ]:        617 :       if ( max_diff < 0.0 )
         [ #  # ][ +  + ]
     554                 :            :       {
     555                 :            :           //Add to group with smaller area.
     556 [ +  + ][ +  + ]:        165 :         if ( v1 < v2 )
         [ #  # ][ -  + ]
     557                 :         22 :           add_to_group_1 = CUBIT_TRUE;
     558 [ -  + ][ -  + ]:        143 :         else if ( v2 < v1 )
         [ #  # ][ -  + ]
     559                 :          0 :           add_to_group_1 = CUBIT_FALSE;
     560                 :            :         else
     561                 :            :         {
     562                 :            :             //add to group with fewest entries.
     563 [ +  - ][ +  - ]:        143 :           int num_left_1 = group_1->space_left();
         [ #  # ][ +  - ]
     564 [ +  - ][ +  - ]:        143 :           int num_left_2 = group_2->space_left();
         [ #  # ][ +  - ]
     565 [ -  + ][ -  + ]:        143 :           if ( num_left_1 > num_left_2 )
         [ #  # ][ +  + ]
     566                 :         10 :             add_to_group_1 = CUBIT_TRUE;
     567                 :            :           else
     568                 :        133 :             add_to_group_1 = CUBIT_FALSE;
     569                 :            :         }
     570                 :        165 :         max_diff = 0.0;
     571                 :        165 :         max_diff_node = curr_node;
     572                 :        165 :         next_index = ii;
     573                 :            :       }
     574                 :            :     }
     575                 :            :   }
     576                 :       3507 :   next = NULL;
     577 [ -  + ][ -  + ]:       3507 :   if ( max_diff_node == NULL )
         [ #  # ][ -  + ]
     578                 :          0 :     return CUBIT_FAILURE;
     579                 :            :   else
     580                 :       3507 :     next = max_diff_node;
     581                 :            :     //remove next from the remaining_nodes list.
     582 [ +  - ][ +  - ]:       3507 :   remaining_nodes.reset();
         [ #  # ][ +  - ]
     583 [ +  - ][ +  - ]:       3507 :   remaining_nodes.step(next_index);
         [ #  # ][ +  - ]
     584 [ +  - ][ +  - ]:       3507 :   RTreeNode<Y> *check_node = remaining_nodes.remove();
         [ #  # ][ +  - ]
     585 [ -  + ][ -  + ]:       3507 :   if ( check_node != max_diff_node )
         [ #  # ][ -  + ]
     586                 :            :   {
     587 [ #  # ][ #  # ]:          0 :     PRINT_ERROR("Error in pick next algorithm logic of rtree...");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     588                 :          0 :     return CUBIT_FAILURE;
     589                 :            :   }
     590 [ +  - ][ +  - ]:       7014 :   return CUBIT_SUCCESS;
         [ #  # ][ +  - ]
     591                 :            : }
     592                 :       2339 : template <class Y> MY_INLINE void RTreeNode<Y>::recalc_b_box()
     593                 :            : {
     594 [ -  + ][ -  + ]:       2339 :   if(myLevel == DATA_RNODE )
         [ #  # ][ -  + ]
     595                 :          0 :     return;
     596                 :            :   int ii;
     597 [ +  - ][ +  - ]:       2339 :   CubitBox temp_box;
         [ #  # ][ +  - ]
     598                 :       2339 :   CubitBoolean first_box = CUBIT_TRUE;
     599 [ +  + ][ +  + ]:      11674 :   for ( ii = 0; ii < nextChildIndex; ii++ )
         [ #  # ][ +  + ]
     600                 :            :   {
     601 [ +  + ][ +  + ]:       9335 :         if ( first_box )
         [ #  # ][ +  + ]
     602                 :            :         {
     603 [ +  - ][ +  - ]:       2339 :           temp_box = myChildrenNodes[ii]->bounding_box();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     604                 :       2339 :           first_box = CUBIT_FALSE;
     605                 :            :         }
     606                 :            :         else
     607 [ +  - ][ +  - ]:       6996 :       temp_box |= myChildrenNodes[ii]->bounding_box();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     608                 :            :   }
     609 [ +  - ][ +  - ]:       2339 :   delete myBoundingBox;
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     610 [ +  - ][ +  - ]:       2339 :   myBoundingBox = new CubitBox(temp_box);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     611 [ +  - ][ +  - ]:       2339 :   return;
         [ #  # ][ +  - ]
     612                 :            : }
     613                 :            : //-------------------------------------------------------------
     614                 :            : // Algorithm: remove.  Remove index record e from an R-tree.
     615                 :            : //   D1)  [Find node containing record].  Invoke find_leaf to locate
     616                 :            : //        the leaf node l containing e.  Stop if the record was not
     617                 :            : //        found.
     618                 :            : //   D2)  [Delete record.]  Remove e from l.
     619                 :            : //   D3)  [Propagate changes.]  Invoke CondenseTree, passing L.
     620                 :            : //   D4)  [Shorten tree.]  If the root node has only one child
     621                 :            : //        after the tree has been adjusted, make the child the new
     622                 :            : //        root.
     623                 :            : //-------------------------------------------------------------
     624                 :         82 : template <class Y> MY_INLINE CubitBoolean RTreeNode<Y>::remove( Y e,
     625                 :            :                                                       RTreeNode<Y> *&new_root,
     626                 :            :                                                       CubitBoolean &delete_root)
     627                 :            : {
     628                 :            :     //D1) Find node containting record.
     629 [ #  # ][ #  # ]:         82 :   if(this->is_data()){
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     630 [ #  # ][ #  # ]:          0 :     if(this->get_data() == e){
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     631                 :          0 :       myData = NULL;
     632                 :          0 :       myLevel = UNSET_RNODE;
     633                 :          0 :       return CUBIT_TRUE;
     634                 :            :     }
     635 [ #  # ][ #  # ]:          0 :     else if(this->num_children() == 0){
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     636                 :          0 :       return CUBIT_FALSE;
     637                 :            :     }
     638                 :            :   }
     639                 :         82 :   RTreeNode<Y> *l = NULL;
     640 [ #  # ][ #  # ]:         82 :   CubitBox my_box = e->bounding_box();
         [ #  # ][ +  - ]
                 [ #  # ]
     641 [ #  # ][ #  # ]:         82 :   CubitStatus stat = find_leaf(e, my_box, this, l);
         [ #  # ][ +  - ]
     642 [ #  # ][ #  # ]:         82 :   if ( l == NULL || stat != CUBIT_SUCCESS )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     643                 :          0 :     return CUBIT_FALSE;
     644                 :            :     //Now l is the RTreeNode that holds the actual data (a DATA_RNODE)
     645                 :            :     //not a leaf.  This was done for efficiency.
     646                 :         82 :   RTreeNode<Y> *data_node = l;
     647 [ #  # ][ #  # ]:         82 :   l = data_node->get_parent();
         [ #  # ][ +  - ]
     648                 :            :     //D2) [Delete record]  Remove e from l.
     649                 :            :   
     650                 :            :     //remove the data node from the children and delete
     651                 :            :     //the node.
     652 [ #  # ][ #  # ]:         82 :   l->remove_child(data_node);
         [ #  # ][ +  - ]
     653 [ #  # ][ #  # ]:         82 :   delete data_node;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     654                 :            : 
     655                 :            :     //D3) [Propogate Changes].
     656 [ #  # ][ #  # ]:         82 :   stat = condense_tree(l, this, new_root);
         [ #  # ][ +  - ]
     657                 :            :     //D4) [Shorten the tree].
     658                 :         82 :   RTreeNode<Y> *root = this;
     659 [ #  # ][ #  # ]:         82 :   if ( new_root != NULL )
         [ #  # ][ -  + ]
     660                 :          0 :     root = new_root;
     661 [ #  # ][ #  # ]:         82 :   if ( root->num_children() == 1 )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     662                 :            :   {
     663 [ #  # ][ #  # ]:          0 :     new_root = root->get_child(0);
         [ #  # ][ #  # ]
     664 [ #  # ][ #  # ]:          0 :     new_root->set_parent((RTreeNode<Y>*)NULL);
         [ #  # ][ #  # ]
     665                 :          0 :     delete_root = CUBIT_TRUE;
     666                 :            :   }
     667 [ #  # ][ #  # ]:         82 :   return CUBIT_TRUE;
         [ #  # ][ +  - ]
     668                 :            : }
     669                 :        266 : template <class Y> MY_INLINE CubitStatus RTreeNode<Y>::find_leaf( Y e,
     670                 :            :                                                         CubitBox &e_box,
     671                 :            :                                                         RTreeNode<Y> *t,
     672                 :            :                                                         RTreeNode<Y> *&l )
     673                 :            : {
     674                 :            :   int ii;
     675                 :        266 :   l = NULL;
     676                 :        266 :   int loop_size = t->num_children();
     677                 :            :   RTreeNode<Y> *curr_node;
     678   [ #  #  #  #  :        266 :   if ( t->get_leaf_level() > LEAF_RNODE )
             #  #  +  + ]
     679                 :            :   {
     680 [ #  # ][ #  # ]:        255 :     for ( ii = 0; ii < loop_size; ii++ )
         [ #  # ][ +  - ]
     681                 :            :     {
     682                 :        255 :       curr_node = t->get_child(ii);
     683   [ #  #  #  #  :        255 :       if ( curr_node == NULL )
             #  #  -  + ]
     684                 :            :       {
     685 [ #  # ][ #  # ]:          0 :         PRINT_ERROR("Problems finding boxes in range.\n");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     686 [ #  # ][ #  # ]:          0 :         assert(curr_node != NULL);
         [ #  # ][ #  # ]
     687                 :          0 :         return CUBIT_FAILURE;
     688                 :            :       }
     689 [ #  # ][ #  # ]:        255 :       if ( e_box.overlap(GEOMETRY_RESABS, curr_node->bounding_box()) )
         [ #  # ][ +  + ]
     690                 :            :       {
     691                 :            :           //okay now search through this now.
     692                 :        184 :         find_leaf(e, e_box,curr_node,l);
     693   [ #  #  #  #  :        184 :         if ( l != NULL )
             #  #  +  + ]
     694                 :         82 :           return CUBIT_SUCCESS;
     695                 :            :       }
     696                 :            :     }
     697                 :            :   }
     698 [ #  # ][ #  # ]:        184 :   else if ( t->is_leaf() )
         [ #  # ][ +  - ]
     699                 :            :   {
     700                 :            :       //search through the children for e.
     701 [ #  # ][ #  # ]:        843 :     for ( ii = 0; ii < loop_size; ii++ )
         [ #  # ][ +  + ]
     702                 :            :     {
     703                 :        741 :       curr_node = t->get_child(ii);
     704   [ #  #  #  #  :        741 :       if ( curr_node == NULL )
             #  #  -  + ]
     705                 :            :       {
     706 [ #  # ][ #  # ]:          0 :         PRINT_ERROR("Problems finding boxes in range.\n");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     707 [ #  # ][ #  # ]:          0 :         assert(curr_node != NULL);
         [ #  # ][ #  # ]
     708                 :          0 :         return CUBIT_FAILURE;
     709                 :            :       }
     710 [ #  # ][ #  # ]:        741 :       if ( curr_node->get_data() == e )
         [ #  # ][ +  + ]
     711                 :            :       {
     712                 :         82 :         l = curr_node;
     713                 :         82 :         return CUBIT_SUCCESS;
     714                 :            :       }
     715                 :            :     }
     716                 :            :   }
     717                 :        266 :   return CUBIT_SUCCESS;
     718                 :            : }
     719                 :         82 : template <class Y> MY_INLINE CubitBoolean RTreeNode<Y>::remove_child( RTreeNode<Y> *child )
     720                 :            : {
     721                 :            :     //first find which item this child is at.
     722                 :            :   int ii;
     723                 :         82 :   int index_child = -1;
     724                 :         82 :   int loop_size = this->num_children();
     725 [ #  # ][ #  # ]:        517 :   for ( ii = 0; ii < loop_size; ii++ )
         [ #  # ][ +  + ]
     726                 :            :   {
     727 [ #  # ][ #  # ]:        435 :     if ( myChildrenNodes[ii] == child )
         [ #  # ][ +  + ]
     728                 :         82 :       index_child = ii;
     729                 :            :   }
     730 [ #  # ][ #  # ]:         82 :   if ( index_child == -1 )
         [ #  # ][ -  + ]
     731                 :          0 :     return CUBIT_FALSE;
     732                 :            :     //Now we need to bubble the array from this point
     733                 :            :     //upward.
     734 [ #  # ][ #  # ]:        165 :   for ( ii = index_child; ii < loop_size-1; ii++ )
         [ #  # ][ +  + ]
     735                 :            :   {
     736                 :         83 :     myChildrenNodes[ii] = myChildrenNodes[ii+1];
     737                 :            :   }
     738                 :            :     //decrement the position of the next available child.
     739                 :         82 :   nextChildIndex--;
     740                 :            :     //now go from nextChildIndex to the end and make sure it is
     741                 :            :     //null.
     742 [ #  # ][ #  # ]:        385 :   for (ii = nextChildIndex; ii < maxChildren; ii++ )
         [ #  # ][ +  + ]
     743                 :        303 :     myChildrenNodes[ii] = NULL;
     744                 :            :   
     745                 :         82 :   return CUBIT_TRUE;
     746                 :            : }
     747                 :            : //--------------------------------------------------------------------------
     748                 :            : // Algorithm: condense_tree
     749                 :            : //  Given a leaf node l from which an entry has been deleted, eliminate
     750                 :            : //  the node if it has too few entries and relocate its entries.  Propagate
     751                 :            : //  node elimination upaward as necessary.  Adjust all covering rectangles
     752                 :            : //  on the path to the root, making them smaller if possible.
     753                 :            : //  CT1) [Initialize]  Set n=l, Set q, the set of eliminated nodes, to be
     754                 :            : //       empty.
     755                 :            : //  CT2) [Find parent entry]  If n is the root, go to CT6.  Otherwise
     756                 :            : //       let p be the parent of n, and let en be n's entry in p.
     757                 :            : //  CT3) [Eliminate under-full node.] If n has fewer than minChildren,
     758                 :            : //       delete en from p and add n to set q.
     759                 :            : //  CT4) [Adjust covering rectangle]  If n has not been eliminated, adjust
     760                 :            : //       en's bounding box to tightly contain all entries in n.
     761                 :            : //  CT5) [Move up one level in tree] Set n=p, and repeat from CT2.
     762                 :            : //  CT6) [Reinsert orphaned entries].  Reinsert all entries of nodes in set q.
     763                 :            : //       entries from eliminated leaf nodes are re-inserted in tree leaves
     764                 :            : //       as described in algorithm insert, but entries from higher-level
     765                 :            : //       nodes must be placed higher in the tree so that leaves of their
     766                 :            : //       dependent subtrees will be on the same level as leaves of the
     767                 :            : //       main tree.
     768                 :            : //--------------------------------------------------------------------------
     769                 :         82 : template <class Y> MY_INLINE CubitStatus RTreeNode<Y>::condense_tree(RTreeNode<Y> *l,
     770                 :            :                                                            RTreeNode<Y> *root,
     771                 :            :                                                            RTreeNode<Y> *&new_root )
     772                 :            : {
     773                 :            :   int ii;
     774                 :         82 :   new_root = NULL;
     775                 :            :     //CT1)
     776                 :         82 :   RTreeNode<Y> *n = l, *p;
     777 [ #  # ][ #  # ]:         82 :   DLIList <RTreeNode<Y>*> set_q;
         [ #  # ][ +  - ]
     778                 :            :     //CT2)
     779 [ #  # ][ #  # ]:        164 :   while ( n != root )
         [ #  # ][ +  + ]
     780                 :            :   {
     781 [ #  # ][ #  # ]:         82 :     p = n->get_parent();
         [ #  # ][ +  - ]
     782 [ #  # ][ #  # ]:         82 :     if ( n->num_children() < minChildren )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     783                 :            :     {
     784                 :            :         //CT3
     785                 :            :         //take these children and add them to set_q.
     786 [ #  # ][ #  # ]:          0 :       for ( ii = 0;ii < n->num_children(); ii++ )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     787 [ #  # ][ #  # ]:          0 :         set_q.append(n->get_child(ii));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     788                 :            :         //remove n from p.
     789 [ #  # ][ #  # ]:          0 :       p->remove_child(n);
         [ #  # ][ #  # ]
     790                 :            :         //delete n.
     791 [ #  # ][ #  # ]:          0 :       delete n;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     792                 :            :         //now continue on.
     793                 :            :     }
     794                 :            :     else
     795                 :            :     {
     796                 :            :         //CT4
     797 [ #  # ][ #  # ]:         82 :       n->recalc_b_box();
         [ #  # ][ +  - ]
     798                 :            :     }
     799                 :            :       //CT5
     800                 :         82 :     n = p;
     801                 :            :   }
     802                 :            :     //now reinsert all nodes in set_q.
     803                 :            :   RTreeNode<Y> *curr_node, *temp_root;
     804                 :         82 :   temp_root = root;
     805 [ #  # ][ #  # ]:         82 :   for (ii = set_q.size(); ii > 0; ii-- )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     806                 :            :   {
     807 [ #  # ][ #  # ]:          0 :     curr_node = set_q.get_and_step();
         [ #  # ][ #  # ]
     808 [ #  # ][ #  # ]:          0 :     temp_root->insert(curr_node, new_root);
         [ #  # ][ #  # ]
     809 [ #  # ][ #  # ]:          0 :     if ( new_root != NULL )
         [ #  # ][ #  # ]
     810                 :          0 :       temp_root = new_root;
     811                 :            :   }
     812 [ #  # ][ #  # ]:         82 :   if ( temp_root != root )
         [ #  # ][ -  + ]
     813                 :          0 :     new_root = temp_root;
     814 [ #  # ][ #  # ]:         82 :   return CUBIT_SUCCESS;
         [ #  # ][ +  - ]
     815                 :            : }
     816                 :            : 
     817                 :            : 
     818                 :            : 
     819                 :            :   

Generated by: LCOV version 1.11