Exemplo n.º 1
0
/*! Rebalance the tree after insertion of a node. */
void GsTreeBase::_rebalance ( GsTreeNode *x )
 {
   GS_TRACE1("Rebalance");

   GsTreeNode *y;

   while ( x!=_root && RED(x->parent) )
    { // if ( !x->parent->parent ) REPORT_ERROR
      if ( x->parent==x->parent->parent->left )
       { y = x->parent->parent->right;
         if ( RED(y) )
          { // handle case 1 (see CLR book, pp. 269)
            x->parent->color = GsTreeNode::Black;
            y->color = GsTreeNode::Black;
            x->parent->parent->color = GsTreeNode::Red;
            x = x->parent->parent;
          }
         else
          { if ( x==x->parent->right )
             { // transform case 2 into case 3 (see CLR book, pp. 269)
               x = x->parent;
               _rotate_left ( x );
             }
            // handle case 3 (see CLR book, pp. 269)
            x->parent->color = GsTreeNode::Black;
            x->parent->parent->color = GsTreeNode::Red;
            _rotate_right ( x->parent->parent );
          }
       }
      else
       { y = x->parent->parent->left;
         if ( RED(y) )
          { // handle case 1 (see CLR book, pp. 269)
            x->parent->color = GsTreeNode::Black;
            y->color = GsTreeNode::Black;
            x->parent->parent->color = GsTreeNode::Red;
            x = x->parent->parent;
          }
         else
          { if ( x==x->parent->left )
             { // transform case 2 into case 3 (see CLR book, pp. 269)
               x = x->parent;
               _rotate_right ( x );
             }
            // handle case 3 (see CLR book, pp. 269)
            x->parent->color = GsTreeNode::Black;
            x->parent->parent->color = GsTreeNode::Red;
            _rotate_left ( x->parent->parent );
          }
       }
    }
 }
void SeLct::_funnelstart ( FunnelDeque* funnel, const GsPnt2& apex, SeBase* ent, FunnelPath* fpath, float radius, float extclear )
 {
   // add the first apex:
   GS_TRACE1 ( "Adding funnel apex..." );
   funnel->pusht().set ( apex.x, apex.y, 'p', 1 ); // initial point becomes the funnel apex
   funnel->apex = apex;
   fpath->push() = funnel->top();

   // check the entrance type:
   int i = ent==_ent[0].s? 0: ent==_ent[1].s? 1:2;
   GS_TRACE1 ( "Used entrance "<<i<<" is "<<(_ent[i].type==EntTrivial?"trivial":"not trivial") );

   // add entrance correction vertices if they exist:
   if ( _ent[i].type==EntNotTrivial )
    { GS_TRACE1 ( "Main entrance side: " << (_ent[i].top?"top":"bottom") );
      GS_TRACE1 ( (_ent[i].top?"Top":"Bottom") << " disturbances: "<<(_ent[i].fps1-2) );
      GS_TRACE1 ( (_ent[i].top?"Bottom":"Top") << " disturbances: "<<(_ent[i].fps2-2) );
      Entrance& e = _ent[i];
      if ( e.fps1>2 )
       { int max = e.fps1-1;
         GS_TRACE1 ( "Adding "<<e.fps1-2<<" disturbance(s) to the funnel..." );
         for ( i=1; i<max; i++ ) 
          _funneladd ( funnel, e.top? 't':'b', fpath, e.fp[i], radius );
       }
      if ( e.fps2>2 )
       { int max = e.fp.size()-1;
         GS_TRACE1 ( "Adding "<<e.fps2-2<<" disturbance(s) to the funnel..." );
         for ( i=e.fps1+1; i<max; i++ ) 
          _funneladd ( funnel, e.top? 'b':'t', fpath, e.fp[i], radius );
       }
    }

   // add the two vertices of the channel entrance:
   GS_TRACE1 ( "Adding channel first edge to the funnel..." );
   double x, y;
   GsPnt2 a, b;
   _man->get_vertex_coordinates ( ent->vtx(), x, y ); a.set((float)x,(float)y);
   _man->get_vertex_coordinates ( ent->nxt()->vtx(), x, y ); b.set((float)x,(float)y);

   if ( extclear>0 ) // extra clearance is to be completed
    { _funneladd ( funnel, 'b', fpath, a, radius );
      _funneladd ( funnel, 't', fpath, b, radius );
    }
   else
    { _funneladd ( funnel, 'b', fpath, a, radius );
      _funneladd ( funnel, 't', fpath, b, radius );
    }
 }
Exemplo n.º 3
0
/*! Method for left rotation of the tree about a given node. */
void GsTreeBase::_rotate_left ( GsTreeNode *x )
 {
   GS_TRACE1("Rotate Left");

   GsTreeNode *y = x->right;

   x->right = y->left;
   if ( y->left!=NIL ) y->left->parent=x;
   y->parent = x->parent;

   if ( x->parent!=NIL )
    { if ( x==x->parent->left ) x->parent->left=y;
       else x->parent->right=y;
    }
   else _root = y;

   y->left = x;
   x->parent = y;
 }
void SeLct::_funnelclose ( FunnelDeque* funnel, FunnelPath* fpath, int ei, float radius )
 {
   // 1. check if additional funnel vertices are needed due corrections detected
   // with arrival tests:
   int i;
   Entrance& ent = _ent[ei];
   if ( ent.type==EntNotTrivial )
    { GS_TRACE1 ( "Arrival has "<<ent.fp.size()-4<<" disturbance(s)..." );
      GS_TRACE1 ( "Main arrival side: " << (ent.top?"top":"bottom") );
      GS_TRACE1 ( (ent.top?"Top":"Bottom") << " disturbances: "<<ent.fps1-2 );
      GS_TRACE1 ( (ent.top?"Bottom":"Top") << " disturbances: "<<ent.fps2-2 );
      bool intop = !ent.top; // top entrance means bottom arrival
      if ( ent.fps1>2 )
       { //int max = ent.fps1-1;
         GS_TRACE1 ( "Adding "<<ent.fps1-2<<" disturbance(s) to the funnel..." );
         for ( i=ent.fps1-2; i>0; i-- ) 
          _funneladd ( funnel, intop? 't':'b', fpath, ent.fp[i], radius );
       }
      if ( ent.fps2>2 )
       { //int max = ent.fp.size()-2;
         GS_TRACE1 ( "Adding "<<ent.fps2-2<<" disturbance(s) to the funnel..." );
         for ( i=ent.fp.size()-2; i>ent.fps1; i-- ) 
          _funneladd ( funnel, intop? 'b':'t', fpath, ent.fp[i], radius );
       }
    }

   // 2. check where is the zone in the funnel that the goal is:
   GsPnt2 pg ( (float)_xg,(float)_yg );
   FunnelDeque& dq = *funnel;
   bool intop=true;
   SeFunnelPt fb;
   dq.topmode ( intop );
   while ( dq.size()>1 )
    { if ( dq.get().apex ) { intop=!intop; dq.topmode(intop); }
      if ( isgoalopening(dq.get(1),dq.get(),pg,radius) ) { fb=dq.get(); break; }
      dq.pop();
    }

   // 3. add the needed portion of the funnel side to the funnel path:
   for ( i=0; dq.get(i).apex==0; i++ ); // stop at the apex
   while ( --i>=0 ) _fpathpush ( fpath, dq.get(i), radius );

   // 4. add the final point:
   _fpathpush ( fpath, FunnelPt(pg.x,pg.y,'p',0,radius), radius );
 }
void SeLct::make_funnel_path ( GsPolygon& path, float radius, float dang, float extclear )
 {
   GS_TRACE1 ( "Entering funnel path..." );

   if ( radius<=0 ) { SeDcdt::make_funnel_path(path); return; }

   path.open ( true );
   path.size ( 0 );

   if ( _path_result==NoPath )
    { GS_TRACE1 ( "No path to compute." );
      return;
    }

   if ( _path_result==TrivialPath )
    { path.push().set((float)_xi,(float)_yi);
      path.push().set((float)_xg,(float)_yg);
      GS_TRACE1 ( "Trivial path computed." );
      return;
    }

   if ( _path_result==LocalPath )
    { GS_TRACE1 ( "Computing local path..." );
      path.push().set((float)_xi,(float)_yi);
      GsArray<GsPnt2>& fp = _ent[0].fp;
      bool top = _ent[0].top;
      if ( !top ) dang=-dang;
      GsVec2 c, v1, v2;
      int k, max = fp.size()-2;
      for ( k=0; k<max; k++ )
       { c = fp[k+1];
         if ( top )
          { v1 = (fp[k]-c).ortho();
            v2 = (c-fp[k+2]).ortho();
          }
         else
          { v1 = (c-fp[k]).ortho();
            v2 = (fp[k+2]-c).ortho();
          }
         path.arc ( c, v1, v2, radius, dang );
       }
      path.push().set((float)_xg,(float)_yg);
      GS_TRACE1 ( "Local path has "<<path.size()<<" vertices." );
      return;
    }

   // ok from now on we are treating the global path search case:
   GS_TRACE1 ( "Computing global path..." );

   // allocate/access used buffers:
   // (we reset autolen to false since this is shared with the optimal search)
   if ( !_fpath ) _fpath = new FunnelPath(false); else { _fpath->size(0); _fpath->autolen=false; }
   if ( !_fdeque ) _fdeque = new FunnelDeque; else _fdeque->init();

   // init auxiliary structures if extra clearance is asked:
   if ( extclear>0 ) _finitextcl ( radius, extclear );

   // check entrances and start funnel:
   _funnelstart ( _fdeque, GsPnt2(_xi,_yi), _channel[0], _fpath, radius, extclear );
   if (_funnelcb) _funnelcb(_fudata);

   // now add remaining vertices of the funnel:
   GS_TRACE1 ( "Running funnel algorithm..." );
   int i, j, max = _channel.size()-1;

   if ( extclear>0 )
    { SeDcdtSymEdge *s;
      float r=radius;
      for ( i=0; i<max; i++ )
       { j=i+1;
         s = (SeDcdtSymEdge*)_channel[j];
         if ( _extcl[j].l=='t' ) // add top vertex
          { r = _extcl[j].r;
            _funneladd ( _fdeque, 't', _fpath, s->nvtx()->p, r ); // add top edge vertex
          }
         else // add bot vertex
          { r = _extcl[j].r;
            _funneladd ( _fdeque, 'b', _fpath, s->vtx()->p, r ); // add bottom edge vertex
          }
        if (_funnelcb) _funnelcb(_fudata);
      }
    }
   else
    { SeDcdtSymEdge *s1, *s2;
      for ( i=0; i<max; i++ )
       { s1 = (SeDcdtSymEdge*)_channel[i];
         s2 = (SeDcdtSymEdge*)_channel[i+1];
         if ( s1->vtx()==s2->vtx() ) // add top vertex
          { GS_TRACE2 ( "Updating funnel top with channel edge "<<(i+1) );
            _funneladd ( _fdeque, 't', _fpath, s2->nvtx()->p, radius ); // add top edge vertex
          }
         else // add bot vertex
          { GS_TRACE2 ( "Updating funnel bottom with channel edge "<<(i+1) );
            _funneladd ( _fdeque, 'b', _fpath, s2->vtx()->p, radius ); // add bottom edge vertex
          }
        if (_funnelcb) _funnelcb(_fudata);
      }
    }

   GS_TRACE1 ( "Path has " << _fpath->size() << " vertices before closure." );
   GS_TRACE1 ( "Processing closure..." );
   _funnelclose ( _fdeque, _fpath, 3, radius );

   // build path approximation based on tangents:
   GS_TRACE1 ( "Building curved path approximation..." );
   _fpathmake ( _fpath, path, radius, dang );

   GS_TRACE1 ( "Done." );
 }
Exemplo n.º 6
0
/*! Method for restoring red-black properties after deletion. */
void GsTreeBase::_fix_remove ( GsTreeNode *x )
 {
   GS_TRACE1("Fix Remove");

   while ( x!=_root && BLACK(x) )
    {
      if ( x==x->parent->left )
       { GsTreeNode *w = x->parent->right;
         if ( RED(w) )
          { w->color = GsTreeNode::Black;
            x->parent->color = GsTreeNode::Red;
            _rotate_left ( x->parent );
            w = x->parent->right;
          }
         if ( BLACK(w->left) && BLACK(w->right) )
          { w->color = GsTreeNode::Red;
            x = x->parent;
          } 
         else
          { if ( BLACK(w->right) )
             { w->left->color = GsTreeNode::Black;
               w->color = GsTreeNode::Red;
               _rotate_right ( w );
               w = x->parent->right;
             }
            w->color = x->parent->color;
            x->parent->color = GsTreeNode::Black;
            w->right->color = GsTreeNode::Black;
            _rotate_left ( x->parent );
            x = _root;
          }
       }
      else
       { GsTreeNode *w = x->parent->left;
         if ( RED(w) )
          { w->color = GsTreeNode::Black;
            x->parent->color = GsTreeNode::Red;
            _rotate_right ( x->parent );
            w = x->parent->left;
          }
         if ( BLACK(w->left) && BLACK(w->right) )
          { w->color = GsTreeNode::Red;
            x = x->parent;
          }
         else
          { if ( BLACK(w->left) )
             { w->right->color = GsTreeNode::Black;
               w->color = GsTreeNode::Red;
               _rotate_left ( w );
               w = x->parent->left;
             }
            w->color = x->parent->color;
            x->parent->color = GsTreeNode::Black;
            w->left->color = GsTreeNode::Black;
            _rotate_right ( x->parent );
            x = _root;
          }
       }
    }

   x->color = GsTreeNode::Black;
 }