Hello all,
I am working on TImerCallback and MouseCallback.
In my MouseCallback I choose a point(seedPoint) with mouse click in a glyph3D field. It creates a sphere in the seedPoint.
Now the glyphfields has vectors and I want the TimerCallback to create spheres iteratively based on the nearest point(with stepsize s) towards the vector direction of the next point.
There should be 1000 iterations.
The idea is based on brain tractography. Please see the seedpoints below with point locations in the terminal. Outside the brain location gives point id as -1.
I am using the following codes for MouseCallback:
class MyMouseCallback : public vtkInteractorStyleTrackballCamera
{
public:
MyMouseCallback() {}
~MyMouseCallback() {}
static MyMouseCallback* New()
{
MyMouseCallback* callback = new MyMouseCallback();
return callback;
}
virtual void OnLeftButtonDown() override
{
// do something customized here
// figure out where the mouse is (pixel x, y)
// we have the interactor from our parent class
int x, y;
this->Interactor->GetEventPosition(x, y); //creates pixel location object this
std::cout << "Picked pixel: " << x << " " << y << std::endl;
// figure out where that maps to in the scene (which point of which mesh?)
// we need to know the picker and renderer
vtkSmartPointer < vtkPointPicker > picker = dynamic_cast < vtkPointPicker *> ( this->Interactor->GetPicker() ) ;
//vtkSmartPointer < vtkCellPicker > picker = dynamic_cast <vtkCellPicker*> (this->Interactor->GetPicker());
vtkSmartPointer < vtkRenderWindow > window = this->Interactor->GetRenderWindow();
vtkSmartPointer < vtkRenderer > renderer = window->GetRenderers()->GetFirstRenderer();
renderer->GetActors()->InitTraversal(); //NS
picker->Pick(x, y, 0, renderer);
std::cout << "Picked point id: " << picker->GetPointId() << std::endl ;
// we need to figure out where the mesh is
vtkSmartPointer < vtkPolyDataMapper > mapper = dynamic_cast <vtkPolyDataMapper*> (picker->GetMapper());
if (mapper != NULL)
{
vtkIdType seedPointID = picker->GetPointId();
double* pos = picker->GetPickPosition(); //getting the world coordinate position
std::cout << "Pick position (world coordinates) is: " << pos[0] << " " << pos[1] << " " << pos[2] << std::endl;
vtkSmartPointer<vtkSphereSource> seedSphere = vtkSmartPointer<vtkSphereSource>::New();
//seedSphere->SetCenter(pos[0], pos[1], pos[2]);
seedSphere->SetCenter(pos);
seedSphere->SetRadius(1.0);
seedSphere->Update(); //NS
//Create a mapper and actor
vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
sphereMapper->SetInputConnection(seedSphere->GetOutputPort());
vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();
sphereActor->SetMapper(sphereMapper);
//std::cout << "Randoms: " << rgb[0] << " " << rgb[1] << " " << rgb[2] << std::endl;
float rgb[3];
rgb[0] = vtkMath::Random(0, 1);
rgb[1] = vtkMath::Random(0, 1);
rgb[2] = vtkMath::Random(0, 1);
sphereActor->GetProperty()->SetColor(rgb[0], rgb[1], rgb[2]);
renderer->AddActor(sphereActor);
//for tract:
/*vtkSmartPointer<vtkPoints> tractPoints = vtkSmartPointer<vtkPoints>::New();
tractPoints->InsertNextPoint(pos);
//creating polylines
vtkSmartPointer <vtkPolyLine> tract = vtkSmartPointer <vtkPolyLine>::New();
vtkIdType numOfTractPoints = tractPoints->GetNumberOfPoints();
tract->GetPointIds()->SetNumberOfIds(numOfTractPoints);
for (unsigned int i = 0; i < numOfTractPoints; i++)
{
tract->GetPointIds()->SetId(i, i);
}
vtkSmartPointer <vtkCellArray> tractCells = vtkSmartPointer <vtkCellArray>::New();
tractCells->InsertNextCell(tract);
vtkSmartPointer <vtkPolyData> polyData = vtkSmartPointer <vtkPolyData>::New();
polyData->SetPoints(tractPoints);
polyData->SetLines(tractCells);
// Setup the mapper and actor for the polydata
vtkSmartPointer <vtkPolyDataMapper> tractMapper = vtkSmartPointer <vtkPolyDataMapper>::New();
tractMapper->SetInputData(polyData);
vtkSmartPointer <vtkActor> tractActor = vtkSmartPointer <vtkActor>::New();
tractActor->SetMapper(tractMapper);
tractActor->GetProperty()->SetColor(rgb[0],rgb[1],rgb[2]); // set the color of tract to blue
// Add this actor to the actor collection of the renderer
renderer->AddActor(tractActor);*/
//for tract
vtkSmartPointer < vtkPolyData > mesh = mapper->GetInput();
// "update"
mesh->Modified(); //if you do not update, doesn't do anything
}
// now go back to doing nromal left button things
vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}
void setStepSize(double stepSize)
{
this->s = stepSize;
}
private:
double s; // step size for the tract growth
};
class TimerCallback : public vtkCommand
{
public:
TimerCallback() {}
~TimerCallback() {}
static TimerCallback* New()
{
TimerCallback* callback = new TimerCallback();
return callback;
}
virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData)
{
vtkSmartPointer < vtkRenderWindowInteractor > interactor = static_cast <vtkRenderWindowInteractor*> (caller);
vtkRenderWindow* renderWindow = interactor->GetRenderWindow();
vtkRenderer* renderer = renderWindow->GetRenderers()->GetFirstRenderer();
this->actor->RotateZ(rotAmount);
// change mesh
vtkPolyDataMapper* mapper = dynamic_cast <vtkPolyDataMapper*> (this->actor->GetMapper());
vtkPolyData* mesh = dynamic_cast <vtkPolyData*> (mapper->GetInput());
int nPts = mesh->GetNumberOfPoints();
for (unsigned int i = 0; i < 10; i++)
{
double pointCoordinates[3];
mesh->GetPoint(i, pointCoordinates);
pointCoordinates[0] += 1;
mesh->GetPoints()->SetPoint(i, pointCoordinates);
}
mesh->Modified();
}
void SetActor(vtkActor* ac, int degrees)
{
this->actor = ac;
this->rotAmount = degrees;
}
private:
vtkActor* actor;
int rotAmount;
};
The rotate codes are from another example where an object is rotated 5 degrees.