Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/viz/src/shapes.cpp
16354 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
14
// Third party copyrights are property of their respective owners.
15
//
16
// Redistribution and use in source and binary forms, with or without modification,
17
// are permitted provided that the following conditions are met:
18
//
19
// * Redistribution's of source code must retain the above copyright notice,
20
// this list of conditions and the following disclaimer.
21
//
22
// * Redistribution's in binary form must reproduce the above copyright notice,
23
// this list of conditions and the following disclaimer in the documentation
24
// and/or other materials provided with the distribution.
25
//
26
// * The name of the copyright holders may not be used to endorse or promote products
27
// derived from this software without specific prior written permission.
28
//
29
// This software is provided by the copyright holders and contributors "as is" and
30
// any express or implied warranties, including, but not limited to, the implied
31
// warranties of merchantability and fitness for a particular purpose are disclaimed.
32
// In no event shall the Intel Corporation or contributors be liable for any direct,
33
// indirect, incidental, special, exemplary, or consequential damages
34
// (including, but not limited to, procurement of substitute goods or services;
35
// loss of use, data, or profits; or business interruption) however caused
36
// and on any theory of liability, whether in contract, strict liability,
37
// or tort (including negligence or otherwise) arising in any way out of
38
// the use of this software, even if advised of the possibility of such damage.
39
//
40
// Authors:
41
// * Ozan Tonkal, [email protected]
42
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
43
//
44
//M*/
45
46
#include "precomp.hpp"
47
48
///////////////////////////////////////////////////////////////////////////////////////////////
49
/// line widget implementation
50
cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color)
51
{
52
vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New();
53
line->SetPoint1(pt1.x, pt1.y, pt1.z);
54
line->SetPoint2(pt2.x, pt2.y, pt2.z);
55
line->Update();
56
57
vtkSmartPointer<vtkPolyData> polydata = line->GetOutput();
58
VtkUtils::FillScalars(polydata, color);
59
60
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
61
VtkUtils::SetInputData(mapper, polydata);
62
63
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
64
actor->SetMapper(mapper);
65
66
WidgetAccessor::setProp(*this, actor);
67
}
68
69
template<> cv::viz::WLine cv::viz::Widget::cast<cv::viz::WLine>()
70
{
71
Widget3D widget = this->cast<Widget3D>();
72
return static_cast<WLine&>(widget);
73
}
74
75
///////////////////////////////////////////////////////////////////////////////////////////////
76
/// sphere widget implementation
77
78
cv::viz::WSphere::WSphere(const Point3d &center, double radius, int sphere_resolution, const Color &color)
79
{
80
vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
81
sphere->SetRadius(radius);
82
sphere->SetCenter(center.x, center.y, center.z);
83
sphere->SetPhiResolution(sphere_resolution);
84
sphere->SetThetaResolution(sphere_resolution);
85
sphere->LatLongTessellationOff();
86
sphere->Update();
87
88
vtkSmartPointer<vtkPolyData> polydata = sphere->GetOutput();
89
VtkUtils::FillScalars(polydata, color);
90
91
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
92
VtkUtils::SetInputData(mapper, polydata);
93
94
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
95
actor->SetMapper(mapper);
96
97
WidgetAccessor::setProp(*this, actor);
98
}
99
100
template<> cv::viz::WSphere cv::viz::Widget::cast<cv::viz::WSphere>()
101
{
102
Widget3D widget = this->cast<Widget3D>();
103
return static_cast<WSphere&>(widget);
104
}
105
106
///////////////////////////////////////////////////////////////////////////////////////////////
107
/// plane widget implementation
108
109
cv::viz::WPlane::WPlane(const Size2d& size, const Color &color)
110
{
111
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
112
plane->SetOrigin(-0.5 * size.width, -0.5 * size.height, 0.0);
113
plane->SetPoint1( 0.5 * size.width, -0.5 * size.height, 0.0);
114
plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0);
115
plane->Update();
116
117
vtkSmartPointer<vtkPolyData> polydata = plane->GetOutput();
118
VtkUtils::FillScalars(polydata, color);
119
120
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
121
VtkUtils::SetInputData(mapper, polydata);
122
123
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
124
actor->SetMapper(mapper);
125
actor->GetProperty()->LightingOff();
126
127
WidgetAccessor::setProp(*this, actor);
128
}
129
130
cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Size2d& size, const Color &color)
131
{
132
Vec3d zvec = normalize(normal);
133
Vec3d xvec = normalize(new_yaxis.cross(zvec));
134
Vec3d yvec = zvec.cross(xvec);
135
136
WPlane plane(size, color);
137
plane.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center));
138
*this = plane;
139
}
140
141
template<> cv::viz::WPlane cv::viz::Widget::cast<cv::viz::WPlane>()
142
{
143
Widget3D widget = this->cast<Widget3D>();
144
return static_cast<WPlane&>(widget);
145
}
146
147
///////////////////////////////////////////////////////////////////////////////////////////////
148
/// arrow widget implementation
149
150
cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness, const Color &color)
151
{
152
vtkSmartPointer<vtkArrowSource> arrow_source = vtkSmartPointer<vtkArrowSource>::New();
153
arrow_source->SetShaftRadius(thickness);
154
arrow_source->SetTipRadius(thickness * 3.0);
155
arrow_source->SetTipLength(thickness * 10.0);
156
157
Vec3d arbitrary = get_random_vec();
158
Vec3d start_point(pt1.x, pt1.y, pt1.z), end_point(pt2.x, pt2.y, pt2.z);
159
160
double length = norm(end_point - start_point);
161
162
Vec3d xvec = normalized(end_point - start_point);
163
Vec3d zvec = normalized(xvec.cross(arbitrary));
164
Vec3d yvec = zvec.cross(xvec);
165
166
Matx33d R = makeTransformToGlobal(xvec, yvec, zvec).rotation();
167
Affine3d transform_with_scale(R * length, start_point);
168
169
vtkSmartPointer<vtkPolyData> polydata = VtkUtils::TransformPolydata(arrow_source->GetOutputPort(), transform_with_scale);
170
VtkUtils::FillScalars(polydata, color);
171
172
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
173
VtkUtils::SetInputData(mapper, polydata);
174
175
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
176
actor->SetMapper(mapper);
177
178
WidgetAccessor::setProp(*this, actor);
179
}
180
181
template<> cv::viz::WArrow cv::viz::Widget::cast<cv::viz::WArrow>()
182
{
183
Widget3D widget = this->cast<Widget3D>();
184
return static_cast<WArrow&>(widget);
185
}
186
187
///////////////////////////////////////////////////////////////////////////////////////////////
188
/// circle widget implementation
189
190
cv::viz::WCircle::WCircle(double radius, double thickness, const Color &color)
191
{
192
vtkSmartPointer<vtkDiskSource> disk = vtkSmartPointer<vtkDiskSource>::New();
193
disk->SetCircumferentialResolution(30);
194
disk->SetInnerRadius(radius - thickness);
195
disk->SetOuterRadius(radius + thickness);
196
disk->Update();
197
198
vtkSmartPointer<vtkPolyData> polydata = disk->GetOutput();
199
VtkUtils::FillScalars(polydata, color);
200
201
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
202
VtkUtils::SetInputData(mapper, polydata);
203
204
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
205
actor->GetProperty()->LightingOff();
206
actor->SetMapper(mapper);
207
208
WidgetAccessor::setProp(*this, actor);
209
}
210
211
cv::viz::WCircle::WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness, const Color &color)
212
{
213
Vec3d arbitrary = get_random_vec();
214
Vec3d zvec = normalized(normal);
215
Vec3d xvec = normalized(zvec.cross(arbitrary));
216
Vec3d yvec = zvec.cross(xvec);
217
218
WCircle circle(radius, thickness, color);
219
circle.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center));
220
*this = circle;
221
}
222
223
template<> cv::viz::WCircle cv::viz::Widget::cast<cv::viz::WCircle>()
224
{
225
Widget3D widget = this->cast<Widget3D>();
226
return static_cast<WCircle&>(widget);
227
}
228
229
///////////////////////////////////////////////////////////////////////////////////////////////
230
/// WCone widget implementation
231
232
cv::viz::WCone::WCone(double length, double radius, int resolution, const Color &color)
233
{
234
vtkSmartPointer<vtkConeSource> cone_source = vtkSmartPointer<vtkConeSource>::New();
235
cone_source->SetCenter(length*0.5, 0.0, 0.0);
236
cone_source->SetHeight(length);
237
cone_source->SetRadius(radius);
238
cone_source->SetResolution(resolution);
239
cone_source->Update();
240
241
vtkSmartPointer<vtkPolyData> polydata = cone_source->GetOutput();
242
VtkUtils::FillScalars(polydata, color);
243
244
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
245
VtkUtils::SetInputData(mapper, polydata);
246
247
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
248
actor->SetMapper(mapper);
249
250
WidgetAccessor::setProp(*this, actor);
251
}
252
253
cv::viz::WCone::WCone(double radius, const Point3d& center, const Point3d& tip, int resolution, const Color &color)
254
{
255
Vec3d arbitrary = get_random_vec();
256
Vec3d xvec = normalized(Vec3d(tip - center));
257
Vec3d zvec = normalized(xvec.cross(arbitrary));
258
Vec3d yvec = zvec.cross(xvec);
259
260
WCone circle(norm(tip - center), radius, resolution, color);
261
circle.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center));
262
*this = circle;
263
}
264
265
template<> cv::viz::WCone cv::viz::Widget::cast<cv::viz::WCone>()
266
{
267
Widget3D widget = this->cast<Widget3D>();
268
return static_cast<WCone&>(widget);
269
}
270
271
///////////////////////////////////////////////////////////////////////////////////////////////
272
/// cylinder widget implementation
273
274
cv::viz::WCylinder::WCylinder(const Point3d& axis_point1, const Point3d& axis_point2, double radius, int numsides, const Color &color)
275
{
276
vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New();
277
line->SetPoint1(axis_point1.x, axis_point1.y, axis_point1.z);
278
line->SetPoint2(axis_point2.x, axis_point2.y, axis_point2.z);
279
280
vtkSmartPointer<vtkTubeFilter> tuber = vtkSmartPointer<vtkTubeFilter>::New();
281
tuber->SetInputConnection(line->GetOutputPort());
282
tuber->SetNumberOfSides(numsides);
283
tuber->SetRadius(radius);
284
tuber->Update();
285
286
vtkSmartPointer<vtkPolyData> polydata = tuber->GetOutput();
287
VtkUtils::FillScalars(polydata, color);
288
289
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
290
VtkUtils::SetInputData(mapper, polydata);
291
292
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
293
actor->SetMapper(mapper);
294
295
WidgetAccessor::setProp(*this, actor);
296
}
297
298
template<> cv::viz::WCylinder cv::viz::Widget::cast<cv::viz::WCylinder>()
299
{
300
Widget3D widget = this->cast<Widget3D>();
301
return static_cast<WCylinder&>(widget);
302
}
303
304
///////////////////////////////////////////////////////////////////////////////////////////////
305
/// cylinder widget implementation
306
307
cv::viz::WCube::WCube(const Point3d& min_point, const Point3d& max_point, bool wire_frame, const Color &color)
308
{
309
double bounds[6];
310
bounds[0] = std::min(min_point.x, max_point.x);
311
bounds[1] = std::max(min_point.x, max_point.x);
312
bounds[2] = std::min(min_point.y, max_point.y);
313
bounds[3] = std::max(min_point.y, max_point.y);
314
bounds[4] = std::min(min_point.z, max_point.z);
315
bounds[5] = std::max(min_point.z, max_point.z);
316
317
vtkSmartPointer<vtkPolyDataAlgorithm> cube;
318
if (wire_frame)
319
{
320
cube = vtkSmartPointer<vtkOutlineSource>::New();
321
vtkOutlineSource::SafeDownCast(cube)->SetBounds(bounds);
322
}
323
else
324
{
325
cube = vtkSmartPointer<vtkCubeSource>::New();
326
vtkCubeSource::SafeDownCast(cube)->SetBounds(bounds);
327
}
328
cube->Update();
329
vtkSmartPointer<vtkPolyData> polydata =cube->GetOutput();
330
VtkUtils::FillScalars(polydata, color);
331
332
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
333
VtkUtils::SetInputData(mapper, polydata);
334
335
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
336
actor->SetMapper(mapper);
337
338
WidgetAccessor::setProp(*this, actor);
339
}
340
341
template<> cv::viz::WCube cv::viz::Widget::cast<cv::viz::WCube>()
342
{
343
Widget3D widget = this->cast<Widget3D>();
344
return static_cast<WCube&>(widget);
345
}
346
347
///////////////////////////////////////////////////////////////////////////////////////////////
348
/// coordinate system widget implementation
349
350
cv::viz::WCoordinateSystem::WCoordinateSystem(double scale)
351
{
352
vtkSmartPointer<vtkAxes> axes = vtkSmartPointer<vtkAxes>::New();
353
axes->SetOrigin(0, 0, 0);
354
axes->SetScaleFactor(scale);
355
axes->Update();
356
357
vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
358
colors->SetNumberOfComponents(3);
359
colors->InsertNextTuple3(255, 0, 0);
360
colors->InsertNextTuple3(255, 0, 0);
361
colors->InsertNextTuple3(0, 255, 0);
362
colors->InsertNextTuple3(0, 255, 0);
363
colors->InsertNextTuple3(0, 0, 255);
364
colors->InsertNextTuple3(0, 0, 255);
365
366
vtkSmartPointer<vtkPolyData> polydata = axes->GetOutput();
367
polydata->GetPointData()->SetScalars(colors);
368
369
vtkSmartPointer<vtkTubeFilter> tube_filter = vtkSmartPointer<vtkTubeFilter>::New();
370
VtkUtils::SetInputData(tube_filter, polydata);
371
tube_filter->SetRadius(axes->GetScaleFactor() / 50.0);
372
tube_filter->SetNumberOfSides(6);
373
tube_filter->Update();
374
375
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
376
mapper->SetScalarModeToUsePointData();
377
VtkUtils::SetInputData(mapper, tube_filter->GetOutput());
378
379
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
380
actor->SetMapper(mapper);
381
382
WidgetAccessor::setProp(*this, actor);
383
}
384
385
template<> cv::viz::WCoordinateSystem cv::viz::Widget::cast<cv::viz::WCoordinateSystem>()
386
{
387
Widget3D widget = this->cast<Widget3D>();
388
return static_cast<WCoordinateSystem&>(widget);
389
}
390
391
///////////////////////////////////////////////////////////////////////////////////////////////
392
/// polyline widget implementation
393
394
cv::viz::WPolyLine::WPolyLine(InputArray points, InputArray colors)
395
{
396
vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New();
397
cloud_source->SetColorCloud(points, colors);
398
cloud_source->Update();
399
400
vtkSmartPointer<vtkPolyData> polydata = cloud_source->GetOutput();
401
402
vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New();
403
cell_array->Allocate(cell_array->EstimateSize(1, polydata->GetNumberOfPoints()));
404
cell_array->InsertNextCell(polydata->GetNumberOfPoints());
405
for(vtkIdType i = 0; i < polydata->GetNumberOfPoints(); ++i)
406
cell_array->InsertCellPoint(i);
407
408
polydata->SetLines(cell_array);
409
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
410
VtkUtils::SetInputData(mapper, polydata);
411
mapper->SetScalarRange(0, 255);
412
413
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
414
actor->SetMapper(mapper);
415
416
WidgetAccessor::setProp(*this, actor);
417
}
418
419
cv::viz::WPolyLine::WPolyLine(InputArray points, const Color &color)
420
{
421
WPolyLine polyline(points, Mat(points.size(), CV_8UC3, color));
422
*this = polyline;
423
}
424
425
template<> cv::viz::WPolyLine cv::viz::Widget::cast<cv::viz::WPolyLine>()
426
{
427
Widget3D widget = this->cast<Widget3D>();
428
return static_cast<WPolyLine&>(widget);
429
}
430
431
///////////////////////////////////////////////////////////////////////////////////////////////
432
/// grid widget implementation
433
434
435
cv::viz::WGrid::WGrid(const Vec2i &cells, const Vec2d &cells_spacing, const Color &color)
436
{
437
vtkSmartPointer<vtkImageData> grid_data = vtkSmartPointer<vtkImageData>::New();
438
439
// Add 1 to dimensions because in ImageData dimensions is the number of lines
440
// - however here it means number of cells
441
grid_data->SetDimensions(cells[0]+1, cells[1]+1, 1);
442
grid_data->SetSpacing(cells_spacing[0], cells_spacing[1], 0.);
443
444
// Set origin of the grid to be the middle of the grid
445
grid_data->SetOrigin(cells[0] * cells_spacing[0] * (-0.5), cells[1] * cells_spacing[1] * (-0.5), 0);
446
447
// Extract the edges so we have the grid
448
vtkSmartPointer<vtkExtractEdges> extract_edges = vtkSmartPointer<vtkExtractEdges>::New();
449
VtkUtils::SetInputData(extract_edges, grid_data);
450
extract_edges->Update();
451
452
vtkSmartPointer<vtkPolyData> polydata = extract_edges->GetOutput();
453
VtkUtils::FillScalars(polydata, color);
454
455
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
456
VtkUtils::SetInputData(mapper, polydata);
457
458
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
459
actor->SetMapper(mapper);
460
461
WidgetAccessor::setProp(*this, actor);
462
}
463
464
cv::viz::WGrid::WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Vec2i &cells, const Vec2d &cells_spacing, const Color &color)
465
{
466
Vec3d zvec = normalize(normal);
467
Vec3d xvec = normalize(new_yaxis.cross(zvec));
468
Vec3d yvec = zvec.cross(xvec);
469
470
WGrid grid(cells, cells_spacing, color);
471
grid.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center));
472
*this = grid;
473
}
474
475
template<> cv::viz::WGrid cv::viz::Widget::cast<cv::viz::WGrid>()
476
{
477
Widget3D widget = this->cast<Widget3D>();
478
return static_cast<WGrid&>(widget);
479
}
480
481
///////////////////////////////////////////////////////////////////////////////////////////////
482
/// text3D widget implementation
483
484
cv::viz::WText3D::WText3D(const String &text, const Point3d &position, double text_scale, bool face_camera, const Color &color)
485
{
486
vtkSmartPointer<vtkVectorText> textSource = vtkSmartPointer<vtkVectorText>::New();
487
textSource->SetText(text.c_str());
488
textSource->Update();
489
490
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
491
mapper->SetInputConnection(textSource->GetOutputPort());
492
493
if (face_camera)
494
{
495
vtkSmartPointer<vtkFollower> actor = vtkSmartPointer<vtkFollower>::New();
496
actor->SetMapper(mapper);
497
actor->SetPosition(position.x, position.y, position.z);
498
actor->SetScale(text_scale);
499
WidgetAccessor::setProp(*this, actor);
500
}
501
else
502
{
503
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
504
actor->SetMapper(mapper);
505
actor->SetPosition(position.x, position.y, position.z);
506
actor->SetScale(text_scale);
507
actor->GetProperty()->LightingOff();
508
WidgetAccessor::setProp(*this, actor);
509
}
510
511
setColor(color);
512
}
513
514
void cv::viz::WText3D::setText(const String &text)
515
{
516
vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
517
CV_Assert("This widget does not support text." && actor);
518
519
// Update text source
520
vtkPolyDataMapper *mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
521
vtkVectorText * textSource = vtkVectorText::SafeDownCast(mapper->GetInputConnection(0,0)->GetProducer());
522
CV_Assert("This widget does not support text." && textSource);
523
524
textSource->SetText(text.c_str());
525
textSource->Modified();
526
textSource->Update();
527
}
528
529
cv::String cv::viz::WText3D::getText() const
530
{
531
vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
532
CV_Assert("This widget does not support text." && actor);
533
534
vtkPolyDataMapper *mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
535
vtkVectorText * textSource = vtkVectorText::SafeDownCast(mapper->GetInputConnection(0,0)->GetProducer());
536
CV_Assert("This widget does not support text." && textSource);
537
538
return textSource->GetText();
539
}
540
541
template<> cv::viz::WText3D cv::viz::Widget::cast<cv::viz::WText3D>()
542
{
543
Widget3D widget = this->cast<Widget3D>();
544
return static_cast<WText3D&>(widget);
545
}
546
547
///////////////////////////////////////////////////////////////////////////////////////////////
548
/// text widget implementation
549
550
cv::viz::WText::WText(const String &text, const Point &pos, int font_size, const Color &color)
551
{
552
vtkSmartPointer<vtkTextActor> actor = vtkSmartPointer<vtkTextActor>::New();
553
actor->SetDisplayPosition(pos.x, pos.y);
554
actor->SetInput(text.c_str());
555
556
actor->GetProperty()->SetDisplayLocationToForeground();
557
558
vtkSmartPointer<vtkTextProperty> tprop = actor->GetTextProperty();
559
tprop->SetFontSize(font_size);
560
tprop->SetFontFamilyToCourier();
561
tprop->SetJustificationToLeft();
562
tprop->BoldOn();
563
564
Color c = vtkcolor(color);
565
tprop->SetColor(c.val);
566
567
WidgetAccessor::setProp(*this, actor);
568
}
569
570
template<> cv::viz::WText cv::viz::Widget::cast<cv::viz::WText>()
571
{
572
Widget2D widget = this->cast<Widget2D>();
573
return static_cast<WText&>(widget);
574
}
575
576
void cv::viz::WText::setText(const String &text)
577
{
578
vtkTextActor *actor = vtkTextActor::SafeDownCast(WidgetAccessor::getProp(*this));
579
CV_Assert("This widget does not support text." && actor);
580
actor->SetInput(text.c_str());
581
}
582
583
cv::String cv::viz::WText::getText() const
584
{
585
vtkTextActor *actor = vtkTextActor::SafeDownCast(WidgetAccessor::getProp(*this));
586
CV_Assert("This widget does not support text." && actor);
587
return actor->GetInput();
588
}
589
590
///////////////////////////////////////////////////////////////////////////////////////////////
591
/// image overlay widget implementation
592
593
cv::viz::WImageOverlay::WImageOverlay(InputArray image, const Rect &rect)
594
{
595
CV_Assert(!image.empty() && image.depth() == CV_8U);
596
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
597
source->SetImage(image);
598
Size sz = image.size();
599
600
// Scale the image based on the Rect, and flip to match y-ais orientation
601
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
602
transform->Scale(sz.width/(double)rect.width, sz.height/(double)rect.height, 1.0);
603
transform->RotateX(180);
604
605
vtkSmartPointer<vtkImageReslice> image_reslice = vtkSmartPointer<vtkImageReslice>::New();
606
image_reslice->SetResliceTransform(transform);
607
image_reslice->SetInputConnection(source->GetOutputPort());
608
image_reslice->SetOutputDimensionality(2);
609
image_reslice->InterpolateOn();
610
image_reslice->AutoCropOutputOn();
611
image_reslice->Update();
612
613
vtkSmartPointer<vtkImageMapper> image_mapper = vtkSmartPointer<vtkImageMapper>::New();
614
image_mapper->SetInputConnection(image_reslice->GetOutputPort());
615
image_mapper->SetColorWindow(255); // OpenCV color
616
image_mapper->SetColorLevel(127.5);
617
618
vtkSmartPointer<vtkActor2D> actor = vtkSmartPointer<vtkActor2D>::New();
619
actor->SetMapper(image_mapper);
620
actor->SetPosition(rect.x, rect.y);
621
actor->GetProperty()->SetDisplayLocationToForeground();
622
623
WidgetAccessor::setProp(*this, actor);
624
}
625
626
void cv::viz::WImageOverlay::setImage(InputArray image)
627
{
628
CV_Assert(!image.empty() && image.depth() == CV_8U);
629
630
vtkActor2D *actor = vtkActor2D::SafeDownCast(WidgetAccessor::getProp(*this));
631
CV_Assert("This widget does not support overlay image." && actor);
632
633
vtkImageMapper *mapper = vtkImageMapper::SafeDownCast(actor->GetMapper());
634
CV_Assert("This widget does not support overlay image." && mapper);
635
\
636
Vec6i extent;
637
mapper->GetInput()->GetExtent(extent.val);
638
Size size(extent[1], extent[3]);
639
640
// Create the vtk image and set its parameters based on input image
641
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
642
source->SetImage(image);
643
Size sz = image.size();
644
645
// Scale the image based on the Rect, and flip to match y-ais orientation
646
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
647
transform->Scale(sz.width/(double)size.width, sz.height/(double)size.height, 1.0);
648
transform->RotateX(180);
649
650
vtkSmartPointer<vtkImageReslice> image_reslice = vtkSmartPointer<vtkImageReslice>::New();
651
image_reslice->SetResliceTransform(transform);
652
image_reslice->SetInputConnection(source->GetOutputPort());
653
image_reslice->SetOutputDimensionality(2);
654
image_reslice->InterpolateOn();
655
image_reslice->AutoCropOutputOn();
656
image_reslice->Update();
657
658
mapper->SetInputConnection(image_reslice->GetOutputPort());
659
}
660
661
template<> cv::viz::WImageOverlay cv::viz::Widget::cast<cv::viz::WImageOverlay>()
662
{
663
Widget2D widget = this->cast<Widget2D>();
664
return static_cast<WImageOverlay&>(widget);
665
}
666
667
///////////////////////////////////////////////////////////////////////////////////////////////
668
/// image 3D widget implementation
669
670
cv::viz::WImage3D::WImage3D(InputArray image, const Size2d &size)
671
{
672
CV_Assert(!image.empty() && image.depth() == CV_8U);
673
674
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
675
source->SetImage(image);
676
677
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
678
texture->SetInputConnection(source->GetOutputPort());
679
680
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
681
plane->SetOrigin(-0.5 * size.width, -0.5 * size.height, 0.0);
682
plane->SetPoint1( 0.5 * size.width, -0.5 * size.height, 0.0);
683
plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0);
684
685
vtkSmartPointer<vtkTextureMapToPlane> textured_plane = vtkSmartPointer<vtkTextureMapToPlane>::New();
686
textured_plane->SetInputConnection(plane->GetOutputPort());
687
688
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
689
mapper->SetInputConnection(textured_plane->GetOutputPort());
690
691
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
692
actor->SetMapper(mapper);
693
actor->SetTexture(texture);
694
actor->GetProperty()->ShadingOff();
695
actor->GetProperty()->LightingOff();
696
697
WidgetAccessor::setProp(*this, actor);
698
}
699
700
cv::viz::WImage3D::WImage3D(InputArray image, const Size2d &size, const Vec3d &center, const Vec3d &normal, const Vec3d &up_vector)
701
{
702
CV_Assert(!image.empty() && image.depth() == CV_8U);
703
704
// Compute the transformation matrix for drawing the camera frame in a scene
705
Vec3d n = normalize(normal);
706
Vec3d u = normalize(up_vector.cross(n));
707
Vec3d v = n.cross(u);
708
Affine3d pose = makeTransformToGlobal(u, v, n, center);
709
710
WImage3D image3d(image, size);
711
image3d.applyTransform(pose);
712
*this = image3d;
713
}
714
715
void cv::viz::WImage3D::setImage(InputArray image)
716
{
717
CV_Assert(!image.empty() && image.depth() == CV_8U);
718
719
vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
720
CV_Assert("This widget does not support 3D image." && actor);
721
722
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
723
source->SetImage(image);
724
725
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
726
texture->SetInputConnection(source->GetOutputPort());
727
728
actor->SetTexture(texture);
729
}
730
731
void cv::viz::WImage3D::setSize(const cv::Size& size)
732
{
733
vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
734
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
735
vtkSmartPointer<vtkTextureMapToPlane> textured_plane;
736
vtkSmartPointer<vtkPlaneSource> plane;
737
#if VTK_MAJOR_VERSION <= 5
738
textured_plane = vtkTextureMapToPlane::SafeDownCast(mapper->GetInputConnection(0,0)->GetProducer());
739
plane = vtkPlaneSource::SafeDownCast(textured_plane->GetInputConnection(0,0)->GetProducer());
740
#else
741
textured_plane = vtkTextureMapToPlane::SafeDownCast(mapper->GetInputAlgorithm());
742
plane = vtkPlaneSource::SafeDownCast(textured_plane->GetInputAlgorithm());
743
#endif
744
plane->SetOrigin(-0.5 * size.width, -0.5 * size.height, 0.0);
745
plane->SetPoint1( 0.5 * size.width, -0.5 * size.height, 0.0);
746
plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0);
747
}
748
749
template<> cv::viz::WImage3D cv::viz::Widget::cast<cv::viz::WImage3D>()
750
{
751
Widget3D widget = this->cast<Widget3D>();
752
return static_cast<WImage3D&>(widget);
753
}
754
755
///////////////////////////////////////////////////////////////////////////////////////////////
756
/// camera position widget implementation
757
758
namespace cv { namespace viz { namespace
759
{
760
struct CameraPositionUtils
761
{
762
static vtkSmartPointer<vtkPolyData> createFrustum(double aspect_ratio, double fovy, double scale)
763
{
764
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
765
camera->SetViewAngle(fovy);
766
camera->SetPosition(0.0, 0.0, 0.0);
767
camera->SetViewUp(0.0, 1.0, 0.0);
768
camera->SetFocalPoint(0.0, 0.0, 1.0);
769
camera->SetClippingRange(1e-9, scale);
770
771
double planes_array[24];
772
camera->GetFrustumPlanes(aspect_ratio, planes_array);
773
774
vtkSmartPointer<vtkPlanes> planes = vtkSmartPointer<vtkPlanes>::New();
775
planes->SetFrustumPlanes(planes_array);
776
777
vtkSmartPointer<vtkFrustumSource> frustumSource = vtkSmartPointer<vtkFrustumSource>::New();
778
frustumSource->SetPlanes(planes);
779
780
vtkSmartPointer<vtkExtractEdges> extract_edges = vtkSmartPointer<vtkExtractEdges>::New();
781
extract_edges->SetInputConnection(frustumSource->GetOutputPort());
782
extract_edges->Update();
783
784
return extract_edges->GetOutput();
785
}
786
787
static Mat ensureColorImage(InputArray image)
788
{
789
Mat color(image.size(), CV_8UC3);
790
if (image.channels() == 1)
791
{
792
Vec3b *drow = color.ptr<Vec3b>();
793
for(int y = 0; y < color.rows; ++y)
794
{
795
const unsigned char *srow = image.getMat().ptr<unsigned char>(y);
796
const unsigned char *send = srow + color.cols;
797
for(;srow < send;)
798
*drow++ = Vec3b::all(*srow++);
799
}
800
}
801
else
802
image.copyTo(color);
803
return color;
804
}
805
};
806
}}}
807
808
cv::viz::WCameraPosition::WCameraPosition(double scale)
809
{
810
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
811
VtkUtils::SetInputData(mapper, getPolyData(WCoordinateSystem(scale)));
812
mapper->SetScalarModeToUsePointData();
813
814
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
815
actor->SetMapper(mapper);
816
817
WidgetAccessor::setProp(*this, actor);
818
}
819
820
cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const Color &color)
821
{
822
double f_x = K(0,0), f_y = K(1,1), c_y = K(1,2);
823
824
// Assuming that this is an ideal camera (c_y and c_x are at the center of the image)
825
double fovy = 2.0 * atan2(c_y, f_y) * 180 / CV_PI;
826
double aspect_ratio = f_y / f_x;
827
828
vtkSmartPointer<vtkPolyData> polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
829
VtkUtils::FillScalars(polydata, color);
830
831
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
832
VtkUtils::SetInputData(mapper, polydata);
833
834
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
835
actor->SetMapper(mapper);
836
837
WidgetAccessor::setProp(*this, actor);
838
}
839
840
cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color)
841
{
842
double aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5);
843
double fovy = fov[1] * 180 / CV_PI;
844
845
vtkSmartPointer<vtkPolyData> polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
846
VtkUtils::FillScalars(polydata, color);
847
848
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
849
VtkUtils::SetInputData(mapper, polydata);
850
851
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
852
actor->SetMapper(mapper);
853
854
WidgetAccessor::setProp(*this, actor);
855
}
856
857
cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, InputArray _image, double scale, const Color &color)
858
{
859
CV_Assert(!_image.empty() && _image.depth() == CV_8U);
860
Mat image = CameraPositionUtils::ensureColorImage(_image);
861
image.at<Vec3b>(0, 0) = Vec3d(color.val); //workaround of VTK limitation
862
863
double f_y = K(1,1), c_y = K(1,2);
864
// Assuming that this is an ideal camera (c_y and c_x are at the center of the image)
865
double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI;
866
double far_end_height = 2.00 * c_y * scale / f_y;
867
double aspect_ratio = image.cols/(double)image.rows;
868
double image_scale = far_end_height/image.rows;
869
870
WImage3D image_widget(image, Size2d(image.size()) * image_scale);
871
image_widget.applyTransform(Affine3d().translate(Vec3d(0, 0, scale)));
872
vtkSmartPointer<vtkPolyData> plane = getPolyData(image_widget);
873
874
vtkSmartPointer<vtkPolyData> frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
875
876
// Frustum needs to be textured or else it can't be combined with image
877
vtkSmartPointer<vtkTextureMapToPlane> frustum_texture = vtkSmartPointer<vtkTextureMapToPlane>::New();
878
VtkUtils::SetInputData(frustum_texture, frustum);
879
frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel
880
frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color
881
882
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
883
append_filter->AddInputConnection(frustum_texture->GetOutputPort());
884
VtkUtils::AddInputData(append_filter, plane);
885
886
vtkSmartPointer<vtkActor> actor = getActor(image_widget);
887
actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort());
888
WidgetAccessor::setProp(*this, actor);
889
}
890
891
cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, InputArray _image, double scale, const Color &color)
892
{
893
CV_Assert(!_image.empty() && _image.depth() == CV_8U);
894
Mat image = CameraPositionUtils::ensureColorImage(_image);
895
image.at<Vec3b>(0, 0) = Vec3d(color.val); //workaround of VTK limitation
896
897
double fovy = fov[1] * 180.0 / CV_PI;
898
double far_end_height = 2.0 * scale * tan(fov[1] * 0.5);
899
double aspect_ratio = image.cols/(double)image.rows;
900
double image_scale = far_end_height/image.rows;
901
902
WImage3D image_widget(image, Size2d(image.size()) * image_scale);
903
image_widget.applyTransform(Affine3d().translate(Vec3d(0, 0, scale)));
904
vtkSmartPointer<vtkPolyData> plane = getPolyData(image_widget);
905
906
vtkSmartPointer<vtkPolyData> frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
907
908
// Frustum needs to be textured or else it can't be combined with image
909
vtkSmartPointer<vtkTextureMapToPlane> frustum_texture = vtkSmartPointer<vtkTextureMapToPlane>::New();
910
VtkUtils::SetInputData(frustum_texture, frustum);
911
frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel
912
frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color
913
914
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
915
append_filter->AddInputConnection(frustum_texture->GetOutputPort());
916
VtkUtils::AddInputData(append_filter, plane);
917
918
vtkSmartPointer<vtkActor> actor = getActor(image_widget);
919
actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort());
920
WidgetAccessor::setProp(*this, actor);
921
}
922
923
template<> cv::viz::WCameraPosition cv::viz::Widget::cast<cv::viz::WCameraPosition>()
924
{
925
Widget3D widget = this->cast<Widget3D>();
926
return static_cast<WCameraPosition&>(widget);
927
}
928
929
///////////////////////////////////////////////////////////////////////////////////////////////
930
/// trajectory widget implementation
931
932
cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double scale, const Color &color)
933
{
934
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
935
936
// Bitwise and with 3 in order to limit the domain to 2 bits
937
if (display_mode & WTrajectory::PATH)
938
{
939
Mat points = vtkTrajectorySource::ExtractPoints(_path);
940
vtkSmartPointer<vtkPolyData> polydata = getPolyData(WPolyLine(points, color));
941
VtkUtils::AddInputData(append_filter, polydata);
942
}
943
944
if (display_mode & WTrajectory::FRAMES)
945
{
946
vtkSmartPointer<vtkTrajectorySource> source = vtkSmartPointer<vtkTrajectorySource>::New();
947
source->SetTrajectory(_path);
948
949
vtkSmartPointer<vtkPolyData> glyph = getPolyData(WCoordinateSystem(scale));
950
951
vtkSmartPointer<vtkTensorGlyph> tensor_glyph = vtkSmartPointer<vtkTensorGlyph>::New();
952
tensor_glyph->SetInputConnection(source->GetOutputPort());
953
VtkUtils::SetSourceData(tensor_glyph, glyph);
954
tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues
955
tensor_glyph->ThreeGlyphsOff();
956
tensor_glyph->SymmetricOff();
957
tensor_glyph->ColorGlyphsOff();
958
959
append_filter->AddInputConnection(tensor_glyph->GetOutputPort());
960
}
961
append_filter->Update();
962
963
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
964
VtkUtils::SetInputData(mapper, append_filter->GetOutput());
965
mapper->SetScalarModeToUsePointData();
966
mapper->SetScalarRange(0, 255);
967
968
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
969
actor->SetMapper(mapper);
970
971
WidgetAccessor::setProp(*this, actor);
972
}
973
974
template<> cv::viz::WTrajectory cv::viz::Widget::cast<cv::viz::WTrajectory>()
975
{
976
Widget3D widget = this->cast<Widget3D>();
977
return static_cast<WTrajectory&>(widget);
978
}
979
980
///////////////////////////////////////////////////////////////////////////////////////////////
981
/// WTrajectoryFrustums widget implementation
982
983
cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33d &K, double scale, const Color &color)
984
{
985
vtkSmartPointer<vtkTrajectorySource> source = vtkSmartPointer<vtkTrajectorySource>::New();
986
source->SetTrajectory(_path);
987
988
vtkSmartPointer<vtkPolyData> glyph = getPolyData(WCameraPosition(K, scale));
989
VtkUtils::FillScalars(glyph, color);
990
991
vtkSmartPointer<vtkTensorGlyph> tensor_glyph = vtkSmartPointer<vtkTensorGlyph>::New();
992
tensor_glyph->SetInputConnection(source->GetOutputPort());
993
VtkUtils::SetSourceData(tensor_glyph, glyph);
994
tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues
995
tensor_glyph->ThreeGlyphsOff();
996
tensor_glyph->SymmetricOff();
997
tensor_glyph->ColorGlyphsOff();
998
tensor_glyph->Update();
999
1000
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
1001
VtkUtils::SetInputData(mapper, tensor_glyph->GetOutput());
1002
1003
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
1004
actor->SetMapper(mapper);
1005
1006
WidgetAccessor::setProp(*this, actor);
1007
}
1008
1009
cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d &fov, double scale, const Color &color)
1010
{
1011
vtkSmartPointer<vtkTrajectorySource> source = vtkSmartPointer<vtkTrajectorySource>::New();
1012
source->SetTrajectory(_path);
1013
1014
vtkSmartPointer<vtkPolyData> glyph = getPolyData(WCameraPosition(fov, scale));
1015
VtkUtils::FillScalars(glyph, color);
1016
1017
vtkSmartPointer<vtkTensorGlyph> tensor_glyph = vtkSmartPointer<vtkTensorGlyph>::New();
1018
tensor_glyph->SetInputConnection(source->GetOutputPort());
1019
VtkUtils::SetSourceData(tensor_glyph, glyph);
1020
tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues
1021
tensor_glyph->ThreeGlyphsOff();
1022
tensor_glyph->SymmetricOff();
1023
tensor_glyph->ColorGlyphsOff();
1024
tensor_glyph->Update();
1025
1026
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
1027
VtkUtils::SetInputData(mapper, tensor_glyph->GetOutput());
1028
1029
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
1030
actor->SetMapper(mapper);
1031
1032
WidgetAccessor::setProp(*this, actor);
1033
}
1034
1035
template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast<cv::viz::WTrajectoryFrustums>()
1036
{
1037
Widget3D widget = this->cast<Widget3D>();
1038
return static_cast<WTrajectoryFrustums&>(widget);
1039
}
1040
1041
///////////////////////////////////////////////////////////////////////////////////////////////
1042
/// WTrajectorySpheres widget implementation
1043
1044
cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_length, double radius, const Color &from, const Color &to)
1045
{
1046
CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT);
1047
CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16));
1048
1049
Mat path64;
1050
_path.getMat().convertTo(path64, CV_64F);
1051
Affine3d *traj = path64.ptr<Affine3d>();
1052
size_t total = path64.total();
1053
1054
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
1055
1056
for(size_t i = 0; i < total; ++i)
1057
{
1058
Vec3d curr = traj[i].translation();
1059
1060
vtkSmartPointer<vtkSphereSource> sphere_source = vtkSmartPointer<vtkSphereSource>::New();
1061
sphere_source->SetCenter(curr.val);
1062
sphere_source->SetRadius( (i == 0) ? 2 * radius : radius );
1063
sphere_source->Update();
1064
1065
double alpha = static_cast<double>(i)/total;
1066
Color c = from * (1 - alpha) + to * alpha;
1067
1068
vtkSmartPointer<vtkPolyData> polydata = sphere_source->GetOutput();
1069
polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c));
1070
VtkUtils::AddInputData(append_filter, polydata);
1071
1072
if (i > 0)
1073
{
1074
Vec3d prev = traj[i-1].translation();
1075
Vec3d lvec = prev - curr;
1076
1077
if(norm(lvec) > line_length)
1078
lvec = normalize(lvec) * line_length;
1079
1080
Vec3d lend = curr + lvec;
1081
1082
vtkSmartPointer<vtkLineSource> line_source = vtkSmartPointer<vtkLineSource>::New();
1083
line_source->SetPoint1(curr.val);
1084
line_source->SetPoint2(lend.val);
1085
line_source->Update();
1086
vtkSmartPointer<vtkPolyData> polydata_ = line_source->GetOutput();
1087
polydata_->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata_->GetNumberOfCells(), c));
1088
VtkUtils::AddInputData(append_filter, polydata_);
1089
}
1090
}
1091
append_filter->Update();
1092
1093
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
1094
mapper->SetScalarModeToUseCellData();
1095
VtkUtils::SetInputData(mapper, append_filter->GetOutput());
1096
1097
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
1098
actor->SetMapper(mapper);
1099
1100
WidgetAccessor::setProp(*this, actor);
1101
}
1102
1103
template<> cv::viz::WTrajectorySpheres cv::viz::Widget::cast<cv::viz::WTrajectorySpheres>()
1104
{
1105
Widget3D widget = this->cast<Widget3D>();
1106
return static_cast<WTrajectorySpheres&>(widget);
1107
}
1108
1109