2013-09-08 21:20:02 +08:00
|
|
|
/*M///////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
|
|
|
//
|
|
|
|
// By downloading, copying, installing or using the software you agree to this license.
|
|
|
|
// If you do not agree to this license, do not download, install,
|
|
|
|
// copy or use the software.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// License Agreement
|
|
|
|
// For Open Source Computer Vision Library
|
|
|
|
//
|
|
|
|
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
|
|
|
// Third party copyrights are property of their respective owners.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
// are permitted provided that the following conditions are met:
|
|
|
|
//
|
|
|
|
// * Redistribution's of source code must retain the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer.
|
|
|
|
//
|
|
|
|
// * Redistribution's in binary form must reproduce the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
|
|
// and/or other materials provided with the distribution.
|
|
|
|
//
|
|
|
|
// * The name of the copyright holders may not be used to endorse or promote products
|
|
|
|
// derived from this software without specific prior written permission.
|
|
|
|
//
|
|
|
|
// This software is provided by the copyright holders and contributors "as is" and
|
|
|
|
// any express or implied warranties, including, but not limited to, the implied
|
|
|
|
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
|
|
|
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
|
|
|
// indirect, incidental, special, exemplary, or consequential damages
|
|
|
|
// (including, but not limited to, procurement of substitute goods or services;
|
|
|
|
// loss of use, data, or profits; or business interruption) however caused
|
|
|
|
// and on any theory of liability, whether in contract, strict liability,
|
|
|
|
// or tort (including negligence or otherwise) arising in any way out of
|
|
|
|
// the use of this software, even if advised of the possibility of such damage.
|
|
|
|
//
|
|
|
|
// Authors:
|
|
|
|
// * Ozan Tonkal, ozantonkal@gmail.com
|
|
|
|
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
|
|
|
//
|
|
|
|
//M*/
|
|
|
|
|
2013-07-04 17:54:00 +08:00
|
|
|
#include "precomp.hpp"
|
|
|
|
|
2013-07-04 21:15:20 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// line widget implementation
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color)
|
2013-09-18 19:50:55 +08:00
|
|
|
{
|
2013-07-04 17:54:00 +08:00
|
|
|
vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New();
|
2013-09-08 21:20:02 +08:00
|
|
|
line->SetPoint1(pt1.x, pt1.y, pt1.z);
|
|
|
|
line->SetPoint2(pt2.x, pt2.y, pt2.z);
|
2014-01-08 21:16:25 +08:00
|
|
|
line->Update();
|
2013-07-04 17:54:00 +08:00
|
|
|
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, line->GetOutput());
|
2013-07-04 17:54:00 +08:00
|
|
|
|
2013-12-09 00:58:55 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2013-07-04 17:54:00 +08:00
|
|
|
actor->SetMapper(mapper);
|
|
|
|
|
2013-07-09 21:18:44 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-04 17:54:00 +08:00
|
|
|
setColor(color);
|
|
|
|
}
|
2013-07-04 21:05:05 +08:00
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WLine cv::viz::Widget::cast<cv::viz::WLine>()
|
2013-07-10 00:02:43 +08:00
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WLine&>(widget);
|
2013-07-10 00:02:43 +08:00
|
|
|
}
|
|
|
|
|
2014-01-08 23:43:20 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// sphere widget implementation
|
|
|
|
|
|
|
|
cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resolution, const Color &color)
|
|
|
|
{
|
|
|
|
vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
|
|
|
|
sphere->SetRadius(radius);
|
|
|
|
sphere->SetCenter(center.x, center.y, center.z);
|
|
|
|
sphere->SetPhiResolution(sphere_resolution);
|
|
|
|
sphere->SetThetaResolution(sphere_resolution);
|
|
|
|
sphere->LatLongTessellationOff();
|
|
|
|
sphere->Update();
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
|
|
|
VtkUtils::SetInputData(mapper, sphere->GetOutput());
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
|
|
|
|
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
setColor(color);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<> cv::viz::WSphere cv::viz::Widget::cast<cv::viz::WSphere>()
|
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
|
|
|
return static_cast<WSphere&>(widget);
|
|
|
|
}
|
|
|
|
|
2013-07-04 21:15:20 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// plane widget implementation
|
|
|
|
|
2013-12-01 19:25:44 +08:00
|
|
|
namespace cv { namespace viz { namespace
|
2013-07-22 20:34:44 +08:00
|
|
|
{
|
2013-12-01 19:25:44 +08:00
|
|
|
struct PlaneUtils
|
2013-07-22 20:34:44 +08:00
|
|
|
{
|
2013-12-01 19:25:44 +08:00
|
|
|
template<typename _Tp>
|
|
|
|
static vtkSmartPointer<vtkTransformPolyDataFilter> setSize(const Vec<_Tp, 3> ¢er, vtkSmartPointer<vtkAlgorithmOutput> poly_data_port, double size)
|
|
|
|
{
|
|
|
|
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
|
|
|
|
transform->PreMultiply();
|
|
|
|
transform->Translate(center[0], center[1], center[2]);
|
|
|
|
transform->Scale(size, size, size);
|
|
|
|
transform->Translate(-center[0], -center[1], -center[2]);
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
|
|
|
|
transform_filter->SetInputConnection(poly_data_port);
|
|
|
|
transform_filter->SetTransform(transform);
|
|
|
|
transform_filter->Update();
|
|
|
|
|
|
|
|
return transform_filter;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}}}
|
2013-07-22 20:34:44 +08:00
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WPlane::WPlane(const Vec4d& coefs, double size, const Color &color)
|
2013-09-18 19:50:55 +08:00
|
|
|
{
|
2013-09-08 21:20:02 +08:00
|
|
|
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
|
|
|
|
plane->SetNormal(coefs[0], coefs[1], coefs[2]);
|
2014-01-08 01:27:11 +08:00
|
|
|
double norm = cv::norm(Vec3d(coefs.val));
|
2013-09-08 21:20:02 +08:00
|
|
|
plane->Push(-coefs[3] / norm);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 20:34:44 +08:00
|
|
|
Vec3d p_center;
|
|
|
|
plane->GetOrigin(p_center.val);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2013-12-01 19:25:44 +08:00
|
|
|
mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-09 00:58:55 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2013-07-04 21:15:20 +08:00
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-09 21:18:44 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-04 21:15:20 +08:00
|
|
|
setColor(color);
|
|
|
|
}
|
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WPlane::WPlane(const Vec4d& coefs, const Point3d& pt, double size, const Color &color)
|
2013-07-04 21:15:20 +08:00
|
|
|
{
|
2013-09-08 21:20:02 +08:00
|
|
|
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
|
2014-01-08 01:27:11 +08:00
|
|
|
Point3d coefs3(coefs[0], coefs[1], coefs[2]);
|
2013-09-08 21:20:02 +08:00
|
|
|
double norm_sqr = 1.0 / coefs3.dot(coefs3);
|
2013-07-04 21:15:20 +08:00
|
|
|
plane->SetNormal(coefs[0], coefs[1], coefs[2]);
|
|
|
|
|
|
|
|
double t = coefs3.dot(pt) + coefs[3];
|
2014-01-08 01:27:11 +08:00
|
|
|
Vec3d p_center = pt - coefs3 * t * norm_sqr;
|
2013-09-08 21:20:02 +08:00
|
|
|
plane->SetCenter(p_center[0], p_center[1], p_center[2]);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2013-12-01 19:25:44 +08:00
|
|
|
mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort());
|
2013-07-04 21:15:20 +08:00
|
|
|
|
2013-12-09 00:58:55 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2013-07-04 21:15:20 +08:00
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-09 21:18:44 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-04 21:32:06 +08:00
|
|
|
setColor(color);
|
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WPlane cv::viz::Widget::cast<cv::viz::WPlane>()
|
2013-07-09 20:12:49 +08:00
|
|
|
{
|
2013-07-10 15:55:42 +08:00
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WPlane&>(widget);
|
2013-07-09 20:12:49 +08:00
|
|
|
}
|
|
|
|
|
2013-07-04 21:54:46 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// arrow widget implementation
|
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness, const Color &color)
|
2013-07-04 21:54:46 +08:00
|
|
|
{
|
2014-01-08 23:43:20 +08:00
|
|
|
vtkSmartPointer<vtkArrowSource> arrow_source = vtkSmartPointer<vtkArrowSource>::New();
|
|
|
|
arrow_source->SetShaftRadius(thickness);
|
|
|
|
arrow_source->SetTipRadius(thickness * 3.0);
|
|
|
|
arrow_source->SetTipLength(thickness * 10.0);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-12 03:29:28 +08:00
|
|
|
Vec3d arbitrary = get_random_vec();
|
|
|
|
Vec3d start_point(pt1.x, pt1.y, pt1.z), end_point(pt2.x, pt2.y, pt2.z);
|
2014-01-07 18:51:32 +08:00
|
|
|
|
2014-01-12 03:29:28 +08:00
|
|
|
double length = norm(end_point - start_point);
|
2013-12-13 03:46:41 +08:00
|
|
|
|
2014-01-12 03:29:28 +08:00
|
|
|
Vec3d xvec = normalized(end_point - start_point);
|
2014-01-07 18:51:32 +08:00
|
|
|
Vec3d zvec = normalized(xvec.cross(arbitrary));
|
|
|
|
Vec3d yvec = zvec.cross(xvec);
|
2013-07-04 21:54:46 +08:00
|
|
|
|
2014-01-12 03:07:30 +08:00
|
|
|
Matx33d R = makeTransformToGlobal(xvec, yvec, zvec).rotation();
|
2014-01-12 03:29:28 +08:00
|
|
|
Affine3d transform_with_scale(R * length, start_point);
|
2013-07-04 21:54:46 +08:00
|
|
|
|
2014-01-12 03:07:30 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> polydata = VtkUtils::TransformPolydata(arrow_source->GetOutputPort(), transform_with_scale);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-12 03:07:30 +08:00
|
|
|
VtkUtils::SetInputData(mapper, polydata);
|
2013-07-04 21:54:46 +08:00
|
|
|
|
2013-12-09 00:58:55 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2013-07-04 21:54:46 +08:00
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-09 21:18:44 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-04 21:54:46 +08:00
|
|
|
setColor(color);
|
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WArrow cv::viz::Widget::cast<cv::viz::WArrow>()
|
2013-07-09 20:12:49 +08:00
|
|
|
{
|
2013-07-10 15:55:42 +08:00
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WArrow&>(widget);
|
2013-07-09 20:12:49 +08:00
|
|
|
}
|
|
|
|
|
2013-07-04 21:54:46 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// circle widget implementation
|
|
|
|
|
2014-01-12 03:29:28 +08:00
|
|
|
cv::viz::WCircle::WCircle(double radius, double thickness, const Color &color)
|
2013-07-04 21:54:46 +08:00
|
|
|
{
|
2013-09-08 21:20:02 +08:00
|
|
|
vtkSmartPointer<vtkDiskSource> disk = vtkSmartPointer<vtkDiskSource>::New();
|
2014-01-12 03:29:28 +08:00
|
|
|
disk->SetCircumferentialResolution(30);
|
2013-09-08 21:20:02 +08:00
|
|
|
disk->SetInnerRadius(radius - thickness);
|
|
|
|
disk->SetOuterRadius(radius + thickness);
|
2014-01-12 03:29:28 +08:00
|
|
|
disk->Update();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-12 03:29:28 +08:00
|
|
|
VtkUtils::SetInputData(mapper, disk->GetOutput());
|
2013-07-04 21:54:46 +08:00
|
|
|
|
2013-12-09 00:58:55 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2014-01-12 03:29:28 +08:00
|
|
|
actor->GetProperty()->LightingOff();
|
2013-07-04 21:54:46 +08:00
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-09 21:18:44 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-04 21:54:46 +08:00
|
|
|
setColor(color);
|
2014-01-12 03:29:28 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::viz::WCircle::WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness, const Color &color)
|
|
|
|
{
|
|
|
|
Vec3d arbitrary = get_random_vec();
|
|
|
|
Vec3d zvec = normalized(normal);
|
|
|
|
Vec3d xvec = normalized(zvec.cross(arbitrary));
|
|
|
|
Vec3d yvec = zvec.cross(xvec);
|
|
|
|
|
|
|
|
WCircle circle(radius, thickness, color);
|
|
|
|
circle.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center));
|
|
|
|
*this = circle;
|
2013-07-04 21:54:46 +08:00
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WCircle cv::viz::Widget::cast<cv::viz::WCircle>()
|
2013-07-09 20:12:49 +08:00
|
|
|
{
|
2013-07-10 15:55:42 +08:00
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WCircle&>(widget);
|
2013-07-09 20:12:49 +08:00
|
|
|
}
|
|
|
|
|
2013-07-04 22:44:41 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// cylinder widget implementation
|
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WCylinder::WCylinder(const Point3d& pt_on_axis, const Point3d& axis_direction, double radius, int numsides, const Color &color)
|
2013-09-18 19:50:55 +08:00
|
|
|
{
|
2014-01-08 01:27:11 +08:00
|
|
|
const Point3d pt2 = pt_on_axis + axis_direction;
|
2013-09-08 21:20:02 +08:00
|
|
|
vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New();
|
|
|
|
line->SetPoint1(pt_on_axis.x, pt_on_axis.y, pt_on_axis.z);
|
|
|
|
line->SetPoint2(pt2.x, pt2.y, pt2.z);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-09-08 21:20:02 +08:00
|
|
|
vtkSmartPointer<vtkTubeFilter> tuber = vtkSmartPointer<vtkTubeFilter>::New();
|
|
|
|
tuber->SetInputConnection(line->GetOutputPort());
|
|
|
|
tuber->SetRadius(radius);
|
|
|
|
tuber->SetNumberOfSides(numsides);
|
2014-01-08 21:16:25 +08:00
|
|
|
tuber->Update();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, tuber->GetOutput());
|
2013-07-04 22:44:41 +08:00
|
|
|
|
2013-12-09 00:58:55 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2013-07-04 22:44:41 +08:00
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-09 21:18:44 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-04 22:44:41 +08:00
|
|
|
setColor(color);
|
|
|
|
}
|
2013-07-04 22:59:11 +08:00
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WCylinder cv::viz::Widget::cast<cv::viz::WCylinder>()
|
2013-07-09 20:12:49 +08:00
|
|
|
{
|
2013-07-10 15:55:42 +08:00
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WCylinder&>(widget);
|
2013-07-09 20:12:49 +08:00
|
|
|
}
|
|
|
|
|
2013-07-04 22:59:11 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// cylinder widget implementation
|
|
|
|
|
2014-01-10 23:57:16 +08:00
|
|
|
cv::viz::WCube::WCube(const Point3d& min_point, const Point3d& max_point, bool wire_frame, const Color &color)
|
2013-09-18 19:50:55 +08:00
|
|
|
{
|
2014-01-08 21:16:25 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataAlgorithm> cube;
|
2013-07-15 22:47:19 +08:00
|
|
|
if (wire_frame)
|
|
|
|
{
|
2014-01-08 21:16:25 +08:00
|
|
|
cube = vtkSmartPointer<vtkOutlineSource>::New();
|
2014-01-10 23:57:16 +08:00
|
|
|
vtkOutlineSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z);
|
2013-07-15 22:47:19 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-01-08 21:16:25 +08:00
|
|
|
cube = vtkSmartPointer<vtkCubeSource>::New();
|
2014-01-10 23:57:16 +08:00
|
|
|
vtkCubeSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z);
|
2013-07-15 22:47:19 +08:00
|
|
|
}
|
2014-01-08 21:16:25 +08:00
|
|
|
cube->Update();
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
|
|
|
VtkUtils::SetInputData(mapper, cube->GetOutput());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-09 00:58:55 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2013-07-04 22:59:11 +08:00
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-09 21:18:44 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-04 22:59:11 +08:00
|
|
|
setColor(color);
|
|
|
|
}
|
2013-07-04 23:19:06 +08:00
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WCube cv::viz::Widget::cast<cv::viz::WCube>()
|
2013-07-09 20:12:49 +08:00
|
|
|
{
|
2013-07-10 15:55:42 +08:00
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WCube&>(widget);
|
2013-07-09 20:12:49 +08:00
|
|
|
}
|
|
|
|
|
2013-07-04 23:19:06 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// coordinate system widget implementation
|
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WCoordinateSystem::WCoordinateSystem(double scale)
|
2013-07-04 23:19:06 +08:00
|
|
|
{
|
2013-09-08 21:20:02 +08:00
|
|
|
vtkSmartPointer<vtkAxes> axes = vtkSmartPointer<vtkAxes>::New();
|
|
|
|
axes->SetOrigin(0, 0, 0);
|
|
|
|
axes->SetScaleFactor(scale);
|
2013-09-09 00:55:41 +08:00
|
|
|
axes->Update();
|
2014-01-08 01:28:29 +08:00
|
|
|
|
|
|
|
vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
|
|
|
|
colors->SetNumberOfComponents(3);
|
|
|
|
colors->InsertNextTuple3(255, 0, 0);
|
|
|
|
colors->InsertNextTuple3(255, 0, 0);
|
|
|
|
colors->InsertNextTuple3(0, 255, 0);
|
|
|
|
colors->InsertNextTuple3(0, 255, 0);
|
|
|
|
colors->InsertNextTuple3(0, 0, 255);
|
|
|
|
colors->InsertNextTuple3(0, 0, 255);
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkPolyData> polydata = axes->GetOutput();
|
|
|
|
polydata->GetPointData()->SetScalars(colors);
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkTubeFilter> tube_filter = vtkSmartPointer<vtkTubeFilter>::New();
|
2014-01-08 02:59:40 +08:00
|
|
|
tube_filter->SetInputConnection(polydata->GetProducerPort());
|
2014-01-08 01:28:29 +08:00
|
|
|
tube_filter->SetRadius(axes->GetScaleFactor() / 50.0);
|
|
|
|
tube_filter->SetNumberOfSides(6);
|
2014-01-08 21:16:25 +08:00
|
|
|
tube_filter->Update();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2013-09-08 21:20:02 +08:00
|
|
|
mapper->SetScalarModeToUsePointData();
|
2014-01-08 01:28:29 +08:00
|
|
|
VtkUtils::SetInputData(mapper, tube_filter->GetOutput());
|
2013-07-04 23:19:06 +08:00
|
|
|
|
2013-12-09 00:58:55 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2013-07-04 23:19:06 +08:00
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-09 21:18:44 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-04 23:19:06 +08:00
|
|
|
}
|
2013-07-08 16:41:42 +08:00
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WCoordinateSystem cv::viz::Widget::cast<cv::viz::WCoordinateSystem>()
|
2013-07-09 20:12:49 +08:00
|
|
|
{
|
2013-07-10 15:55:42 +08:00
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WCoordinateSystem&>(widget);
|
2013-07-09 20:12:49 +08:00
|
|
|
}
|
|
|
|
|
2013-07-10 18:51:17 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// polyline widget implementation
|
|
|
|
|
2014-01-07 22:18:06 +08:00
|
|
|
cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color)
|
2013-09-18 19:50:55 +08:00
|
|
|
{
|
2014-01-07 22:18:06 +08:00
|
|
|
CV_Assert(_points.type() == CV_32FC3 || _points.type() == CV_32FC4 || _points.type() == CV_64FC3 || _points.type() == CV_64FC4);
|
2013-07-10 18:51:17 +08:00
|
|
|
|
2014-01-07 22:18:06 +08:00
|
|
|
const float *fpoints = _points.getMat().ptr<float>();
|
|
|
|
const double *dpoints = _points.getMat().ptr<double>();
|
|
|
|
size_t total = _points.total();
|
|
|
|
int s_chs = _points.channels();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-09-08 21:20:02 +08:00
|
|
|
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
|
2014-01-07 22:18:06 +08:00
|
|
|
points->SetDataType(_points.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE);
|
|
|
|
points->SetNumberOfPoints(total);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-07 22:18:06 +08:00
|
|
|
if (_points.depth() == CV_32F)
|
|
|
|
for(size_t i = 0; i < total; ++i, fpoints += s_chs)
|
|
|
|
points->SetPoint(i, fpoints);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-07 22:18:06 +08:00
|
|
|
if (_points.depth() == CV_64F)
|
|
|
|
for(size_t i = 0; i < total; ++i, dpoints += s_chs)
|
|
|
|
points->SetPoint(i, dpoints);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-07 22:18:06 +08:00
|
|
|
vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New();
|
|
|
|
cell_array->Allocate(cell_array->EstimateSize(1, total));
|
|
|
|
cell_array->InsertNextCell(total);
|
|
|
|
for(size_t i = 0; i < total; ++i)
|
|
|
|
cell_array->InsertCellPoint(i);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 01:48:32 +08:00
|
|
|
vtkSmartPointer<vtkUnsignedCharArray> scalars = VtkUtils::FillScalars(total, color);
|
2014-01-08 01:32:54 +08:00
|
|
|
|
2014-01-07 22:18:06 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
|
|
|
|
polydata->SetPoints(points);
|
|
|
|
polydata->SetLines(cell_array);
|
2014-01-08 01:32:54 +08:00
|
|
|
polydata->GetPointData()->SetScalars(scalars);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 18:51:17 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, polydata);
|
2014-01-08 01:32:54 +08:00
|
|
|
mapper->SetScalarRange(0, 255);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 18:51:17 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 18:51:17 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WPolyLine cv::viz::Widget::cast<cv::viz::WPolyLine>()
|
2013-07-10 18:51:17 +08:00
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WPolyLine&>(widget);
|
2013-07-10 18:51:17 +08:00
|
|
|
}
|
|
|
|
|
2013-07-10 21:34:19 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// grid widget implementation
|
|
|
|
|
2013-12-01 19:25:44 +08:00
|
|
|
namespace cv { namespace viz { namespace
|
2013-07-24 16:13:01 +08:00
|
|
|
{
|
2013-12-01 19:25:44 +08:00
|
|
|
struct GridUtils
|
2013-07-24 16:13:01 +08:00
|
|
|
{
|
2014-01-01 21:55:18 +08:00
|
|
|
static vtkSmartPointer<vtkPolyData> createGrid(const Vec2i &dimensions, const Vec2f &spacing)
|
2013-12-01 19:25:44 +08:00
|
|
|
{
|
|
|
|
// Create the grid using image data
|
|
|
|
vtkSmartPointer<vtkImageData> grid = vtkSmartPointer<vtkImageData>::New();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-01 19:25:44 +08:00
|
|
|
// Add 1 to dimensions because in ImageData dimensions is the number of lines
|
|
|
|
// - however here it means number of cells
|
|
|
|
grid->SetDimensions(dimensions[0]+1, dimensions[1]+1, 1);
|
|
|
|
grid->SetSpacing(spacing[0], spacing[1], 0.);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-01 19:25:44 +08:00
|
|
|
// Set origin of the grid to be the middle of the grid
|
|
|
|
grid->SetOrigin(dimensions[0] * spacing[0] * (-0.5), dimensions[1] * spacing[1] * (-0.5), 0);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-01 19:25:44 +08:00
|
|
|
// Extract the edges so we have the grid
|
|
|
|
vtkSmartPointer<vtkExtractEdges> filter = vtkSmartPointer<vtkExtractEdges>::New();
|
|
|
|
filter->SetInputConnection(grid->GetProducerPort());
|
|
|
|
filter->Update();
|
|
|
|
return filter->GetOutput();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}}}
|
2013-07-24 16:13:01 +08:00
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color)
|
2013-07-10 21:34:19 +08:00
|
|
|
{
|
2013-12-01 19:25:44 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> grid = GridUtils::createGrid(dimensions, spacing);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, grid);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-24 16:02:33 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-24 16:02:33 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
setColor(color);
|
|
|
|
}
|
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WGrid::WGrid(const Vec4d &coefs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color)
|
2013-07-24 16:02:33 +08:00
|
|
|
{
|
2013-12-01 19:25:44 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> grid = GridUtils::createGrid(dimensions, spacing);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-24 16:02:33 +08:00
|
|
|
// Estimate the transform to set the normal based on the coefficients
|
2014-01-07 18:51:32 +08:00
|
|
|
Vec3d normal(coefs[0], coefs[1], coefs[2]);
|
|
|
|
Vec3d up_vector(0.0, 1.0, 0.0); // Just set as default
|
2014-01-08 01:27:11 +08:00
|
|
|
double push_distance = -coefs[3]/cv::norm(Vec3d(coefs.val));
|
2014-01-07 18:51:32 +08:00
|
|
|
Vec3d n = normalize(normal);
|
|
|
|
Vec3d u = normalize(up_vector.cross(n));
|
|
|
|
Vec3d v = n.cross(u);
|
|
|
|
|
|
|
|
Affine3d pose = makeTransformToGlobal(u, v, n, n * push_distance);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-24 16:02:33 +08:00
|
|
|
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
|
|
|
|
transform->PreMultiply();
|
2014-01-07 18:51:32 +08:00
|
|
|
transform->SetMatrix(vtkmatrix(pose.matrix));
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-24 16:02:33 +08:00
|
|
|
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
|
|
|
|
transform_filter->SetTransform(transform);
|
2013-07-24 16:13:01 +08:00
|
|
|
transform_filter->SetInputConnection(grid->GetProducerPort());
|
2013-07-24 16:02:33 +08:00
|
|
|
transform_filter->Update();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, transform_filter->GetOutput());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 21:34:19 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 21:34:19 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-13 23:08:25 +08:00
|
|
|
setColor(color);
|
2013-07-10 21:34:19 +08:00
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WGrid cv::viz::Widget::cast<cv::viz::WGrid>()
|
2013-07-10 21:34:19 +08:00
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WGrid&>(widget);
|
2013-07-10 21:34:19 +08:00
|
|
|
}
|
|
|
|
|
2013-07-10 22:34:47 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// text3D widget implementation
|
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WText3D::WText3D(const String &text, const Point3d &position, double text_scale, bool face_camera, const Color &color)
|
2013-07-10 22:34:47 +08:00
|
|
|
{
|
2013-09-08 18:19:14 +08:00
|
|
|
vtkSmartPointer<vtkVectorText> textSource = vtkSmartPointer<vtkVectorText>::New();
|
|
|
|
textSource->SetText(text.c_str());
|
|
|
|
textSource->Update();
|
2013-07-10 22:34:47 +08:00
|
|
|
|
2013-09-08 18:19:14 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2013-09-08 21:20:02 +08:00
|
|
|
mapper->SetInputConnection(textSource->GetOutputPort());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-09-08 18:19:14 +08:00
|
|
|
if (face_camera)
|
|
|
|
{
|
|
|
|
vtkSmartPointer<vtkFollower> actor = vtkSmartPointer<vtkFollower>::New();
|
|
|
|
actor->SetMapper(mapper);
|
|
|
|
actor->SetPosition(position.x, position.y, position.z);
|
|
|
|
actor->SetScale(text_scale);
|
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
|
|
|
actor->SetPosition(position.x, position.y, position.z);
|
|
|
|
actor->SetScale(text_scale);
|
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 22:34:47 +08:00
|
|
|
setColor(color);
|
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
void cv::viz::WText3D::setText(const String &text)
|
2013-07-10 22:34:47 +08:00
|
|
|
{
|
|
|
|
vtkFollower *actor = vtkFollower::SafeDownCast(WidgetAccessor::getProp(*this));
|
2013-08-31 17:30:37 +08:00
|
|
|
CV_Assert("This widget does not support text." && actor);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 22:34:47 +08:00
|
|
|
// Update text source
|
|
|
|
vtkPolyDataMapper *mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
|
|
|
|
vtkVectorText * textSource = vtkVectorText::SafeDownCast(mapper->GetInputConnection(0,0)->GetProducer());
|
2013-08-31 17:30:37 +08:00
|
|
|
CV_Assert("This widget does not support text." && textSource);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 22:34:47 +08:00
|
|
|
textSource->SetText(text.c_str());
|
2014-01-08 21:16:25 +08:00
|
|
|
textSource->Modified();
|
2013-07-10 22:34:47 +08:00
|
|
|
textSource->Update();
|
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
cv::String cv::viz::WText3D::getText() const
|
2013-07-10 22:34:47 +08:00
|
|
|
{
|
|
|
|
vtkFollower *actor = vtkFollower::SafeDownCast(WidgetAccessor::getProp(*this));
|
2013-08-31 17:30:37 +08:00
|
|
|
CV_Assert("This widget does not support text." && actor);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 22:34:47 +08:00
|
|
|
vtkPolyDataMapper *mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
|
|
|
|
vtkVectorText * textSource = vtkVectorText::SafeDownCast(mapper->GetInputConnection(0,0)->GetProducer());
|
2013-08-31 17:30:37 +08:00
|
|
|
CV_Assert("This widget does not support text." && textSource);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-10 22:34:47 +08:00
|
|
|
return textSource->GetText();
|
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WText3D cv::viz::Widget::cast<cv::viz::WText3D>()
|
2013-07-10 22:34:47 +08:00
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WText3D&>(widget);
|
2013-07-10 22:34:47 +08:00
|
|
|
}
|
|
|
|
|
2013-07-08 21:12:50 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// text widget implementation
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
cv::viz::WText::WText(const String &text, const Point2i &pos, int font_size, const Color &color)
|
2013-07-08 16:41:42 +08:00
|
|
|
{
|
2013-07-09 21:18:44 +08:00
|
|
|
vtkSmartPointer<vtkTextActor> actor = vtkSmartPointer<vtkTextActor>::New();
|
2013-09-08 21:20:02 +08:00
|
|
|
actor->SetPosition(pos.x, pos.y);
|
|
|
|
actor->SetInput(text.c_str());
|
2013-07-08 16:41:42 +08:00
|
|
|
|
2013-09-08 21:20:02 +08:00
|
|
|
vtkSmartPointer<vtkTextProperty> tprop = actor->GetTextProperty();
|
|
|
|
tprop->SetFontSize(font_size);
|
|
|
|
tprop->SetFontFamilyToArial();
|
|
|
|
tprop->SetJustificationToLeft();
|
|
|
|
tprop->BoldOn();
|
2013-07-08 16:41:42 +08:00
|
|
|
|
|
|
|
Color c = vtkcolor(color);
|
2013-09-08 21:20:02 +08:00
|
|
|
tprop->SetColor(c.val);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-09 21:18:44 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
2013-07-08 16:41:42 +08:00
|
|
|
}
|
2013-07-08 21:12:50 +08:00
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WText cv::viz::Widget::cast<cv::viz::WText>()
|
2013-07-09 20:12:49 +08:00
|
|
|
{
|
2013-07-10 15:55:42 +08:00
|
|
|
Widget2D widget = this->cast<Widget2D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WText&>(widget);
|
2013-07-09 20:12:49 +08:00
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
void cv::viz::WText::setText(const String &text)
|
2013-07-09 21:18:44 +08:00
|
|
|
{
|
|
|
|
vtkTextActor *actor = vtkTextActor::SafeDownCast(WidgetAccessor::getProp(*this));
|
2013-08-31 17:30:37 +08:00
|
|
|
CV_Assert("This widget does not support text." && actor);
|
2013-07-09 21:18:44 +08:00
|
|
|
actor->SetInput(text.c_str());
|
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
cv::String cv::viz::WText::getText() const
|
2013-07-09 21:18:44 +08:00
|
|
|
{
|
|
|
|
vtkTextActor *actor = vtkTextActor::SafeDownCast(WidgetAccessor::getProp(*this));
|
2013-08-31 17:30:37 +08:00
|
|
|
CV_Assert("This widget does not support text." && actor);
|
2013-07-09 21:18:44 +08:00
|
|
|
return actor->GetInput();
|
|
|
|
}
|
2013-07-17 17:35:14 +08:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// image overlay widget implementation
|
|
|
|
|
2014-01-12 02:43:58 +08:00
|
|
|
cv::viz::WImageOverlay::WImageOverlay(InputArray image, const Rect &rect)
|
2013-07-17 17:35:14 +08:00
|
|
|
{
|
|
|
|
CV_Assert(!image.empty() && image.depth() == CV_8U);
|
2014-01-10 05:57:11 +08:00
|
|
|
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
|
|
|
|
source->SetImage(image);
|
2014-01-12 02:43:58 +08:00
|
|
|
Size sz = image.size();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-12 02:13:45 +08:00
|
|
|
// Scale the image based on the Rect, and flip to match y-ais orientation
|
2013-07-22 22:12:22 +08:00
|
|
|
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
|
2014-01-12 02:43:58 +08:00
|
|
|
transform->Scale(sz.width/(double)rect.width, sz.height/(double)rect.height, 1.0);
|
2014-01-12 02:13:45 +08:00
|
|
|
transform->RotateX(180);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 22:12:22 +08:00
|
|
|
vtkSmartPointer<vtkImageReslice> image_reslice = vtkSmartPointer<vtkImageReslice>::New();
|
|
|
|
image_reslice->SetResliceTransform(transform);
|
2014-01-12 02:13:45 +08:00
|
|
|
image_reslice->SetInputConnection(source->GetOutputPort());
|
2013-07-22 22:12:22 +08:00
|
|
|
image_reslice->SetOutputDimensionality(2);
|
|
|
|
image_reslice->InterpolateOn();
|
2013-09-18 19:50:55 +08:00
|
|
|
image_reslice->AutoCropOutputOn();
|
2014-01-10 05:57:11 +08:00
|
|
|
image_reslice->Update();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-10 04:31:27 +08:00
|
|
|
vtkSmartPointer<vtkImageMapper> image_mapper = vtkSmartPointer<vtkImageMapper>::New();
|
|
|
|
image_mapper->SetInputConnection(image_reslice->GetOutputPort());
|
|
|
|
image_mapper->SetColorWindow(255); // OpenCV color
|
|
|
|
image_mapper->SetColorLevel(127.5);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-17 17:35:14 +08:00
|
|
|
vtkSmartPointer<vtkActor2D> actor = vtkSmartPointer<vtkActor2D>::New();
|
2014-01-10 04:31:27 +08:00
|
|
|
actor->SetMapper(image_mapper);
|
2013-07-22 22:12:22 +08:00
|
|
|
actor->SetPosition(rect.x, rect.y);
|
2014-01-12 02:43:58 +08:00
|
|
|
actor->GetProperty()->SetDisplayLocationToForeground();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-17 17:35:14 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
|
|
|
|
2014-01-12 02:43:58 +08:00
|
|
|
void cv::viz::WImageOverlay::setImage(InputArray image)
|
2013-07-17 17:35:14 +08:00
|
|
|
{
|
|
|
|
CV_Assert(!image.empty() && image.depth() == CV_8U);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-17 17:35:14 +08:00
|
|
|
vtkActor2D *actor = vtkActor2D::SafeDownCast(WidgetAccessor::getProp(*this));
|
2013-08-31 17:30:37 +08:00
|
|
|
CV_Assert("This widget does not support overlay image." && actor);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-17 17:35:14 +08:00
|
|
|
vtkImageMapper *mapper = vtkImageMapper::SafeDownCast(actor->GetMapper());
|
2013-08-31 17:30:37 +08:00
|
|
|
CV_Assert("This widget does not support overlay image." && mapper);
|
2014-01-12 02:13:45 +08:00
|
|
|
\
|
|
|
|
Vec6i extent;
|
|
|
|
mapper->GetInput()->GetExtent(extent.val);
|
|
|
|
Size size(extent[1], extent[3]);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-17 17:35:14 +08:00
|
|
|
// Create the vtk image and set its parameters based on input image
|
2014-01-10 05:57:11 +08:00
|
|
|
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
|
|
|
|
source->SetImage(image);
|
2014-01-12 02:43:58 +08:00
|
|
|
Size sz = image.size();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-12 02:13:45 +08:00
|
|
|
// Scale the image based on the Rect, and flip to match y-ais orientation
|
|
|
|
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
|
2014-01-12 02:43:58 +08:00
|
|
|
transform->Scale(sz.width/(double)size.width, sz.height/(double)size.height, 1.0);
|
2014-01-12 02:13:45 +08:00
|
|
|
transform->RotateX(180);
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkImageReslice> image_reslice = vtkSmartPointer<vtkImageReslice>::New();
|
|
|
|
image_reslice->SetResliceTransform(transform);
|
|
|
|
image_reslice->SetInputConnection(source->GetOutputPort());
|
|
|
|
image_reslice->SetOutputDimensionality(2);
|
|
|
|
image_reslice->InterpolateOn();
|
|
|
|
image_reslice->AutoCropOutputOn();
|
|
|
|
image_reslice->Update();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-12 02:13:45 +08:00
|
|
|
mapper->SetInputConnection(image_reslice->GetOutputPort());
|
2013-07-17 17:35:14 +08:00
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WImageOverlay cv::viz::Widget::cast<cv::viz::WImageOverlay>()
|
2013-07-17 17:35:14 +08:00
|
|
|
{
|
|
|
|
Widget2D widget = this->cast<Widget2D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WImageOverlay&>(widget);
|
2013-07-17 17:35:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// image 3D widget implementation
|
|
|
|
|
2014-01-12 02:43:58 +08:00
|
|
|
cv::viz::WImage3D::WImage3D(InputArray image, const Size2d &size)
|
2013-07-17 17:35:14 +08:00
|
|
|
{
|
|
|
|
CV_Assert(!image.empty() && image.depth() == CV_8U);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-10 05:57:11 +08:00
|
|
|
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
|
|
|
|
source->SetImage(image);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-10 23:57:16 +08:00
|
|
|
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
|
|
|
|
texture->SetInputConnection(source->GetOutputPort());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 22:48:17 +08:00
|
|
|
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
|
2014-01-10 23:57:16 +08:00
|
|
|
plane->SetOrigin(-0.5 * size.width, -0.5 * size.height, 0.0);
|
|
|
|
plane->SetPoint1( 0.5 * size.width, -0.5 * size.height, 0.0);
|
|
|
|
plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-10 23:57:16 +08:00
|
|
|
vtkSmartPointer<vtkTextureMapToPlane> textured_plane = vtkSmartPointer<vtkTextureMapToPlane>::New();
|
|
|
|
textured_plane->SetInputConnection(plane->GetOutputPort());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-10 23:57:16 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
|
|
|
mapper->SetInputConnection(textured_plane->GetOutputPort());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 22:48:17 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2014-01-10 23:57:16 +08:00
|
|
|
actor->SetMapper(mapper);
|
2013-07-22 22:48:17 +08:00
|
|
|
actor->SetTexture(texture);
|
2014-01-10 23:57:16 +08:00
|
|
|
actor->GetProperty()->ShadingOff();
|
|
|
|
actor->GetProperty()->LightingOff();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-17 17:35:14 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
|
|
|
|
2014-01-12 02:43:58 +08:00
|
|
|
cv::viz::WImage3D::WImage3D(InputArray image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector)
|
2013-07-22 23:18:19 +08:00
|
|
|
{
|
|
|
|
CV_Assert(!image.empty() && image.depth() == CV_8U);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 23:18:19 +08:00
|
|
|
// Compute the transformation matrix for drawing the camera frame in a scene
|
2014-01-07 18:51:32 +08:00
|
|
|
Vec3d n = normalize(normal);
|
|
|
|
Vec3d u = normalize(up_vector.cross(n));
|
|
|
|
Vec3d v = n.cross(u);
|
2014-01-10 23:57:16 +08:00
|
|
|
Affine3d pose = makeTransformToGlobal(u, v, n, center);
|
2014-01-07 18:51:32 +08:00
|
|
|
|
2014-01-10 23:57:16 +08:00
|
|
|
WImage3D image3d(image, size);
|
|
|
|
image3d.applyTransform(pose);
|
|
|
|
*this = image3d;
|
2013-07-22 23:18:19 +08:00
|
|
|
}
|
|
|
|
|
2014-01-12 02:43:58 +08:00
|
|
|
void cv::viz::WImage3D::setImage(InputArray image)
|
2013-07-17 17:35:14 +08:00
|
|
|
{
|
|
|
|
CV_Assert(!image.empty() && image.depth() == CV_8U);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 22:48:17 +08:00
|
|
|
vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
|
2013-08-31 17:30:37 +08:00
|
|
|
CV_Assert("This widget does not support 3D image." && actor);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-10 05:57:11 +08:00
|
|
|
vtkSmartPointer<vtkImageMatSource> source = vtkSmartPointer<vtkImageMatSource>::New();
|
|
|
|
source->SetImage(image);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 22:48:17 +08:00
|
|
|
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
|
2014-01-10 23:57:16 +08:00
|
|
|
texture->SetInputConnection(source->GetOutputPort());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 22:48:17 +08:00
|
|
|
actor->SetTexture(texture);
|
2013-07-17 17:35:14 +08:00
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WImage3D cv::viz::Widget::cast<cv::viz::WImage3D>()
|
2013-07-17 17:35:14 +08:00
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WImage3D&>(widget);
|
2013-07-18 16:39:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// camera position widget implementation
|
2013-07-18 23:08:58 +08:00
|
|
|
|
2013-12-01 19:25:44 +08:00
|
|
|
namespace cv { namespace viz { namespace
|
2013-09-08 19:06:40 +08:00
|
|
|
{
|
2013-12-01 19:25:44 +08:00
|
|
|
struct CameraPositionUtils
|
2013-09-08 19:06:40 +08:00
|
|
|
{
|
2014-01-10 04:31:27 +08:00
|
|
|
static vtkSmartPointer<vtkPolyData> createFrustum(double aspect_ratio, double fovy, double scale)
|
2013-12-01 19:25:44 +08:00
|
|
|
{
|
|
|
|
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
|
2014-01-10 04:31:27 +08:00
|
|
|
camera->SetViewAngle(fovy);
|
|
|
|
camera->SetPosition(0.0, 0.0, 0.0);
|
|
|
|
camera->SetViewUp(0.0, 1.0, 0.0);
|
|
|
|
camera->SetFocalPoint(0.0, 0.0, 1.0);
|
|
|
|
camera->SetClippingRange(1e-9, scale);
|
|
|
|
|
|
|
|
double planes_array[24];
|
|
|
|
camera->GetFrustumPlanes(aspect_ratio, planes_array);
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkPlanes> planes = vtkSmartPointer<vtkPlanes>::New();
|
|
|
|
planes->SetFrustumPlanes(planes_array);
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkFrustumSource> frustumSource = vtkSmartPointer<vtkFrustumSource>::New();
|
|
|
|
frustumSource->SetPlanes(planes);
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkExtractEdges> extract_edges = vtkSmartPointer<vtkExtractEdges>::New();
|
|
|
|
extract_edges->SetInputConnection(frustumSource->GetOutputPort());
|
|
|
|
extract_edges->Update();
|
|
|
|
|
|
|
|
return extract_edges->GetOutput();
|
|
|
|
}
|
|
|
|
|
2014-01-12 00:40:10 +08:00
|
|
|
static Mat ensureColorImage(InputArray image)
|
2014-01-10 04:31:27 +08:00
|
|
|
{
|
2014-01-12 00:40:10 +08:00
|
|
|
Mat color(image.size(), CV_8UC3);
|
|
|
|
if (image.channels() == 1)
|
2014-01-12 00:01:57 +08:00
|
|
|
{
|
2014-01-12 00:40:10 +08:00
|
|
|
Vec3b *drow = color.ptr<Vec3b>();
|
|
|
|
for(int y = 0; y < color.rows; ++y)
|
2014-01-12 00:01:57 +08:00
|
|
|
{
|
2014-01-12 00:40:10 +08:00
|
|
|
const unsigned char *srow = image.getMat().ptr<unsigned char>(y);
|
|
|
|
const unsigned char *send = srow + color.cols;
|
2014-01-12 00:01:57 +08:00
|
|
|
for(;srow < send;)
|
|
|
|
*drow++ = Vec3b::all(*srow++);
|
|
|
|
}
|
|
|
|
}
|
2014-01-12 00:40:10 +08:00
|
|
|
else
|
|
|
|
image.copyTo(color);
|
|
|
|
return color;
|
2014-01-08 02:21:42 +08:00
|
|
|
}
|
2013-12-01 19:25:44 +08:00
|
|
|
};
|
|
|
|
}}}
|
2013-09-08 19:06:40 +08:00
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WCameraPosition::WCameraPosition(double scale)
|
2013-07-18 23:08:58 +08:00
|
|
|
{
|
2013-12-08 22:31:04 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 01:48:32 +08:00
|
|
|
VtkUtils::SetInputData(mapper, getPolyData(WCoordinateSystem(scale)));
|
2013-09-08 21:20:02 +08:00
|
|
|
mapper->SetScalarModeToUsePointData();
|
2013-07-18 23:08:58 +08:00
|
|
|
|
2013-12-09 00:58:55 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
2013-07-18 23:08:58 +08:00
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-18 23:08:58 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const Color &color)
|
2013-07-18 23:08:58 +08:00
|
|
|
{
|
2014-01-08 02:21:42 +08:00
|
|
|
double f_x = K(0,0), f_y = K(1,1), c_y = K(1,2);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 02:21:42 +08:00
|
|
|
// Assuming that this is an ideal camera (c_y and c_x are at the center of the image)
|
|
|
|
double fovy = 2.0 * atan2(c_y, f_y) * 180 / CV_PI;
|
|
|
|
double aspect_ratio = f_y / f_x;
|
2013-07-18 23:08:58 +08:00
|
|
|
|
2014-01-08 23:43:20 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-18 23:08:58 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, polydata);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-18 23:08:58 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-18 23:08:58 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
setColor(color);
|
|
|
|
}
|
2013-07-20 00:30:12 +08:00
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color)
|
2013-07-20 00:30:12 +08:00
|
|
|
{
|
2013-07-25 16:23:24 +08:00
|
|
|
double aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5);
|
2014-01-08 02:21:42 +08:00
|
|
|
double fovy = fov[1] * 180 / CV_PI;
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 23:43:20 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-20 00:30:12 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, polydata);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-20 00:30:12 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-20 00:30:12 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
setColor(color);
|
|
|
|
}
|
2013-07-22 18:53:19 +08:00
|
|
|
|
2014-01-12 00:40:10 +08:00
|
|
|
cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, InputArray _image, double scale, const Color &color)
|
2013-07-23 21:43:23 +08:00
|
|
|
{
|
2014-01-12 00:40:10 +08:00
|
|
|
CV_Assert(!_image.empty() && _image.depth() == CV_8U);
|
|
|
|
Mat image = CameraPositionUtils::ensureColorImage(_image);
|
|
|
|
image.at<Vec3b>(0, 0) = Vec3d(color.val); //workaround of VTK limitation
|
|
|
|
|
2014-01-08 02:21:42 +08:00
|
|
|
double f_y = K(1,1), c_y = K(1,2);
|
2013-07-23 21:43:23 +08:00
|
|
|
// Assuming that this is an ideal camera (c_y and c_x are at the center of the image)
|
2014-01-08 02:21:42 +08:00
|
|
|
double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI;
|
|
|
|
double far_end_height = 2.00 * c_y * scale / f_y;
|
2014-01-12 00:01:57 +08:00
|
|
|
double aspect_ratio = image.cols/(double)image.rows;
|
2014-01-12 00:40:10 +08:00
|
|
|
double image_scale = far_end_height/image.rows;
|
|
|
|
|
|
|
|
WImage3D image_widget(image, Size2d(image.size()) * image_scale);
|
|
|
|
image_widget.applyTransform(Affine3d().translate(Vec3d(0, 0, scale)));
|
|
|
|
vtkSmartPointer<vtkPolyData> plane = getPolyData(image_widget);
|
2014-01-12 00:01:57 +08:00
|
|
|
|
|
|
|
vtkSmartPointer<vtkPolyData> frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-12 00:40:10 +08:00
|
|
|
// Frustum needs to be textured or else it can't be combined with image
|
|
|
|
vtkSmartPointer<vtkTextureMapToPlane> frustum_texture = vtkSmartPointer<vtkTextureMapToPlane>::New();
|
|
|
|
frustum_texture->SetInputConnection(frustum->GetProducerPort());
|
|
|
|
frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel
|
|
|
|
frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
|
|
|
|
append_filter->AddInputConnection(frustum_texture->GetOutputPort());
|
|
|
|
append_filter->AddInputConnection(plane->GetProducerPort());
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkActor> actor = getActor(image_widget);
|
|
|
|
actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort());
|
2013-09-08 19:06:40 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
|
|
|
|
2014-01-12 00:40:10 +08:00
|
|
|
cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, InputArray _image, double scale, const Color &color)
|
2013-09-08 19:06:40 +08:00
|
|
|
{
|
2014-01-12 00:40:10 +08:00
|
|
|
CV_Assert(!_image.empty() && _image.depth() == CV_8U);
|
|
|
|
Mat image = CameraPositionUtils::ensureColorImage(_image);
|
|
|
|
image.at<Vec3b>(0, 0) = Vec3d(color.val); //workaround of VTK limitation
|
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
double fovy = fov[1] * 180.0 / CV_PI;
|
|
|
|
double far_end_height = 2.0 * scale * tan(fov[1] * 0.5);
|
2014-01-12 00:01:57 +08:00
|
|
|
double aspect_ratio = image.cols/(double)image.rows;
|
2014-01-12 00:40:10 +08:00
|
|
|
double image_scale = far_end_height/image.rows;
|
|
|
|
|
|
|
|
WImage3D image_widget(image, Size2d(image.size()) * image_scale);
|
|
|
|
image_widget.applyTransform(Affine3d().translate(Vec3d(0, 0, scale)));
|
|
|
|
vtkSmartPointer<vtkPolyData> plane = getPolyData(image_widget);
|
2014-01-12 00:01:57 +08:00
|
|
|
|
|
|
|
vtkSmartPointer<vtkPolyData> frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-12 00:40:10 +08:00
|
|
|
// Frustum needs to be textured or else it can't be combined with image
|
|
|
|
vtkSmartPointer<vtkTextureMapToPlane> frustum_texture = vtkSmartPointer<vtkTextureMapToPlane>::New();
|
|
|
|
frustum_texture->SetInputConnection(frustum->GetProducerPort());
|
|
|
|
frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel
|
|
|
|
frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
|
|
|
|
append_filter->AddInputConnection(frustum_texture->GetOutputPort());
|
|
|
|
append_filter->AddInputConnection(plane->GetProducerPort());
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkActor> actor = getActor(image_widget);
|
|
|
|
actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort());
|
2013-07-23 21:43:23 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
|
|
|
|
2013-09-15 22:26:53 +08:00
|
|
|
template<> cv::viz::WCameraPosition cv::viz::Widget::cast<cv::viz::WCameraPosition>()
|
2013-07-25 16:23:24 +08:00
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-09-15 22:26:53 +08:00
|
|
|
return static_cast<WCameraPosition&>(widget);
|
2013-07-25 16:23:24 +08:00
|
|
|
}
|
|
|
|
|
2013-07-22 18:53:19 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// trajectory widget implementation
|
|
|
|
|
2014-01-08 01:27:11 +08:00
|
|
|
cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double scale, const Color &color)
|
2014-01-01 23:58:41 +08:00
|
|
|
{
|
2014-01-08 21:16:25 +08:00
|
|
|
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-25 22:08:23 +08:00
|
|
|
// Bitwise and with 3 in order to limit the domain to 2 bits
|
2014-01-08 01:37:33 +08:00
|
|
|
if (display_mode & WTrajectory::PATH)
|
2013-07-22 18:53:19 +08:00
|
|
|
{
|
2014-01-08 01:37:33 +08:00
|
|
|
Mat points = vtkTrajectorySource::ExtractPoints(_path);
|
|
|
|
vtkSmartPointer<vtkPolyData> polydata = getPolyData(WPolyLine(points, color));
|
2014-01-08 21:16:25 +08:00
|
|
|
append_filter->AddInputConnection(polydata->GetProducerPort());
|
2013-07-25 16:56:54 +08:00
|
|
|
}
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 01:37:33 +08:00
|
|
|
if (display_mode & WTrajectory::FRAMES)
|
2013-07-22 18:53:19 +08:00
|
|
|
{
|
2014-01-08 01:37:33 +08:00
|
|
|
vtkSmartPointer<vtkTrajectorySource> source = vtkSmartPointer<vtkTrajectorySource>::New();
|
|
|
|
source->SetTrajectory(_path);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 01:37:33 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> glyph = getPolyData(WCoordinateSystem(scale));
|
|
|
|
|
2014-01-08 02:35:21 +08:00
|
|
|
vtkSmartPointer<vtkTensorGlyph> tensor_glyph = vtkSmartPointer<vtkTensorGlyph>::New();
|
2014-01-08 01:37:33 +08:00
|
|
|
tensor_glyph->SetInputConnection(source->GetOutputPort());
|
|
|
|
tensor_glyph->SetSourceConnection(glyph->GetProducerPort());
|
|
|
|
tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues
|
|
|
|
tensor_glyph->ThreeGlyphsOff();
|
|
|
|
tensor_glyph->SymmetricOff();
|
|
|
|
tensor_glyph->ColorGlyphsOff();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 21:16:25 +08:00
|
|
|
append_filter->AddInputConnection(tensor_glyph->GetOutputPort());
|
2013-07-22 18:53:19 +08:00
|
|
|
}
|
2014-01-08 21:16:25 +08:00
|
|
|
append_filter->Update();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 18:53:19 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, append_filter->GetOutput());
|
2013-09-08 21:20:02 +08:00
|
|
|
mapper->SetScalarModeToUsePointData();
|
2014-01-08 01:37:33 +08:00
|
|
|
mapper->SetScalarRange(0, 255);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 18:53:19 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 18:53:19 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
|
|
|
|
2013-12-08 22:07:16 +08:00
|
|
|
template<> cv::viz::WTrajectory cv::viz::Widget::cast<cv::viz::WTrajectory>()
|
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
|
|
|
return static_cast<WTrajectory&>(widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// WTrajectoryFrustums widget implementation
|
|
|
|
|
2014-01-08 02:35:21 +08:00
|
|
|
cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33d &K, double scale, const Color &color)
|
2013-09-18 19:50:55 +08:00
|
|
|
{
|
2014-01-08 02:35:21 +08:00
|
|
|
vtkSmartPointer<vtkTrajectorySource> source = vtkSmartPointer<vtkTrajectorySource>::New();
|
|
|
|
source->SetTrajectory(_path);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 02:35:21 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> glyph = getPolyData(WCameraPosition(K, scale));
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 02:35:21 +08:00
|
|
|
vtkSmartPointer<vtkTensorGlyph> tensor_glyph = vtkSmartPointer<vtkTensorGlyph>::New();
|
|
|
|
tensor_glyph->SetInputConnection(source->GetOutputPort());
|
|
|
|
tensor_glyph->SetSourceConnection(glyph->GetProducerPort());
|
|
|
|
tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues
|
|
|
|
tensor_glyph->ThreeGlyphsOff();
|
|
|
|
tensor_glyph->SymmetricOff();
|
|
|
|
tensor_glyph->ColorGlyphsOff();
|
|
|
|
tensor_glyph->Update();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-25 21:08:45 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, tensor_glyph->GetOutput());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-25 21:08:45 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-25 21:08:45 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
setColor(color);
|
|
|
|
}
|
|
|
|
|
2014-01-08 02:35:21 +08:00
|
|
|
cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d &fov, double scale, const Color &color)
|
2013-07-25 21:08:45 +08:00
|
|
|
{
|
2014-01-08 02:35:21 +08:00
|
|
|
vtkSmartPointer<vtkTrajectorySource> source = vtkSmartPointer<vtkTrajectorySource>::New();
|
|
|
|
source->SetTrajectory(_path);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 02:35:21 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> glyph = getPolyData(WCameraPosition(fov, scale));
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 02:35:21 +08:00
|
|
|
vtkSmartPointer<vtkTensorGlyph> tensor_glyph = vtkSmartPointer<vtkTensorGlyph>::New();
|
|
|
|
tensor_glyph->SetInputConnection(source->GetOutputPort());
|
|
|
|
tensor_glyph->SetSourceConnection(glyph->GetProducerPort());
|
|
|
|
tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues
|
|
|
|
tensor_glyph->ThreeGlyphsOff();
|
|
|
|
tensor_glyph->SymmetricOff();
|
|
|
|
tensor_glyph->ColorGlyphsOff();
|
|
|
|
tensor_glyph->Update();
|
2013-07-25 21:08:45 +08:00
|
|
|
|
2013-07-22 20:11:06 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
2014-01-08 21:16:25 +08:00
|
|
|
VtkUtils::SetInputData(mapper, tensor_glyph->GetOutput());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 20:11:06 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-07-22 20:11:06 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
setColor(color);
|
|
|
|
}
|
2013-07-25 16:23:24 +08:00
|
|
|
|
2013-12-08 22:07:16 +08:00
|
|
|
template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast<cv::viz::WTrajectoryFrustums>()
|
2013-07-25 16:23:24 +08:00
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-12-08 22:07:16 +08:00
|
|
|
return static_cast<WTrajectoryFrustums&>(widget);
|
2013-08-03 21:40:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
2013-12-08 22:07:16 +08:00
|
|
|
/// WTrajectorySpheres widget implementation
|
2013-08-03 21:40:36 +08:00
|
|
|
|
2014-01-08 20:25:14 +08:00
|
|
|
cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_length, double radius, const Color &from, const Color &to)
|
2013-08-03 21:40:36 +08:00
|
|
|
{
|
2014-01-08 20:25:14 +08:00
|
|
|
CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT);
|
|
|
|
CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16));
|
2014-01-08 01:48:32 +08:00
|
|
|
|
2014-01-08 20:25:14 +08:00
|
|
|
Mat path64;
|
|
|
|
_path.getMat().convertTo(path64, CV_64F);
|
|
|
|
Affine3d *traj = path64.ptr<Affine3d>();
|
|
|
|
size_t total = path64.total();
|
2014-01-08 01:48:32 +08:00
|
|
|
|
2014-01-08 20:25:14 +08:00
|
|
|
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 20:25:14 +08:00
|
|
|
for(size_t i = 0; i < total; ++i)
|
2013-08-03 21:40:36 +08:00
|
|
|
{
|
2014-01-08 20:25:14 +08:00
|
|
|
Vec3d curr = traj[i].translation();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-08-03 21:40:36 +08:00
|
|
|
vtkSmartPointer<vtkSphereSource> sphere_source = vtkSmartPointer<vtkSphereSource>::New();
|
2014-01-08 20:25:14 +08:00
|
|
|
sphere_source->SetCenter(curr.val);
|
|
|
|
sphere_source->SetRadius( (i == 0) ? 2 * radius : radius );
|
|
|
|
sphere_source->Update();
|
|
|
|
|
|
|
|
double alpha = static_cast<double>(i)/total;
|
|
|
|
Color c = from * (1 - alpha) + to * alpha;
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 20:25:14 +08:00
|
|
|
vtkSmartPointer<vtkPolyData> polydata = sphere_source->GetOutput();
|
|
|
|
polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c));
|
|
|
|
append_filter->AddInputConnection(polydata->GetProducerPort());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 20:25:14 +08:00
|
|
|
if (i > 0)
|
|
|
|
{
|
|
|
|
Vec3d prev = traj[i-1].translation();
|
|
|
|
Vec3d lvec = prev - curr;
|
|
|
|
|
|
|
|
if(norm(lvec) > line_length)
|
|
|
|
lvec = normalize(lvec) * line_length;
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 20:25:14 +08:00
|
|
|
Vec3d lend = curr + lvec;
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2014-01-08 20:25:14 +08:00
|
|
|
vtkSmartPointer<vtkLineSource> line_source = vtkSmartPointer<vtkLineSource>::New();
|
|
|
|
line_source->SetPoint1(curr.val);
|
|
|
|
line_source->SetPoint2(lend.val);
|
|
|
|
line_source->Update();
|
|
|
|
vtkSmartPointer<vtkPolyData> polydata = line_source->GetOutput();
|
|
|
|
polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c));
|
|
|
|
append_filter->AddInputConnection(polydata->GetProducerPort());
|
|
|
|
}
|
2013-08-03 21:40:36 +08:00
|
|
|
}
|
2014-01-08 20:25:14 +08:00
|
|
|
append_filter->Update();
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-08-03 21:40:36 +08:00
|
|
|
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
|
|
|
mapper->SetScalarModeToUseCellData();
|
2014-01-08 20:25:14 +08:00
|
|
|
VtkUtils::SetInputData(mapper, append_filter->GetOutput());
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-08-03 21:40:36 +08:00
|
|
|
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
actor->SetMapper(mapper);
|
2013-09-18 19:50:55 +08:00
|
|
|
|
2013-08-03 21:40:36 +08:00
|
|
|
WidgetAccessor::setProp(*this, actor);
|
|
|
|
}
|
|
|
|
|
2013-12-08 21:12:02 +08:00
|
|
|
template<> cv::viz::WTrajectorySpheres cv::viz::Widget::cast<cv::viz::WTrajectorySpheres>()
|
2013-08-03 21:40:36 +08:00
|
|
|
{
|
|
|
|
Widget3D widget = this->cast<Widget3D>();
|
2013-12-08 21:12:02 +08:00
|
|
|
return static_cast<WTrajectorySpheres&>(widget);
|
2013-09-08 21:20:02 +08:00
|
|
|
}
|