Commit 1a5dfe42 authored by Anatoly Baksheev's avatar Anatoly Baksheev

Added WidgetMerger, Polyline - colors support for each point independently,…

Added WidgetMerger, Polyline - colors support for each point independently, simple widgets now compute color array instead of setting global color
parent 261546f6
......@@ -1025,3 +1025,44 @@ Constructs a WMesh.
:param polygons: Points of the mesh object.
:param colors: Point colors.
:param normals: Point normals.
viz::WWidgetMerger
---------------------
.. ocv:class:: WWidgetMerger
This class allos to merge several widgets to single one. It has quite limited functionality and can't merge widgets with different attributes. For instance,
if widgetA has color array and widgetB has only global color defined, then result of merge won't have color at all. The class is suitable for merging large amount of similar widgets.
class CV_EXPORTS WWidgetMerger : public Widget3D
{
public:
WWidgetMerger();
//! Add widget to merge with optional position change
void addWidget(const Widget3D& widget, const Affine3d &pose = Affine3d::Identity());
//! Repacks internal structure to sinle widget
void finalize();
};
viz::WWidgetMerger::WWidgetMerger
---------------------------------------
Constructs a WWidgetMerger.
.. ocv:WWidgetMerger:: WWidgetMerger()
viz::WWidgetMerger::addCloud
-------------------------------
Adds a cloud to the collection.
.. ocv:function:: void addWidget(const Widget3D& widget, const Affine3d &pose = Affine3d::Identity())
:param widget: Widget to merge.
:param pose: Pose of the widget.
viz::WWidgetMerger::finalize
-------------------------------
Finalizes merger data and constructs final merged widget
.. ocv:function:: void finalize()
\ No newline at end of file
......@@ -201,6 +201,7 @@ namespace cv
class CV_EXPORTS WPolyLine : public Widget3D
{
public:
WPolyLine(InputArray points, InputArray colors);
WPolyLine(InputArray points, const Color &color = Color::white());
};
......@@ -362,6 +363,19 @@ namespace cv
WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray());
};
class CV_EXPORTS WWidgetMerger : public Widget3D
{
public:
WWidgetMerger();
//! Add widget to merge with optional position change
void addWidget(const Widget3D& widget, const Affine3d &pose = Affine3d::Identity());
//! Repacks internal structure to sinle widget
void finalize();
};
/////////////////////////////////////////////////////////////////////////////
/// Utility exports
......@@ -391,6 +405,7 @@ namespace cv
template<> CV_EXPORTS WCloudCollection Widget::cast<WCloudCollection>();
template<> CV_EXPORTS WCloudNormals Widget::cast<WCloudNormals>();
template<> CV_EXPORTS WMesh Widget::cast<WMesh>();
template<> CV_EXPORTS WWidgetMerger Widget::cast<WWidgetMerger>();
} /* namespace viz */
} /* namespace cv */
......
......@@ -193,8 +193,21 @@ template<> cv::viz::WPaintedCloud cv::viz::Widget::cast<cv::viz::WPaintedCloud>(
cv::viz::WCloudCollection::WCloudCollection()
{
// Just create the actor
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(append_filter->GetOutputPort());
mapper->SetScalarModeToUsePointData();
mapper->ImmediateModeRenderingOff();
mapper->SetScalarRange(0, 255);
mapper->ScalarVisibilityOn();
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New();
actor->SetNumberOfCloudPoints(1);
actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->BackfaceCullingOn();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
}
......@@ -206,33 +219,11 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co
vtkSmartPointer<vtkPolyData> polydata = VtkUtils::TransformPolydata(source->GetOutputPort(), pose);
vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this));
CV_Assert("Incompatible widget type." && actor);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
if (!mapper)
{
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
VtkUtils::AddInputData(append_filter, polydata);
CV_Assert("Correctness check." && actor);
// This is the first cloud
mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetScalarRange(0, 255);
mapper->SetScalarModeToUsePointData();
mapper->ScalarVisibilityOn();
mapper->ImmediateModeRenderingOff();
mapper->SetInputConnection(append_filter->GetOutputPort());
actor->SetNumberOfCloudPoints(std::max<vtkIdType>(1, polydata->GetNumberOfPoints()/10));
actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->BackfaceCullingOn();
actor->SetMapper(mapper);
return;
}
vtkSmartPointer<vtkAlgorithm> producer = mapper->GetInputConnection(0, 0)->GetProducer();
vtkSmartPointer<vtkAlgorithm> producer = actor->GetMapper()->GetInputConnection(0, 0)->GetProducer();
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkAppendPolyData::SafeDownCast(producer);
VtkUtils::AddInputData(append_filter, polydata);
append_filter->Modified();
actor->SetNumberOfCloudPoints(std::max<vtkIdType>(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10));
}
......@@ -257,7 +248,6 @@ void cv::viz::WCloudCollection::finalize()
vtkSmartPointer<vtkPolyData> polydata = append_filter->GetOutput();
mapper->RemoveInputConnection(0, 0);
VtkUtils::SetInputData(mapper, polydata);
mapper->Modified();
}
template<> cv::viz::WCloudCollection cv::viz::Widget::cast<cv::viz::WCloudCollection>()
......@@ -332,20 +322,18 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in
}
}
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(lines);
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
polydata->SetPoints(points);
polydata->SetLines(lines);
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
mapper->SetColorModeToMapScalars();
mapper->SetScalarModeToUsePointData();
VtkUtils::SetInputData(mapper, polyData);
VtkUtils::SetInputData(mapper, polydata);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
template<> cv::viz::WCloudNormals cv::viz::Widget::cast<cv::viz::WCloudNormals>()
......@@ -455,3 +443,63 @@ template<> CV_EXPORTS cv::viz::WMesh cv::viz::Widget::cast<cv::viz::WMesh>()
Widget3D widget = this->cast<Widget3D>();
return static_cast<WMesh&>(widget);
}
///////////////////////////////////////////////////////////////////////////////////////////////
/// Widget Merger implementation
cv::viz::WWidgetMerger::WWidgetMerger()
{
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(append_filter->GetOutputPort());
mapper->SetScalarModeToUsePointData();
mapper->ImmediateModeRenderingOff();
mapper->SetScalarRange(0, 255);
mapper->ScalarVisibilityOn();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->SetInterpolationToFlat();
actor->GetProperty()->BackfaceCullingOn();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
}
void cv::viz::WWidgetMerger::addWidget(const Widget3D& widget, const Affine3d &pose)
{
vtkActor *widget_actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(widget));
CV_Assert("Widget is not 3D actor." && widget_actor);
vtkSmartPointer<vtkPolyDataMapper> widget_mapper = vtkPolyDataMapper::SafeDownCast(widget_actor->GetMapper());
CV_Assert("Widget doesn't have a polydata mapper" && widget_mapper);
widget_mapper->Update();
vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
vtkSmartPointer<vtkAlgorithm> producer = actor->GetMapper()->GetInputConnection(0, 0)->GetProducer();
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkAppendPolyData::SafeDownCast(producer);
CV_Assert("Correctness check" && append_filter);
VtkUtils::AddInputData(append_filter, VtkUtils::TransformPolydata(widget_mapper->GetInput(), pose));
}
void cv::viz::WWidgetMerger::finalize()
{
vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this));
vtkSmartPointer<vtkAlgorithm> producer = actor->GetMapper()->GetInputConnection(0, 0)->GetProducer();
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkAppendPolyData::SafeDownCast(producer);
CV_Assert("Correctness check" && append_filter);
append_filter->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
mapper->RemoveInputConnection(0, 0);
VtkUtils::SetInputData(mapper, append_filter->GetOutput());
mapper->Modified();
}
template<> CV_EXPORTS cv::viz::WWidgetMerger cv::viz::Widget::cast<cv::viz::WWidgetMerger>()
{
Widget3D widget = this->cast<Widget3D>();
return static_cast<WWidgetMerger&>(widget);
}
......@@ -272,6 +272,11 @@ namespace cv
return scalars;
}
static vtkSmartPointer<vtkPolyData> FillScalars(vtkSmartPointer<vtkPolyData> polydata, const Color& color)
{
return polydata->GetPointData()->SetScalars(FillScalars(polydata->GetNumberOfPoints(), color)), polydata;
}
static vtkSmartPointer<vtkPolyData> ComputeNormals(vtkSmartPointer<vtkPolyData> polydata)
{
vtkSmartPointer<vtkPolyDataNormals> normals_generator = vtkSmartPointer<vtkPolyDataNormals>::New();
......
This diff is collapsed.
......@@ -156,6 +156,27 @@ TEST(Viz, show_mesh_random_colors)
viz.spin();
}
TEST(Viz, show_widget_merger)
{
WWidgetMerger merger;
merger.addWidget(WCube(Vec3d::all(0.0), Vec3d::all(1.0), true, Color::gold()));
RNG& rng = theRNG();
for(int i = 0; i < 77; ++i)
{
Vec3b c;
rng.fill(c, RNG::NORMAL, Scalar::all(128), Scalar::all(48), true);
merger.addWidget(WSphere(Vec3d(c)*(1.0/255.0), 7.0/255.0, 10, Color(c[2], c[1], c[0])));
}
merger.finalize();
Viz3d viz("show_mesh_random_color");
viz.showWidget("coo", WCoordinateSystem());
viz.showWidget("merger", merger);
viz.showWidget("text2d", WText("Widget merger", Point(20, 20), 20, Color::green()));
viz.spin();
}
TEST(Viz, show_textured_mesh)
{
Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png"));
......@@ -195,12 +216,18 @@ TEST(Viz, show_textured_mesh)
TEST(Viz, show_polyline)
{
Mat polyline(1, 32, CV_64FC3);
const Color palette[] = { Color::red(), Color::green(), Color::blue(), Color::gold(), Color::raspberry(), Color::bluberry(), Color::lime() };
size_t palette_size = sizeof(palette)/sizeof(palette[0]);
Mat polyline(1, 32, CV_64FC3), colors(1, 32, CV_8UC3);
for(int i = 0; i < (int)polyline.total(); ++i)
{
polyline.at<Vec3d>(i) = Vec3d(i/16.0, cos(i * CV_PI/6), sin(i * CV_PI/6));
colors.at<Vec3b>(i) = palette[i & palette_size];
}
Viz3d viz("show_polyline");
viz.showWidget("polyline", WPolyLine(Mat(polyline), Color::apricot()));
viz.showWidget("polyline", WPolyLine(polyline, colors));
viz.showWidget("coosys", WCoordinateSystem());
viz.showWidget("text2d", WText("Polyline", Point(20, 20), 20, Color::green()));
viz.spin();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment