1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkTextureMapToSphere.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 "vtkTextureMapToSphere.h"
16 
17 #include "vtkCellData.h"
18 #include "vtkDataSet.h"
19 #include "vtkFloatArray.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkMath.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkPointData.h"
25 
26 vtkStandardNewMacro(vtkTextureMapToSphere);
27 
28 // Create object with Center (0,0,0) and the PreventSeam ivar is set to true. The
29 // sphere center is automatically computed.
vtkTextureMapToSphere()30 vtkTextureMapToSphere::vtkTextureMapToSphere()
31 {
32   this->Center[0] = this->Center[1] = this->Center[2] = 0.0;
33 
34   this->AutomaticSphereGeneration = 1;
35   this->PreventSeam = 1;
36 }
37 
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)38 int vtkTextureMapToSphere::RequestData(
39   vtkInformation *vtkNotUsed(request),
40   vtkInformationVector **inputVector,
41   vtkInformationVector *outputVector)
42 {
43   // get the info objects
44   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
45   vtkInformation *outInfo = outputVector->GetInformationObject(0);
46 
47   // get the input and output
48   vtkDataSet *input = vtkDataSet::SafeDownCast(
49     inInfo->Get(vtkDataObject::DATA_OBJECT()));
50   vtkDataSet *output = vtkDataSet::SafeDownCast(
51     outInfo->Get(vtkDataObject::DATA_OBJECT()));
52 
53   vtkFloatArray *newTCoords;
54   vtkIdType numPts=input->GetNumberOfPoints();
55   vtkIdType ptId;
56   double x[3], rho, r, tc[2], phi=0.0, thetaX, thetaY;
57   double diff, PiOverTwo=vtkMath::Pi()/2.0;
58 
59   vtkDebugMacro(<<"Generating Spherical Texture Coordinates");
60 
61   // First, copy the input to the output as a starting point
62   output->CopyStructure( input );
63 
64   if ( numPts < 1 )
65   {
66     vtkErrorMacro(<<"Can't generate texture coordinates without points");
67     return 1;
68   }
69 
70   if ( this->AutomaticSphereGeneration )
71   {
72     this->Center[0] = this->Center[1] = this->Center[2] = 0.0;
73     for ( ptId=0; ptId < numPts; ptId++ )
74     {
75       input->GetPoint(ptId, x);
76       this->Center[0] += x[0];
77       this->Center[1] += x[1];
78       this->Center[2] += x[2];
79     }
80     this->Center[0] /= numPts;
81     this->Center[1] /= numPts;
82     this->Center[2] /= numPts;
83 
84     vtkDebugMacro(<<"Center computed as: (" << this->Center[0] <<", "
85                   << this->Center[1] <<", " << this->Center[2] <<")");
86   }
87 
88   //loop over all points computing spherical coordinates. Only tricky part
89   //is keeping track of singularities/numerical problems.
90   newTCoords = vtkFloatArray::New();
91   newTCoords->SetName("Texture Coordinates");
92   newTCoords->SetNumberOfComponents(2);
93   newTCoords->SetNumberOfTuples(numPts);
94   for ( ptId=0; ptId < numPts; ptId++ )
95   {
96     input->GetPoint(ptId, x);
97     rho = sqrt((double)vtkMath::Distance2BetweenPoints(x,this->Center));
98     if ( rho != 0.0 )
99     {
100       // watch for truncation problems
101       if ( fabs((diff=x[2]-this->Center[2])) > rho )
102       {
103         phi = 0.0;
104         if ( diff > 0.0 )
105         {
106           tc[1] = 0.0;
107         }
108         else
109         {
110           tc[1] = 1.0;
111         }
112       }
113       else
114       {
115         phi = acos((double)(diff/rho));
116         tc[1] = phi / vtkMath::Pi();
117       }
118     }
119     else
120     {
121       tc[1] = 0.0;
122     }
123 
124     r = rho * sin((double)phi);
125     if ( r != 0.0 )
126     {
127       // watch for truncation problems
128       if ( fabs((diff=x[0]-this->Center[0])) > r )
129       {
130         if ( diff > 0.0 )
131         {
132           thetaX = 0.0;
133         }
134         else
135         {
136           thetaX = vtkMath::Pi();
137         }
138       }
139       else
140       {
141         thetaX = acos ((double)diff/r);
142       }
143 
144       if ( fabs((diff=x[1]-this->Center[1])) > r )
145       {
146         if ( diff > 0.0 )
147         {
148           thetaY = PiOverTwo;
149         }
150         else
151         {
152           thetaY = -PiOverTwo;
153         }
154       }
155       else
156       {
157         thetaY = asin ((double)diff/r);
158       }
159     }
160     else
161     {
162       thetaX = thetaY = 0.0;
163     }
164 
165     if ( this->PreventSeam )
166     {
167       tc[0] = thetaX / vtkMath::Pi();
168     }
169     else
170     {
171       tc[0] = thetaX / (2.0*vtkMath::Pi());
172       if ( thetaY < 0.0 )
173       {
174         tc[0] = 1.0 - tc[0];
175       }
176     }
177 
178     newTCoords->SetTuple(ptId,tc);
179   }
180 
181   output->GetPointData()->CopyTCoordsOff();
182   output->GetPointData()->PassData(input->GetPointData());
183 
184   output->GetCellData()->PassData(input->GetCellData());
185 
186   output->GetPointData()->SetTCoords(newTCoords);
187   newTCoords->Delete();
188 
189   return 1;
190 }
191 
PrintSelf(ostream & os,vtkIndent indent)192 void vtkTextureMapToSphere::PrintSelf(ostream& os, vtkIndent indent)
193 {
194   this->Superclass::PrintSelf(os,indent);
195 
196   os << indent << "Automatic Sphere Generation: " <<
197                   (this->AutomaticSphereGeneration ? "On\n" : "Off\n");
198   os << indent << "Prevent Seam: " <<
199                   (this->PreventSeam ? "On\n" : "Off\n");
200   os << indent << "Center: (" << this->Center[0] << ", "
201                               << this->Center[1] << ", "
202                               << this->Center[2] << ")\n";
203 }
204 
205