1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkPSphereSource.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 "vtkPSphereSource.h"
16
17 #include "vtkCellArray.h"
18 #include "vtkFloatArray.h"
19 #include "vtkInformation.h"
20 #include "vtkInformationVector.h"
21 #include "vtkLargeInteger.h"
22 #include "vtkMath.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkPointData.h"
25 #include "vtkPoints.h"
26 #include "vtkPolyData.h"
27 #include "vtkStreamingDemandDrivenPipeline.h"
28
29 #include <math.h>
30
31 vtkStandardNewMacro(vtkPSphereSource);
32
33 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)34 int vtkPSphereSource::RequestData(
35 vtkInformation *vtkNotUsed(request),
36 vtkInformationVector **vtkNotUsed(inputVector),
37 vtkInformationVector *outputVector)
38 {
39 vtkInformation *outInfo = outputVector->GetInformationObject(0);
40
41 vtkIdType i, j, numOffset;
42 int jStart, jEnd;
43 vtkIdType numPts, numPolys;
44 vtkPoints *newPoints;
45 vtkFloatArray *newNormals;
46 vtkCellArray *newPolys;
47 float x[3], n[3], deltaPhi, deltaTheta, phi, theta, radius, norm;
48 float startTheta, endTheta, startPhi, endPhi;
49 vtkIdType base, thetaResolution, phiResolution;
50 int numPoles = 0;
51 vtkIdType pts[3];
52 vtkPolyData *output = vtkPolyData::SafeDownCast(
53 outInfo->Get(vtkDataObject::DATA_OBJECT()));
54 int piece =
55 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
56 int numPieces =
57 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
58
59 // I want to modify the ivars resoultion start theta and end theta,
60 // so I will make local copies of them. THese might be able to be merged
61 // with the other copies of them, ...
62 int localThetaResolution = this->ThetaResolution;
63 float localStartTheta = this->StartTheta;
64 float localEndTheta = this->EndTheta;
65
66 while (localEndTheta < localStartTheta)
67 {
68 localEndTheta += 360.0;
69 }
70 deltaTheta = (localEndTheta - localStartTheta) / localThetaResolution;
71
72 // Change the ivars based on pieces.
73 vtkIdType start, end;
74 start = piece * localThetaResolution / numPieces;
75 end = (piece+1) * localThetaResolution / numPieces;
76 localEndTheta = localStartTheta + (float)(end) * deltaTheta;
77 localStartTheta = localStartTheta + (float)(start) * deltaTheta;
78 localThetaResolution = end - start;
79
80 //
81 // Set things up; allocate memory
82 //
83
84 vtkDebugMacro("PSphereSource Executing");
85
86 numPts = this->PhiResolution * localThetaResolution + 2;
87 // creating triangles
88 numPolys = this->PhiResolution * 2 * localThetaResolution;
89
90 newPoints = vtkPoints::New();
91 newPoints->Allocate(numPts);
92 newNormals = vtkFloatArray::New();
93 newNormals->SetNumberOfComponents(3);
94 newNormals->Allocate(3*numPts);
95
96 newPolys = vtkCellArray::New();
97 newPolys->Allocate(newPolys->EstimateSize(numPolys, 3));
98 //
99 // Create sphere
100 //
101 // Create north pole if needed
102 if ( this->StartPhi <= 0.0 )
103 {
104 x[0] = this->Center[0];
105 x[1] = this->Center[1];
106 x[2] = this->Center[2] + this->Radius;
107 newPoints->InsertPoint(numPoles,x);
108
109 x[0] = x[1] = 0.0; x[2] = 1.0;
110 newNormals->InsertTuple(numPoles,x);
111 numPoles++;
112 }
113
114 // Create south pole if needed
115 if ( this->EndPhi >= 180.0 )
116 {
117 x[0] = this->Center[0];
118 x[1] = this->Center[1];
119 x[2] = this->Center[2] - this->Radius;
120 newPoints->InsertPoint(numPoles,x);
121
122 x[0] = x[1] = 0.0; x[2] = -1.0;
123 newNormals->InsertTuple(numPoles,x);
124 numPoles++;
125 }
126
127 // Check data, determine increments, and convert to radians
128 startTheta = (localStartTheta < localEndTheta ? localStartTheta
129 : localEndTheta);
130 startTheta *= vtkMath::Pi() / 180.0;
131 endTheta = (localEndTheta > localStartTheta ? localEndTheta
132 : localStartTheta);
133 endTheta *= vtkMath::Pi() / 180.0;
134
135 startPhi = (this->StartPhi < this->EndPhi ? this->StartPhi : this->EndPhi);
136 startPhi *= vtkMath::Pi() / 180.0;
137 endPhi = (this->EndPhi > this->StartPhi ? this->EndPhi : this->StartPhi);
138 endPhi *= vtkMath::Pi() / 180.0;
139
140 phiResolution = this->PhiResolution - numPoles;
141 deltaPhi = (endPhi - startPhi) / (this->PhiResolution - 1);
142 thetaResolution = localThetaResolution;
143 if (fabs(localStartTheta - localEndTheta) < 360.0)
144 {
145 ++localThetaResolution;
146 }
147 deltaTheta = (endTheta - startTheta) / thetaResolution;
148
149 jStart = (this->StartPhi <= 0.0 ? 1 : 0);
150 jEnd = (this->EndPhi >= 180.0 ? this->PhiResolution - 1
151 : this->PhiResolution);
152
153 // Create intermediate points
154 for (i=0; i < localThetaResolution; i++)
155 {
156 theta = localStartTheta * vtkMath::Pi() / 180.0 + i*deltaTheta;
157
158 for (j=jStart; j<jEnd; j++)
159 {
160 phi = startPhi + j*deltaPhi;
161 radius = this->Radius * sin((double)phi);
162 n[0] = radius * cos((double)theta);
163 n[1] = radius * sin((double)theta);
164 n[2] = this->Radius * cos((double)phi);
165 x[0] = n[0] + this->Center[0];
166 x[1] = n[1] + this->Center[1];
167 x[2] = n[2] + this->Center[2];
168 newPoints->InsertNextPoint(x);
169
170 if ( (norm = vtkMath::Norm(n)) == 0.0 )
171 {
172 norm = 1.0;
173 }
174 n[0] /= norm; n[1] /= norm; n[2] /= norm;
175 newNormals->InsertNextTuple(n);
176 }
177 }
178
179 // Generate mesh connectivity
180 base = phiResolution * localThetaResolution;
181
182 if (fabs(localStartTheta - localEndTheta) < 360.0)
183 {
184 --localThetaResolution;
185 }
186
187 if ( this->StartPhi <= 0.0 ) // around north pole
188 {
189 for (i=0; i < localThetaResolution; i++)
190 {
191 pts[0] = phiResolution*i + numPoles;
192 pts[1] = (phiResolution*(i+1) % base) + numPoles;
193 pts[2] = 0;
194 newPolys->InsertNextCell(3, pts);
195 }
196 }
197
198 if ( this->EndPhi >= 180.0 ) // around south pole
199 {
200 numOffset = phiResolution - 1 + numPoles;
201
202 for (i=0; i < localThetaResolution; i++)
203 {
204 pts[0] = phiResolution*i + numOffset;
205 pts[2] = ((phiResolution*(i+1)) % base) + numOffset;
206 pts[1] = numPoles - 1;
207 newPolys->InsertNextCell(3, pts);
208 }
209 }
210
211 // bands in-between poles
212 for (i=0; i < localThetaResolution; i++)
213 {
214 for (j=0; j < (phiResolution-1); j++)
215 {
216 pts[0] = phiResolution*i + j + numPoles;
217 pts[1] = pts[0] + 1;
218 pts[2] = ((phiResolution*(i+1)+j) % base) + numPoles + 1;
219 newPolys->InsertNextCell(3, pts);
220
221 pts[1] = pts[2];
222 pts[2] = pts[1] - 1;
223 newPolys->InsertNextCell(3, pts);
224 }
225 }
226 //
227 // Update ourselves and release memeory
228 //
229 newPoints->Squeeze();
230 output->SetPoints(newPoints);
231 newPoints->Delete();
232
233 newNormals->Squeeze();
234 output->GetPointData()->SetNormals(newNormals);
235 newNormals->Delete();
236
237 output->SetPolys(newPolys);
238 newPolys->Delete();
239
240 return 1;
241 }
242
243 //----------------------------------------------------------------------------
GetEstimatedMemorySize()244 unsigned long vtkPSphereSource::GetEstimatedMemorySize()
245 {
246 vtkLargeInteger sz;
247 vtkLargeInteger sz2;
248 unsigned long thetaResolution = this->ThetaResolution;
249 vtkInformation *outInfo = this->GetExecutive()->GetOutputInformation(0);
250 int numPieces =
251 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
252
253 if (numPieces)
254 {
255 thetaResolution /= numPieces;
256 }
257
258 if (thetaResolution < 1)
259 {
260 thetaResolution = 1;
261 }
262
263 // ignore poles
264 sz = thetaResolution;
265 sz = sz * (this->PhiResolution + 1);
266 sz2 = thetaResolution;
267 sz2 = sz2 * this->PhiResolution * 2;
268 sz = sz * 3 * sizeof(float);
269 sz2 = sz2 * 4 * sizeof(int);
270
271 sz = sz + sz2;
272
273 // convert to kilobytes
274 sz >>= 10;
275
276 return sz.CastToUnsignedLong();
277 }
278
PrintSelf(ostream & os,vtkIndent indent)279 void vtkPSphereSource::PrintSelf(ostream& os, vtkIndent indent)
280 {
281 this->Superclass::PrintSelf(os, indent);
282 }
283