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 <cmath>
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=nullptr;
71 vtkCellArray *newPolys=nullptr;
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 VTK_FALLTHROUGH;
191
192 case 1:
193 x[0] = xbot;
194 x[1] = -this->Radius;
195 x[2] = 0.0;
196 pts[1] = newPoints->InsertNextPoint(x);
197 x[0] = xbot;
198 x[1] = this->Radius;
199 x[2] = 0.0;
200 pts[2] = newPoints->InsertNextPoint(x);
201 newPolys->InsertNextCell(3,pts);
202 break;
203
204 default: // General case: create Resolution triangles and single cap
205 // create the bottom.
206 if ( createBottom )
207 {
208 for (i=0; i < this->Resolution; i++)
209 {
210 x[0] = xbot;
211 x[1] = this->Radius * cos (i*angle);
212 x[2] = this->Radius * sin (i*angle);
213 // Reverse the order
214 pts[this->Resolution - i - 1] = newPoints->InsertNextPoint(x);
215 }
216 newPolys->InsertNextCell(this->Resolution,pts);
217 }
218
219 pts[0] = 0;
220 if ( ! createBottom)
221 {
222 // we need to create the points also
223 x[0] = xbot;
224 x[1] = this->Radius * cos (start*angle);
225 x[2] = this->Radius * sin (start*angle);
226 pts[1] = newPoints->InsertNextPoint(x);
227 for (i = start; i <= end; ++i)
228 {
229 x[1] = this->Radius * cos ((i+1)*angle);
230 x[2] = this->Radius * sin ((i+1)*angle);
231 pts[2] = newPoints->InsertNextPoint(x);
232 newPolys->InsertNextCell(3,pts);
233 pts[1] = pts[2];
234 }
235 }
236 else
237 {
238 // bottom and points have already been created.
239 for (i=start; i <= end; i++)
240 {
241 pts[1] = i+1;
242 pts[2] = i+2;
243 if (pts[2] > this->Resolution)
244 {
245 pts[2] = 1;
246 }
247 newPolys->InsertNextCell(3,pts);
248 }
249 } // createBottom
250
251 } //switch
252
253 // A non-default origin and/or direction requires transformation
254 //
255 if ( this->Center[0] != 0.0 || this->Center[1] != 0.0 ||
256 this->Center[2] != 0.0 || this->Direction[0] != 1.0 ||
257 this->Direction[1] != 0.0 || this->Direction[2] != 0.0 )
258 {
259 vtkTransform *t = vtkTransform::New();
260 t->Translate(this->Center[0], this->Center[1], this->Center[2]);
261 double vMag = vtkMath::Norm(this->Direction);
262 if ( this->Direction[0] < 0.0 )
263 {
264 // flip x -> -x to avoid instability
265 t->RotateWXYZ(180.0, (this->Direction[0]-vMag)/2.0,
266 this->Direction[1]/2.0, this->Direction[2]/2.0);
267 t->RotateWXYZ(180.0, 0, 1, 0);
268 }
269 else
270 {
271 t->RotateWXYZ(180.0, (this->Direction[0]+vMag)/2.0,
272 this->Direction[1]/2.0, this->Direction[2]/2.0);
273 }
274 float *ipts=
275 static_cast<vtkFloatArray *>(newPoints->GetData())->GetPointer(0);
276 for (i=0; i<numPts; i++, ipts+=3)
277 {
278 t->TransformPoint(ipts,ipts);
279 }
280
281 t->Delete();
282 }
283
284 // Update ourselves
285 //
286 output->SetPoints(newPoints);
287 newPoints->Delete();
288
289 if ( newPolys )
290 {
291 newPolys->Squeeze(); // we may have estimated size; reclaim some space
292 output->SetPolys(newPolys);
293 newPolys->Delete();
294 }
295 else
296 {
297 output->SetLines(newLines);
298 newLines->Delete();
299 }
300
301 return 1;
302 }
303
304 //----------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)305 int vtkConeSource::RequestInformation(
306 vtkInformation *vtkNotUsed(request),
307 vtkInformationVector **vtkNotUsed(inputVector),
308 vtkInformationVector *outputVector)
309 {
310 vtkInformation *outInfo = outputVector->GetInformationObject(0);
311 outInfo->Set(CAN_HANDLE_PIECE_REQUEST(),
312 1);
313 return 1;
314 }
315
316
317 //----------------------------------------------------------------------------
SetAngle(double angle)318 void vtkConeSource::SetAngle(double angle)
319 {
320 this->SetRadius( this->Height * tan( vtkMath::RadiansFromDegrees( angle ) ) );
321 }
322
323 //----------------------------------------------------------------------------
GetAngle()324 double vtkConeSource::GetAngle()
325 {
326 return vtkMath::DegreesFromRadians( atan2( this->Radius, this->Height ) );
327 }
328
329 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)330 void vtkConeSource::PrintSelf(ostream& os, vtkIndent indent)
331 {
332 this->Superclass::PrintSelf(os,indent);
333
334 os << indent << "Resolution: " << this->Resolution << "\n";
335 os << indent << "Height: " << this->Height << "\n";
336 os << indent << "Radius: " << this->Radius << "\n";
337 os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
338 os << indent << "Center: (" << this->Center[0] << ", "
339 << this->Center[1] << ", " << this->Center[2] << ")\n";
340 os << indent << "Direction: (" << this->Direction[0] << ", "
341 << this->Direction[1] << ", " << this->Direction[2] << ")\n";
342 os << indent << "Output Points Precision: " << this->OutputPointsPrecision << "\n";
343 }
344