Beispiel #1
0
MinCircle2<Real>::MinCircle2 (int numPoints, const Vector2<Real>* points,
    Circle2<Real>& minimal, Real epsilon)
    :
    mEpsilon(epsilon)
{
    mUpdate[0] = 0;
    mUpdate[1] = &MinCircle2<Real>::UpdateSupport1;
    mUpdate[2] = &MinCircle2<Real>::UpdateSupport2;
    mUpdate[3] = &MinCircle2<Real>::UpdateSupport3;

    Support support;
    Real distDiff;

    if (numPoints >= 1)
    {
        // Create identity permutation (0,1,...,numPoints-1).
        Vector2<Real>** permuted = new1<Vector2<Real>*>(numPoints);
        int i;
        for (i = 0; i < numPoints; ++i)
        {
            permuted[i] = (Vector2<Real>*)&points[i];
        }
        
        // Generate random permutation.
        for (i = numPoints - 1; i > 0; --i)
        {
            int j = rand() % (i+1);
            if (j != i)
            {
                Vector2<Real>* save = permuted[i];
                permuted[i] = permuted[j];
                permuted[j] = save;
            }
        }
        
        minimal = ExactCircle1(*permuted[0]);
        support.Quantity = 1;
        support.Index[0] = 0;

        // The previous version of the processing loop is
        //  i = 1;
        //  while (i < numPoints)
        //  {
        //      if (!support.Contains(i, permuted, mEpsilon))
        //      {
        //          if (!Contains(*permuted[i], minimal, distDiff))
        //          {
        //              UpdateFunction update = mUpdate[support.Quantity];
        //              Circle2<Real> circle = (this->*update)(i, permuted,
        //                  support);
        //              if (circle.Radius > minimal.Radius)
        //              {
        //                  minimal = circle;
        //                  i = 0;
        //                  continue;
        //              }
        //          }
        //      }
        //      ++i;
        //  }
        // This loop restarts from the beginning of the point list each time
        // the circle needs updating.  Linus Källberg (Computer Science at
        // Mälardalen University in Sweden) discovered that performance is
        // better when the remaining points in the array are processed before
        // restarting.  The points processed before the point that caused the
        // update are likely to be enclosed by the new circle (or near the
        // circle boundary) because they were enclosed by the previous circle.
        // The chances are better that points after the current one will cause
        // growth of the bounding circle.
        for (int i = 1 % numPoints, n = 0; i != n; i = (i + 1) % numPoints)
        {
            if (!support.Contains(i, permuted, mEpsilon))
            {
                if (!Contains(*permuted[i], minimal, distDiff))
                {
                    UpdateFunction update = mUpdate[support.Quantity];
                    Circle2<Real> circle =(this->*update)(i, permuted,
                        support);
                    if (circle.Radius > minimal.Radius)
                    {
                        minimal = circle;
                        n = i;
                    }
                }
            }
        }
        
        delete1(permuted);
    }
    else
    {
        assertion(false, "Input must contain points\n");
    }

    minimal.Radius = Math<Real>::Sqrt(minimal.Radius);
}
    MinCircle2<Real>::MinCircle2 ( int numPoints, const Vector2<Real>* points,
                                   Circle2<Real>& minimal, Real epsilon )
        :
        mEpsilon( epsilon )
    {
        mUpdate[0] = 0;
        mUpdate[1] = &MinCircle2<Real>::UpdateSupport1;
        mUpdate[2] = &MinCircle2<Real>::UpdateSupport2;
        mUpdate[3] = &MinCircle2<Real>::UpdateSupport3;

        Support support;
        Real distDiff;

        if ( numPoints >= 1 )
        {
            // Create identity permutation (0,1,...,numPoints-1).
            Vector2<Real>** permuted = new1<Vector2<Real>*>( numPoints );
            int i;
            for ( i = 0; i < numPoints; ++i )
            {
                permuted[i] = ( Vector2<Real>* )&points[i];
            }

            // Generate random permutation.
            for ( i = numPoints - 1; i > 0; --i )
            {
                int j = rand() % ( i + 1 );
                if ( j != i )
                {
                    Vector2<Real>* save = permuted[i];
                    permuted[i] = permuted[j];
                    permuted[j] = save;
                }
            }

            minimal = ExactCircle1( *permuted[0] );
            support.Quantity = 1;
            support.Index[0] = 0;
            i = 1;
            while ( i < numPoints )
            {
                if ( !support.Contains( i, permuted, mEpsilon ) )
                {
                    if ( !Contains( *permuted[i], minimal, distDiff ) )
                    {
                        UpdateFunction update = mUpdate[support.Quantity];
                        Circle2<Real> circle = ( this->*update )( i, permuted,
                                               support );
                        if ( circle.Radius > minimal.Radius )
                        {
                            minimal = circle;
                            i = 0;
                            continue;
                        }
                    }
                }
                ++i;
            }

            delete1( permuted );
        }
        else
        {
            assertion( false, "Input must contain points\n" );
        }

        minimal.Radius = Math<Real>::Sqrt( minimal.Radius );
    }