/*========================================================================= Program: Visualization Toolkit Module: vtkTreeRingToPolyData.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. =========================================================================*/ /*------------------------------------------------------------------------- Copyright 2008 Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. -------------------------------------------------------------------------*/ #include "vtkTreeRingToPolyData.h" #include "vtkAppendPolyData.h" #include "vtkCellArray.h" #include "vtkCellData.h" #include "vtkCommand.h" #include "vtkFloatArray.h" #include "vtkIdTypeArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkSectorSource.h" #include "vtkStripper.h" #include "vtkTimerLog.h" #include "vtkTree.h" #include "vtkSmartPointer.h" #define VTK_CREATE(type, name) vtkSmartPointer name = vtkSmartPointer::New() vtkStandardNewMacro(vtkTreeRingToPolyData); vtkTreeRingToPolyData::vtkTreeRingToPolyData() { this->SetSectorsArrayName("sectors"); this->ShrinkPercentage = 0.0; } vtkTreeRingToPolyData::~vtkTreeRingToPolyData() = default; int vtkTreeRingToPolyData::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree"); return 1; } int vtkTreeRingToPolyData::RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { // get the info objects vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); vtkInformation* outInfo = outputVector->GetInformationObject(0); // get the input and output vtkTree* inputTree = vtkTree::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); vtkPolyData* outputPoly = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); if (inputTree->GetNumberOfVertices() == 0) { return 1; } // Now set the point coordinates, normals, and insert the cell vtkDataArray* coordArray = this->GetInputArrayToProcess(0, inputTree); if (!coordArray) { vtkErrorMacro("Sectors array not found."); return 0; } double pt1x[3] = { 0.0, 0.0, 0.0 }; double pt2x[3] = { 0.0, 0.0, 0.0 }; double ang = 0.0; double cos_ang = 0.0; double sin_ang = 0.0; vtkIdType pt1 = 0; vtkIdType pt2 = 0; vtkIdType rootId = inputTree->GetRoot(); VTK_CREATE(vtkCellArray, strips); VTK_CREATE(vtkPoints, pts); double progress = 0.0; this->InvokeEvent(vtkCommand::ProgressEvent, &progress); for (int i = 0; i < inputTree->GetNumberOfVertices(); i++) { // Grab coords from the input double coords[4]; if (i == rootId) { // don't draw the root node... coords[0] = 0.0; coords[1] = 0.0; coords[2] = 1.0; coords[3] = 1.0; } else { coordArray->GetTuple(i, coords); } double radial_length = coords[3] - coords[2]; // Calculate the amount of change in the arcs based on the shrink // percentage of the arc_length double conversion = vtkMath::Pi() / 180.; double arc_length = (conversion * (coords[1] - coords[0]) * coords[3]); double radial_shrink = radial_length * this->ShrinkPercentage; double arc_length_shrink; if (radial_shrink > 0.25 * arc_length) { arc_length_shrink = 0.25 * arc_length; } else { arc_length_shrink = radial_shrink; } double arc_length_new = arc_length - arc_length_shrink; double angle_change = ((arc_length_new / coords[3]) / conversion); double delta_change_each = 0.5 * ((coords[1] - coords[0]) - angle_change); double inner_radius = coords[2] + (0.5 * (radial_length * this->ShrinkPercentage)); double outer_radius = coords[3] - (0.5 * (radial_length * this->ShrinkPercentage)); double start_angle; double end_angle; if (coords[1] - coords[0] == 360.) { start_angle = coords[0]; end_angle = coords[1]; } else { start_angle = coords[0] + delta_change_each; end_angle = coords[1] - delta_change_each; } int num_angles = static_cast(end_angle - start_angle); if (num_angles < 1) { num_angles = 1; } int num_points = 2 * num_angles + 2; strips->InsertNextCell(num_points); for (int j = 0; j < num_angles; ++j) { ang = start_angle + j; cos_ang = cos(vtkMath::RadiansFromDegrees(ang)); sin_ang = sin(vtkMath::RadiansFromDegrees(ang)); pt1x[0] = cos_ang * inner_radius; pt1x[1] = sin_ang * inner_radius; pt2x[0] = cos_ang * outer_radius; pt2x[1] = sin_ang * outer_radius; pt1 = pts->InsertNextPoint(pt1x); pt2 = pts->InsertNextPoint(pt2x); strips->InsertCellPoint(pt1); strips->InsertCellPoint(pt2); } ang = end_angle; cos_ang = cos(vtkMath::RadiansFromDegrees(ang)); sin_ang = sin(vtkMath::RadiansFromDegrees(ang)); pt1x[0] = cos_ang * inner_radius; pt1x[1] = sin_ang * inner_radius; pt2x[0] = cos_ang * outer_radius; pt2x[1] = sin_ang * outer_radius; pt1 = pts->InsertNextPoint(pt1x); pt2 = pts->InsertNextPoint(pt2x); strips->InsertCellPoint(pt1); strips->InsertCellPoint(pt2); if (i % 1000 == 0) { progress = static_cast(i) / inputTree->GetNumberOfVertices() * 0.8; this->InvokeEvent(vtkCommand::ProgressEvent, &progress); } } outputPoly->SetPoints(pts); outputPoly->SetStrips(strips); // Pass the input vertex data to the output cell data :) vtkDataSetAttributes* const input_vertex_data = inputTree->GetVertexData(); vtkDataSetAttributes* const output_cell_data = outputPoly->GetCellData(); output_cell_data->PassData(input_vertex_data); return 1; } void vtkTreeRingToPolyData::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "ShrinkPercentage: " << this->ShrinkPercentage << endl; }