/*========================================================================= Program: Visualization Toolkit Module: vtkSpiderPlotActor.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 "vtkSpiderPlotActor.h" #include "vtkAlgorithmOutput.h" #include "vtkAxisActor2D.h" #include "vtkCellArray.h" #include "vtkCellData.h" #include "vtkFieldData.h" #include "vtkGlyphSource2D.h" #include "vtkLegendBoxActor.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper2D.h" #include "vtkProperty2D.h" #include "vtkTextMapper.h" #include "vtkTextProperty.h" #include "vtkTrivialProducer.h" #include "vtkUnsignedCharArray.h" #include "vtkViewport.h" #include "vtkWindow.h" #include #include vtkStandardNewMacro(vtkSpiderPlotActor); vtkCxxSetObjectMacro(vtkSpiderPlotActor, LabelTextProperty, vtkTextProperty); vtkCxxSetObjectMacro(vtkSpiderPlotActor, TitleTextProperty, vtkTextProperty); // PIMPL'd list of labels class vtkAxisLabelArray : public std::vector { }; // PIMPL'd list of ranges struct vtkAxisRange { double Min; double Max; vtkAxisRange() : Min(0.0) , Max(0.0) { } vtkAxisRange(double min, double max) : Min(min) , Max(max) { } }; class vtkAxisRanges : public std::vector { }; class vtkSpiderPlotActorConnection : public vtkAlgorithm { public: static vtkSpiderPlotActorConnection* New(); vtkTypeMacro(vtkSpiderPlotActorConnection, vtkAlgorithm); vtkSpiderPlotActorConnection() { this->SetNumberOfInputPorts(1); } }; vtkStandardNewMacro(vtkSpiderPlotActorConnection); //------------------------------------------------------------------------------ // Instantiate object vtkSpiderPlotActor::vtkSpiderPlotActor() { // Actor2D positions this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport(); this->PositionCoordinate->SetValue(0.1, 0.1); this->Position2Coordinate->SetCoordinateSystemToNormalizedViewport(); this->Position2Coordinate->SetValue(0.9, 0.8); this->Position2Coordinate->SetReferenceCoordinate(nullptr); this->ConnectionHolder = vtkSpiderPlotActorConnection::New(); this->IndependentVariables = VTK_IV_COLUMN; this->TitleVisibility = 1; this->Title = nullptr; this->Labels = new vtkAxisLabelArray; this->Ranges = new vtkAxisRanges; this->LabelMappers = nullptr; this->LabelActors = nullptr; this->LabelTextProperty = vtkTextProperty::New(); this->LabelTextProperty->SetFontSize(12); this->LabelTextProperty->SetBold(1); this->LabelTextProperty->SetItalic(1); this->LabelTextProperty->SetShadow(0); this->LabelTextProperty->SetFontFamilyToArial(); this->TitleTextProperty = vtkTextProperty::New(); this->TitleTextProperty->ShallowCopy(this->LabelTextProperty); this->TitleTextProperty->SetFontSize(24); this->TitleTextProperty->SetBold(1); this->TitleTextProperty->SetItalic(0); this->TitleTextProperty->SetShadow(1); this->TitleTextProperty->SetFontFamilyToArial(); this->LabelVisibility = 1; this->NumberOfRings = 2; this->LegendVisibility = 1; this->LegendActor = vtkLegendBoxActor::New(); this->LegendActor->GetPositionCoordinate()->SetCoordinateSystemToViewport(); this->LegendActor->GetPosition2Coordinate()->SetCoordinateSystemToViewport(); this->LegendActor->GetPosition2Coordinate()->SetReferenceCoordinate(nullptr); this->LegendActor->BorderOff(); this->LegendActor->SetNumberOfEntries(100); // initial allocation this->LegendActor->SetPadding(2); this->LegendActor->ScalarVisibilityOff(); this->GlyphSource = vtkGlyphSource2D::New(); this->GlyphSource->SetGlyphTypeToNone(); this->GlyphSource->DashOn(); this->GlyphSource->FilledOff(); this->GlyphSource->Update(); this->PlotData = vtkPolyData::New(); this->PlotMapper = vtkPolyDataMapper2D::New(); this->PlotMapper->SetInputData(this->PlotData); this->PlotActor = vtkActor2D::New(); this->PlotActor->SetMapper(this->PlotMapper); this->TitleMapper = vtkTextMapper::New(); this->TitleActor = vtkActor2D::New(); this->TitleActor->SetMapper(this->TitleMapper); this->TitleActor->GetPositionCoordinate()->SetCoordinateSystemToViewport(); this->N = 0; this->Mins = nullptr; this->Maxs = nullptr; this->WebData = vtkPolyData::New(); this->WebMapper = vtkPolyDataMapper2D::New(); this->WebMapper->SetInputData(this->WebData); this->WebActor = vtkActor2D::New(); this->WebActor->SetMapper(this->WebMapper); this->LastPosition[0] = this->LastPosition[1] = this->LastPosition2[0] = this->LastPosition2[1] = 0; this->P1[0] = this->P1[1] = this->P2[0] = this->P2[1] = 0.0; } //------------------------------------------------------------------------------ vtkSpiderPlotActor::~vtkSpiderPlotActor() { this->ConnectionHolder->Delete(); this->ConnectionHolder = nullptr; delete[] this->Title; this->Title = nullptr; delete this->Labels; delete this->Ranges; this->SetLabelTextProperty(nullptr); this->SetTitleTextProperty(nullptr); this->LegendActor->Delete(); this->GlyphSource->Delete(); this->Initialize(); this->TitleMapper->Delete(); this->TitleMapper = nullptr; this->TitleActor->Delete(); this->TitleActor = nullptr; this->WebData->Delete(); this->WebMapper->Delete(); this->WebActor->Delete(); this->PlotData->Delete(); this->PlotMapper->Delete(); this->PlotActor->Delete(); } //------------------------------------------------------------------------------ void vtkSpiderPlotActor::SetInputConnection(vtkAlgorithmOutput* ao) { this->ConnectionHolder->SetInputConnection(ao); } //------------------------------------------------------------------------------ void vtkSpiderPlotActor::SetInputData(vtkDataObject* dobj) { vtkTrivialProducer* tp = vtkTrivialProducer::New(); tp->SetOutput(dobj); this->SetInputConnection(tp->GetOutputPort()); tp->Delete(); } //------------------------------------------------------------------------------ vtkDataObject* vtkSpiderPlotActor::GetInput() { return this->ConnectionHolder->GetInputDataObject(0, 0); } //------------------------------------------------------------------------------ // Free-up axes and related stuff void vtkSpiderPlotActor::Initialize() { if (this->LabelActors) { for (int i = 0; i < this->N; i++) { this->LabelMappers[i]->Delete(); this->LabelActors[i]->Delete(); } delete[] this->LabelMappers; this->LabelMappers = nullptr; delete[] this->LabelActors; this->LabelActors = nullptr; } if (this->Mins) { delete[] this->Mins; this->Mins = nullptr; delete[] this->Maxs; this->Maxs = nullptr; } this->N = 0; } //------------------------------------------------------------------------------ // Plot scalar data for each input dataset. int vtkSpiderPlotActor::RenderOverlay(vtkViewport* viewport) { int renderedSomething = 0; if (!this->BuildPlot(viewport)) { return 0; } // Done rebuilding, render as appropriate. if (this->GetInput() == nullptr || this->N <= 0) { vtkErrorMacro(<< "Nothing to plot!"); return 0; } if (this->TitleVisibility) { renderedSomething += this->TitleActor->RenderOverlay(viewport); } this->WebActor->SetProperty(this->GetProperty()); renderedSomething += this->WebActor->RenderOverlay(viewport); renderedSomething += this->PlotActor->RenderOverlay(viewport); if (this->LabelVisibility) { for (int i = 0; i < this->N; i++) { renderedSomething += this->LabelActors[i]->RenderOverlay(viewport); } } if (this->LegendVisibility) { renderedSomething += this->LegendActor->RenderOverlay(viewport); } return renderedSomething; } //------------------------------------------------------------------------------ // Plot scalar data for each input dataset. int vtkSpiderPlotActor::RenderOpaqueGeometry(vtkViewport* viewport) { int renderedSomething = 0; if (!this->BuildPlot(viewport)) { return 0; } // Done rebuilding, render as appropriate. if (this->GetInput() == nullptr || this->N <= 0) { vtkErrorMacro(<< "Nothing to plot!"); return 0; } if (this->TitleVisibility) { renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport); } this->WebActor->SetProperty(this->GetProperty()); renderedSomething += this->WebActor->RenderOpaqueGeometry(viewport); renderedSomething += this->PlotActor->RenderOpaqueGeometry(viewport); if (this->LabelVisibility) { for (int i = 0; i < this->N; i++) { renderedSomething += this->LabelActors[i]->RenderOpaqueGeometry(viewport); } } if (this->LegendVisibility) { renderedSomething += this->LegendActor->RenderOpaqueGeometry(viewport); } return renderedSomething; } //------------------------------------------------------------------------------ // Description: // Does this prop have some translucent polygonal geometry? vtkTypeBool vtkSpiderPlotActor::HasTranslucentPolygonalGeometry() { return 0; } //------------------------------------------------------------------------------ int vtkSpiderPlotActor::BuildPlot(vtkViewport* viewport) { // Initialize vtkDebugMacro(<< "Building spider plot"); // Make sure input is up to date, and that the data is the correct shape to // plot. if (!this->GetInput()) { vtkErrorMacro(<< "Nothing to plot!"); return 0; } if (!this->TitleTextProperty) { vtkErrorMacro(<< "Need title text property to render plot"); return 0; } if (!this->LabelTextProperty) { vtkErrorMacro(<< "Need label text property to render plot"); return 0; } // Viewport change may not require rebuild int positionsHaveChanged = 0; if (viewport->GetMTime() > this->BuildTime || (viewport->GetVTKWindow() && viewport->GetVTKWindow()->GetMTime() > this->BuildTime)) { int* lastPosition = this->PositionCoordinate->GetComputedViewportValue(viewport); int* lastPosition2 = this->Position2Coordinate->GetComputedViewportValue(viewport); if (lastPosition[0] != this->LastPosition[0] || lastPosition[1] != this->LastPosition[1] || lastPosition2[0] != this->LastPosition2[0] || lastPosition2[1] != this->LastPosition2[1]) { this->LastPosition[0] = lastPosition[0]; this->LastPosition[1] = lastPosition[1]; this->LastPosition2[0] = lastPosition2[0]; this->LastPosition2[1] = lastPosition2[1]; positionsHaveChanged = 1; } } // Check modified time to see whether we have to rebuild. this->ConnectionHolder->GetInputAlgorithm()->Update(); if (positionsHaveChanged || this->GetMTime() > this->BuildTime || this->GetInput()->GetMTime() > this->BuildTime || this->LabelTextProperty->GetMTime() > this->BuildTime || this->TitleTextProperty->GetMTime() > this->BuildTime) { vtkDebugMacro(<< "Rebuilding plot"); // Build axes const int* size = viewport->GetSize(); if (!this->PlaceAxes(viewport, size)) { return 0; } this->BuildTime.Modified(); } // If need to rebuild the plot return 1; } //------------------------------------------------------------------------------ static inline int vtkSpiderPlotActorGetComponent( vtkFieldData* field, vtkIdType tuple, int component, double* val) { int array_comp; int array_index = field->GetArrayContainingComponent(component, array_comp); if (array_index < 0) { return 0; } vtkDataArray* da = field->GetArray(array_index); if (!da) { // non-numeric array. return 0; } *val = da->GetComponent(tuple, array_comp); return 1; } #define VTK_RING_PTS 64 //------------------------------------------------------------------------------ int vtkSpiderPlotActor::PlaceAxes(vtkViewport* viewport, const int* vtkNotUsed(size)) { vtkIdType i, j, k; vtkDataObject* input = this->GetInput(); vtkFieldData* field = input->GetFieldData(); double v = 0.0; this->Initialize(); if (!field) { return 0; } // Determine the shape of the field int numComponents = field->GetNumberOfComponents(); // number of components // Note: numComponents also includes the non-numeric arrays. int numColumns = 0; // number of "columns" -- includes only numeric arrays. vtkIdType numRows = VTK_ID_MAX; // figure out number of rows vtkIdType numTuples; vtkDataArray* array; for (i = 0; i < field->GetNumberOfArrays(); i++) { array = field->GetArray(i); if (!array) { // skip over non-numeric arrays. continue; } numColumns += array->GetNumberOfComponents(); numTuples = array->GetNumberOfTuples(); if (numTuples < numRows) { numRows = numTuples; } } // Determine the number of independent variables if (this->IndependentVariables == VTK_IV_COLUMN) { this->N = numColumns; } else // row { this->N = numRows; } if (this->N <= 0 || this->N >= VTK_ID_MAX) { this->N = 0; vtkErrorMacro(<< "No field data to plot"); return 0; } // We need to loop over the field to determine the range of // each independent variable. this->Mins = new double[this->N]; this->Maxs = new double[this->N]; for (i = 0; i < this->N; i++) { this->Mins[i] = VTK_DOUBLE_MAX; this->Maxs[i] = -VTK_DOUBLE_MAX; } if (this->Ranges->size() < static_cast(this->N)) { // ranges not specified if (this->IndependentVariables == VTK_IV_COLUMN) { k = 0; for (j = 0; j < numComponents; j++) { int array_comp, array_index; array_index = field->GetArrayContainingComponent(j, array_comp); if (array_index < 0 || !field->GetArray(array_index)) { // non-numeric component, simply skip it. continue; } for (i = 0; i < numRows; i++) { // v = field->GetComponent(i,j); ::vtkSpiderPlotActorGetComponent(field, i, j, &v); if (v < this->Mins[k]) { this->Mins[k] = v; } if (v > this->Maxs[k]) { this->Maxs[k] = v; } } k++; } } else // row { for (j = 0; j < numRows; j++) { for (i = 0; i < numComponents; i++) { // v = field->GetComponent(j,i); if (::vtkSpiderPlotActorGetComponent(field, j, i, &v) == 0) { // non-numeric component, simply skip. continue; } if (v < this->Mins[j]) { this->Mins[j] = v; } if (v > this->Maxs[j]) { this->Maxs[j] = v; } } } } for (i = 0; i < this->N; i++) { this->Ranges->push_back(vtkAxisRange(this->Mins[i], this->Maxs[i])); } } // if automatic range computation else // specified correctly { vtkAxisRange range; for (i = 0; i < this->N; i++) { range = this->Ranges->at(i); this->Mins[i] = range.Min; this->Maxs[i] = range.Max; } } // Get the location of the corners of the box double* p1 = this->PositionCoordinate->GetComputedDoubleViewportValue(viewport); double* p2 = this->Position2Coordinate->GetComputedDoubleViewportValue(viewport); this->P1[0] = (p1[0] < p2[0] ? p1[0] : p2[0]); this->P1[1] = (p1[1] < p2[1] ? p1[1] : p2[1]); this->P2[0] = (p1[0] > p2[0] ? p1[0] : p2[0]); this->P2[1] = (p1[1] > p2[1] ? p1[1] : p2[1]); p1 = this->P1; p2 = this->P2; // Create the spider web // Determine the center of the spider plot. Leave room for the title and the legend double titleSpace = 0.0, legendSpace = 0.0; if (this->TitleVisibility) { titleSpace = 0.1; } if (this->LegendVisibility) { legendSpace = 0.15; } double d1 = p2[0] - legendSpace * (p2[0] - p1[0]) - p1[0]; double d2 = p2[1] - titleSpace * (p2[1] - p1[1]) - p1[1]; this->Center[0] = p1[0] + d1 / 2.0; this->Center[1] = p1[1] + d2 / 2.0; this->Center[2] = 0.0; this->Radius = (d1 < d2 ? d1 : d2); this->Radius /= 2.0; // Now generate the web points this->WebData->Initialize(); // remove old polydata, if any vtkPoints* webPts = vtkPoints::New(); webPts->Allocate(this->NumberOfRings * VTK_RING_PTS); vtkCellArray* webLines = vtkCellArray::New(); webLines->AllocateEstimate(this->N + this->NumberOfRings, VTK_RING_PTS); this->WebData->SetPoints(webPts); this->WebData->SetLines(webLines); vtkIdType ptId, pIds[VTK_RING_PTS + 1]; double currentTheta, x[3]; x[2] = 0.0; // Specify the positions for the axes this->Theta = 2.0 * vtkMath::Pi() / this->N; pIds[0] = webPts->InsertNextPoint(this->Center); for (i = 0; i < this->N; i++) { x[0] = this->Center[0] + this->Radius * cos(i * this->Theta); x[1] = this->Center[1] + this->Radius * sin(i * this->Theta); pIds[1] = webPts->InsertNextPoint(x); webLines->InsertNextCell(2, pIds); } if (this->NumberOfRings > 0) { double currentRadius, deltaRadius = this->Radius / this->NumberOfRings; currentTheta = 2.0 * vtkMath::Pi() / VTK_RING_PTS; for (i = 0; i < this->NumberOfRings; i++) { currentRadius = static_cast(i + 1) * deltaRadius; for (j = 0; j < VTK_RING_PTS; j++) { x[0] = this->Center[0] + currentRadius * cos(j * currentTheta); x[1] = this->Center[1] + currentRadius * sin(j * currentTheta); pIds[j] = webPts->InsertNextPoint(x); } pIds[VTK_RING_PTS] = pIds[0]; webLines->InsertNextCell(VTK_RING_PTS + 1, pIds); } } // Produce labels around the rim of the plot int minFontSize = 1000, fontSize, tsize[2]; if (this->LabelVisibility) { this->LabelActors = new vtkActor2D*[this->N]; this->LabelMappers = new vtkTextMapper*[this->N]; char label[1024]; const char* str; for (i = 0; i < this->N; i++) { x[0] = this->Center[0] + (this->Radius + 5) * cos(i * this->Theta); x[1] = this->Center[1] + (this->Radius + 5) * sin(i * this->Theta); this->LabelMappers[i] = vtkTextMapper::New(); if ((str = this->GetAxisLabel(i)) != nullptr) { this->LabelMappers[i]->SetInput(str); } else { snprintf(label, sizeof(label), "%d", static_cast(i)); this->LabelMappers[i]->SetInput(label); } this->LabelMappers[i]->GetTextProperty()->ShallowCopy(this->LabelTextProperty); tsize[0] = static_cast(0.15 * d1); tsize[1] = static_cast(0.15 * d2); fontSize = this->LabelMappers[i]->SetConstrainedFontSize(viewport, tsize[0], tsize[1]); minFontSize = (fontSize < minFontSize ? fontSize : minFontSize); this->LabelActors[i] = vtkActor2D::New(); this->LabelActors[i]->SetMapper(this->LabelMappers[i]); this->LabelActors[i]->GetPositionCoordinate()->SetCoordinateSystemToViewport(); this->LabelActors[i]->SetPosition(x); // depending on the qudrant, the text is aligned differently if (x[0] >= this->Center[0] && x[1] >= this->Center[1]) { this->LabelMappers[i]->GetTextProperty()->SetJustificationToLeft(); this->LabelMappers[i]->GetTextProperty()->SetVerticalJustificationToBottom(); } else if (x[0] < this->Center[0] && x[1] >= this->Center[1]) { this->LabelMappers[i]->GetTextProperty()->SetJustificationToRight(); this->LabelMappers[i]->GetTextProperty()->SetVerticalJustificationToBottom(); } else if (x[0] < this->Center[0] && x[1] < this->Center[1]) { this->LabelMappers[i]->GetTextProperty()->SetJustificationToRight(); this->LabelMappers[i]->GetTextProperty()->SetVerticalJustificationToTop(); } else if (x[0] >= this->Center[0] && x[1] < this->Center[1]) { this->LabelMappers[i]->GetTextProperty()->SetJustificationToLeft(); this->LabelMappers[i]->GetTextProperty()->SetVerticalJustificationToTop(); } } // for all axes // Now reset font sizes to the same value for (i = 0; i < this->N; i++) { this->LabelMappers[i]->GetTextProperty()->SetFontSize(minFontSize); } } // Now generate the lines to plot this->PlotData->Initialize(); // remove old polydata, if any vtkPoints* pts = vtkPoints::New(); pts->Allocate(numRows * numColumns); vtkCellArray* lines = vtkCellArray::New(); vtkUnsignedCharArray* colors = vtkUnsignedCharArray::New(); colors->SetNumberOfComponents(3); this->PlotData->SetPoints(pts); this->PlotData->SetLines(lines); this->PlotData->GetCellData()->SetScalars(colors); colors->Delete(); this->LegendActor->GetProperty()->DeepCopy(this->GetProperty()); double r, *color; vtkIdType firstId = 0; char buf[1024]; if (this->IndependentVariables == VTK_IV_COLUMN) { lines->AllocateEstimate(numRows, numColumns); for (j = 0; j < numRows; j++) { lines->InsertNextCell(numColumns + 1); color = this->LegendActor->GetEntryColor(j); colors->InsertNextTuple3(255 * color[0], 255 * color[1], 255 * color[2]); this->LegendActor->SetEntrySymbol(j, this->GlyphSource->GetOutput()); snprintf(buf, sizeof(buf), "%d", static_cast(j)); this->LegendActor->SetEntryString(j, buf); for (i = 0, k = 0; i < numColumns && k < numComponents; k++) { if (::vtkSpiderPlotActorGetComponent(field, j, k, &v) == 0) { // skip non-numeric components. continue; } if ((this->Maxs[i] - this->Mins[i]) == 0.0) { r = 0.0; } else { r = this->Radius * (v - this->Mins[i]) / (this->Maxs[i] - this->Mins[i]); } x[0] = this->Center[0] + r * cos(i * this->Theta); x[1] = this->Center[1] + r * sin(i * this->Theta); ptId = pts->InsertNextPoint(x); firstId = (i == 0 ? ptId : firstId); lines->InsertCellPoint(ptId); i++; } lines->InsertCellPoint(firstId); } } else // row { lines->AllocateEstimate(numColumns, numRows); for (j = 0; j < numComponents; j++) { int array_comp; int array_index = field->GetArrayContainingComponent(j, array_comp); if (!field->GetArray(array_index)) { // non-numeric component, skip it. continue; } lines->InsertNextCell(numColumns + 1); color = this->LegendActor->GetEntryColor(j); colors->InsertNextTuple3(255 * color[0], 255 * color[1], 255 * color[2]); this->LegendActor->SetEntrySymbol(j, this->GlyphSource->GetOutput()); snprintf(buf, sizeof(buf), "%d", static_cast(j)); this->LegendActor->SetEntryString(j, buf); for (i = 0; i < numRows; i++) { vtkSpiderPlotActorGetComponent(field, i, j, &v); if ((this->Maxs[i] - this->Mins[i]) == 0.0) { r = 0.0; } else { r = this->Radius * (v - this->Mins[i]) / (this->Maxs[i] - this->Mins[i]); } x[0] = this->Center[0] + r * cos(i * this->Theta); x[1] = this->Center[1] + r * sin(i * this->Theta); ptId = pts->InsertNextPoint(x); firstId = (i == 0 ? ptId : firstId); lines->InsertCellPoint(ptId); } lines->InsertCellPoint(firstId); } } // Display the legend if (this->LegendVisibility) { this->LegendActor->GetPositionCoordinate()->SetValue( p1[0] + 0.85 * (p2[0] - p1[0]), p1[1] + 0.20 * (p2[1] - p1[1])); this->LegendActor->GetPosition2Coordinate()->SetValue(p2[0], p1[1] + 0.80 * (p2[1] - p1[1])); } // Build title this->TitleMapper->SetInput(this->Title); if (this->TitleTextProperty->GetMTime() > this->BuildTime) { // Shallow copy here since the justification is changed but we still // want to allow actors to share the same text property, and in that case // specifically allow the title and label text prop to be the same. this->TitleMapper->GetTextProperty()->ShallowCopy(this->TitleTextProperty); this->TitleMapper->GetTextProperty()->SetJustificationToCentered(); } // We could do some caching here, but hey, that's just the title tsize[0] = static_cast(0.25 * d1); tsize[1] = static_cast(0.15 * d2); this->TitleMapper->SetConstrainedFontSize(viewport, tsize[0], tsize[1]); this->TitleActor->GetPositionCoordinate()->SetValue( this->Center[0], this->Center[1] + this->Radius + tsize[1]); // Clean up webPts->Delete(); webLines->Delete(); pts->Delete(); lines->Delete(); return 1; } #undef VTK_RING_PTS //------------------------------------------------------------------------------ // Release any graphics resources that are being consumed by this actor. // The parameter window could be used to determine which graphic // resources to release. void vtkSpiderPlotActor::ReleaseGraphicsResources(vtkWindow* win) { this->TitleActor->ReleaseGraphicsResources(win); this->LegendActor->ReleaseGraphicsResources(win); this->WebActor->ReleaseGraphicsResources(win); this->PlotActor->ReleaseGraphicsResources(win); for (int i = 0; this->LabelActors && i < this->N; i++) { this->LabelActors[i]->ReleaseGraphicsResources(win); } } //------------------------------------------------------------------------------ void vtkSpiderPlotActor::SetAxisLabel(const int i, const char* label) { if (i < 0) { return; } if (static_cast(i) >= this->Labels->size()) { this->Labels->resize(i + 1); } (*this->Labels)[i] = std::string(label); this->Modified(); } //------------------------------------------------------------------------------ const char* vtkSpiderPlotActor::GetAxisLabel(int i) { if (i < 0) { return nullptr; } return this->Labels->at(i).c_str(); } //------------------------------------------------------------------------------ void vtkSpiderPlotActor::SetAxisRange(int i, double min, double max) { if (i < 0) { return; } if (static_cast(i) >= this->Ranges->size()) { this->Ranges->resize(i + 1); } (*this->Ranges)[i] = vtkAxisRange(min, max); this->Modified(); } //------------------------------------------------------------------------------ void vtkSpiderPlotActor::SetAxisRange(int i, double range[2]) { this->SetAxisRange(i, range[0], range[1]); } //------------------------------------------------------------------------------ void vtkSpiderPlotActor::GetAxisRange(int i, double range[2]) { if (i < 0) { return; } vtkAxisRange arange = this->Ranges->at(i); range[0] = arange.Min; range[1] = arange.Max; } //------------------------------------------------------------------------------ void vtkSpiderPlotActor::SetPlotColor(int i, double r, double g, double b) { this->LegendActor->SetEntryColor(i, r, g, b); } //------------------------------------------------------------------------------ double* vtkSpiderPlotActor::GetPlotColor(int i) { return this->LegendActor->GetEntryColor(i); } //------------------------------------------------------------------------------ void vtkSpiderPlotActor::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Input: " << this->GetInput() << "\n"; os << indent << "Number Of Independent Variables: " << this->N << "\n"; os << indent << "Independent Variables: "; if (this->IndependentVariables == VTK_IV_COLUMN) { os << "Columns\n"; } else { os << "Rows\n"; } os << indent << "Title Visibility: " << (this->TitleVisibility ? "On\n" : "Off\n"); os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n"; if (this->TitleTextProperty) { os << indent << "Title Text Property:\n"; this->TitleTextProperty->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "Title Text Property: (none)\n"; } os << indent << "Label Visibility: " << (this->LabelVisibility ? "On\n" : "Off\n"); if (this->LabelTextProperty) { os << indent << "Label Text Property:\n"; this->LabelTextProperty->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "Label Text Property: (none)\n"; } os << indent << "Number of Rings: " << this->NumberOfRings << "\n"; os << indent << "Legend Visibility: " << (this->LegendVisibility ? "On\n" : "Off\n"); os << indent << "Legend Actor: " << this->LegendActor << "\n"; this->LegendActor->PrintSelf(os, indent.GetNextIndent()); }