Skip to content
Snippets Groups Projects
Commit c5ef1ee4 authored by Andras Lasso's avatar Andras Lasso Committed by Andras Lasso
Browse files

Improve vtkSelectVisiblePoints tolerance specification

Add the option to specify tolerance in world coordinates. It allows testing visibility when the tested points are visualized with glyphs. The glyphs always occlude the tested point, so a tolerance must be specified that is equal to the size of the point glyph. Size of the point glyph is known in world coordinate system, therefore it is necessary to specify the tolerance in world coordinate system.
parent 77228990
Branches
Tags
No related merge requests found
......@@ -81,6 +81,7 @@ vtk_add_test_cxx(vtkRenderingCoreCxxTests tests
TestPolygonSelection.cxx
TestResetCameraVerticalAspectRatio.cxx
TestResetCameraVerticalAspectRatioParallel.cxx
TestSelectVisiblePoints.cxx,NO_VALID
TestSplitViewportStereoHorizontal.cxx
TestTexturedBackground.cxx
TestTextureSize.cxx,NO_VALID
......
/*=========================================================================
Program: Visualization Toolkit
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkActor.h"
#include "vtkCamera.h"
#include "vtkGlyph3DMapper.h"
#include "vtkInteractorStyleSwitch.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderWindow.h"
#include "vtkSelectVisiblePoints.h"
#include "vtkSphereSource.h"
int GetNumberOfVisiblePoints(vtkSelectVisiblePoints* selectVisiblePoints, vtkPoints* points)
{
// Points on the back side of the sphere should not be visible
int numberOfVisiblePoints = 0;
for (vtkIdType pointIndex = 0; pointIndex<points->GetNumberOfPoints(); pointIndex++)
{
bool occluded = selectVisiblePoints->IsPointOccluded(points->GetPoint(pointIndex), nullptr);
if (occluded)
{
numberOfVisiblePoints++;
}
}
return numberOfVisiblePoints;
}
int TestSelectVisiblePoints(int argc, char *argv[])
{
// Create a point set that we will test visibility of,
// using a sphere source.
vtkNew<vtkSphereSource> sphere;
sphere->SetRadius(20);
sphere->Update();
vtkPoints* spherePoints = sphere->GetOutput()->GetPoints();
std::cout << "Total number of points: " << spherePoints->GetNumberOfPoints() << std::endl;
// Set up renderer
vtkNew<vtkRenderer> ren;
vtkNew<vtkRenderWindow> win;
win->AddRenderer(ren);
vtkNew<vtkRenderWindowInteractor> iren;
vtkInteractorStyleSwitch::SafeDownCast(iren->GetInteractorStyle())->SetCurrentStyleToTrackballCamera();
iren->SetRenderWindow(win);
ren->SetBackground(0.5,0.5,0.5);
win->SetSize(450,450);
// Create a sphere actor (to test that labels are only visible on one side).
vtkNew<vtkActor> sphereActor;
vtkNew<vtkPolyDataMapper> sphereMapper;
sphereMapper->SetInputConnection(sphere->GetOutputPort());
sphereActor->SetMapper(sphereMapper);
ren->AddActor(sphereActor);
// Initialize camera
win->Render();
ren->GetActiveCamera()->Azimuth(30);
ren->ResetCamera();
ren->GetActiveCamera()->Zoom(1.5);
ren->ResetCameraClippingRange();
win->Render();
// Initialize visible point selector
vtkNew<vtkSelectVisiblePoints> selectVisiblePoints;
selectVisiblePoints->SetRenderer(ren);
selectVisiblePoints->Initialize(false);
int result = EXIT_SUCCESS;
// Points on the back side of the sphere should not be visible
int numberOfVisiblePoints = GetNumberOfVisiblePoints(selectVisiblePoints, spherePoints);
std::cout << "Visible points when sphere is shown: " << numberOfVisiblePoints << std::endl;
if (numberOfVisiblePoints == 0 || numberOfVisiblePoints == spherePoints->GetNumberOfPoints())
{
std::cerr << "Number of points is incorrect" << std::endl;
result = EXIT_FAILURE;
}
// If we hide the sphere then all points should be visible
if (result == EXIT_SUCCESS)
{
sphereActor->SetVisibility(false);
win->Render();
numberOfVisiblePoints = GetNumberOfVisiblePoints(selectVisiblePoints, spherePoints);
std::cout << "Visible points when sphere is not shown: " << numberOfVisiblePoints << std::endl;
if (numberOfVisiblePoints != spherePoints->GetNumberOfPoints())
{
std::cerr << "Number of points is incorrect" << std::endl;
result = EXIT_FAILURE;
}
}
// We now use glyph filter to visualize the points.
// At least some points are occluded by the glyphs
// (some may be considered as visible, due to vtkSelectVisiblePoints Tolerance).
vtkNew<vtkGlyph3DMapper> glypher;
if (result == EXIT_SUCCESS)
{
// Add glyph at each point
glypher->SetInputConnection(sphere->GetOutputPort());
vtkNew<vtkSphereSource> glyphSource;
glypher->SetSourceConnection(glyphSource->GetOutputPort());
glypher->SetScaleFactor(3.0);
vtkNew<vtkActor> glyphActor;
glyphActor->SetMapper(glypher);
ren->AddActor(glyphActor);
win->Render();
numberOfVisiblePoints = GetNumberOfVisiblePoints(selectVisiblePoints, spherePoints);
std::cout << "Visible points when glyph is shown at each point: " << numberOfVisiblePoints << std::endl;
if (numberOfVisiblePoints == spherePoints->GetNumberOfPoints())
{
std::cerr << "Number of points is incorrect" << std::endl;
result = EXIT_FAILURE;
}
}
// All points should be visible if we set tolerance to be the glyph size
// (except those 4 points that are covered by another point's glyph).
const int numberOfOccludedPoints = 4;
if (result == EXIT_SUCCESS)
{
selectVisiblePoints->SetToleranceWorld(glypher->GetScaleFactor()*0.5);
win->Render();
numberOfVisiblePoints = GetNumberOfVisiblePoints(selectVisiblePoints, spherePoints);
std::cout << "Visible points when sphere is shown, with world tolerance set: " << numberOfVisiblePoints << std::endl;
if (numberOfVisiblePoints != spherePoints->GetNumberOfPoints() - numberOfOccludedPoints)
{
std::cerr << "Number of points is incorrect" << std::endl;
result = EXIT_FAILURE;
}
}
// All points should be visible if we rotate the view to avoid occluding
// a point with another point's glyph.
if (result == EXIT_SUCCESS)
{
ren->GetActiveCamera()->Pitch(40);
ren->ResetCamera();
ren->GetActiveCamera()->Zoom(1.5);
ren->ResetCameraClippingRange();
win->Render();
numberOfVisiblePoints = GetNumberOfVisiblePoints(selectVisiblePoints, spherePoints);
std::cout << "Visible points when sphere is shown, with world tolerance set, view aligned: "
<< numberOfVisiblePoints << std::endl;
if (numberOfVisiblePoints != spherePoints->GetNumberOfPoints())
{
std::cerr << "Number of points is incorrect" << std::endl;
result = EXIT_FAILURE;
}
}
// Show the sphere again. Points on the back side of the sphere should not be visible.
if (result == EXIT_SUCCESS)
{
sphereActor->SetVisibility(true);
win->Render();
numberOfVisiblePoints = GetNumberOfVisiblePoints(selectVisiblePoints, spherePoints);
std::cout << "Visible points when sphere and glyphs are shown: " << numberOfVisiblePoints << std::endl;
if (numberOfVisiblePoints == 0 || numberOfVisiblePoints == spherePoints->GetNumberOfPoints())
{
std::cerr << "Number of points is incorrect" << std::endl;
result = EXIT_FAILURE;
}
}
int retVal = vtkRegressionTestImage(win);
if ( retVal == vtkRegressionTester::DO_INTERACTOR)
{
iren->Start();
}
return result;
}
......@@ -40,7 +40,9 @@ vtkSelectVisiblePoints::vtkSelectVisiblePoints()
this->InternalSelection[0] = this->InternalSelection[2] = 0;
this->InternalSelection[1] = this->InternalSelection[3] = 1600;
this->CompositePerspectiveTransform = vtkMatrix4x4::New();
this->DirectionOfProjection[0] = this->DirectionOfProjection[1] = this->DirectionOfProjection[2] = 0.0;
this->Tolerance = 0.01;
this->ToleranceWorld = 0.0;
this->SelectInvisible = 0;
}
......@@ -197,6 +199,12 @@ void vtkSelectVisiblePoints::PrintSelf(ostream& os, vtkIndent indent)
float * vtkSelectVisiblePoints::Initialize(bool getZbuff)
{
vtkCamera* cam = this->Renderer->GetActiveCamera();
if (!cam)
{
return nullptr;
}
cam->GetDirectionOfProjection(this->DirectionOfProjection);
int *size = this->Renderer->GetRenderWindow()->GetSize();
......@@ -246,6 +254,12 @@ bool vtkSelectVisiblePoints::IsPointOccluded(
double view[4];
double dx[3], z;
double xx[4] = {x[0], x[1], x[2], 1.0};
if (this->ToleranceWorld > 0.0)
{
xx[0] -= this->DirectionOfProjection[0] * this->ToleranceWorld;
xx[1] -= this->DirectionOfProjection[1] * this->ToleranceWorld;
xx[2] -= this->DirectionOfProjection[2] * this->ToleranceWorld;
}
this->CompositePerspectiveTransform->MultiplyPoint(xx, view);
if (view[3] == 0.0)
......@@ -275,7 +289,7 @@ bool vtkSelectVisiblePoints::IsPointOccluded(
static_cast<int>(dx[1]));
}
if( dx[2] < (z + this->Tolerance) )
if (dx[2] < (z + this->Tolerance))
{
return true;
}
......
......@@ -111,7 +111,8 @@ public:
//@{
/**
* Set/Get a tolerance to use to determine whether a point is visible. A
* Set/Get a tolerance in normalized display coordinate system
* to use to determine whether a point is visible. A
* tolerance is usually required because the conversion from world space
* to display space during rendering introduces numerical round-off.
*/
......@@ -119,6 +120,18 @@ public:
vtkGetMacro(Tolerance, double);
//@}
//@{
/**
* Set/Get a tolerance in world coordinate system
* to use to determine whether a point is visible.
* This allows determining visibility of small spheroid objects
* (such as glyphs) with known size in world coordinates.
* By default it is set to 0.
*/
vtkSetClampMacro(ToleranceWorld, double, 0.0, VTK_DOUBLE_MAX);
vtkGetMacro(ToleranceWorld, double);
//@}
/**
* Requires the renderer to be set. Populates the composite perspective transform
* and returns a pointer to the Z-buffer (that must be deleted) if getZbuff is set.
......@@ -150,7 +163,9 @@ protected:
int Selection[4];
int InternalSelection[4];
vtkTypeBool SelectInvisible;
double DirectionOfProjection[3];
double Tolerance;
double ToleranceWorld;
private:
vtkSelectVisiblePoints(const vtkSelectVisiblePoints&) = delete;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment