1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkConeSource.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 "vtkConeSource.h"
16
17 #include "vtkFloatArray.h"
18 #include "vtkMath.h"
19 #include "vtkInformation.h"
20 #include "vtkInformationVector.h"
21 #include "vtkObjectFactory.h"
22 #include "vtkStreamingDemandDrivenPipeline.h"
23 #include "vtkPolyData.h"
24 #include "vtkTransform.h"
25 #include "vtkCellArray.h"
26
27 #include <math.h>
28
29 vtkStandardNewMacro(vtkConeSource);
30
31 //----------------------------------------------------------------------------
32 // Construct with default resolution 6, height 1.0, radius 0.5, and capping
33 // on.
vtkConeSource(int res)34 vtkConeSource::vtkConeSource(int res)
35 {
36 res = (res < 0 ? 0 : res);
37 this->Resolution = res;
38 this->Height = 1.0;
39 this->Radius = 0.5;
40 this->Capping = 1;
41
42 this->Center[0] = 0.0;
43 this->Center[1] = 0.0;
44 this->Center[2] = 0.0;
45
46 this->Direction[0] = 1.0;
47 this->Direction[1] = 0.0;
48 this->Direction[2] = 0.0;
49
50 this->OutputPointsPrecision = SINGLE_PRECISION;
51
52 this->SetNumberOfInputPorts(0);
53 }
54
55 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)56 int vtkConeSource::RequestData(
57 vtkInformation *vtkNotUsed(request),
58 vtkInformationVector **vtkNotUsed(inputVector),
59 vtkInformationVector *outputVector)
60 {
61 // get the info objects
62 vtkInformation *outInfo = outputVector->GetInformationObject(0);
63
64 double angle;
65 int numLines, numPolys, numPts;
66 double x[3], xbot;
67 int i;
68 vtkIdType pts[VTK_CELL_SIZE];
69 vtkPoints *newPoints;
70 vtkCellArray *newLines=0;
71 vtkCellArray *newPolys=0;
72 vtkPolyData *output = vtkPolyData::SafeDownCast(
73 outInfo->Get(vtkDataObject::DATA_OBJECT()));
74 // for streaming
75 int piece;
76 int numPieces;
77 int maxPieces;
78 int start, end;
79 int createBottom;
80
81 piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
82 if (piece >= this->Resolution && !(piece == 0 && this->Resolution == 0))
83 {
84 return 1;
85 }
86 numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
87 maxPieces = this->Resolution != 0 ? this->Resolution : 1;
88 if (numPieces > maxPieces)
89 {
90 numPieces = maxPieces;
91 }
92 if (piece >= maxPieces)
93 {
94 // Super class should do this for us,
95 // but I put this condition in any way.
96 return 1;
97 }
98 start = maxPieces * piece / numPieces;
99 end = (maxPieces * (piece+1) / numPieces) - 1;
100 createBottom = (this->Capping && (start == 0));
101
102 vtkDebugMacro("ConeSource Executing");
103
104 if ( this->Resolution )
105 {
106 angle = 2.0 * vtkMath::Pi()/this->Resolution;
107 }
108 else
109 {
110 angle = 0.0;
111 }
112
113 // Set things up; allocate memory
114 //
115 switch ( this->Resolution )
116 {
117 case 0:
118 numPts = 2;
119 numLines = 1;
120 newLines = vtkCellArray::New();
121 newLines->Allocate(newLines->EstimateSize(numLines,numPts));
122 break;
123
124 case 1: case 2:
125 numPts = 2*this->Resolution + 1;
126 numPolys = this->Resolution;
127 newPolys = vtkCellArray::New();
128 newPolys->Allocate(newPolys->EstimateSize(numPolys,3));
129 break;
130
131 default:
132 if (createBottom)
133 {
134 // piece 0 has cap.
135 numPts = this->Resolution + 1;
136 numPolys = end - start + 2;
137 }
138 else
139 {
140 numPts = end - start + 3;
141 numPolys = end - start + 2;
142 }
143 newPolys = vtkCellArray::New();
144 newPolys->Allocate(newPolys->EstimateSize(numPolys,this->Resolution));
145 break;
146 }
147 newPoints = vtkPoints::New();
148
149 // Set the desired precision for the points in the output.
150 if(this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION)
151 {
152 newPoints->SetDataType(VTK_DOUBLE);
153 }
154 else
155 {
156 newPoints->SetDataType(VTK_FLOAT);
157 }
158
159 newPoints->Allocate(numPts);
160
161 // Create cone
162 //
163 x[0] = this->Height / 2.0; // zero-centered
164 x[1] = 0.0;
165 x[2] = 0.0;
166 pts[0] = newPoints->InsertNextPoint(x);
167
168 xbot = -this->Height / 2.0;
169
170 switch (this->Resolution)
171 {
172 case 0:
173 x[0] = xbot;
174 x[1] = 0.0;
175 x[2] = 0.0;
176 pts[1] = newPoints->InsertNextPoint(x);
177 newLines->InsertNextCell(2,pts);
178 break;
179
180 case 2: // fall through this case to use the code in case 1
181 x[0] = xbot;
182 x[1] = 0.0;
183 x[2] = -this->Radius;
184 pts[1] = newPoints->InsertNextPoint(x);
185 x[0] = xbot;
186 x[1] = 0.0;
187 x[2] = this->Radius;
188 pts[2] = newPoints->InsertNextPoint(x);
189 newPolys->InsertNextCell(3,pts);
190
191 case 1:
192 x[0] = xbot;
193 x[1] = -this->Radius;
194 x[2] = 0.0;
195 pts[1] = newPoints->InsertNextPoint(x);
196 x[0] = xbot;
197 x[1] = this->Radius;
198 x[2] = 0.0;
199 pts[2] = newPoints->InsertNextPoint(x);
200 newPolys->InsertNextCell(3,pts);
201 break;
202
203 default: // General case: create Resolution triangles and single cap
204 // create the bottom.
205 if ( createBottom )
206 {
207 for (i=0; i < this->Resolution; i++)
208 {
209 x[0] = xbot;
210 x[1] = this->Radius * cos (i*angle);
211 x[2] = this->Radius * sin (i*angle);
212 // Reverse the order
213 pts[this->Resolution - i - 1] = newPoints->InsertNextPoint(x);
214 }
215 newPolys->InsertNextCell(this->Resolution,pts);
216 }
217
218 pts[0] = 0;
219 if ( ! createBottom)
220 {
221 // we need to create the points also
222 x[0] = xbot;
223 x[1] = this->Radius * cos (start*angle);
224 x[2] = this->Radius * sin (start*angle);
225 pts[1] = newPoints->InsertNextPoint(x);
226 for (i = start; i <= end; ++i)
227 {
228 x[1] = this->Radius * cos ((i+1)*angle);
229 x[2] = this->Radius * sin ((i+1)*angle);
230 pts[2] = newPoints->InsertNextPoint(x);
231 newPolys->InsertNextCell(3,pts);
232 pts[1] = pts[2];
233 }
234 }
235 else
236 {
237 // bottom and points have already been created.
238 for (i=start; i <= end; i++)
239 {
240 pts[1] = i+1;
241 pts[2] = i+2;
242 if (pts[2] > this->Resolution)
243 {
244 pts[2] = 1;
245 }
246 newPolys->InsertNextCell(3,pts);
247 }
248 } // createBottom
249
250 } //switch
251
252 // A non-default origin and/or direction requires transformation
253 //
254 if ( this->Center[0] != 0.0 || this->Center[1] != 0.0 ||
255 this->Center[2] != 0.0 || this->Direction[0] != 1.0 ||
256 this->Direction[1] != 0.0 || this->Direction[2] != 0.0 )
257 {
258 vtkTransform *t = vtkTransform::New();
259 t->Translate(this->Center[0], this->Center[1], this->Center[2]);
260 double vMag = vtkMath::Norm(this->Direction);
261 if ( this->Direction[0] < 0.0 )
262 {
263 // flip x -> -x to avoid instability
264 t->RotateWXYZ(180.0, (this->Direction[0]-vMag)/2.0,
265 this->Direction[1]/2.0, this->Direction[2]/2.0);
266 t->RotateWXYZ(180.0, 0, 1, 0);
267 }
268 else
269 {
270 t->RotateWXYZ(180.0, (this->Direction[0]+vMag)/2.0,
271 this->Direction[1]/2.0, this->Direction[2]/2.0);
272 }
273 float *ipts=
274 static_cast<vtkFloatArray *>(newPoints->GetData())->GetPointer(0);
275 for (i=0; i<numPts; i++, ipts+=3)
276 {
277 t->TransformPoint(ipts,ipts);
278 }
279
280 t->Delete();
281 }
282
283 // Update ourselves
284 //
285 output->SetPoints(newPoints);
286 newPoints->Delete();
287
288 if ( newPolys )
289 {
290 newPolys->Squeeze(); // we may have estimated size; reclaim some space
291 output->SetPolys(newPolys);
292 newPolys->Delete();
293 }
294 else
295 {
296 output->SetLines(newLines);
297 newLines->Delete();
298 }
299
300 return 1;
301 }
302
303 //----------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)304 int vtkConeSource::RequestInformation(
305 vtkInformation *vtkNotUsed(request),
306 vtkInformationVector **vtkNotUsed(inputVector),
307 vtkInformationVector *outputVector)
308 {
309 vtkInformation *outInfo = outputVector->GetInformationObject(0);
310 outInfo->Set(CAN_HANDLE_PIECE_REQUEST(),
311 1);
312 return 1;
313 }
314
315
316 //----------------------------------------------------------------------------
SetAngle(double angle)317 void vtkConeSource::SetAngle(double angle)
318 {
319 this->SetRadius( this->Height * tan( vtkMath::RadiansFromDegrees( angle ) ) );
320 }
321
322 //----------------------------------------------------------------------------
GetAngle()323 double vtkConeSource::GetAngle()
324 {
325 return vtkMath::DegreesFromRadians( atan2( this->Radius, this->Height ) );
326 }
327
328 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)329 void vtkConeSource::PrintSelf(ostream& os, vtkIndent indent)
330 {
331 this->Superclass::PrintSelf(os,indent);
332
333 os << indent << "Resolution: " << this->Resolution << "\n";
334 os << indent << "Height: " << this->Height << "\n";
335 os << indent << "Radius: " << this->Radius << "\n";
336 os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
337 os << indent << "Center: (" << this->Center[0] << ", "
338 << this->Center[1] << ", " << this->Center[2] << ")\n";
339 os << indent << "Direction: (" << this->Direction[0] << ", "
340 << this->Direction[1] << ", " << this->Direction[2] << ")\n";
341 os << indent << "Output Points Precision: " << this->OutputPointsPrecision << "\n";
342 }
343