/*========================================================================= 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 "vtkSmartPointer.h" #include "vtkTubeFilter.h" #include "vtkUnstructuredGrid.h" #include #include #include #if defined(_MSC_VER) /* Visual C++ (and Intel C++) */ #pragma warning(disable : 4996) // 'function': was declared deprecated #endif static vtkSmartPointer 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) { std::cout << "Usage: " << argv[0] << " financial_file" << endl; return EXIT_FAILURE; } char* fname = argv[1]; // read data vtkSmartPointer dataSet = ReadFinancialData(fname, "MONTHLY_PAYMENT", "INTEREST_RATE", "LOAN_AMOUNT", "TIME_LATE"); // construct pipeline for original population vtkSmartPointer popSplatter = vtkSmartPointer::New(); popSplatter->SetInputData(dataSet); popSplatter->SetSampleDimensions(50, 50, 50); popSplatter->SetRadius(0.05); popSplatter->ScalarWarpingOff(); vtkSmartPointer popSurface = vtkSmartPointer::New(); popSurface->SetInputConnection(popSplatter->GetOutputPort()); popSurface->SetValue(0, 0.01); vtkSmartPointer popMapper = vtkSmartPointer::New(); popMapper->SetInputConnection(popSurface->GetOutputPort()); popMapper->ScalarVisibilityOff(); vtkSmartPointer popActor = vtkSmartPointer::New(); popActor->SetMapper(popMapper); popActor->GetProperty()->SetOpacity(0.3); popActor->GetProperty()->SetColor(.9, .9, .9); // construct pipeline for delinquent population vtkSmartPointer lateSplatter = vtkSmartPointer::New(); lateSplatter->SetInputData(dataSet); lateSplatter->SetSampleDimensions(50, 50, 50); lateSplatter->SetRadius(0.05); lateSplatter->SetScaleFactor(0.005); vtkSmartPointer lateSurface = vtkSmartPointer::New(); lateSurface->SetInputConnection(lateSplatter->GetOutputPort()); lateSurface->SetValue(0, 0.01); vtkSmartPointer lateMapper = vtkSmartPointer::New(); lateMapper->SetInputConnection(lateSurface->GetOutputPort()); lateMapper->ScalarVisibilityOff(); vtkSmartPointer lateActor = vtkSmartPointer::New(); lateActor->SetMapper(lateMapper); lateActor->GetProperty()->SetColor(1.0, 0.0, 0.0); // create axes popSplatter->Update(); popSplatter->GetOutput()->GetBounds(bounds); vtkSmartPointer axes = vtkSmartPointer::New(); axes->SetOrigin(bounds[0], bounds[2], bounds[4]); axes->SetScaleFactor(popSplatter->GetOutput()->GetLength() / 5); vtkSmartPointer axesTubes = vtkSmartPointer::New(); axesTubes->SetInputConnection(axes->GetOutputPort()); axesTubes->SetRadius(axes->GetScaleFactor() / 25.0); axesTubes->SetNumberOfSides(6); vtkSmartPointer axesMapper = vtkSmartPointer::New(); axesMapper->SetInputConnection(axesTubes->GetOutputPort()); vtkSmartPointer axesActor = vtkSmartPointer::New(); axesActor->SetMapper(axesMapper); // graphics stuff vtkSmartPointer renderer = vtkSmartPointer::New(); vtkSmartPointer renWin = vtkSmartPointer::New(); renWin->AddRenderer(renderer); vtkSmartPointer iren = vtkSmartPointer::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); // For testing, check if "-V" is used to provide a regression test image if (argc >= 4 && strcmp(argv[2], "-V") == 0) { renWin->Render(); int retVal = vtkRegressionTestImage(renWin); if (retVal == vtkTesting::FAILED) { return EXIT_FAILURE; } else if (retVal != vtkTesting::DO_INTERACTOR) { return EXIT_SUCCESS; } } // interact with data iren->Initialize(); iren->Start(); return EXIT_SUCCESS; } static vtkSmartPointer 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 = vtksys::SystemTools::Fopen(filename, "r")) == nullptr) { std::cerr << "ERROR: Can't open file: " << filename << std::endl; return nullptr; } int n = fscanf(file, "%s %d", tag, &npts); // read number of points if (n != 2) { std::cerr << "ERROR: Can't read file: " << filename << std::endl; fclose(file); return nullptr; } // Check for a reasonable npts if (npts <= 0) { std::cerr << "ERROR: Number of points must be greater that 0" << std::endl; fclose(file); return nullptr; } // We arbitrarily pick a large upper limit on npts if (npts > VTK_INT_MAX / 10) { std::cerr << "ERROR: npts (" << npts << ") is unreasonably large" << std::endl; fclose(file); return nullptr; } vtkSmartPointer dataSet = vtkSmartPointer::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)) { std::cerr << "ERROR: Couldn't read data!" << std::endl; delete[] xV; delete[] yV; delete[] zV; delete[] sV; fclose(file); return nullptr; } vtkSmartPointer newPts = vtkSmartPointer::New(); vtkSmartPointer newScalars = vtkSmartPointer::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 == nullptr || label == nullptr) return 0; rewind(file); if (fscanf(file, "%s %d", tag, &npts) != 2) { std::cerr << "ERROR: IO Error " << __FILE__ << ":" << __LINE__ << std::endl; 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) { std::cerr << "ERROR: IO Error " << __FILE__ << ":" << __LINE__ << std::endl; 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) { std::cerr << "ERROR: IO Error " << __FILE__ << ":" << __LINE__ << std::endl; return 0; } } } } if (!readData) return 0; else return 1; }