1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkTreeRingToPolyData.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10   This software is distributed WITHOUT ANY WARRANTY; without even
11   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12   PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /*-------------------------------------------------------------------------
16   Copyright 2008 Sandia Corporation.
17   Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
18   the U.S. Government retains certain rights in this software.
19 -------------------------------------------------------------------------*/
20 #include "vtkTreeRingToPolyData.h"
21 
22 #include "vtkCellArray.h"
23 #include "vtkCellData.h"
24 #include "vtkCommand.h"
25 #include "vtkFloatArray.h"
26 #include "vtkMath.h"
27 #include "vtkIdTypeArray.h"
28 #include "vtkInformation.h"
29 #include "vtkInformationVector.h"
30 #include "vtkObjectFactory.h"
31 #include "vtkPointData.h"
32 #include "vtkTimerLog.h"
33 #include "vtkTree.h"
34 #include "vtkStripper.h"
35 #include "vtkSectorSource.h"
36 #include "vtkAppendPolyData.h"
37 
38 #include "vtkSmartPointer.h"
39 #define VTK_CREATE(type, name)                                  \
40   vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
41 
42 vtkStandardNewMacro(vtkTreeRingToPolyData);
43 
vtkTreeRingToPolyData()44 vtkTreeRingToPolyData::vtkTreeRingToPolyData()
45 {
46   this->SetSectorsArrayName("sectors");
47   this->ShrinkPercentage = 0.0;
48 }
49 
50 vtkTreeRingToPolyData::~vtkTreeRingToPolyData() = default;
51 
FillInputPortInformation(int vtkNotUsed (port),vtkInformation * info)52 int vtkTreeRingToPolyData::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info)
53 {
54   info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTree");
55   return 1;
56 }
57 
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)58 int vtkTreeRingToPolyData::RequestData(
59   vtkInformation *vtkNotUsed(request),
60   vtkInformationVector **inputVector,
61   vtkInformationVector *outputVector)
62 {
63   // get the info objects
64   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
65   vtkInformation *outInfo = outputVector->GetInformationObject(0);
66 
67   // get the input and output
68   vtkTree *inputTree = vtkTree::SafeDownCast(
69     inInfo->Get(vtkDataObject::DATA_OBJECT()));
70   vtkPolyData *outputPoly = vtkPolyData::SafeDownCast(
71     outInfo->Get(vtkDataObject::DATA_OBJECT()));
72 
73   if( inputTree->GetNumberOfVertices() == 0 )
74   {
75     return 1;
76   }
77 
78   // Now set the point coordinates, normals, and insert the cell
79   vtkDataArray* coordArray = this->GetInputArrayToProcess(0, inputTree);
80   if (!coordArray)
81   {
82     vtkErrorMacro("Sectors array not found.");
83     return 0;
84   }
85 
86   double pt1x[3] = {0.0, 0.0, 0.0};
87   double pt2x[3] = {0.0, 0.0, 0.0};
88   double ang = 0.0;
89   double cos_ang = 0.0;
90   double sin_ang = 0.0;
91   vtkIdType pt1 = 0;
92   vtkIdType pt2 = 0;
93   vtkIdType rootId = inputTree->GetRoot();
94   VTK_CREATE(vtkCellArray, strips);
95   VTK_CREATE(vtkPoints, pts);
96   double progress = 0.0;
97   this->InvokeEvent(vtkCommand::ProgressEvent, &progress);
98 
99   for( int i = 0; i < inputTree->GetNumberOfVertices(); i++ )
100   {
101     // Grab coords from the input
102     double coords[4];
103     if( i == rootId )
104     {
105       //don't draw the root node...
106       coords[0] = 0.0;
107       coords[1] = 0.0;
108       coords[2] = 1.0;
109       coords[3] = 1.0;
110     }
111     else
112     {
113       coordArray->GetTuple(i,coords);
114     }
115 
116     double radial_length = coords[3] - coords[2];
117 
118     // Calculate the amount of change in the arcs based on the shrink
119     // percentage of the arc_length
120     double conversion = vtkMath::Pi()/180.;
121     double arc_length = (conversion*(coords[1] - coords[0])*coords[3]);
122     double radial_shrink = radial_length*this->ShrinkPercentage;
123     double arc_length_shrink;
124     if( radial_shrink > 0.25*arc_length )
125     {
126       arc_length_shrink = 0.25*arc_length;
127     }
128     else
129     {
130       arc_length_shrink = radial_shrink;
131     }
132 
133     double arc_length_new = arc_length - arc_length_shrink;
134     double angle_change = ((arc_length_new/coords[3])/conversion);
135     double delta_change_each = 0.5*((coords[1]-coords[0]) - angle_change);
136 
137     double inner_radius = coords[2] + (0.5*(radial_length*this->ShrinkPercentage));
138     double outer_radius = coords[3] - (0.5*(radial_length*this->ShrinkPercentage));
139     double start_angle;
140     double end_angle;
141     if( coords[1] - coords[0] == 360. )
142     {
143       start_angle = coords[0];
144       end_angle = coords[1];
145     }
146     else
147     {
148       start_angle = coords[0] + delta_change_each;
149       end_angle = coords[1] - delta_change_each;
150     }
151 
152     int num_angles = static_cast<int>(end_angle - start_angle);
153     if ( num_angles < 1 )
154     {
155       num_angles = 1;
156     }
157     int num_points = 2*num_angles + 2;
158     strips->InsertNextCell(num_points);
159     for ( int j = 0; j < num_angles; ++j )
160     {
161       ang = start_angle + j;
162       cos_ang = cos(vtkMath::RadiansFromDegrees(ang));
163       sin_ang = sin(vtkMath::RadiansFromDegrees(ang));
164       pt1x[0] = cos_ang*inner_radius;
165       pt1x[1] = sin_ang*inner_radius;
166       pt2x[0] = cos_ang*outer_radius;
167       pt2x[1] = sin_ang*outer_radius;
168       pt1 = pts->InsertNextPoint(pt1x);
169       pt2 = pts->InsertNextPoint(pt2x);
170       strips->InsertCellPoint(pt1);
171       strips->InsertCellPoint(pt2);
172     }
173     ang = end_angle;
174     cos_ang = cos(vtkMath::RadiansFromDegrees(ang));
175     sin_ang = sin(vtkMath::RadiansFromDegrees(ang));
176     pt1x[0] = cos_ang*inner_radius;
177     pt1x[1] = sin_ang*inner_radius;
178     pt2x[0] = cos_ang*outer_radius;
179     pt2x[1] = sin_ang*outer_radius;
180     pt1 = pts->InsertNextPoint(pt1x);
181     pt2 = pts->InsertNextPoint(pt2x);
182     strips->InsertCellPoint(pt1);
183     strips->InsertCellPoint(pt2);
184 
185     if ( i%1000 == 0 )
186     {
187       progress = static_cast<double>(i) / inputTree->GetNumberOfVertices() * 0.8;
188       this->InvokeEvent(vtkCommand::ProgressEvent, &progress);
189     }
190   }
191 
192   outputPoly->SetPoints(pts);
193   outputPoly->SetStrips(strips);
194 
195   // Pass the input vertex data to the output cell data :)
196   vtkDataSetAttributes* const input_vertex_data = inputTree->GetVertexData();
197   vtkDataSetAttributes* const output_cell_data = outputPoly->GetCellData();
198   output_cell_data->PassData(input_vertex_data);
199 
200   return 1;
201 }
202 
PrintSelf(ostream & os,vtkIndent indent)203 void vtkTreeRingToPolyData::PrintSelf(ostream& os, vtkIndent indent)
204 {
205   this->Superclass::PrintSelf(os,indent);
206   os << indent << "ShrinkPercentage: " << this->ShrinkPercentage << endl;
207 }
208