1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkTextureMapToCylinder.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 "vtkTextureMapToCylinder.h"
16
17 #include "vtkCellData.h"
18 #include "vtkDataSet.h"
19 #include "vtkFloatArray.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkLine.h"
23 #include "vtkMath.h"
24 #include "vtkOBBTree.h"
25 #include "vtkObjectFactory.h"
26 #include "vtkPointData.h"
27 #include "vtkPoints.h"
28
29 vtkStandardNewMacro(vtkTextureMapToCylinder);
30
31 // Create object with cylinder axis parallel to z-axis (points (0,0,-0.5)
32 // and (0,0,0.5)). The PreventSeam ivar is set to true. The cylinder is
33 // automatically generated.
vtkTextureMapToCylinder()34 vtkTextureMapToCylinder::vtkTextureMapToCylinder()
35 {
36 this->Point1[0] = 0.0;
37 this->Point1[1] = 0.0;
38 this->Point1[2] = -0.5;
39
40 this->Point2[0] = 0.0;
41 this->Point2[1] = 0.0;
42 this->Point2[2] = 0.5;
43
44 this->AutomaticCylinderGeneration = 1;
45 this->PreventSeam = 1;
46 }
47
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)48 int vtkTextureMapToCylinder::RequestData(
49 vtkInformation *vtkNotUsed(request),
50 vtkInformationVector **inputVector,
51 vtkInformationVector *outputVector)
52 {
53 // get the info objects
54 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
55 vtkInformation *outInfo = outputVector->GetInformationObject(0);
56
57 // get the input and output
58 vtkDataSet *input = vtkDataSet::SafeDownCast(
59 inInfo->Get(vtkDataObject::DATA_OBJECT()));
60 vtkDataSet *output = vtkDataSet::SafeDownCast(
61 outInfo->Get(vtkDataObject::DATA_OBJECT()));
62
63 vtkFloatArray *newTCoords;
64 vtkIdType numPts=input->GetNumberOfPoints();
65 vtkIdType ptId;
66 int i;
67 double x[3], tc[2], thetaX, thetaY, closest[3], v[3];
68 double axis[3], vP[3], vec[3];
69
70 vtkDebugMacro(<<"Generating Cylindrical Texture Coordinates");
71
72 // First, copy the input to the output as a starting point
73 output->CopyStructure( input );
74
75 if ( numPts < 1 )
76 {
77 vtkErrorMacro(<<"Can't generate texture coordinates without points");
78 return 1;
79 }
80
81 if ( this->AutomaticCylinderGeneration )
82 {
83 vtkPoints *pts=vtkPoints::New(); pts->SetNumberOfPoints(numPts);
84 double corner[3], max[3], mid[3], min[3], size[3], l;
85 vtkOBBTree *OBB = vtkOBBTree::New();
86
87 for ( ptId=0; ptId < numPts; ptId++ )
88 {
89 input->GetPoint(ptId, x);
90 pts->SetPoint(ptId,x);
91 }
92
93 OBB->ComputeOBB(pts,corner,max,mid,min,size);
94 pts->Delete();
95 OBB->Delete();
96
97 for ( i=0; i < 3; i++)
98 {
99 l = (mid[i] + min[i])/2.0;
100 this->Point1[i] = corner[i] + l;
101 this->Point2[i] = corner[i] + max[i] + l;
102 }
103
104 vtkDebugMacro(<<"Cylinder axis computed as \tPoint1: ("
105 << this->Point1[0] <<", " << this->Point1[1] <<", "
106 << this->Point1[2] <<")\n\t\t\t\tPoint2: ("
107 << this->Point2[0] <<", " << this->Point2[1] <<", "
108 << this->Point2[2] <<")");
109 }
110
111 //compute axis which is theta (angle measure) origin
112 for ( i=0; i < 3; i++ )
113 {
114 axis[i] = this->Point2[i] - this->Point1[i];
115 }
116 if ( vtkMath::Norm(axis) == 0.0 )
117 {
118 vtkErrorMacro(<<"Bad cylinder axis");
119 return 1;
120 }
121
122 v[0] = 1.0; v[1] = v[2] = 0.0;
123 vtkMath::Cross(axis,v,vP);
124 if ( vtkMath::Norm(vP) == 0.0 )
125 {//must be prependicular
126 v[1] = 1.0; v[0] = v[2] = 0.0;
127 vtkMath::Cross(axis,v,vP);
128 }
129 vtkMath::Cross(vP,axis,vec);
130 if ( vtkMath::Normalize(vec) == 0.0 )
131 {
132 vtkErrorMacro(<<"Bad cylinder axis");
133 return 1;
134 }
135 newTCoords = vtkFloatArray::New();
136 newTCoords->SetName("Texture Coordinates");
137 newTCoords->SetNumberOfComponents(2);
138 newTCoords->Allocate(2*numPts);
139
140 //loop over all points computing spherical coordinates
141 for ( ptId=0; ptId < numPts; ptId++ )
142 {
143 input->GetPoint(ptId, x);
144 vtkLine::DistanceToLine(x,this->Point1,this->Point2,tc[1],closest);
145
146 for (i=0; i < 3; i++)
147 {
148 v[i] = x[i] - closest[i];
149 }
150 vtkMath::Normalize(v);
151
152 thetaX = acos ((double)vtkMath::Dot(v,vec));
153 vtkMath::Cross(vec,v,vP);
154 thetaY = vtkMath::Dot(axis,vP); //not really interested in angle, just +/- sign
155
156 if ( this->PreventSeam )
157 {
158 tc[0] = thetaX / vtkMath::Pi();
159 }
160 else
161 {
162 tc[0] = thetaX / (2.0*vtkMath::Pi());
163 if ( thetaY < 0.0 )
164 {
165 tc[0] = 1.0 - tc[0];
166 }
167 }
168
169 newTCoords->InsertTuple(ptId,tc);
170 }
171
172 output->GetPointData()->CopyTCoordsOff();
173 output->GetPointData()->PassData(input->GetPointData());
174 output->GetCellData()->PassData(input->GetCellData());
175
176 output->GetPointData()->SetTCoords(newTCoords);
177 newTCoords->Delete();
178
179 return 1;
180 }
181
PrintSelf(ostream & os,vtkIndent indent)182 void vtkTextureMapToCylinder::PrintSelf(ostream& os, vtkIndent indent)
183 {
184 this->Superclass::PrintSelf(os,indent);
185
186 os << indent << "Automatic Cylinder Generation: " <<
187 (this->AutomaticCylinderGeneration ? "On\n" : "Off\n");
188 os << indent << "Prevent Seam: " <<
189 (this->PreventSeam ? "On\n" : "Off\n");
190 os << indent << "Point1: (" << this->Point1[0] << ", "
191 << this->Point1[1] << ", "
192 << this->Point1[2] << ")\n";
193 os << indent << "Point2: (" << this->Point2[0] << ", "
194 << this->Point2[1] << ", "
195 << this->Point2[2] << ")\n";
196 }
197