//----------------------------------------------------------------------------------
//! Handle field changes of the field field.
//----------------------------------------------------------------------------------
void FuzzyConnectedness::handleNotification (Field *field)
{
  ML_TRACE_IN("FuzzyConnectedness::handleNotification ()");
  // Calculation will only be performed if either the start 
  // button is pressed or  the auto update mechanism is used. 
  if ((field ==_startButtonFld) || ((field != _startButtonFld) && _autoUpdateFld->isOn()))
  {
    _state = ML_RESULT_OK;
    //If either input image is open the calculation will be cancelled.
    if(!getUpdatedInImg(0) || !getUpdatedInImg(1))
    {
      _state = ML_DISCONNECTED_GRAPH;
      clearData();
      getOutImg(0)->setOutOfDate();
      getOutImg(1)->setOutOfDate();
      getOutField(0)->notifyAttachments();
      getOutField(1)->notifyAttachments();
    }
    else
    {
      // Same extent of image data and seed point image are required
      if ( getUpdatedInImg(0)->getImgExt() != getUpdatedInImg(1)->getImgExt() )
      {
        _state=ML_BAD_DIMENSION;
      }
      // Calculation will be started here
      else{
        _state = calculate(getUpdatedInImg(0),getUpdatedInImg(1));
      }
    }
    // Let the connected modules know that the output has changed.
    getOutField(0)->notifyAttachments();
    getOutField(1)->notifyAttachments();
  }
}
//! Modify item at position \a index. If \a fromCurrentItem is true, the
//! item is copied from _currentItem, otherwise the item property corresponding
//! to the property field \a field is modified.
//! Return true if item has been modified.
bool ColoredMarkerListContainer::modifyItem(MLssize_t index, Field *field, bool fromCurrentItem)
{
    ML_TRACE_IN("bool ColoredMarkerListContainer::modifyItem(MLssize_t index, Field *field, bool fromCurrentItem)");

    ML_TRY{
      bool modified = true;
      ColoredMarker *marker=NULL;
    
      // Valid list and item?
      if (_listPtr && (index >= 0) && (index < mlrange_cast<MLssize_t>(_listPtr->getSize())) )
      {
          // Modify from property field?
          if (!fromCurrentItem)
          {
              // Pointer to list item
              marker = &(*_listPtr)[mlrange_cast<size_t>(index)];
            
              // Position fields
              if ((field == _fldPos3D) || (field == _fldPosC) || (field == _fldPosT) || (field == _fldPosU))
              {
                  marker->pos = Vector6(_fldPos3D->getVector3Value(),0,0,0);
                  marker->c() = _fldPosC->getFloatValue();
                  marker->t() = _fldPosT->getFloatValue();
                  marker->u() = _fldPosU->getFloatValue();

              } 
              else if (field == _fldColor  || (field == _fldAlpha))
              {
                  // ImageVector field
                  marker->rgba()          = Vector4(_fldColor->getVector3Value(),_fldAlpha->getFloatValue());

              } 
              else if (field == _fldType)
              {
                  // Type field
                  marker->type = _fldType->getIntValue();
                
              } 
              else 
              {
                  // Not an ColoredMarker-specific field, pass call to base class
                  modified = ListContainerTemplate<ColoredMarkerList>::modifyItem(index, field, fromCurrentItem);
              }

          } 
          else 
          {
              // Modify from _currentItem, handled in base class
              modified = ListContainerTemplate<ColoredMarkerList>::modifyItem(index, field, fromCurrentItem);
          }

      } else 
      {
          modified = false;
      }
    
      return modified;
    }
    ML_CATCH_RETHROW;
}
//----------------------------------------------------------------------------------
//! Handle notifications of CSOList
//----------------------------------------------------------------------------------
void CSOPointsToXMarkers::CSOListNotifyObserverCB(void* userData, int /*notificationFlag*/)
{
  ML_TRACE_IN("CSOPointsToXMarkers::_csoListNotifyObserverCB");

  CSOPointsToXMarkers * thisPointer = static_cast<CSOPointsToXMarkers*>(userData);
  thisPointer->convertCSOToXMarkerList();
}
void ListModifyProperties::activateAttachments() {  
   
  ML_TRACE_IN("void ListModifyProperties::activateAttachments()");

  Engine::activateAttachments();
  _autoUpdateModeFld->touch();
}
//! Return true if \a field points to an item property field
bool ColoredMarkerListContainer::isPropertyField(Field *field)
{
    ML_TRACE_IN("bool ColoredMarkerListContainer::isPropertyField(Field *field)");

    return ( (field == _fldPos3D) || (field == _fldPosC) || (field == _fldPosT) || (field == _fldPosU) || 
             (field == _fldColor) || (field == _fldAlpha) ||  (field == _fldType) || ListContainerBase::isPropertyField(field) );
}
//----------------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------------
WEMVolume::WEMVolume (std::string type)
  : WEMInspector(type)
{
  ML_TRACE_IN("WEMVolume::WEMVolume()")

  FieldContainer *fields = getFieldContainer();
  ML_CHECK(fields);

  // Suppress calls of handleNotification on field changes.
  handleNotificationOff();

  // Add min, max volume, and corresponding index fields
  _minVolumeFld = fields->addFloat("minVolume");
  _minVolumeFld->setFloatValue(0.0f);
  _maxVolumeFld = fields->addFloat("maxVolume");
  _maxVolumeFld->setFloatValue(0.0f);
  _minVolumeIndexFld = fields->addInt("minVolumePatchIndex");
  _minVolumeIndexFld->setIntValue(0);
  _maxVolumeIndexFld = fields->addInt("maxVolumePatchIndex");
  _maxVolumeIndexFld->setIntValue(0);
  
  // Add output curve field
  _outputVolumeCurveFld = fields->addBase("outputVolumeCurve");
  _outputVolumeCurveFld->setBaseValue(&_outputVolumeCurve);

  // Reactivate calls of handleNotification on field changes.
  handleNotificationOn();
}
//----------------------------------------------------------------------------------
//! Handle field changes of the field \c field.
//----------------------------------------------------------------------------------
void WEMVolume::handleNotification (Field *field)
{
  ML_TRACE_IN("WEMVolume::handleNotification()")

  // call parent class and handle apply/autoApply and in/outputs
  WEMInspector::handleNotification(field);
}
void CSODistance::_csoListNotificationCB(void* userData, int notificationFlag)
{
  ML_TRACE_IN("void CSODistance::_csoListNotificationCB()");

  CSODistance* thisp = static_cast<CSODistance*>(userData);

  thisp->_isInNotificationCB = true;
  bool autoApply = thisp->_autoApplyFld->getBoolValue();

  if ((notificationFlag & CSOList::NOTIFICATION_CSO_SELECTION) ||
      (notificationFlag & CSOList::NOTIFICATION_GROUP_SELECTION))
  {
      if (thisp->_listenToSelectionChangedNotificationsFld->getBoolValue()){
        if (autoApply) { thisp->_process(); }
      }
  }
  if ((notificationFlag & CSOList::NOTIFICATION_CSO_FINISHED) ||
      (notificationFlag & CSOList::NOTIFICATION_GROUP_FINISHED))
  {
      if (thisp->_listenToFinishingNotificationsFld->getBoolValue()){
        if (autoApply) { thisp->_process(); }
      }
  }
  if (notificationFlag & CSOList::NOTIFICATION_REPAINT){
    if (thisp->_listenToRepaintNotificationsFld->getBoolValue()){
        if (autoApply) { thisp->_process(); }
    }
  }
  if (notificationFlag & CSOList::NOTIFICATION_INTERACTION_INIT){
    // do nothing
  }

  thisp->_isInNotificationCB = false;
}
//----------------------------------------------------------------------------------
//! Code below is performed after module and network initialization.
//----------------------------------------------------------------------------------
void WEMVolume::activateAttachments()
{
    ML_TRACE_IN("WEMVolume::activateAttachments()")

    // call parent class
    WEMInspector::activateAttachments();
}
//----------------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------------
StringToCurve::StringToCurve () : BaseOp(0, 0)
{
  ML_TRACE_IN("StringToCurve::StringToCurve ()")

  handleNotificationOff();

  FieldContainer *fieldC = getFieldContainer();

  m_OutCurveList = new CurveList;
  f_OutCurveList = fieldC->addBase( "outCurveList" );
  f_OutCurveList->setBaseValue( m_OutCurveList );

  f_CurveString = fieldC->addString("curveString");
  f_CurveString->setStringValue("");

  f_IndexString = fieldC->addString("indexString");
  f_IndexString->setStringValue("");

  f_ValueSeparator = fieldC->addString("valueSeparator");
  f_ValueSeparator->setStringValue(" ");

  f_CurveSeparator = fieldC->addString( "curveSeparator" );
  f_CurveSeparator->setStringValue(";");

  handleNotificationOn();
}
//----------------------------------------------------------------------------------
//! Handle field changes of the field field.
//----------------------------------------------------------------------------------
void StringToCurve::handleNotification (Field * /*field*/)
{
  ML_TRACE_IN("StringToCurve::handleNotification ()");

  UpdateCurve();
  f_OutCurveList->notifyAttachments();
}
//----------------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------------
WEMCMSelectPatches::WEMCMSelectPatches (std::string type)
  : WEMProcessor(type, false)
{
  ML_TRACE_IN("WEMCMSelectPatches::WEMCMSelectPatches()")

  FieldContainer *fields = getFieldContainer();
  ML_CHECK(fields);

  // Suppress calls of hanbdleNotification on field changes.
  handleNotificationOff();

  // WEM Patch start and end index field
  _patchStartIndexFld = fields->addInt("patchStartIndex");
  _patchStartIndexFld->setIntValue(0);
  _patchEndIndexFld = fields->addInt("patchEndIndex");
  _patchEndIndexFld->setIntValue(0);

  // Bool field to enable to select only one patch based on start index value
  _onePatchFld = fields->addBool("onePatch");
  _onePatchFld->setBoolValue(false);
  
  // Set auto apply fields
  _autoApplyFld->setBoolValue(true);

  _notifyFld = fields->addNotify("notify");
 
  // Reactivate calls of handleNotification on field changes.
  handleNotificationOn();
}
ML_START_NAMESPACE

  // Initialization of the run type system

  int MLBaseListExtensionsInit()
  {
    ML_TRACE_IN("MLBaseListExtensionsInit()")

    IndexPair                  ::initClass();
    IndexPairList              ::initClass();
    IndexPairListContainer     ::initClass();

    ColoredMarker              ::initClass();
    ColoredMarkerList          ::initClass();
    ColoredMarkerListContainer ::initClass();

    XMarkerToColoredMarker     ::initClass();
    ColoredMarkerToXMarker     ::initClass();

    ListInfo                   ::initClass();
    ListFilter                 ::initClass();
    ListModifyProperties       ::initClass();

    MarkerListImport           ::initClass();

    return 1;
  }
//----------------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------------
CalcCodedSegmentation::CalcCodedSegmentation (void) : BaseOp(1, 1)
{
  ML_TRACE_IN("CalcCodedSegmentation::CalcCodedSegmentation()")

  FieldContainer *fields = getFieldContainer();

  // Suppress calls of handleNotification on field changes.
  handleNotificationOff();

  MAX_SIZE = SHRT_MAX; //32767

  _fld_Add = fields->addNotify("Add");  
  (_fld_NameToAdd = fields->addString("NameToAdd"))->setStringValue("");
  (_fld_addMinValue = fields->addInt("addMinValue"))->setIntValue(1);
  (_fld_addMaxValue = fields->addInt("addMaxValue"))->setIntValue(ML_INT_MAX);
  (_fld_addAllExceptNull = fields->addBool("addAllExceptNull"))->setBoolValue(false);
  _fld_Reset = fields->addNotify("Reset");
  _fld_Purge = fields->addNotify("Purge");
  _fld_Finish = fields->addNotify("Finish");
  (_fld_ImageValues = fields->addString("ImageValues"))->setStringValue("");
  (_fld_ObjectValues = fields->addString("ObjectValues"))->setStringValue("");

  //All pointer values need to be set NULL here, before reset, otherwise, default random values of pointe can be interpreted as real values and a non existing pointer is tried to delete ... uuhhhh
  _virtualVolume = NULL;
  replaceValues = NULL;
  objectValues = NULL;
  valuesForObjects = NULL;
  objectNames = NULL;

  reset();

  // Reactivate calls of handleNotification on field changes.
  handleNotificationOn();
}
//----------------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------------
WEMNodesToFile::WEMNodesToFile (std::string type)
  : WEMInspector(type)
{
  ML_TRACE_IN("WEMNodesToFile::WEMNodesToFile()")

  FieldContainer *fields = getFieldContainer();
  ML_CHECK(fields);

  // Suppress calls of handleNotification on field changes.
  handleNotificationOff();

  // Add filename field
  _filenameFld = fields->addString("filename");
  _filenameFld->setStringValue("");

  // Add transformix option field
  _transformixCompatibleFld = fields->addBool("transformixCompatible");
  _transformixCompatibleFld->setBoolValue(false);

  // Add save button
  _saveFld = fields->addNotify("save");

  // Reactivate calls of handleNotification on field changes.
  handleNotificationOn();
}
//----------------------------------------------------------------------------------
//! Code below is performed after module and network initialization.
//----------------------------------------------------------------------------------
void WEMCenterOfMass::activateAttachments()
{
    ML_TRACE_IN("WEMCenterOfMass::activateAttachments()")

    // call parent class
    WEMInspector::activateAttachments();
}
void MainAxisPCA::getInverseMatrix(float **aMatrix, float **invMatrix) 
{
    ML_TRACE_IN("void MainAxisPCA::getInverseMatrix(float **aMatrix, float **invMatrix) ");

    // Compute inverse matrix (only for 3x3 matrices)
    // calculate determinant D and multiply the result with 1/D
    
    float det = aMatrix[1][1] * aMatrix[2][2] * aMatrix[3][3]
        + aMatrix[1][2] * aMatrix[2][3] * aMatrix[3][1]
        + aMatrix[1][3] * aMatrix[2][1] * aMatrix[3][2]
        - aMatrix[1][3] * aMatrix[2][2] * aMatrix[3][1]
        - aMatrix[1][1] * aMatrix[2][3] * aMatrix[3][2]
        - aMatrix[1][2] * aMatrix[2][1] * aMatrix[3][3];
    
    if (det != 0){ det = 1.0f/det; }
    
    // Compute adjacent matrix, transpose it and multiply with D
    
    invMatrix[1][1] =  det * (aMatrix[2][2] * aMatrix[3][3] - aMatrix[2][3] * aMatrix[3][2]);
    invMatrix[2][1] = -det * (aMatrix[2][1] * aMatrix[3][3] - aMatrix[2][3] * aMatrix[3][1]);
    invMatrix[3][1] =  det * (aMatrix[2][1] * aMatrix[3][2] - aMatrix[2][2] * aMatrix[3][1]);
    invMatrix[1][2] = -det * (aMatrix[1][2] * aMatrix[3][3] - aMatrix[1][3] * aMatrix[3][2]);
    invMatrix[2][2] =  det * (aMatrix[1][1] * aMatrix[3][3] - aMatrix[1][3] * aMatrix[3][1]);
    invMatrix[3][2] = -det * (aMatrix[1][1] * aMatrix[3][2] - aMatrix[1][2] * aMatrix[3][1]);
    invMatrix[1][3] =  det * (aMatrix[1][2] * aMatrix[2][3] - aMatrix[1][3] * aMatrix[2][2]);
    invMatrix[2][3] = -det * (aMatrix[1][1] * aMatrix[2][3] - aMatrix[1][3] * aMatrix[2][1]);
    invMatrix[3][3] =  det * (aMatrix[1][1] * aMatrix[2][2] - aMatrix[1][2] * aMatrix[2][1]);
}
float* MainAxisPCA::calcBaryCenter(const float* vertices, int size) 
{
    ML_TRACE_IN("float* MainAxisPCA::calcBaryCenter(const float* vertices, int size) ");   

    // Computes the center of mass of a set of points and returns the center point
    if (size != 0) {
        float* meanVec = NULL;
        ML_CHECK_NEW(meanVec, float[3]);

        meanVec[0] = 0;
        meanVec[1] = 0;
        meanVec[2] = 0;
        
        for (int counter = 0; counter < size; counter++) {
            meanVec[0] += *vertices++;
            meanVec[1] += *vertices++;
            meanVec[2] += *vertices++;
        }
        // Division by the number of points
        meanVec[0] /= size;
        meanVec[1] /= size;
        meanVec[2] /= size;
        
        return meanVec;
    } 
    else{
        return 0;
    }
}
float* MainAxisPCA::getLargestMainAxis()
{
    ML_TRACE_IN("float* MainAxisPCA::getLargestMainAxis()");

    float* lA = NULL;
    ML_CHECK_NEW(lA, float[3]);

    if (_xDiameter > _yDiameter && _xDiameter > _zDiameter) {
        lA[0] = _xAxis[0];
        lA[1] = _xAxis[1];
        lA[2] = _xAxis[2];
        
        return lA;
    }
    if (_yDiameter > _xDiameter && _yDiameter > _zDiameter) {
        lA[0] = _yAxis[0];
        lA[1] = _yAxis[1];
        lA[2] = _yAxis[2];
    
        return lA;
    }
    lA[0] = _zAxis[0];
    lA[1] = _zAxis[1];
    lA[2] = _zAxis[2];

    return lA;
}
float* MainAxisPCA::stretchVector(const float* vector, const float length) 
{
    ML_TRACE_IN("float* MainAxisPCA::stretchVector(const float* vector, const float length)");

    float* strVec = NULL;
    ML_CHECK_NEW(strVec, float[3]);
    
    // Sum of squares of the direction vector
    float sumVec = vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2];
    
    // return if this sum equals 0
    if (sumVec == 0) {
        strVec[0] = strVec[1] = strVec[2] = 0;
        return strVec;
    }
    
    // |aVector| = sqrt(aVector[0]^2 + aVector[1]^2 + aVector[2]^2):
    float factor = sqrtf((length * length) / sumVec);
    
    strVec[0] = vector[0] * factor;
    strVec[1] = vector[1] * factor;
    strVec[2] = vector[2] * factor;
    
    return strVec;
}
void MainAxisPCA::getBoundingBox(const float* pointSet, const long size, 
                                 float& minX, float& maxX, 
                                 float& minY, float& maxY, 
                                 float& minZ, float& maxZ) 
{
    ML_TRACE_IN("void MainAxisPCA::getBoundingBox(...)");

    // Return the bounding box of a point set
    if (pointSet != NULL && size > 0) {
        const float* pointer = pointSet;
        minX = maxX = *(pointer++);
        minY = maxY = *(pointer++);
        minZ = maxZ = *(pointer++);
        for (long counter = 1; counter < size; counter++) {
            if (minX > *pointer) minX = *pointer;
            if (maxX < *pointer) maxX = *pointer;
            pointer++;
            if (minY > *pointer) minY = *pointer;
            if (maxY < *pointer) maxY = *pointer;
            pointer++;
            if (minZ > *pointer) minZ = *pointer;
            if (maxZ < *pointer) maxZ = *pointer;
            pointer++;
        } // for
    } // if
}
TileSphere::~TileSphere() 
{
    ML_TRACE_IN("TileSphere::~TileSphere()");

    ML_DELETE_ARR(_tileSpheres);
    ML_DELETE_ARR(_subset);
}
void TileSphere::_getSubset(float** &subset, int &size)
{
    ML_TRACE_IN("void TileSphere::_getSubset(float** &subset, int &size)");

    subset = _subset;
    size   = _numEntries;
}
void TileSphere::getStatistics(int &_treeDepth, int &_usedSpheres, int &_leafSpheres, int &_maxEnt) 
{
    ML_TRACE_IN("void TileSphere::getStatistics(int &_treeDepth, int &_usedSpheres, int &_leafSpheres, int &_maxEnt) ");

    int treeDepth  = 0, treeDepthTmp = 0;
    float** dummy  = NULL;
    int subsetSize = 0;

    unsigned int counter=0;

    // Has sub spheres
    if (_hasSubSpheresFlag) {
        for (counter = 0; counter < _cubicPartition; counter++) {
            _tileSpheres[counter]._getSubset(dummy, subsetSize);
            if (subsetSize != 0 || _tileSpheres[counter]._hasSubSpheres()) {
                _tileSpheres[counter].getStatistics(treeDepthTmp, _usedSpheres, _leafSpheres, _maxEnt);
                if (treeDepthTmp > treeDepth) {
                    treeDepth = treeDepthTmp;
                }
            }
        }
    } else {
        // Has set of points
        if (_numEntries > _maxEnt){ _maxEnt = _numEntries; }
        _leafSpheres++;
    }

    treeDepth++;
    _usedSpheres++;

    _treeDepth = treeDepth;
}
float METKSurfaceDistance3D::getImageValue(const SbVec3f* vertex) {
    ML_TRACE_IN("METKSurfaceDistance3D::getImageValue(const SbVec3f* vertex)");
    // if intersection contains node, retrieve according
    // value, else fill in default value
    float imgVal = -1;
    if (_inputImageIsValid) {
        // compute node's position in voxel space
        vec3 pos;
        pos[0] = vertex->getValue()[0];
        pos[1] = vertex->getValue()[1];
        pos[2] = vertex->getValue()[2];

        _image->transformToVoxelCoord(pos, pos);

        Vector nodeVPos;
        nodeVPos.x = pos[0];
        nodeVPos.y = pos[1];
        nodeVPos.z = pos[2];
        if (_intersectBB.contains(nodeVPos)) {
            imgVal = _subImageMemory[ (int)std::floor ((nodeVPos.x - _intersectBB.v1.x))            +
                                      (int)std::floor(((nodeVPos.y - _intersectBB.v1.y) * _yStride)) +
                                      (int)std::floor(((nodeVPos.z - _intersectBB.v1.z) * _zStride))];
        }
    }
    return imgVal;
}
//----------------------------------------------------------------------------------
//! Handle field changes of the field \c field.
//----------------------------------------------------------------------------------
void WEMCenterOfMass::handleNotification (Field *field)
{
  ML_TRACE_IN("WEMCenterOfMass::handleNotification()");

  if ( field == _useSurface ) { this->_process(); }
  // call parent class and handle apply/autoApply and in/outputs
  WEMInspector::handleNotification(field);
}
void MainAxisPCA::getExtension(float& xExt, float& yExt, float& zExt) 
{
    ML_TRACE_IN("void MainAxisPCA::getExtension(float& xExt, float& yExt, float& zExt) ");

    xExt = _xDiameter;
    yExt = _yDiameter;
    zExt = _zDiameter;
}
float MainAxisPCA::dotProduct(const float* vec1, const float* vec2) 
{
    ML_TRACE_IN("float MainAxisPCA::dotProduct(const float* vec1, const float* vec2) ");
    
    return (* vec1     ) * (* vec2     ) + 
           (*(vec1 + 1)) * (*(vec2 + 1)) + 
           (*(vec1 + 2)) * (*(vec2 + 2));
}
const void METKMsgManager::add(const ml::METKMsgSender* sender) {
    ML_TRACE_IN("METKMsgManager::add(const ml::METKMsgSender* sender)");
    // if there is no cache at all, create one
    if (!metkMsgManager)
        metkMsgManager = new METKMsgManager();
    // append sender
    metkMsgManager->SenderVec.push_back(sender);
}
TileSphere* TileSphere::_getPreciserSphere(TileSphere* referenceSphere, float closestDistance) 
{
    ML_TRACE_IN("TileSphere* TileSphere::_getPreciserSphere(TileSphere* referenceSphere, float closestDistance) ");

    bool unInit   = true;
    bool firstRun = false;

    if (closestDistance == -1){
        firstRun = true;
    }

    TileSphere *closestTileSphere = NULL, *tmpSphere = NULL;
    float tmpDistance=0;

    unsigned int counter=0;

    // Traverse each sub sphere.

    for (counter = 0; counter < _cubicPartition; counter++) {

        // Only examine further if the sphere contains more details.        
        if ((_tileSpheres[counter]._getRadius() != -1) &&
            !_minimalDistance->getHashTable()->existPair(&_tileSpheres[counter], referenceSphere))
        {
            if (unInit) {
                // Initialize variables once if they are yet uninitialized.
                tmpDistance = _distance(&_tileSpheres[counter], referenceSphere);
                if (firstRun) {
                    unInit = false;
                    closestTileSphere = &_tileSpheres[counter];
                    closestDistance = tmpDistance;
                } else {                
                    if ((tmpDistance * (1 + _error)) < closestDistance) {
                        unInit = false;
                        closestTileSphere = &_tileSpheres[counter];
                        closestDistance = tmpDistance;
                    }
                }
            } else {
                tmpSphere = &_tileSpheres[counter];
                tmpDistance = _distance(tmpSphere, referenceSphere);
                if (firstRun) {
                    if (tmpDistance < closestDistance) {
                        closestDistance = tmpDistance;
                        closestTileSphere = tmpSphere;
                    }
                } else {
                    if ((tmpDistance * (1 + _error)) < closestDistance) {
                        closestDistance = tmpDistance;
                        closestTileSphere = tmpSphere;
                    }
                }
            }
        }
    }

    return closestTileSphere;
}