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