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