All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines
Public Member Functions
DinverCore::VoronoiNavigator Class Reference

Brief description of class still missing. More...

#include <VoronoiNavigator.h>

List of all members.

Public Member Functions

QVector< int > cellAt (const int *p) const
QVector< int > cellAt (const double *p) const
int cellCount () const
void cellLimits (int &xMin, int &xMax, int &iMin, int &iMax)
void checkAxisDistances ()
void checkCurrentPoint ()
int currentAxis () const
int currentCell () const
void incrementAxis ()
PdfCurve intersections (double xMinLimit, double xMaxLimit)
void printCurrentPoint ()
void setCurrentAxis (int a)
void setCurrentCell (int index)
void setCurrentPoint (int index)
void setCurrentPoint (const int *coordinates)
void setValue (int v)
void setValue (double v)
 VoronoiNavigator (const ScaledModels *m)
 ~VoronoiNavigator ()

Detailed Description

Brief description of class still missing.

Full description of class still missing


Constructor & Destructor Documentation

Description of constructor still missing

References DinverCore::ScaledModels::modelCount(), DinverCore::ScaledModels::parameterCount(), and TRACE.

{
  TRACE;
  _cells=m;

  _currentAxis=-1;
  _currentCell=-1;

  _axisDistances=new double [ _cells->modelCount() ];
  _currentPoint=new double [ _cells->parameterCount() ];
}

Description of destructor still missing

References TRACE.

{
  TRACE;
  delete [] _axisDistances;
  delete [] _currentPoint;
}

Member Function Documentation

QVector< int > DinverCore::VoronoiNavigator::cellAt ( const int *  p) const

Debug purpose, get the cells containing model.

References DinverCore::ScaledModels::modelCount(), DinverCore::ScaledModels::parameterCount(), DinverCore::ScaledModels::scale(), TRACE, and DinverCore::ScaledModels::v().

Referenced by checkCurrentPoint().

{
  TRACE;
  QVector<int> belongs;
  double minDistance=1e99;
  int nm=_cells->modelCount();
  int nd=_cells->parameterCount();
  for(int im=0; im < nm; im++ ) {
    double distance=0.0, tmp;
    for(int id=0; id < nd; id++) {
      tmp=_cells->v(id)[im] - p[id] * _cells->scale(id);
      distance += tmp*tmp;
    }
    if(distance<minDistance) {
      belongs.clear();
      belongs.append(im);
      minDistance=distance;
    } else if(distance==minDistance) {
      belongs.append(im);
    }
  }
  return belongs;
}
QVector< int > DinverCore::VoronoiNavigator::cellAt ( const double *  p) const

Debug purpose, get the cells containing scaled model.

References DinverCore::ScaledModels::modelCount(), DinverCore::ScaledModels::parameterCount(), TRACE, and DinverCore::ScaledModels::v().

{
  TRACE;
  QVector<int> belongs;
  double minDistance=1e99;
  int nm=_cells->modelCount();
  int nd=_cells->parameterCount();
  for(int im=0; im < nm; im++ ) {
    double distance=0.0, tmp;
    for(int id=0; id < nd; id++) {
      tmp=_cells->v(id)[im] - p[id];
      distance += tmp*tmp;
    }
    if(distance<minDistance) {
      belongs.clear();
      belongs.append(im);
      minDistance=distance;
    } else if(distance==minDistance) {
      belongs.append(im);
    }
  }
  return belongs;
}
{return _cells->modelCount();}
void DinverCore::VoronoiNavigator::cellLimits ( int &  xMin,
int &  xMax,
int &  iMin,
int &  iMax 
)

If Xj[i] is right on the cell border (between Vj and Vk),

2 * Xj[i] * s[i]^2 * (Vk[i] - Vj[i] )=(Vk[i]^2 - Vj[i]^2) * s[i]^2 + (dk^2 - dj^2)

Or,

2 * Xj[i] * s[i]=xLim/dx, dx includes the scaling

if xLim/(2*dx)<Pk[i]*s[i] && xLim/dx>xMin, move xMin to xLim/dx if xLim/(2*dx)>Pk[i]*s[i] && xLim/dx<xMax, move xMax to xLim/dx

Where Pk is the current point inside cell of Vk, hence,

xLim < 2 * s[i] * Pk[i] * dx

if dx>0, xLim/dx < 2 * s[i] * Pk[i] if dx<0, xLim/dx > 2 * s[i] * Pk[i]

We would like to postpone the division by dx only when the limits is really moved. hence, we multiply xMin and xMax by dx (division is approximately 5 times slower than multiplication). xMin and xMax are multiplied by 2 upon startup.

if dx>0, the conditions become:

if xLim/dx<2*Pk[i]*s[i] && xLim>xMin*dx, move xMin to xLim/dx (a) if xLim/dx>2*Pk[i]*s[i] && xLim<xMax*dx, move xMax to xLim/dx (b) (first condition of (b) is always false, of (a) is always true)

if dx<0, the conditions become:

if xLim/dx<2*Pk[i]*s[i] && xLim<xMin*dx, move xMin to xLim/dx (a) if xLim/dx>2*Pk[i]*s[i] && xLim>xMax*dx, move xMax to xLim/dx (b) (first condition of (a) is always false, of (b) is always true)

if dx==0, no intersection, hence skip

if dx>0, the conditions become:

if xLim>xMin*dx, move xMin to xLim/dx (a)

if dx<0, the conditions become:

if xLim>xMax*dx, move xMax to xLim/dx (b)

_currentCell is k, _axisDistances[ _currentCell ] is dk _axisDistances[ j ] is dj

Thus, we just test the sign of dx and we can directly compare to the current min and max of the cell.

iMin and iMax are set the cell indexes of the two neighbors crossed by the current axis (-1 if there are no neighbors).

References DinverCore::ScaledModels::modelCount(), DinverCore::ScaledModels::scale(), TRACE, DinverCore::ScaledModels::v(), and DinverCore::ScaledModels::v2().

Referenced by DinverCore::Neighborhood::setVolumes().

{
  TRACE;
  ASSERT(_currentAxis>-1);
  ASSERT(_currentCell>-1);
  const double * vp=_cells->v(_currentAxis);
  const double * v2p=_cells->v2(_currentAxis);
  double vk=vp[ _currentCell ];
  double vk2dk2=v2p[ _currentCell ] + _axisDistances[ _currentCell ];
  double xLim, dx;
  double s=_cells->scale(_currentAxis);
  double s2=2.0*s;
  double dxMin=(double)xMin*s2;
  double dxMax=(double)xMax*s2;
  iMin=-1;
  iMax=-1;
  int n=_cells->modelCount();
  for(int j=0; j< n; j++ ) {
    dx=vk - vp[ j ];
    xLim=vk2dk2 - (v2p[ j ] + _axisDistances[ j ] );
    if(dx > 0.0) {
      if(xLim > dxMin * dx) {
        ASSERT(xLim>0);
        dxMin=xLim/dx;
        iMin=j;
      }
    } else if(dx < 0.0) {
      if(xLim > dxMax * dx) {
        ASSERT(xLim<0);
        dxMax=xLim/dx;
        iMax=j;
      }
    }
  }
  /*
     Distances to axes are updated incrementaly, which is likely to introduce
     some errors in the determination of dxMin and dxMax. By experience, the
     maximum relative error is of the order of 1e-16. This is negligible except
     when rounding limits to integers. By default, we keep as conservative as
     possible, hence limits are rounded with ceil and floor for xMin and xMax,
     respectively. If the current point, which is a valid model (fit with all
     conditions) and which has proved to belong to the current cell, is very
     close to the edge of the cell, the conservative rounding might consider
     the current point as outside.
  */
  double invS=1.0/s;
  double invS2=0.5*invS;
  int pk=(int)round(_currentPoint[ _currentAxis ]*invS);
  if(iMin>-1) {
    dxMin*=invS2;
    xMin=(int) ceil(dxMin);
    if(pk==xMin-1) {
      xMin=pk;
      //App::stream() << tr("Adjust xMin limit to Pk(%1), dxMin=%2")
      //         .arg(pk).arg(dxMin, 0, 'g', 20) << endl;
    }
  }
  if(iMax>-1) {
    dxMax*=invS2;
    xMax=(int) floor(dxMax);
    if(pk==xMax+1) {
      xMax=pk;
      //App::stream() << tr("Adjust xMax limit to Pk(%1), dxMax=%2")
      //         .arg(pk).arg(dxMax, 0, 'g', 20) << endl;
    }
  }
}

Brute comparison of current distance, check for precison leakage This function is strictly for debug purposes

References QGpCoreTools::endl(), DinverCore::ScaledModels::modelCount(), DinverCore::ScaledModels::parameterCount(), QGpCoreTools::tr(), TRACE, and DinverCore::ScaledModels::v().

{
  TRACE;
  double d, dtot;
  double * dist=_axisDistances;
  int id;
  int nm=_cells->modelCount();
  int nd=_cells->parameterCount();
  for(int im=0;im<nm; im++ ) {
    dtot=0;
    for(id=0; id < _currentAxis; id++ ) {
      d=_currentPoint[ id ] - _cells->v(id)[im];
      dtot += d * d;
    }
    for(id++; id < nd; id++ ) {
      d=_currentPoint[ id ] - _cells->v(id)[im];
      dtot += d * d;
    }
    if(dtot > 0.0) {
      double relErr=( *dist - dtot)/dtot;
      if(fabs( relErr) > 1e-10) {
        App::stream() << tr( "  Error in iterative square distance for model %1: %2\n"
                      "      iterative square distance=%3\n"
                      "      true square distance=%4" )
                  .arg(im).arg(relErr).arg(*dist).arg(dtot) << endl;
      }
    } else {
      if(fabs(*dist)>1e-15) {
        App::stream() << tr( "  Error in iterative square distance for model %1:\n"
                      "      iterative square distance=%2\n"
                      "      true square distance=%3" )
                  .arg(im).arg(*dist).arg(dtot) << endl;
      }
    }
    dist++;
  }
}

Check if current point belongs to current cell

References cellAt().

{
  QVector<int> iGenModel=cellAt(_currentPoint);
  if( ! iGenModel.contains(_currentCell) ) {
    printf("Model effectively NOT generated in cell %i but:\n", _currentCell);
    for(QVector<int>::iterator it=iGenModel.begin(); it!=iGenModel.end(); it++) {
      printf("%i ", *it);
    }
    printf("\n" );
    ASSERT(false);
  }
}
{return _currentCell;}

Increment axis and update the distances to new axis

References DinverCore::ScaledModels::modelCount(), DinverCore::ScaledModels::parameterCount(), TRACE, and DinverCore::ScaledModels::v().

Referenced by DinverCore::ImportanceSampling::generate(), and DinverCore::Neighborhood::setVolumes().

{
  TRACE;
  ASSERT(_currentAxis>-1);
  double d;
  int newAxis=_currentAxis + 1;
  if(newAxis==_cells->parameterCount()) newAxis=0;
  double xcur=_currentPoint[ _currentAxis ];
  double xnew=_currentPoint[ newAxis ];
  double * dist=_axisDistances;
  int nm=_cells->modelCount();
  for(int im=0;im<nm; im++ ) {
    d=xnew - _cells->v(newAxis)[im];
    double& distVal=*dist;
    distVal -= d * d;
    d=xcur - _cells->v(_currentAxis)[im];
    distVal += d * d;
    //fprintf(stdout,"Axis Dist=%8lg\n",sqrt(distVal));
    dist++;
  }
  _currentAxis=newAxis;
}
PdfCurve DinverCore::VoronoiNavigator::intersections ( double  xMin,
double  xMax 
)

The intersections are returned along current axis set by setAxis()

References QGpCoreTools::Curve< pointType >::append(), DinverCore::ScaledModels::modelCount(), DinverCore::ScaledModels::scale(), QGpCoreTools::Curve< pointType >::setFunction(), DinverCore::ScaledModels::v(), and DinverCore::ScaledModels::v2().

Referenced by DinverCore::ImportanceSampling::generate().

{
  ASSERT(_currentAxis>-1);
  ASSERT(_currentCell>-1);
  PdfCurve f;
  // f for the first cell, separate models into lower and higher (along axis)
  const double * vp=_cells->v(_currentAxis);
  const double * v2p=_cells->v2(_currentAxis);
  double vk=vp[_currentCell];
  double vk2dk2=v2p[ _currentCell ] + _axisDistances[ _currentCell ];
  double xLim, dx;
  double s=_cells->scale(_currentAxis);
  double s2=2.0*s;
  double dxMinLimit=xMin*s2;
  double dxMaxLimit=xMax*s2;
  double dxMin=dxMinLimit;
  double dxMax=dxMaxLimit;
  int n=_cells->modelCount();
  int * lowerCells=new int [n];
  int * higherCells=new int [n];
  int nLowerCells=0, nHigherCells=0, iMin=-1, iMax=-1;
  for(int j=0; j< n; j++ ) {
    dx=vk - vp[ j ];
    xLim=vk2dk2 - (v2p[ j ] + _axisDistances[ j ] );
    if(dx > 0.0) {
      if(xLim > dxMin * dx) {
        ASSERT(xLim>0);
        dxMin=xLim/dx;
        iMin=j;
      }
      lowerCells[nLowerCells]=j;
      nLowerCells++;
    } else if(dx < 0.0) {
      if(xLim > dxMax * dx) {
        ASSERT(xLim<0);
        dxMax=xLim/dx;
        iMax=j;
      }
      higherCells[nHigherCells]=j;
      nHigherCells++;
    }
  }
  /*if(dxMin>=dxMax) {
    printf("dxMin %lf dxMax %lf\n",dxMin,dxMax);
    checkCurrentPoint();
    ASSERT(false);
  }*/
  int originalCell=_currentCell;
  double invS2=0.5/s;
  if(iMin>-1) {
    _currentCell=iMin;
    lowerIntersections(f, dxMinLimit, lowerCells, nLowerCells, invS2);
  }
  //App::stream() << "main append " << invS2*dxMin << " " << originalCell << endl;
  f.append(PdfPoint(invS2*dxMin, originalCell));
  //App::stream() << "main append " << invS2*dxMax << " " << iMax << endl;
  f.append(PdfPoint(invS2*dxMax, iMax));
  //ASSERT(f.count()>1);
  if(iMax>-1) {
    _currentCell=iMax;
    higherIntersections(f, dxMaxLimit, higherCells, nHigherCells, invS2);
  }
  _currentCell=originalCell;
  delete [] lowerCells;
  delete [] higherCells;
  f.setFunction();
  //ASSERT(f.count()>1);
  return f;
}

References DinverCore::ScaledModels::parameterCount(), and DinverCore::ScaledModels::scale().

{
  int nd=_cells->parameterCount();
  for(int id=0; id<nd; id++) {
    printf(" %lf",_currentPoint[id]/_cells->scale(id));
  }
  printf("\n");
}

Set current axis and calculate the square distances to axis to init the iterative computation implemented in incrementAxis(). The current pos must be initialized by setCurrentPos().

|Vk-Xj|=|Vj-Xj| defines the intersection of the cell boundary (between cells k and j) with the considered axis. k is the current cell.

Along the axis i, looking at the cell boundary between cells k and j:

dk^2 + (( Vk[i] - Xj[i] ) * s[i] )^2=dj^2 + (( Vj[i] - Xj[i] ) * s[i] )^2

dk^2 + (Vk[i] * s[i] )^2 + (Xj[i] * s[i] )^2 - 2 * Vk[i] * Xj[i] * s[i]^2 =dj^2 + (Vj[i] * s[i] )^2 + (Xj[i] * s[i] )^2 - 2 * Vj[i] * Xj[i] * s[i]^2

dk^2 + (Vk[i] * s[i] )^2=dj^2 + (Vj[i] * s[i] )^2 - 2 * s[i]^2 * Xj[i] (Vj[i] - Vk[i] )

where dk and dj are the distances from axis to centers of cells. Vk and Vj are the centers of cells k and j, respectively. Vk[i] is the ith coordinate of point Vk. s[i] is the scale along axis i.

2 * Xj[i] * s[i]^2 * (Vk[i] - Vj[i] )=(Vk[i]^2 - Vj[i]^2) * s[i]^2 + (dk^2 - dj^2)

Pre-calculates all dk and dj.

References DinverCore::ScaledModels::modelCount(), DinverCore::ScaledModels::parameterCount(), and DinverCore::ScaledModels::v().

Referenced by DinverCore::ImportanceSampling::generate(), and DinverCore::Neighborhood::setVolumes().

{
  if(a==_cells->parameterCount()) a=0;
  _currentAxis=a;
  double d, dtot;
  double * dist=_axisDistances;
  int nm=_cells->modelCount();
  int nd=_cells->parameterCount();
  int id;
  for(int im=0;im<nm; im++ ) {
    dtot=0.0;
    for(id=0; id < _currentAxis; id++ ) {
      d=_currentPoint[ id ] - _cells->v(id)[im];
      dtot += d * d;
    }
    for(id++; id < nd;id++ ) {
      d=_currentPoint[ id ] - _cells->v(id)[im];
      dtot += d * d;
    }
    *(dist++ )=dtot;
  }
}
void DinverCore::VoronoiNavigator::setCurrentCell ( int  index) [inline]

Referenced by DinverCore::ImportanceSampling::generate().

{_currentCell=index;}
void DinverCore::VoronoiNavigator::setCurrentPoint ( int  index) [inline]

References DinverCore::ScaledModels::parameterCount(), TRACE, and DinverCore::ScaledModels::v().

Referenced by DinverCore::ImportanceSampling::generate(), and DinverCore::Neighborhood::setVolumes().

{
  TRACE;
  _currentCell=index;
  int nd=_cells->parameterCount();
  for(int id=0; id < nd; id++ ) {
    _currentPoint[ id ]=_cells->v(id)[_currentCell];
  }
}
void DinverCore::VoronoiNavigator::setCurrentPoint ( const int *  coordinates) [inline]

References DinverCore::ScaledModels::parameterCount(), DinverCore::ScaledModels::scale(), and TRACE.

{
  TRACE;
  _currentCell=-1;
  int nd=_cells->parameterCount();
  for(int id=0; id < nd; id++ ) {
    _currentPoint[ id ]=_cells->scale(id) * coordinates[id];
  }
}
void DinverCore::VoronoiNavigator::setValue ( int  v) [inline]

Referenced by DinverCore::ImportanceSampling::generate().

{_currentPoint[ _currentAxis ]=v * _cells->scale(_currentAxis);}
void DinverCore::VoronoiNavigator::setValue ( double  v) [inline]
{_currentPoint[ _currentAxis ]=v * _cells->scale(_currentAxis);}

The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines