1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkVolumeOfRevolutionFilter.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 "vtkVolumeOfRevolutionFilter.h"
16
17 #include "vtkCellArray.h"
18 #include "vtkCellData.h"
19 #include "vtkCellIterator.h"
20 #include "vtkGenericCell.h"
21 #include "vtkIdList.h"
22 #include "vtkInformation.h"
23 #include "vtkInformationVector.h"
24 #include "vtkMath.h"
25 #include "vtkMergePoints.h"
26 #include "vtkNew.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkPointData.h"
29 #include "vtkPolyData.h"
30 #include "vtkUnsignedCharArray.h"
31 #include "vtkUnstructuredGrid.h"
32
33 #include <vector>
34
35 vtkStandardNewMacro(vtkVolumeOfRevolutionFilter);
36
37 namespace
38 {
39 struct AxisOfRevolution
40 {
41 double Position[3];
42 double Direction[3];
43 };
44
RevolvePoint(const double in[3],const AxisOfRevolution * axis,double angleInRadians,double out[3])45 void RevolvePoint(
46 const double in[3], const AxisOfRevolution* axis, double angleInRadians, double out[3])
47 {
48 double c = cos(angleInRadians);
49 double cm = 1. - c;
50 double s = sin(angleInRadians);
51
52 double translated[3];
53 vtkMath::Subtract(in, axis->Position, translated);
54
55 double dot = vtkMath::Dot(translated, axis->Direction);
56 double cross[3];
57 vtkMath::Cross(translated, axis->Direction, cross);
58
59 for (vtkIdType i = 0; i < 3; i++)
60 {
61 out[i] =
62 ((translated[i] * c + axis->Direction[i] * dot * cm - cross[i] * s) + axis->Position[i]);
63 }
64 }
65
RevolvePoints(vtkDataSet * pts,vtkPoints * newPts,AxisOfRevolution * axis,double sweepAngle,int resolution,vtkPointData * outPd,bool partialSweep)66 void RevolvePoints(vtkDataSet* pts, vtkPoints* newPts, AxisOfRevolution* axis, double sweepAngle,
67 int resolution, vtkPointData* outPd, bool partialSweep)
68 {
69 double angleInRadians = vtkMath::RadiansFromDegrees(sweepAngle / resolution);
70
71 vtkIdType n2DPoints = pts->GetNumberOfPoints();
72 vtkIdType counter = 0;
73 double p2d[3], p3d[3];
74
75 for (int i = 0; i < resolution + partialSweep; i++)
76 {
77 for (int id = 0; id < n2DPoints; id++)
78 {
79 pts->GetPoint(id, p2d);
80 RevolvePoint(p2d, axis, i * angleInRadians, p3d);
81 newPts->SetPoint(counter, p3d);
82 outPd->CopyData(pts->GetPointData(), i, counter);
83 counter++;
84 }
85 }
86 }
87
88 template <int CellType>
89 void Revolve(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution, vtkCellArray* connectivity,
90 vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId, vtkCellData* outCd,
91 bool partialSweep);
92
93 template <>
Revolve(vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)94 void Revolve<VTK_VERTEX>(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
95 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
96 vtkCellData* outCd, bool partialSweep)
97 {
98 vtkIdType newPtIds[2], newCellId;
99
100 newPtIds[0] = pointIds->GetId(0);
101
102 for (int i = 0; i < resolution; i++)
103 {
104 newPtIds[1] = (pointIds->GetId(0) + ((i + 1) % (resolution + partialSweep)) * n2DPoints);
105 newCellId = connectivity->InsertNextCell(2, newPtIds);
106 types->InsertNextValue(VTK_LINE);
107 outCd->CopyData(inCd, cellId, newCellId);
108 newPtIds[0] = newPtIds[1];
109 }
110 }
111
112 template <>
Revolve(vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)113 void Revolve<VTK_POLY_VERTEX>(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
114 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
115 vtkCellData* outCd, bool partialSweep)
116 {
117 vtkNew<vtkIdList> pointId;
118 pointId->SetNumberOfIds(1);
119 for (vtkIdType i = 0; i < pointIds->GetNumberOfIds(); i++)
120 {
121 pointId->SetId(0, pointIds->GetId(i));
122 Revolve<VTK_VERTEX>(
123 pointId, n2DPoints, resolution, connectivity, types, inCd, cellId, outCd, partialSweep);
124 }
125 }
126
127 template <>
Revolve(vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)128 void Revolve<VTK_LINE>(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
129 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
130 vtkCellData* outCd, bool partialSweep)
131 {
132 static const int nPoints = 2;
133
134 vtkIdType newPtIds[2 * nPoints], newCellId;
135
136 for (vtkIdType i = 0; i < nPoints; i++)
137 {
138 newPtIds[i] = pointIds->GetId(i);
139 }
140
141 for (int i = 0; i < resolution; i++)
142 {
143 for (vtkIdType j = 0; j < nPoints; j++)
144 {
145 newPtIds[2 * nPoints - 1 - j] =
146 pointIds->GetId(j) + ((i + 1) % (resolution + partialSweep)) * n2DPoints;
147 }
148 newCellId = connectivity->InsertNextCell(2 * nPoints, newPtIds);
149 types->InsertNextValue(VTK_QUAD);
150 outCd->CopyData(inCd, cellId, newCellId);
151 for (vtkIdType j = 0; j < nPoints; j++)
152 {
153 newPtIds[nPoints - 1 - j] = newPtIds[j + nPoints];
154 }
155 }
156 }
157
158 template <>
Revolve(vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)159 void Revolve<VTK_POLY_LINE>(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
160 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
161 vtkCellData* outCd, bool partialSweep)
162 {
163 vtkNew<vtkIdList> newPointIds;
164 newPointIds->SetNumberOfIds(2);
165 newPointIds->SetId(0, pointIds->GetId(0));
166 for (vtkIdType i = 1; i < pointIds->GetNumberOfIds(); i++)
167 {
168 newPointIds->SetId(1, pointIds->GetId(i));
169 Revolve<VTK_LINE>(
170 newPointIds, n2DPoints, resolution, connectivity, types, inCd, cellId, outCd, partialSweep);
171 newPointIds->SetId(0, pointIds->GetId(i));
172 }
173 }
174
175 template <>
Revolve(vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)176 void Revolve<VTK_TRIANGLE>(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
177 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
178 vtkCellData* outCd, bool partialSweep)
179 {
180 static const int nPoints = 3;
181
182 vtkIdType newPtIds[2 * nPoints], newCellId;
183
184 for (vtkIdType i = 0; i < nPoints; i++)
185 {
186 newPtIds[i] = pointIds->GetId(i);
187 }
188
189 for (int i = 0; i < resolution; i++)
190 {
191 for (vtkIdType j = 0; j < nPoints; j++)
192 {
193 newPtIds[j + nPoints] =
194 pointIds->GetId(j) + ((i + 1) % (resolution + partialSweep)) * n2DPoints;
195 }
196 newCellId = connectivity->InsertNextCell(2 * nPoints, newPtIds);
197 types->InsertNextValue(VTK_WEDGE);
198 outCd->CopyData(inCd, cellId, newCellId);
199 for (vtkIdType j = 0; j < nPoints; j++)
200 {
201 newPtIds[j] = newPtIds[j + nPoints];
202 }
203 }
204 }
205
206 template <>
Revolve(vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)207 void Revolve<VTK_TRIANGLE_STRIP>(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
208 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
209 vtkCellData* outCd, bool partialSweep)
210 {
211 vtkNew<vtkIdList> newPointIds;
212 newPointIds->SetNumberOfIds(3);
213 newPointIds->SetId(0, pointIds->GetId(0));
214 newPointIds->SetId(1, pointIds->GetId(1));
215 for (vtkIdType i = 2; i < pointIds->GetNumberOfIds(); i++)
216 {
217 newPointIds->SetId(2, pointIds->GetId(i));
218 Revolve<VTK_TRIANGLE>(
219 newPointIds, n2DPoints, resolution, connectivity, types, inCd, cellId, outCd, partialSweep);
220 newPointIds->SetId(0, pointIds->GetId(i));
221 newPointIds->SetId(1, pointIds->GetId(i - 1));
222 }
223 }
224
225 template <>
Revolve(vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)226 void Revolve<VTK_QUAD>(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
227 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
228 vtkCellData* outCd, bool partialSweep)
229 {
230 static const int nPoints = 4;
231
232 vtkIdType newPtIds[2 * nPoints], newCellId;
233
234 for (vtkIdType i = 0; i < nPoints; i++)
235 {
236 newPtIds[i] = pointIds->GetId(i);
237 }
238
239 for (int i = 0; i < resolution; i++)
240 {
241 for (vtkIdType j = 0; j < nPoints; j++)
242 {
243 newPtIds[j + nPoints] =
244 pointIds->GetId(j) + ((i + 1) % (resolution + partialSweep)) * n2DPoints;
245 }
246 newCellId = connectivity->InsertNextCell(2 * nPoints, newPtIds);
247 types->InsertNextValue(VTK_HEXAHEDRON);
248 outCd->CopyData(inCd, cellId, newCellId);
249 for (vtkIdType j = 0; j < nPoints; j++)
250 {
251 newPtIds[j] = newPtIds[j + nPoints];
252 }
253 }
254 }
255
256 template <>
Revolve(vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)257 void Revolve<VTK_PIXEL>(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
258 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
259 vtkCellData* outCd, bool partialSweep)
260 {
261 static const int nPoints = 4;
262
263 vtkIdType newPtIds[2 * nPoints], newCellId;
264
265 for (vtkIdType i = 0; i < nPoints; i++)
266 {
267 newPtIds[i] = pointIds->GetId(i);
268 }
269
270 for (int i = 0; i < resolution; i++)
271 {
272 for (vtkIdType j = 0; j < nPoints; j++)
273 {
274 newPtIds[j + nPoints] =
275 pointIds->GetId(j) + ((i + 1) % (resolution + partialSweep)) * n2DPoints;
276 }
277 newCellId = connectivity->InsertNextCell(2 * nPoints, newPtIds);
278 types->InsertNextValue(VTK_HEXAHEDRON);
279 outCd->CopyData(inCd, cellId, newCellId);
280 for (vtkIdType j = 0; j < nPoints; j++)
281 {
282 newPtIds[j] = newPtIds[j + nPoints];
283 }
284 }
285 }
286
287 template <>
Revolve(vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)288 void Revolve<VTK_POLYGON>(vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
289 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
290 vtkCellData* outCd, bool partialSweep)
291 {
292 // A swept polygon creates a polyhedron with two polygon faces and <nPoly>
293 // quad faces, comprised from 2*<nPoly> points. Because polyhedra have a
294 // special connectivity format, the length of the connectivity array is
295 // 1 + (<nPoly>+2) + 2*<nPoly> + 4*<nPoly> = 7*<nPoly> + 3.
296 // ^ ^ ^ ^
297 // integer describing # of faces (<nPoly> + 2)
298 // ^ ^ ^
299 // integers describing # of points per face
300 // ^ ^
301 // point ids for the two polygon faces
302 // ^
303 // point ids for the 4 quad faces
304
305 int nPoly = pointIds->GetNumberOfIds();
306 std::vector<vtkIdType> newPtIds(7 * nPoly + 3);
307 // newFacePtIds are pointers to the point arrays describing each face
308 std::vector<vtkIdType*> newFacePtIds(nPoly + 2);
309 vtkIdType newCellId;
310
311 newPtIds[0] = nPoly + 2;
312 newPtIds[1] = nPoly;
313 newPtIds[nPoly + 2] = nPoly;
314 newFacePtIds[0] = &newPtIds[2];
315 newFacePtIds[1] = &newPtIds[nPoly + 3];
316 for (vtkIdType i = 0; i < nPoly; i++)
317 {
318 // All of the subsequent faces have four point ids
319 newPtIds[3 + 2 * nPoly + 5 * i] = 4;
320 newFacePtIds[2 + i] = &newPtIds[4 + 2 * nPoly + 5 * i];
321 newFacePtIds[0][i] = pointIds->GetId(i);
322 }
323
324 for (int i = 0; i < resolution; i++)
325 {
326 for (vtkIdType j = 0; j < nPoly; j++)
327 {
328 newFacePtIds[1][nPoly - 1 - j] =
329 pointIds->GetId(j) + ((i + 1) % (resolution + partialSweep)) * n2DPoints;
330 }
331 for (vtkIdType j = 0; j < nPoly; j++)
332 {
333 newFacePtIds[j + 2][0] = newFacePtIds[0][j];
334 newFacePtIds[j + 2][1] = newFacePtIds[0][(j + 1) % nPoly];
335 newFacePtIds[j + 2][2] = newFacePtIds[1][(2 * nPoly - 2 - j) % nPoly];
336 newFacePtIds[j + 2][3] = newFacePtIds[1][nPoly - 1 - j];
337 }
338 newCellId = connectivity->InsertNextCell(7 * nPoly + 3, &newPtIds[0]);
339 types->InsertNextValue(VTK_POLYHEDRON);
340 outCd->CopyData(inCd, cellId, newCellId);
341 for (vtkIdType j = 0; j < nPoly; j++)
342 {
343 newFacePtIds[0][j] = newFacePtIds[1][nPoly - 1 - j];
344 }
345 }
346 }
347
RevolveCell(int cellType,vtkIdList * pointIds,vtkIdType n2DPoints,int resolution,vtkCellArray * connectivity,vtkUnsignedCharArray * types,vtkCellData * inCd,vtkIdType cellId,vtkCellData * outCd,bool partialSweep)348 int RevolveCell(int cellType, vtkIdList* pointIds, vtkIdType n2DPoints, int resolution,
349 vtkCellArray* connectivity, vtkUnsignedCharArray* types, vtkCellData* inCd, vtkIdType cellId,
350 vtkCellData* outCd, bool partialSweep)
351 {
352 int returnValue = 0;
353 #define RevolveCellCase(CellType) \
354 case CellType: \
355 Revolve<CellType>( \
356 pointIds, n2DPoints, resolution, connectivity, types, inCd, cellId, outCd, partialSweep); \
357 break
358
359 switch (cellType)
360 {
361 RevolveCellCase(VTK_VERTEX);
362 RevolveCellCase(VTK_POLY_VERTEX);
363 RevolveCellCase(VTK_LINE);
364 RevolveCellCase(VTK_POLY_LINE);
365 RevolveCellCase(VTK_TRIANGLE);
366 RevolveCellCase(VTK_TRIANGLE_STRIP);
367 RevolveCellCase(VTK_POLYGON);
368 RevolveCellCase(VTK_PIXEL);
369 RevolveCellCase(VTK_QUAD);
370 default:
371 returnValue = 1;
372 }
373 return returnValue;
374 #undef RevolveCellCase
375 }
376 }
377
378 //------------------------------------------------------------------------------
vtkVolumeOfRevolutionFilter()379 vtkVolumeOfRevolutionFilter::vtkVolumeOfRevolutionFilter()
380 {
381 this->SweepAngle = 360.0;
382 this->Resolution = 12; // 30 degree increments
383 this->AxisPosition[0] = this->AxisPosition[1] = this->AxisPosition[2] = 0.;
384 this->AxisDirection[0] = this->AxisDirection[1] = 0.;
385 this->AxisDirection[2] = 1.;
386 this->OutputPointsPrecision = DEFAULT_PRECISION;
387 }
388
389 //------------------------------------------------------------------------------
390 vtkVolumeOfRevolutionFilter::~vtkVolumeOfRevolutionFilter() = default;
391
392 //------------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)393 int vtkVolumeOfRevolutionFilter::RequestData(vtkInformation* vtkNotUsed(request),
394 vtkInformationVector** inputVector, vtkInformationVector* outputVector)
395 {
396 // get the info objects
397 vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
398 vtkInformation* outInfo = outputVector->GetInformationObject(0);
399
400 // get the input and output
401 vtkDataSet* input = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
402 vtkUnstructuredGrid* output =
403 vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
404 vtkPointData* inPd = input->GetPointData();
405 vtkCellData* inCd = input->GetCellData();
406 vtkPointData* outPd = output->GetPointData();
407 vtkCellData* outCd = output->GetCellData();
408
409 vtkNew<vtkPoints> outPts;
410
411 // Check to see that the input data is amenable to this operation
412 vtkCellIterator* it = input->NewCellIterator();
413 for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextCell())
414 {
415 int cellDimension = it->GetCellDimension();
416 if (cellDimension > 2)
417 {
418 vtkErrorMacro(<< "All cells must have a topological dimension < 2.");
419 return 1;
420 }
421 }
422 it->Delete();
423
424 // Set up output points
425 if (this->OutputPointsPrecision == vtkAlgorithm::DEFAULT_PRECISION)
426 {
427 vtkPointSet* inputPointSet = vtkPointSet::SafeDownCast(input);
428 if (inputPointSet)
429 {
430 outPts->SetDataType(inputPointSet->GetPoints()->GetDataType());
431 }
432 else
433 {
434 outPts->SetDataType(VTK_FLOAT);
435 }
436 }
437 else if (this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION)
438 {
439 outPts->SetDataType(VTK_FLOAT);
440 }
441 else if (this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION)
442 {
443 outPts->SetDataType(VTK_DOUBLE);
444 }
445
446 // determine whether or not the sweep angle is a full 2*pi
447 bool partialSweep = false;
448 if (fabs(360. - fabs(this->SweepAngle)) > 1024 * VTK_DBL_EPSILON)
449 {
450 partialSweep = true;
451 }
452
453 // Set up output points and point data
454 outPts->SetNumberOfPoints(input->GetNumberOfPoints() * (this->Resolution + partialSweep));
455 outPd->CopyAllocate(inPd, input->GetNumberOfPoints() * (this->Resolution + partialSweep));
456
457 // Set up output cell data
458 vtkIdType nNewCells = input->GetNumberOfCells() * this->Resolution;
459 outCd->CopyAllocate(inCd, nNewCells);
460
461 vtkNew<vtkUnsignedCharArray> outTypes;
462 vtkNew<vtkCellArray> outCells;
463
464 AxisOfRevolution axis;
465 for (vtkIdType i = 0; i < 3; i++)
466 {
467 axis.Position[i] = this->AxisPosition[i];
468 axis.Direction[i] = this->AxisDirection[i];
469 }
470
471 RevolvePoints(input, outPts, &axis, this->SweepAngle, this->Resolution, outPd, partialSweep);
472
473 it = input->NewCellIterator();
474 for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextCell())
475 {
476 if (RevolveCell(it->GetCellType(), it->GetPointIds(), input->GetNumberOfPoints(),
477 this->Resolution, outCells, outTypes, inCd, it->GetCellId(), outCd, partialSweep) == 1)
478 {
479 vtkWarningMacro(<< "No method for revolving cell type " << it->GetCellType()
480 << ". Skipping.");
481 }
482 }
483 it->Delete();
484
485 output->SetPoints(outPts);
486 output->SetCells(outTypes, outCells);
487
488 return 1;
489 }
490
491 //------------------------------------------------------------------------------
FillInputPortInformation(int,vtkInformation * info)492 int vtkVolumeOfRevolutionFilter::FillInputPortInformation(int, vtkInformation* info)
493 {
494 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
495 return 1;
496 }
497
498 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)499 void vtkVolumeOfRevolutionFilter::PrintSelf(ostream& os, vtkIndent indent)
500 {
501 this->Superclass::PrintSelf(os, indent);
502
503 os << indent << "Resolution: " << this->Resolution << "\n";
504 os << indent << "Sweep Angle: " << this->SweepAngle << "\n";
505 os << indent << "Axis Position: (" << this->AxisPosition[0] << "," << this->AxisPosition[1] << ","
506 << this->AxisPosition[2] << ")\n";
507 os << indent << "Axis Direction: (" << this->AxisPosition[0] << "," << this->AxisDirection[1]
508 << "," << this->AxisDirection[2] << ")\n";
509 os << indent << "Output Points Precision: " << this->OutputPointsPrecision << "\n";
510 }
511