/*========================================================================= Program: Visualization Toolkit Module: vtkPlot3D.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 "vtkPlot3D.h" #include "vtkChartXYZ.h" #include "vtkDataArray.h" #include "vtkIdTypeArray.h" #include "vtkLookupTable.h" #include "vtkObjectFactory.h" #include "vtkPen.h" #include "vtkStringArray.h" #include "vtkTable.h" namespace { // FIXME: Put this in a central header, as it is used across several classes. // Copy the two arrays into the points array template void CopyToPoints(float* data, A* input, size_t offset, size_t n) { for (size_t i = 0; i < n; ++i) { data[3 * i + offset] = *(input++); } } } //------------------------------------------------------------------------------ vtkPlot3D::vtkPlot3D() { this->Pen = vtkSmartPointer::New(); this->Pen->SetWidth(2.0); this->SelectionPen = vtkSmartPointer::New(); this->SelectionPen->SetColor(255, 50, 0, 150); this->SelectionPen->SetWidth(4.0); this->NumberOfComponents = 0; this->Chart = nullptr; } //------------------------------------------------------------------------------ vtkPlot3D::~vtkPlot3D() = default; //------------------------------------------------------------------------------ void vtkPlot3D::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } //------------------------------------------------------------------------------ void vtkPlot3D::SetPen(vtkPen* pen) { if (this->Pen != pen) { this->Pen = pen; this->Modified(); } } //------------------------------------------------------------------------------ vtkPen* vtkPlot3D::GetSelectionPen() { return this->SelectionPen; } //------------------------------------------------------------------------------ void vtkPlot3D::SetSelectionPen(vtkPen* pen) { if (this->SelectionPen != pen) { this->SelectionPen = pen; this->Modified(); } } //------------------------------------------------------------------------------ vtkPen* vtkPlot3D::GetPen() { return this->Pen; } //------------------------------------------------------------------------------ void vtkPlot3D::SetInputData(vtkTable* input) { assert(input->GetNumberOfColumns() >= 3); // assume the 4th column is color info if available if (input->GetNumberOfColumns() > 3) { this->SetInputData(input, input->GetColumnName(0), input->GetColumnName(1), input->GetColumnName(2), input->GetColumnName(3)); } else { this->SetInputData( input, input->GetColumnName(0), input->GetColumnName(1), input->GetColumnName(2)); } } //------------------------------------------------------------------------------ void vtkPlot3D::SetInputData( vtkTable* input, vtkIdType xColumn, vtkIdType yColumn, vtkIdType zColumn) { this->SetInputData(input, input->GetColumnName(xColumn), input->GetColumnName(yColumn), input->GetColumnName(zColumn)); } //------------------------------------------------------------------------------ void vtkPlot3D::SetInputData( vtkTable* input, const vtkStdString& xName, const vtkStdString& yName, const vtkStdString& zName) { // Copy the points into our data structure for rendering - pack x, y, z... vtkDataArray* xArr = vtkArrayDownCast(input->GetColumnByName(xName.c_str())); vtkDataArray* yArr = vtkArrayDownCast(input->GetColumnByName(yName.c_str())); vtkDataArray* zArr = vtkArrayDownCast(input->GetColumnByName(zName.c_str())); // Ensure that we have valid data arrays, and that they are of the same length. assert(xArr); assert(yArr); assert(zArr); assert(xArr->GetNumberOfTuples() == yArr->GetNumberOfTuples() && xArr->GetNumberOfTuples() == zArr->GetNumberOfTuples()); size_t n = xArr->GetNumberOfTuples(); this->Points.resize(n); float* data = this->Points[0].GetData(); switch (xArr->GetDataType()) { vtkTemplateMacro(CopyToPoints(data, static_cast(xArr->GetVoidPointer(0)), 0, n)); } switch (yArr->GetDataType()) { vtkTemplateMacro(CopyToPoints(data, static_cast(yArr->GetVoidPointer(0)), 1, n)); } switch (zArr->GetDataType()) { vtkTemplateMacro(CopyToPoints(data, static_cast(zArr->GetVoidPointer(0)), 2, n)); } this->PointsBuildTime.Modified(); // This removes the colors from our points. // They will be (re-)added by SetColors if necessary. this->NumberOfComponents = 0; this->XAxisLabel = xName; this->YAxisLabel = yName; this->ZAxisLabel = zName; this->ComputeDataBounds(); } //------------------------------------------------------------------------------ void vtkPlot3D::SetInputData(vtkTable* input, const vtkStdString& xName, const vtkStdString& yName, const vtkStdString& zName, const vtkStdString& colorName) { this->SetInputData(input, xName, yName, zName); vtkDataArray* colorArr = vtkArrayDownCast(input->GetColumnByName(colorName.c_str())); this->SetColors(colorArr); } //------------------------------------------------------------------------------ void vtkPlot3D::SetColors(vtkDataArray* colorArr) { assert(colorArr); assert((unsigned int)colorArr->GetNumberOfTuples() == this->Points.size()); this->NumberOfComponents = 3; // generate a color lookup table vtkNew lookupTable; double min = VTK_DOUBLE_MAX; double max = VTK_DOUBLE_MIN; for (unsigned int i = 0; i < this->Points.size(); ++i) { double value = colorArr->GetComponent(i, 0); if (value > max) { max = value; } if (value < min) { min = value; } } lookupTable->SetNumberOfTableValues(256); lookupTable->SetRange(min, max); lookupTable->Build(); this->Colors->Reset(); for (unsigned int i = 0; i < this->Points.size(); ++i) { double value = colorArr->GetComponent(i, 0); const unsigned char* rgb = lookupTable->MapValue(value); this->Colors->InsertNextTypedTuple(&rgb[0]); this->Colors->InsertNextTypedTuple(&rgb[1]); this->Colors->InsertNextTypedTuple(&rgb[2]); } this->Modified(); } //------------------------------------------------------------------------------ void vtkPlot3D::ComputeDataBounds() { double xMin = VTK_DOUBLE_MAX; double xMax = VTK_DOUBLE_MIN; double yMin = VTK_DOUBLE_MAX; double yMax = VTK_DOUBLE_MIN; double zMin = VTK_DOUBLE_MAX; double zMax = VTK_DOUBLE_MIN; for (unsigned int i = 0; i < this->Points.size(); ++i) { float* point = this->Points[i].GetData(); if (point[0] < xMin) { xMin = point[0]; } if (point[0] > xMax) { xMax = point[0]; } if (point[1] < yMin) { yMin = point[1]; } if (point[1] > yMax) { yMax = point[1]; } if (point[2] < zMin) { zMin = point[2]; } if (point[2] > zMax) { zMax = point[2]; } } this->DataBounds.clear(); this->DataBounds.resize(8); float* data = this->DataBounds[0].GetData(); // point 1: xMin, yMin, zMin data[0] = xMin; data[1] = yMin; data[2] = zMin; // point 2: xMin, yMin, zMax data[3] = xMin; data[4] = yMin; data[5] = zMax; // point 3: xMin, yMax, zMin data[6] = xMin; data[7] = yMax; data[8] = zMin; // point 4: xMin, yMax, zMax data[9] = xMin; data[10] = yMax; data[11] = zMax; // point 5: xMax, yMin, zMin data[12] = xMax; data[13] = yMin; data[14] = zMin; // point 6: xMax, yMin, zMax data[15] = xMax; data[16] = yMin; data[17] = zMax; // point 7: xMax, yMax, zMin data[18] = xMax; data[19] = yMax; data[20] = zMin; // point 8: xMax, yMax, zMax data[21] = xMax; data[22] = yMax; data[23] = zMax; } //------------------------------------------------------------------------------ void vtkPlot3D::SetChart(vtkChartXYZ* chart) { this->Chart = chart; } //------------------------------------------------------------------------------ std::string vtkPlot3D::GetXAxisLabel() { return this->XAxisLabel; } //------------------------------------------------------------------------------ std::string vtkPlot3D::GetYAxisLabel() { return this->YAxisLabel; } //------------------------------------------------------------------------------ std::string vtkPlot3D::GetZAxisLabel() { return this->ZAxisLabel; } //------------------------------------------------------------------------------ void vtkPlot3D::SetSelection(vtkIdTypeArray* id) { if (id == this->Selection) { return; } this->Selection = id; this->Modified(); } //------------------------------------------------------------------------------ vtkIdTypeArray* vtkPlot3D::GetSelection() { return this->Selection; } //------------------------------------------------------------------------------ std::vector vtkPlot3D::GetPoints() { return this->Points; }