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