
.
I used the old project which was introduced on the post What will happen if we pass wrong vtkRenderer object for vtkPicker::Pick? to explore variable Tolerance
effect.
Let’s make Tolerance
to be 0.1 in the picking experiment.
#include "worker.h"
#include "Log.hpp"
#include "CustomIteractorStyle.h"
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
Worker::Worker()
{
#ifdef __EMSCRIPTEN__
m_RenderWindowInteractor = vtkSPtr<vtkSDL2RenderWindowInteractor>::New();
m_RenderWindow = vtkSPtr<vtkSDL2OpenGLRenderWindow>::New();
#else
m_RenderWindowInteractor = vtkSPtr<vtkRenderWindowInteractor>::New();
m_RenderWindow = vtkSPtr<vtkRenderWindow>::New();
#endif
m_Picker = vtkSPtr<vtkCellPicker>::New();
m_Picker->PickFromListOn();
Log( IInfo, "m_Picker->GetTolerance(): ", m_Picker->GetTolerance() ); // 1e-06
m_Picker->SetTolerance( m_Picker->GetTolerance() * 1e5 );
Log( IInfo, "m_Picker->GetTolerance(): ", m_Picker->GetTolerance() ); // 0.1
}
void Worker::Init()
{
vtkSPtrNew( cone, vtkConeSource );
vtkSPtrNew( mapper, vtkPolyDataMapper );
mapper->SetInputConnection( cone->GetOutputPort() );
m_Actor = vtkSPtr<vtkActor>::New();
m_Actor->SetMapper( mapper );
m_Renderer = vtkSPtr<vtkRenderer>::New();
m_Renderer->SetBackground( 0, 0.2, 0 );
m_Renderer->SetLayer( 0 );
m_TopRenderer = vtkSPtr<vtkRenderer>::New();
m_TopRenderer->SetLayer( 1 );
m_TopRenderer->SetActiveCamera( m_Renderer->GetActiveCamera() );
m_TopRenderer->AddActor(m_Actor);
m_RenderWindow->AddRenderer( m_Renderer );
m_RenderWindow->AddRenderer( m_TopRenderer );
m_RenderWindow->SetNumberOfLayers( 2 );
m_RenderWindowInteractor->SetRenderWindow( m_RenderWindow );
vtkSPtrNew( iStyle, CustomIteractorStyle );
iStyle->Setm_Worder( this );
m_RenderWindowInteractor->SetInteractorStyle( iStyle );
m_Renderer->ResetCamera();
m_RenderWindow->Render();
m_Picker->AddPickList( m_Actor );
Log( IInfo, "Init!" );
}
void Worker::Start()
{
m_RenderWindowInteractor->Start();
Log( IInfo, "Start!" );
}
void Worker::OnLeftButtonDown()
{
auto eventPos = m_RenderWindowInteractor->GetEventPosition();
auto pickResult = m_Picker->Pick(eventPos[0], eventPos[1], 0, m_TopRenderer);
Log( IInfo, "pickResult: ", pickResult );
if (m_Picker->GetPointId() > -1 )
{
vtkSPtr<vtkActor> actor = m_Picker->GetActor();
Log( IInfo, "actor: ", actor );
}
}
We can see the picking range become bigger, but the range can’t scale as we zoom in/out.
Tolerance is specified as fraction of rendering window size. It affects bounding box intersection algorithm and get the intersection judging result.
Then project the model center point onto the ray and determine its parametric value.
int vtkPicker::Pick3DInternal(vtkRenderer* renderer, double p1World[4], double p2World[4])
{
//...
for (tol = 0.0, i = 0; i < 3; i++)
{
tol += (windowUpperRight[i] - windowLowerLeft[i]) * (windowUpperRight[i] - windowLowerLeft[i]);
}
tol = sqrt(tol) * this->Tolerance;
//...
// Have the ray endpoints in mapper space, now need to compare this
// with the mapper bounds to see whether intersection is possible.
//
// Get the bounding box of the modeller. Note that the tolerance is
// added to the bounding box to make sure things on the edge of the
// bounding box are picked correctly.
if (mapper != nullptr)
{
mapper->GetBounds(bounds);
}
bounds[0] -= tol;
bounds[1] += tol;
bounds[2] -= tol;
bounds[3] += tol;
bounds[4] -= tol;
bounds[5] += tol;
if (vtkBox::IntersectBox(bounds, p1Mapper, ray, hitPosition, t))
{
t = this->IntersectWithLine(p1Mapper, p2Mapper,
tol * 0.333 * (scale[0] + scale[1] + scale[2]), path,
static_cast<vtkProp3D*>(propCandidate), mapper);
// Intersect data with specified ray.
double vtkPicker::IntersectWithLine(const double p1[3], const double p2[3], double tol,
vtkAssemblyPath* path, vtkProp3D* prop3D, vtkAbstractMapper3D* mapper)
{
//...
for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
{
vtkDataSet* ds = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject());
if (!ds)
{
continue;
}
// First check if the bounding box of the data set is hit.
double bounds[6];
ds->GetBounds(bounds);
bounds[0] -= tol;
bounds[1] += tol;
bounds[2] -= tol;
bounds[3] += tol;
bounds[4] -= tol;
bounds[5] += tol;