1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkPlatonicSolidSource.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 #include "vtkPlatonicSolidSource.h"
16 
17 #include "vtkInformation.h"
18 #include "vtkInformationVector.h"
19 #include "vtkObjectFactory.h"
20 #include "vtkPolyData.h"
21 #include "vtkCellArray.h"
22 #include "vtkCellData.h"
23 #include "vtkPoints.h"
24 
25 vtkStandardNewMacro(vtkPlatonicSolidSource);
26 
27 // Wrapping this in namespaces because the short names (a, b, c, etc) are
28 // throwing warnings on MSVC when inlined methods in vtkGenericDataArray are
29 // being used ('warning C4459: declaration of 'c' hides global declaration')
30 namespace {
31 namespace vtkPlatonicSolidSourceDetail {
32 // The geometry and topology of each solid. Solids are centered at
33 // the origin with radius 1.0.
34 // The golden ration phi = (1+sqrt(5))/2=1.61803398875 enters into many
35 // of these values.
36 static double TetraPoints[] = {
37   1.0,1.0,1.0, -1.0,1.0,-1.0, 1.0,-1.0,-1.0, -1.0,-1.0,1.0
38 };
39 static vtkIdType TetraVerts[] = {
40   0,1,2, 1,3,2, 0,2,3, 0,3,1
41 };
42 
43 static double CubePoints[] = {
44   -1.0,-1.0,-1.0, 1.0,-1.0,-1.0, 1.0,1.0,-1.0, -1.0,1.0,-1.0,
45   -1.0,-1.0,1.0, 1.0,-1.0,1.0, 1.0,1.0,1.0, -1.0,1.0,1.0
46 };
47 static vtkIdType CubeVerts[] = {
48   0,1,5,4, 0,4,7,3, 4,5,6,7, 3,7,6,2, 1,2,6,5, 0,3,2,1
49 };
50 
51 static double OctPoints[] = {
52   -1.0,-1.0,0.0, 1.0,-1.0,0.0, 1.0,1.0,0.0, -1.0,1.0,0.0,
53   0.0,0.0,-1.4142135623731, 0.0,0.0,1.4142135623731
54 };
55 static vtkIdType OctVerts[] = {
56   4,1,0, 4,2,1, 4,3,2, 4,0,3, 0,1,5, 1,2,5, 2,3,5, 3,0,5
57 };
58 
59 static double a_0 = 0.61803398875;
60 static double b = 0.381966011250;
61 static double DodePoints[] = {
62    b, 0, 1,  -b, 0, 1,  b, 0,-1, -b, 0,-1,  0, 1,-b,
63    0, 1, b,   0,-1,-b,  0,-1, b,  1, b, 0,  1,-b, 0,
64   -1, b, 0,  -1,-b, 0, -a_0, a_0, a_0,  a_0,-a_0, a_0, -a_0,-a_0,-a_0,
65    a_0, a_0,-a_0,   a_0, a_0, a_0, -a_0, a_0,-a_0, -a_0,-a_0, a_0,  a_0,-a_0,-a_0
66 };
67 static vtkIdType DodeVerts[] = {
68   0,16,5,12,1, 1,18,7,13,0, 2,19,6,14,3, 3,17,4,15,2, 4,5,16,8,15,
69   5,4,17,10,12, 6,7,18,11,14, 7,6,19,9,13, 8,16,0,13,9, 9,19,2,15,8,
70   10,17,3,14,11, 11,18,1,12,10
71 };
72 
73 static double c = 0.5;
74 static double d = 0.30901699;
75 static double IcosaPoints[] = {
76    0.0,d,-c, 0.0,d,c,  0.0,-d,c, -d,c,0.0,
77   -d,-c,0.0, d,c,0.0,  d,-c,0.0,  0.0,-d,-c,
78    c,0.0,d, -c,0.0,d, -c,0.0,-d,  c,0.0,-d
79 };
80 static vtkIdType IcosaVerts[] = {
81   0,5,3, 1,3,5, 1,2,9, 1,8,2, 0,7,11, 0,10,7, 2,6,4, 7,4,6, 3,9,10,
82   4,10,9, 5,11,8, 6,8,11, 1,9,3, 1,5,8, 0,3,10, 0,11,5, 7,10,4, 7,6,11,
83   2,4,9, 2,8,6
84 };
85 } // end namespace detail
86 } // end anon namespace
87 
vtkPlatonicSolidSource()88 vtkPlatonicSolidSource::vtkPlatonicSolidSource()
89 {
90   this->SolidType = VTK_SOLID_TETRAHEDRON;
91   this->OutputPointsPrecision = SINGLE_PRECISION;
92   this->SetNumberOfInputPorts(0);
93 }
94 
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)95 int vtkPlatonicSolidSource::RequestData(
96   vtkInformation *vtkNotUsed(request),
97   vtkInformationVector **vtkNotUsed(inputVector),
98   vtkInformationVector *outputVector)
99 {
100   // get the info object
101   vtkInformation *outInfo = outputVector->GetInformationObject(0);
102 
103   // get the output
104   vtkPolyData *output = vtkPolyData::SafeDownCast(
105     outInfo->Get(vtkDataObject::DATA_OBJECT()));
106 
107   int i;
108   double *pptr, *solidPoints=nullptr, solidScale=1.0;
109   vtkIdType *cptr, numPts=0, numCells=0, cellSize=0, *solidVerts=nullptr;
110 
111   vtkDebugMacro(<<"Creating Platonic solid");
112 
113   // Based on type, select correct connectivity and point arrays
114   //
115   switch (this->SolidType)
116   {
117     case VTK_SOLID_TETRAHEDRON:
118       numPts = 4;
119       cellSize = 3;
120       numCells = 4;
121       solidPoints = vtkPlatonicSolidSourceDetail::TetraPoints;
122       solidVerts = vtkPlatonicSolidSourceDetail::TetraVerts;
123       solidScale = 1.0/sqrt(3.0);
124       break;
125 
126     case VTK_SOLID_CUBE:
127       numPts = 8;
128       cellSize = 4;
129       numCells = 6;
130       solidPoints = vtkPlatonicSolidSourceDetail::CubePoints;
131       solidVerts = vtkPlatonicSolidSourceDetail::CubeVerts;
132       solidScale = 1.0/sqrt(3.0);
133       break;
134 
135     case VTK_SOLID_OCTAHEDRON:
136       numPts = 6;
137       cellSize = 3;
138       numCells = 8;
139       solidPoints = vtkPlatonicSolidSourceDetail::OctPoints;
140       solidVerts = vtkPlatonicSolidSourceDetail::OctVerts;
141       solidScale = 1.0/sqrt(2.0);
142       break;
143 
144     case VTK_SOLID_ICOSAHEDRON:
145       numPts = 12;
146       cellSize = 3;
147       numCells = 20;
148       solidPoints = vtkPlatonicSolidSourceDetail::IcosaPoints;
149       solidVerts = vtkPlatonicSolidSourceDetail::IcosaVerts;
150       solidScale = 1.0/0.58778524999243;
151       break;
152 
153     case VTK_SOLID_DODECAHEDRON:
154       numPts = 20;
155       cellSize = 5;
156       numCells = 12;
157       solidPoints = vtkPlatonicSolidSourceDetail::DodePoints;
158       solidVerts = vtkPlatonicSolidSourceDetail::DodeVerts;
159       solidScale = 1.0/1.070466269319;
160       break;
161   }
162 
163   // Create the solids
164   //
165   vtkPoints *pts = vtkPoints::New();
166 
167   // Set the desired precision for the points in the output.
168   if(this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION)
169   {
170     pts->SetDataType(VTK_DOUBLE);
171   }
172   else
173   {
174     pts->SetDataType(VTK_FLOAT);
175   }
176 
177   pts->SetNumberOfPoints(numPts);
178   vtkCellArray *polys = vtkCellArray::New();
179   polys->Allocate(polys->EstimateSize(numCells,cellSize));
180   vtkIntArray *colors = vtkIntArray::New();
181   colors->SetNumberOfComponents(1);
182   colors->SetNumberOfTuples(numCells);
183 
184   // Points
185   for ( i=0, pptr=solidPoints; i<numPts; i++, pptr+=3 )
186   {
187     pts->SetPoint(i, solidScale*(pptr[0]), solidScale*(pptr[1]),
188                      solidScale*(pptr[2]));
189   }
190 
191   // Cells
192   for ( i=0, cptr=solidVerts; i<numCells; i++, cptr+=cellSize )
193   {
194     polys->InsertNextCell(cellSize,cptr);
195     colors->SetTuple1(i,i);
196   }
197 
198   // Assemble the output
199   output->SetPoints(pts);
200   output->SetPolys(polys);
201   int idx = output->GetCellData()->AddArray(colors);
202   output->GetCellData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
203 
204   pts->Delete();
205   polys->Delete();
206   colors->Delete();
207 
208   return 1;
209 }
210 
PrintSelf(ostream & os,vtkIndent indent)211 void vtkPlatonicSolidSource::PrintSelf(ostream& os, vtkIndent indent)
212 {
213   this->Superclass::PrintSelf(os,indent);
214 
215   os << indent << "Solid Type: " << "\n";
216   if ( this->SolidType == VTK_SOLID_TETRAHEDRON )
217   {
218     os << "Tetrahedron\n";
219   }
220   else if ( this->SolidType == VTK_SOLID_CUBE )
221   {
222     os << "Cube\n";
223   }
224   else if ( this->SolidType == VTK_SOLID_OCTAHEDRON )
225   {
226     os << "Octahedron\n";
227   }
228   else if ( this->SolidType == VTK_SOLID_ICOSAHEDRON )
229   {
230     os << "Icosahedron\n";
231   }
232   else //if ( this->SolidType == VTK_SOLID_DODECAHEDRON )
233   {
234     os << "Dodecahedron\n";
235   }
236 
237   os << indent << "Output Points Precision: " << this->OutputPointsPrecision
238      << "\n";
239 }
240