TestBSplineTransform.cxx 10.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestBSplineTransform.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

/*
  This test builds a thin-plate spline transform, and then approximates
  it with a B-Spline transform.  It applies both the B-Spline transform
  and the original thin-plate spline transform to a polydata so that they
  can be compared.

  The output image is displayed as eight separate panels, as follows:

  Top row:
    1) thin-plate spline applied to a sphere
    2) B-spline applied to a sphere
    3) thin-plate spline applied to a sphere with normals
    4) B-spline applied to a sphere with normals
  Bottom row:
    Same as top row, but with inverted transform
*/

33
34
35
#include <vtkActor.h>
#include <vtkBSplineTransform.h>
#include <vtkImageBSplineCoefficients.h>
36
37
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
38
#include <vtkProperty.h>
39
40
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
41
42
43
44
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkTestUtilities.h>
45
46
47
48
#include <vtkThinPlateSplineTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkTransformToGrid.h>

49
int TestBSplineTransform(int vtkNotUsed(argc), char* vtkNotUsed(argv)[])
50
{
51
52
  vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
  renWin->SetSize(600, 300);
53
54

  // Make a sphere
55
  vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
56
57
58
59
60
  sphere->SetThetaResolution(20);
  sphere->SetPhiResolution(20);
  sphere->Update();

  // Make another sphere, with no normals
61
  vtkSmartPointer<vtkPolyData> sphereData = vtkSmartPointer<vtkPolyData>::New();
62
63
64
65
66
  sphereData->SetPoints(sphere->GetOutput()->GetPoints());
  sphereData->SetPolys(sphere->GetOutput()->GetPolys());

  // ---------------------------
  // start with a thin plate spline transform
67
  vtkSmartPointer<vtkPoints> spoints = vtkSmartPointer<vtkPoints>::New();
68
  spoints->SetNumberOfPoints(10);
69
70
71
72
73
74
75
76
77
78
79
80
  spoints->SetPoint(0, 0.000, 0.000, 0.500);
  spoints->SetPoint(1, 0.000, 0.000, -0.500);
  spoints->SetPoint(2, 0.433, 0.000, 0.250);
  spoints->SetPoint(3, 0.433, 0.000, -0.250);
  spoints->SetPoint(4, -0.000, 0.433, 0.250);
  spoints->SetPoint(5, -0.000, 0.433, -0.250);
  spoints->SetPoint(6, -0.433, -0.000, 0.250);
  spoints->SetPoint(7, -0.433, -0.000, -0.250);
  spoints->SetPoint(8, 0.000, -0.433, 0.250);
  spoints->SetPoint(9, 0.000, -0.433, -0.250);

  vtkSmartPointer<vtkPoints> tpoints = vtkSmartPointer<vtkPoints>::New();
81
  tpoints->SetNumberOfPoints(10);
82
83
84
85
86
87
88
89
90
91
  tpoints->SetPoint(0, 0.000, 0.000, 0.800);
  tpoints->SetPoint(1, 0.000, 0.000, -0.200);
  tpoints->SetPoint(2, 0.433, 0.000, 0.350);
  tpoints->SetPoint(3, 0.433, 0.000, -0.150);
  tpoints->SetPoint(4, -0.000, 0.233, 0.350);
  tpoints->SetPoint(5, -0.000, 0.433, -0.150);
  tpoints->SetPoint(6, -0.433, -0.000, 0.350);
  tpoints->SetPoint(7, -0.433, -0.000, -0.150);
  tpoints->SetPoint(8, 0.000, -0.233, 0.350);
  tpoints->SetPoint(9, 0.000, -0.433, -0.150);
92
93
94
95
96
97
98
99
100
101
102
103
104

  vtkSmartPointer<vtkThinPlateSplineTransform> thin =
    vtkSmartPointer<vtkThinPlateSplineTransform>::New();
  thin->SetSourceLandmarks(spoints);
  thin->SetTargetLandmarks(tpoints);
  thin->SetBasisToR2LogR();

  // First pane: thin-plate, no normals
  vtkSmartPointer<vtkTransformPolyDataFilter> f11 =
    vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  f11->SetInputData(sphereData);
  f11->SetTransform(thin);

105
  vtkSmartPointer<vtkPolyDataMapper> m11 = vtkSmartPointer<vtkPolyDataMapper>::New();
106
107
  m11->SetInputConnection(f11->GetOutputPort());

108
  vtkSmartPointer<vtkActor> a11 = vtkSmartPointer<vtkActor>::New();
109
110
  a11->SetMapper(m11);
  a11->RotateY(90);
111
  a11->GetProperty()->SetColor(1, 0, 0);
112

113
114
115
  vtkSmartPointer<vtkRenderer> ren11 = vtkSmartPointer<vtkRenderer>::New();
  ren11->SetViewport(0.0, 0.5, 0.25, 1.0);
  ren11->ResetCamera(-0.5, 0.5, -0.5, 0.5, -1, 1);
116
117
118
119
120
121
122
123
124
  ren11->AddActor(a11);
  renWin->AddRenderer(ren11);

  // Invert the transform
  vtkSmartPointer<vtkTransformPolyDataFilter> f12 =
    vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  f12->SetInputData(sphereData);
  f12->SetTransform(thin->GetInverse());

125
  vtkSmartPointer<vtkPolyDataMapper> m12 = vtkSmartPointer<vtkPolyDataMapper>::New();
126
127
  m12->SetInputConnection(f12->GetOutputPort());

128
  vtkSmartPointer<vtkActor> a12 = vtkSmartPointer<vtkActor>::New();
129
130
  a12->SetMapper(m12);
  a12->RotateY(90);
131
  a12->GetProperty()->SetColor(0.9, 0.9, 0);
132

133
134
135
  vtkSmartPointer<vtkRenderer> ren12 = vtkSmartPointer<vtkRenderer>::New();
  ren12->SetViewport(0.0, 0.0, 0.25, 0.5);
  ren12->ResetCamera(-0.5, 0.5, -0.5, 0.5, -1, 1);
136
137
138
139
  ren12->AddActor(a12);
  renWin->AddRenderer(ren12);

  // Second pane: b-spline transform, no normals
140
  vtkSmartPointer<vtkTransformToGrid> transformToGrid = vtkSmartPointer<vtkTransformToGrid>::New();
141
  transformToGrid->SetInput(thin);
142
143
144
  transformToGrid->SetGridOrigin(-1.5, -1.5, -1.5);
  transformToGrid->SetGridExtent(0, 60, 0, 60, 0, 60);
  transformToGrid->SetGridSpacing(0.05, 0.05, 0.05);
145
146
147
148
149

  vtkSmartPointer<vtkImageBSplineCoefficients> coeffs =
    vtkSmartPointer<vtkImageBSplineCoefficients>::New();
  coeffs->SetInputConnection(transformToGrid->GetOutputPort());

150
  vtkSmartPointer<vtkBSplineTransform> t2 = vtkSmartPointer<vtkBSplineTransform>::New();
151
152
153
154
155
156
157
  t2->SetCoefficientConnection(coeffs->GetOutputPort());

  vtkSmartPointer<vtkTransformPolyDataFilter> f21 =
    vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  f21->SetInputData(sphereData);
  f21->SetTransform(t2);

158
  vtkSmartPointer<vtkPolyDataMapper> m21 = vtkSmartPointer<vtkPolyDataMapper>::New();
159
160
  m21->SetInputConnection(f21->GetOutputPort());

161
  vtkSmartPointer<vtkActor> a21 = vtkSmartPointer<vtkActor>::New();
162
163
  a21->SetMapper(m21);
  a21->RotateY(90);
164
  a21->GetProperty()->SetColor(1, 0, 0);
165

166
167
168
  vtkSmartPointer<vtkRenderer> ren21 = vtkSmartPointer<vtkRenderer>::New();
  ren21->SetViewport(0.25, 0.5, 0.50, 1.0);
  ren21->ResetCamera(-0.5, 0.5, -0.5, 0.5, -1, 1);
169
170
171
172
173
174
175
176
177
  ren21->AddActor(a21);
  renWin->AddRenderer(ren21);

  // Invert the transform
  vtkSmartPointer<vtkTransformPolyDataFilter> f22 =
    vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  f22->SetInputData(sphereData);
  f22->SetTransform(t2->GetInverse());

178
  vtkSmartPointer<vtkPolyDataMapper> m22 = vtkSmartPointer<vtkPolyDataMapper>::New();
179
180
  m22->SetInputConnection(f22->GetOutputPort());

181
  vtkSmartPointer<vtkActor> a22 = vtkSmartPointer<vtkActor>::New();
182
183
  a22->SetMapper(m22);
  a22->RotateY(90);
184
  a22->GetProperty()->SetColor(0.9, 0.9, 0);
185

186
187
188
  vtkSmartPointer<vtkRenderer> ren22 = vtkSmartPointer<vtkRenderer>::New();
  ren22->SetViewport(0.25, 0.0, 0.50, 0.5);
  ren22->ResetCamera(-0.5, 0.5, -0.5, 0.5, -1, 1);
189
190
191
192
193
194
195
196
197
  ren22->AddActor(a22);
  renWin->AddRenderer(ren22);

  // Third pane: thin-plate, no normals
  vtkSmartPointer<vtkTransformPolyDataFilter> f31 =
    vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  f31->SetInputConnection(sphere->GetOutputPort());
  f31->SetTransform(thin);

198
  vtkSmartPointer<vtkPolyDataMapper> m31 = vtkSmartPointer<vtkPolyDataMapper>::New();
199
200
  m31->SetInputConnection(f31->GetOutputPort());

201
  vtkSmartPointer<vtkActor> a31 = vtkSmartPointer<vtkActor>::New();
202
203
  a31->SetMapper(m31);
  a31->RotateY(90);
204
  a31->GetProperty()->SetColor(1, 0, 0);
205

206
207
208
  vtkSmartPointer<vtkRenderer> ren31 = vtkSmartPointer<vtkRenderer>::New();
  ren31->SetViewport(0.50, 0.5, 0.75, 1.0);
  ren31->ResetCamera(-0.5, 0.5, -0.5, 0.5, -1, 1);
209
210
211
212
213
214
215
216
217
  ren31->AddActor(a31);
  renWin->AddRenderer(ren31);

  // Invert the transform
  vtkSmartPointer<vtkTransformPolyDataFilter> f32 =
    vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  f32->SetInputConnection(sphere->GetOutputPort());
  f32->SetTransform(thin->GetInverse());

218
  vtkSmartPointer<vtkPolyDataMapper> m32 = vtkSmartPointer<vtkPolyDataMapper>::New();
219
220
  m32->SetInputConnection(f32->GetOutputPort());

221
  vtkSmartPointer<vtkActor> a32 = vtkSmartPointer<vtkActor>::New();
222
223
  a32->SetMapper(m32);
  a32->RotateY(90);
224
  a32->GetProperty()->SetColor(0.9, 0.9, 0);
225

226
227
228
  vtkSmartPointer<vtkRenderer> ren32 = vtkSmartPointer<vtkRenderer>::New();
  ren32->SetViewport(0.5, 0.0, 0.75, 0.5);
  ren32->ResetCamera(-0.5, 0.5, -0.5, 0.5, -1, 1);
229
230
231
232
  ren32->AddActor(a32);
  renWin->AddRenderer(ren32);

  // Third pane: b-spline, normals
233
  vtkSmartPointer<vtkBSplineTransform> t4 = vtkSmartPointer<vtkBSplineTransform>::New();
234
235
236
237
238
239
240
  t4->SetCoefficientConnection(coeffs->GetOutputPort());

  vtkSmartPointer<vtkTransformPolyDataFilter> f41 =
    vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  f41->SetInputConnection(sphere->GetOutputPort());
  f41->SetTransform(t4);

241
  vtkSmartPointer<vtkPolyDataMapper> m41 = vtkSmartPointer<vtkPolyDataMapper>::New();
242
243
  m41->SetInputConnection(f41->GetOutputPort());

244
  vtkSmartPointer<vtkActor> a41 = vtkSmartPointer<vtkActor>::New();
245
246
  a41->SetMapper(m41);
  a41->RotateY(90);
247
  a41->GetProperty()->SetColor(1, 0, 0);
248

249
250
251
  vtkSmartPointer<vtkRenderer> ren41 = vtkSmartPointer<vtkRenderer>::New();
  ren41->SetViewport(0.75, 0.5, 1.0, 1.0);
  ren41->ResetCamera(-0.5, 0.5, -0.5, 0.5, -1, 1);
252
253
254
255
256
257
258
259
260
  ren41->AddActor(a41);
  renWin->AddRenderer(ren41);

  // Invert the transform
  vtkSmartPointer<vtkTransformPolyDataFilter> f42 =
    vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  f42->SetInputConnection(sphere->GetOutputPort());
  f42->SetTransform(t4->GetInverse());

261
  vtkSmartPointer<vtkPolyDataMapper> m42 = vtkSmartPointer<vtkPolyDataMapper>::New();
262
263
  m42->SetInputConnection(f42->GetOutputPort());

264
  vtkSmartPointer<vtkActor> a42 = vtkSmartPointer<vtkActor>::New();
265
266
  a42->SetMapper(m42);
  a42->RotateY(90);
267
  a42->GetProperty()->SetColor(0.9, 0.9, 0);
268

269
270
271
  vtkSmartPointer<vtkRenderer> ren42 = vtkSmartPointer<vtkRenderer>::New();
  ren42->SetViewport(0.75, 0.0, 1.0, 0.5);
  ren42->ResetCamera(-0.5, 0.5, -0.5, 0.5, -1, 1);
272
273
274
  ren42->AddActor(a42);
  renWin->AddRenderer(ren42);

275
276
  // you MUST NOT call renderWindow->Render() before
  // iren->SetRenderWindow(renderWindow);
277
278
279
280
  vtkSmartPointer<vtkRenderWindowInteractor> iren =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  iren->SetRenderWindow(renWin);

281
  // render and interact
282
283
284
285
286
  renWin->Render();
  iren->Start();

  return EXIT_SUCCESS;
}