Added WidgetMerger, Polyline - colors support for each point independently, simple widgets now compute color array instead of setting global color

This commit is contained in:
Anatoly Baksheev
2014-02-15 17:02:17 +04:00
parent 261546f6f6
commit 1a5dfe421d
6 changed files with 222 additions and 85 deletions

View File

@@ -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);
CV_Assert("Correctness check." && actor);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
if (!mapper)
{
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New();
VtkUtils::AddInputData(append_filter, polydata);
// 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);
}

View File

@@ -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();

View File

@@ -54,14 +54,16 @@ cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color
line->SetPoint2(pt2.x, pt2.y, pt2.z);
line->Update();
vtkSmartPointer<vtkPolyData> polydata = line->GetOutput();
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, line->GetOutput());
VtkUtils::SetInputData(mapper, polydata);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
template<> cv::viz::WLine cv::viz::Widget::cast<cv::viz::WLine>()
@@ -83,14 +85,16 @@ cv::viz::WSphere::WSphere(const Point3d &center, double radius, int sphere_resol
sphere->LatLongTessellationOff();
sphere->Update();
vtkSmartPointer<vtkPolyData> polydata = sphere->GetOutput();
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, sphere->GetOutput());
VtkUtils::SetInputData(mapper, polydata);
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>()
@@ -110,15 +114,17 @@ cv::viz::WPlane::WPlane(const Size2d& size, const Color &color)
plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0);
plane->Update();
vtkSmartPointer<vtkPolyData> polydata = plane->GetOutput();
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, plane->GetOutput());
VtkUtils::SetInputData(mapper, polydata);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->LightingOff();
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Size2d& size, const Color &color)
@@ -161,6 +167,7 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness
Affine3d transform_with_scale(R * length, start_point);
vtkSmartPointer<vtkPolyData> polydata = VtkUtils::TransformPolydata(arrow_source->GetOutputPort(), transform_with_scale);
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, polydata);
@@ -169,7 +176,6 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
template<> cv::viz::WArrow cv::viz::Widget::cast<cv::viz::WArrow>()
@@ -189,16 +195,17 @@ cv::viz::WCircle::WCircle(double radius, double thickness, const Color &color)
disk->SetOuterRadius(radius + thickness);
disk->Update();
vtkSmartPointer<vtkPolyData> polydata = disk->GetOutput();
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, disk->GetOutput());
VtkUtils::SetInputData(mapper, polydata);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->LightingOff();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
cv::viz::WCircle::WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness, const Color &color)
@@ -231,14 +238,16 @@ cv::viz::WCone::WCone(double length, double radius, int resolution, const Color
cone_source->SetResolution(resolution);
cone_source->Update();
vtkSmartPointer<vtkPolyData> polydata = cone_source->GetOutput();
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, cone_source->GetOutput());
VtkUtils::SetInputData(mapper, polydata);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
cv::viz::WCone::WCone(double radius, const Point3d& center, const Point3d& tip, int resolution, const Color &color)
@@ -274,14 +283,16 @@ cv::viz::WCylinder::WCylinder(const Point3d& axis_point1, const Point3d& axis_po
tuber->SetRadius(radius);
tuber->Update();
vtkSmartPointer<vtkPolyData> polydata = tuber->GetOutput();
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, tuber->GetOutput());
VtkUtils::SetInputData(mapper, polydata);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
template<> cv::viz::WCylinder cv::viz::Widget::cast<cv::viz::WCylinder>()
@@ -315,15 +326,16 @@ cv::viz::WCube::WCube(const Point3d& min_point, const Point3d& max_point, bool w
vtkCubeSource::SafeDownCast(cube)->SetBounds(bounds);
}
cube->Update();
vtkSmartPointer<vtkPolyData> polydata =cube->GetOutput();
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, cube->GetOutput());
VtkUtils::SetInputData(mapper, polydata);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
template<> cv::viz::WCube cv::viz::Widget::cast<cv::viz::WCube>()
@@ -379,40 +391,21 @@ template<> cv::viz::WCoordinateSystem cv::viz::Widget::cast<cv::viz::WCoordinate
///////////////////////////////////////////////////////////////////////////////////////////////
/// polyline widget implementation
cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color)
cv::viz::WPolyLine::WPolyLine(InputArray points, InputArray colors)
{
CV_Assert(_points.type() == CV_32FC3 || _points.type() == CV_32FC4 || _points.type() == CV_64FC3 || _points.type() == CV_64FC4);
vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New();
cloud_source->SetColorCloud(points, colors);
cloud_source->Update();
const float *fpoints = _points.getMat().ptr<float>();
const double *dpoints = _points.getMat().ptr<double>();
size_t total = _points.total();
int s_chs = _points.channels();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->SetDataType(_points.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE);
points->SetNumberOfPoints((vtkIdType)total);
if (_points.depth() == CV_32F)
for(size_t i = 0; i < total; ++i, fpoints += s_chs)
points->SetPoint((vtkIdType)i, fpoints);
if (_points.depth() == CV_64F)
for(size_t i = 0; i < total; ++i, dpoints += s_chs)
points->SetPoint((vtkIdType)i, dpoints);
vtkSmartPointer<vtkPolyData> polydata = cloud_source->GetOutput();
vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New();
cell_array->Allocate(cell_array->EstimateSize(1, (int)total));
cell_array->InsertNextCell((int)total);
for(size_t i = 0; i < total; ++i)
cell_array->InsertCellPoint((vtkIdType)i);
cell_array->Allocate(cell_array->EstimateSize(1, polydata->GetNumberOfPoints()));
cell_array->InsertNextCell(polydata->GetNumberOfPoints());
for(vtkIdType i = 0; i < polydata->GetNumberOfPoints(); ++i)
cell_array->InsertCellPoint(i);
vtkSmartPointer<vtkUnsignedCharArray> scalars = VtkUtils::FillScalars(total, color);
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
polydata->SetPoints(points);
polydata->SetLines(cell_array);
polydata->GetPointData()->SetScalars(scalars);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, polydata);
mapper->SetScalarRange(0, 255);
@@ -423,6 +416,12 @@ cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color)
WidgetAccessor::setProp(*this, actor);
}
cv::viz::WPolyLine::WPolyLine(InputArray points, const Color &color)
{
WPolyLine polyline(points, Mat(points.size(), CV_8UC3, color));
*this = polyline;
}
template<> cv::viz::WPolyLine cv::viz::Widget::cast<cv::viz::WPolyLine>()
{
Widget3D widget = this->cast<Widget3D>();
@@ -450,14 +449,16 @@ cv::viz::WGrid::WGrid(const Vec2i &cells, const Vec2d &cells_spacing, const Colo
VtkUtils::SetInputData(extract_edges, grid_data);
extract_edges->Update();
vtkSmartPointer<vtkPolyData> polydata = extract_edges->GetOutput();
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, extract_edges->GetOutput());
VtkUtils::SetInputData(mapper, polydata);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
cv::viz::WGrid::WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Vec2i &cells, const Vec2d &cells_spacing, const Color &color)
@@ -807,6 +808,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const
double aspect_ratio = f_y / f_x;
vtkSmartPointer<vtkPolyData> polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, polydata);
@@ -815,7 +817,6 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color)
@@ -824,6 +825,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const
double fovy = fov[1] * 180 / CV_PI;
vtkSmartPointer<vtkPolyData> polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale);
VtkUtils::FillScalars(polydata, color);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
VtkUtils::SetInputData(mapper, polydata);
@@ -832,7 +834,6 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, InputArray _image, double scale, const Color &color)
@@ -967,6 +968,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33
source->SetTrajectory(_path);
vtkSmartPointer<vtkPolyData> glyph = getPolyData(WCameraPosition(K, scale));
VtkUtils::FillScalars(glyph, color);
vtkSmartPointer<vtkTensorGlyph> tensor_glyph = vtkSmartPointer<vtkTensorGlyph>::New();
tensor_glyph->SetInputConnection(source->GetOutputPort());
@@ -984,7 +986,6 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d &fov, double scale, const Color &color)
@@ -993,6 +994,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d
source->SetTrajectory(_path);
vtkSmartPointer<vtkPolyData> glyph = getPolyData(WCameraPosition(fov, scale));
VtkUtils::FillScalars(glyph, color);
vtkSmartPointer<vtkTensorGlyph> tensor_glyph = vtkSmartPointer<vtkTensorGlyph>::New();
tensor_glyph->SetInputConnection(source->GetOutputPort());
@@ -1010,7 +1012,6 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d
actor->SetMapper(mapper);
WidgetAccessor::setProp(*this, actor);
setColor(color);
}
template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast<cv::viz::WTrajectoryFrustums>()