text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    finance.cxx
  
    Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
    All rights reserved.
    See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  
       This software is distributed WITHOUT ANY WARRANTY; without even
       the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
       PURPOSE.  See the above copyright notice for more information.
  
  =========================================================================*/
  #include "vtkActor.h"
  #include "vtkAxes.h"
  #include "vtkContourFilter.h"
  #include "vtkDataSet.h"
  #include "vtkFloatArray.h"
  #include "vtkGaussianSplatter.h"
  #include "vtkImageData.h"
  #include "vtkPointData.h"
  #include "vtkPoints.h"
  #include "vtkPolyDataMapper.h"
  #include "vtkProperty.h"
  #include "vtkRenderWindow.h"
  #include "vtkRenderWindowInteractor.h"
  #include "vtkRenderer.h"
  #include "vtkTubeFilter.h"
  #include "vtkUnstructuredGrid.h"
  #include "vtkSmartPointer.h"
  
  #if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
  #pragma warning(disable : 4996) // 'function': was declared deprecated
  #endif
  
  static vtkSmartPointer<vtkDataSet> ReadFinancialData(const char *fname, const char *x, const char *y, const char *z, const char *s);
  static int ParseFile(FILE *file, const char *tag, float *data);
  
  int main( int argc, char *argv[] )
  {
    double bounds[6];
  
    if (argc < 2)
      {
      cout << "Usage: " << argv[0] << " financial_file" << endl;
      return 1;
      }
    char* fname = argv[1];
  
    // read data
    vtkSmartPointer<vtkDataSet> dataSet = ReadFinancialData(fname, "MONTHLY_PAYMENT","INTEREST_RATE",
                                            "LOAN_AMOUNT","TIME_LATE");
    // construct pipeline for original population
    vtkSmartPointer<vtkGaussianSplatter> popSplatter =
      vtkSmartPointer<vtkGaussianSplatter>::New();
    popSplatter->SetInputData(dataSet);
    popSplatter->SetSampleDimensions(50,50,50);
    popSplatter->SetRadius(0.05);
    popSplatter->ScalarWarpingOff();
  
    vtkSmartPointer<vtkContourFilter> popSurface =
      vtkSmartPointer<vtkContourFilter>::New();
    popSurface->SetInputConnection(popSplatter->GetOutputPort());
    popSurface->SetValue(0,0.01);
  
    vtkSmartPointer<vtkPolyDataMapper> popMapper =
      vtkSmartPointer<vtkPolyDataMapper>::New();
    popMapper->SetInputConnection(popSurface->GetOutputPort());
    popMapper->ScalarVisibilityOff();
  
    vtkSmartPointer<vtkActor> popActor = vtkSmartPointer<vtkActor>::New();
    popActor->SetMapper(popMapper);
    popActor->GetProperty()->SetOpacity(0.3);
    popActor->GetProperty()->SetColor(.9,.9,.9);
  
    // construct pipeline for delinquent population
    vtkSmartPointer<vtkGaussianSplatter> lateSplatter =
      vtkSmartPointer<vtkGaussianSplatter>::New();
    lateSplatter->SetInputData(dataSet);
    lateSplatter->SetSampleDimensions(50,50,50);
    lateSplatter->SetRadius(0.05);
    lateSplatter->SetScaleFactor(0.005);
  
    vtkSmartPointer<vtkContourFilter> lateSurface =
      vtkSmartPointer<vtkContourFilter>::New();
    lateSurface->SetInputConnection(lateSplatter->GetOutputPort());
    lateSurface->SetValue(0,0.01);
  
    vtkSmartPointer<vtkPolyDataMapper> lateMapper =
      vtkSmartPointer<vtkPolyDataMapper>::New();
    lateMapper->SetInputConnection(lateSurface->GetOutputPort());
    lateMapper->ScalarVisibilityOff();
  
    vtkSmartPointer<vtkActor> lateActor =
      vtkSmartPointer<vtkActor>::New();
    lateActor->SetMapper(lateMapper);
    lateActor->GetProperty()->SetColor(1.0,0.0,0.0);
  
    // create axes
    popSplatter->Update();
    popSplatter->GetOutput()->GetBounds(bounds);
  
    vtkSmartPointer<vtkAxes> axes =
      vtkSmartPointer<vtkAxes>::New();
    axes->SetOrigin(bounds[0], bounds[2], bounds[4]);
    axes->SetScaleFactor(popSplatter->GetOutput()->GetLength()/5);
  
    vtkSmartPointer<vtkTubeFilter> axesTubes =
      vtkSmartPointer<vtkTubeFilter>::New();
    axesTubes->SetInputConnection(axes->GetOutputPort());
    axesTubes->SetRadius(axes->GetScaleFactor()/25.0);
    axesTubes->SetNumberOfSides(6);
  
    vtkSmartPointer<vtkPolyDataMapper> axesMapper =
      vtkSmartPointer<vtkPolyDataMapper>::New();
    axesMapper->SetInputConnection(axesTubes->GetOutputPort());
  
    vtkSmartPointer<vtkActor> axesActor =
      vtkSmartPointer<vtkActor>::New();
    axesActor->SetMapper(axesMapper);
  
    // graphics stuff
    vtkSmartPointer<vtkRenderer> renderer =
      vtkSmartPointer<vtkRenderer>::New();
  
    vtkSmartPointer<vtkRenderWindow> renWin =
      vtkSmartPointer<vtkRenderWindow>::New();
    renWin->AddRenderer(renderer);
  
    vtkSmartPointer<vtkRenderWindowInteractor> iren =
      vtkSmartPointer<vtkRenderWindowInteractor>::New();
    iren->SetRenderWindow(renWin);
  
    // read data  //set up renderer
    renderer->AddActor(lateActor);
    renderer->AddActor(axesActor);
    renderer->AddActor(popActor);
    renderer->SetBackground(1,1,1);
    renWin->SetSize(300,300);
  
    // interact with data
    iren->Initialize();
  
    renWin->Render();
    iren->Start();
  
    return 0;
  }
  
  static vtkSmartPointer<vtkDataSet> ReadFinancialData(const char* filename, const char *x, const char *y, const char *z, const char *s)
  {
    float xyz[3];
    FILE *file;
    int i, npts;
    char tag[80];
  
    if ( (file = fopen(filename,"r")) == 0 )
      {
      cerr << "ERROR: Can't open file: " << filename << "\n";
      return NULL;
      }
  
    int n = fscanf (file, "%s %d", tag, &npts); // read number of points
    if (n != 2)
      {
      cerr << "ERROR: Can't read file: " << filename << "\n";
      fclose(file);
      return NULL;
      }
  
    vtkSmartPointer<vtkUnstructuredGrid> dataSet =
      vtkSmartPointer<vtkUnstructuredGrid>::New();
    float *xV = new float[npts];
    float *yV = new float[npts];
    float *zV = new float[npts];
    float *sV = new float[npts];
  
    if ( ! ParseFile(file, x, xV) || ! ParseFile(file, y, yV) ||
         ! ParseFile(file, z, zV) || ! ParseFile(file, s, sV) )
      {
      cerr << "Couldn't read data!\n";
      delete [] xV;
      delete [] yV;
      delete [] zV;
      delete [] sV;
      fclose(file);
      return NULL;
      }
  
    vtkSmartPointer<vtkPoints> newPts =
      vtkSmartPointer<vtkPoints>::New();
    vtkSmartPointer<vtkFloatArray> newScalars =
      vtkSmartPointer<vtkFloatArray>::New();
  
    for (i=0; i<npts; i++)
      {
      xyz[0] = xV[i]; xyz[1] = yV[i]; xyz[2] = zV[i];
      newPts->InsertPoint(i, xyz);
      newScalars->InsertValue(i, sV[i]);
      }
  
    dataSet->SetPoints(newPts);
    dataSet->GetPointData()->SetScalars(newScalars);
  
    // cleanup
    delete [] xV;
    delete [] yV;
    delete [] zV;
    delete [] sV;
    fclose(file);
  
    return dataSet;
  }
  
  static int ParseFile(FILE *file, const char *label, float *data)
  {
    char tag[80];
    int i, npts, readData=0;
    float min=VTK_FLOAT_MAX;
    float max=(-VTK_FLOAT_MAX);
  
    if ( file == NULL || label == NULL ) return 0;
  
    rewind(file);
  
    if (fscanf(file, "%s %d", tag, &npts) != 2)
      {
      cerr << "IO Error " << __FILE__ << ":" << __LINE__ << "\n";
      return 0;
      }
  
    while ( !readData && fscanf(file, "%s", tag) == 1 )
      {
      if ( ! strcmp(tag,label) )
        {
        readData = 1;
        for (i=0; i<npts; i++)
          {
          if (fscanf(file, "%f", data+i) != 1)
            {
            cerr << "IO Error " << __FILE__ << ":" << __LINE__ << "\n";
            return 0;
            }
          if ( data[i] < min ) min = data[i];
          if ( data[i] > min ) max = data[i];
          }
        // normalize data
        for (i=0; i<npts; i++) data[i] = min + data[i]/(max-min);
        }
      else
        {
        for (i=0; i<npts; i++)
          {
          if (fscanf(file, "%*f") != 0)
            {
            cerr << "IO Error " << __FILE__ << ":" << __LINE__ << "\n";
            return 0;
            }
          }
        }
      }
  
    if ( ! readData ) return 0;
    else return 1;
  }
  