vtkKMeansDistanceFunctor.cxx 6.71 KB
Newer Older
1 2 3 4 5 6 7 8 9
#include "vtkKMeansDistanceFunctor.h"

#include "vtkObjectFactory.h"
#include "vtkDoubleArray.h"
#include "vtkTable.h"
#include "vtkVariantArray.h"
#include "vtkIntArray.h"
#include "vtkIdTypeArray.h"

10
vtkStandardNewMacro(vtkKMeansDistanceFunctor);
11 12

// ----------------------------------------------------------------------
13
vtkKMeansDistanceFunctor::vtkKMeansDistanceFunctor()
14
{
15
  this->EmptyTuple = vtkVariantArray::New();
16 17 18
}

// ----------------------------------------------------------------------
19
vtkKMeansDistanceFunctor::~vtkKMeansDistanceFunctor()
20
{
21
  this->EmptyTuple->Delete();
22 23
}

24
// ----------------------------------------------------------------------
25 26 27 28 29 30
void vtkKMeansDistanceFunctor::PrintSelf( ostream& os, vtkIndent indent )
{
  this->Superclass::PrintSelf( os, indent );
  os << indent << "EmptyTuple: " << this->EmptyTuple << "\n";
}

31
// ----------------------------------------------------------------------
32
vtkVariantArray* vtkKMeansDistanceFunctor::GetEmptyTuple( vtkIdType dimension )
33
{
34
  if ( this->EmptyTuple->GetNumberOfValues() != dimension )
35 36
    {
    this->EmptyTuple->SetNumberOfValues( dimension );
37
    for( vtkIdType i = 0; i < dimension; ++ i )
38 39 40 41
      {
      this->EmptyTuple->SetValue( i, 0.0 );
      }
    }
42
  return this->EmptyTuple;
43 44 45
}

// ----------------------------------------------------------------------
46 47
void vtkKMeansDistanceFunctor::operator() (
  double& distance, vtkVariantArray* clusterCoord, vtkVariantArray* dataCoord )
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
{
  distance = 0.0;
  if(clusterCoord->GetNumberOfValues() != dataCoord->GetNumberOfValues() )
    {
    cout << "The dimensions of the cluster and data do not match." << endl;
    distance = -1;
    }

  for(vtkIdType i = 0; i < clusterCoord->GetNumberOfValues(); i++ )
    {
    distance += ( clusterCoord->GetValue( i ).ToDouble() - dataCoord->GetValue( i ).ToDouble() ) *
                ( clusterCoord->GetValue( i ).ToDouble() - dataCoord->GetValue( i ).ToDouble() );
    }
}

// ----------------------------------------------------------------------
64 65 66
void vtkKMeansDistanceFunctor::PairwiseUpdate(
  vtkTable* clusterCoords, vtkIdType rowIndex, vtkVariantArray* dataCoord,
  vtkIdType dataCoordCardinality, vtkIdType totalCardinality )
67
{
68
  if ( clusterCoords->GetNumberOfColumns() != dataCoord->GetNumberOfValues() )
69 70 71 72 73
    {
    cout << "The dimensions of the cluster and/or data do not match." << endl;
    return;
    }

74
  if ( totalCardinality > 0 )
75
    {
76
    for ( vtkIdType i = 0; i < clusterCoords->GetNumberOfColumns(); ++ i )
77 78
      {
      double curCoord = clusterCoords->GetValue( rowIndex, i ).ToDouble();
79 80 81 82
      clusterCoords->SetValue( rowIndex, i,
        curCoord + static_cast<double>(dataCoordCardinality)*
        (dataCoord->GetValue( i ).ToDouble() - curCoord)/
        static_cast<double>( totalCardinality ) );
83
      }
84 85 86 87 88
    }
}


// ----------------------------------------------------------------------
89 90 91 92
void vtkKMeansDistanceFunctor::PerturbElement(
  vtkTable* newClusterElements, vtkTable* curClusterElements,
  vtkIdType changeID, vtkIdType startRunID, vtkIdType endRunID,
  double alpha )
93 94 95
{
  double numInRange = static_cast<double>( endRunID-startRunID );
  vtkIdType dimension = newClusterElements->GetNumberOfColumns();
96
  std::vector<double> perturbedValues( dimension );
97 98 99 100 101 102 103 104 105

  for( vtkIdType i = startRunID; i < endRunID; i++)
    {
    for( vtkIdType j = 0; j < dimension; j++ )
      {
      if( i  == changeID )
        {
        perturbedValues[j] = alpha*curClusterElements->GetValue( i, j ).ToDouble();
        }
106
      else
107
        {
108
        if ( numInRange > 1.0)
109 110 111 112 113 114 115 116 117 118 119
          {
          perturbedValues[j] = ( 1.0-alpha )/( numInRange-1.0 )*
                               curClusterElements->GetValue( i, j ).ToDouble();
          }
        else
          {
          perturbedValues[j] = ( 1.0-alpha )/( numInRange )*
                               curClusterElements->GetValue( i, j ).ToDouble();
          }
        }
      }
120
    }
121
}
122 123

// ----------------------------------------------------------------------
124
void* vtkKMeansDistanceFunctor::AllocateElementArray( vtkIdType size )
125 126 127 128
{
  return new double[size];
}

129
// ----------------------------------------------------------------------
130
void vtkKMeansDistanceFunctor::DeallocateElementArray( void* array )
131 132 133 134 135
{
  delete [] static_cast< double* >( array );
}

// ----------------------------------------------------------------------
136
vtkAbstractArray* vtkKMeansDistanceFunctor::CreateCoordinateArray( )
137 138 139 140
{
  return vtkDoubleArray::New();
}

141
// ----------------------------------------------------------------------
142
void vtkKMeansDistanceFunctor::PackElements( vtkTable* curTable, void* vElements )
143 144 145 146
{
  vtkIdType numCols = curTable->GetNumberOfColumns();
  vtkIdType numRows = curTable->GetNumberOfRows();
  double* localElements = static_cast< double* >( vElements );
147

148 149 150 151 152 153 154
  for( vtkIdType col = 0; col < numCols; col++ )
    {
    vtkDoubleArray* doubleArr = vtkDoubleArray::SafeDownCast( curTable->GetColumn( col ) );
    memcpy( &(localElements[col*numRows]), doubleArr->GetPointer( 0 ), numRows*sizeof( double ) );
    }
}

155
// ----------------------------------------------------------------------
156
void vtkKMeansDistanceFunctor::UnPackElements( vtkTable* curTable, void* vLocalElements, vtkIdType numRows, vtkIdType numCols )
157 158 159 160 161 162 163 164 165 166 167 168 169
{
  double *localElements = static_cast< double* >( vLocalElements );
  for ( vtkIdType i = 0; i < numRows; i++ )
    {
    vtkVariantArray *curRow = vtkVariantArray::New();
    for ( int j = 0; j < numCols; j++ )
      {
      curRow->InsertNextValue( localElements[ j*numRows + i ] );
      }
    curTable->InsertNextRow( curRow );
    curRow->Delete();
    }
}
170 171

// ----------------------------------------------------------------------
172
void vtkKMeansDistanceFunctor::UnPackElements( vtkTable* curTable, vtkTable* newTable, void* vLocalElements, void* vGlobalElements, int np )
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
{
  double *globalElements = static_cast< double* >( vGlobalElements );
  double *localElements = static_cast< double* >( vLocalElements );
  vtkIdType numCols = curTable->GetNumberOfColumns();
  vtkIdType numRows = curTable->GetNumberOfRows();
  vtkIdType numElements = numCols*numRows;
  for( vtkIdType col = 0; col < numCols; col++ )
    {
    vtkDoubleArray *doubleArr = vtkDoubleArray::New();
    doubleArr->SetName( curTable->GetColumnName( col ) );
    doubleArr->SetNumberOfComponents( 1 );
    doubleArr->SetNumberOfTuples( numRows*np );
    for( int j = 0; j < np; j++ )
      {
      double *ptr = doubleArr->GetPointer(j*numRows);
      memcpy(ptr, &(globalElements[j*numElements+col*numRows]), numRows*sizeof( double ) );
      }
    newTable->AddColumn(doubleArr);
    doubleArr->Delete();
    }
193 194
  delete [] localElements;
  delete [] globalElements;
195 196 197
}

// ----------------------------------------------------------------------
198
int vtkKMeansDistanceFunctor::GetDataType()
199 200 201
{
  return VTK_DOUBLE;
}