[vtkusers] vtkPointPicker / vtkGlyph3D problem
Henrik Westerberg
henrik.westerberg at crg.es
Wed May 5 10:06:45 EDT 2010
Hi,
I am not really sure if I understand the question.
If you have a pipeline like this:
pts = vtkPoints()
pts.InsertNextPoint(0,0,0)
pts.InsertNextPoint(5,0,0)
vecs = vtkFloatArray()
vecs.SetNumberOfComponents(3)
vecs.InsertTuple3(1,0,0)
vecs.InsertTuple3(1,1,1)
pd = vtkPolyData()
pd.SetPoints(pts)
pd.GetPointData().SetVectors(vecs)
sphereSource = vtkSphereSource()
glyphs3D = vtkGlyph3D()
glyphs3D.SetSource(sphereSource.GetOutput())
glyphs3D.SetInput(pd)
glyphs3D.GeneratePointIdsOn()
picker = vtkPointPicker()
def handlePick(object, event):
pid = picker.GetPointId()
inputIds = glyphs3D.GetOutput().GetPointData().GetArray("InputPointIds")
app = int(inputIds.GetTuple1(pid))
# the point
print pts.GetPoint(app)
# the vector
print vecs.GetTuple3(app)
So this would get you the vector and point for any sphere you picked. Is this what you are after?
hth,
Henrik
________________________________________
From: Gomez, Alberto [alberto.gomez at kcl.ac.uk]
Sent: 05 May 2010 15:03
To: Henrik Westerberg
Cc: Allan James; vtkusers at vtk.org
Subject: Re: [vtkusers] vtkPointPicker / vtkGlyph3D problem
On 04/05/10 17:40, Henrik Westerberg wrote:
Hi,
thanks for the answers. I achieved successful picking with vtkPointPicker doing the following:
double *vector = new double[3];
double *pos = new double[3];
//vectors
vector = glyph->GetOutput()->GetPointData()->GetVectors()->GetTuple(picker->GetPointId());
//points
pos = glyph->GetOutput()->GetPoint(picker->GetPointId());
//pos = glyph->GetOutput()->GetPoints()->GetPoint(picker->GetPointId());//This gives the same result
However, this picks any point in the polydata, which is not what I want. I will explain through an example:
Lets say I have two vectors. They are displayed through the pipeline vtkPolyData->vtkGlyph3D->vtkPolyDataMapper->vtkActor, where my polydata contains two points and two vector tuples. The picker selects any point, i.e. any vertex of the vectors, so I can pick like 10 different points for each vector. What I want is to pick each vector itself, i.e. If I click anywhere in the vector, to get the position where the vector is placed, this is, the position of one point of the original polydata. Would this be possible?
Thanks for your help,
Alberto
Hi,
Be sure to have GeneratePointIdsOn() as this make like a lot easier on your vtkGlyph3D (which you do, just writing it for the general situation)
glyphs = vtkGlyph3D()
glyphs.GeneratePointIdsOn()
In my case I have a scalar associated with each point.
Then you should be able to do something like the following:
picker = vtkPointPicker()
def handlePick(object, event):
pid = picker.GetPointId()
inputIds = glyphs.GetOutput().GetPointData().GetArray("InputPointIds")
app = int(inputIds.GetTuple1(pid))
if (app < tf_scale.GetOutput().GetPoints().GetNumberOfPoints()):
print tf_scale.GetOutput().GetPoints().GetPoint(app)
print scalars.GetValue(app)
where iren is a vtkRenderWindowInteractor
iren.SetPicker(picker)
And you can pick with 'p' key without having to write your own observer.
bye,
Henrik
________________________________________
From: vtkusers-bounces at vtk.org<mailto:vtkusers-bounces at vtk.org> [vtkusers-bounces at vtk.org<mailto:vtkusers-bounces at vtk.org>] On Behalf Of Allan James [ar.james at qut.edu.au<mailto:ar.james at qut.edu.au>]
Sent: 04 May 2010 04:34
To: Gomez, Alberto
Cc: vtkusers at vtk.org<mailto:vtkusers at vtk.org>
Subject: Re: [vtkusers] vtkPointPicker / vtkGlyph3D problem
Hi Alberto,
I could not fix the problem with point picker not producing correct results. After much banging of head against wall I tried cellpicker instead which is now working correctly. I would love to know what I was doing wrong with point picker!
Below is some code snippets for using cellpicker to select a glyph generated using vtkGlyph3D. This code has been hacked a bit from a larger project so it's a bit messy and I havent tested it as is. However it should work by left-clicking on a glyph.
If anyone has suggestions on making this code better, please let me know.
////////////////////////////////////////////////////////
// Make sure GeneratePointIdsOn() called on vtkGlyph3D
// This generates an array on the output dataset called
// "InputPointIds" which generates pointIDs in the glyphs
// that match the original input pointIDs.
////////////////////////////////////////////////////////
_glyphs->GeneratePointIdsOn();
///////////////////////////////////////////
// Setup pick callback (ScenePickCallback)
///////////////////////////////////////////
_scenePickCallback = ScenePickCallback::New();
_scenePickCallback->actorToPick = _glyphActor;
_scenePickCallback->glyphsToPick = _glyphs;
_scenePickCallback->sceneRenderWindowInteractor = _sceneRenderWindowInteractor;
_sceneRenderWindowInteractor->GetInteractorStyle()->AddObserver(vtkCommand::LeftButtonReleaseEvent, _scenePickCallback);
class ScenePickCallback : public vtkCommand
{
public:
static ScenePickCallback *New();
virtual void Execute(vtkObject *caller, unsigned long eventId, void* data);
vtkSmartPointer<vtkActor> actorToPick;
vtkSmartPointer<vtkGlyph3D> glyphsToPick;
vtkSmartPointer<vtkRenderWindowInteractor> sceneRenderWindowInteractor;
private:
ScenePickCallback();
};
void ScenePickCallback::Execute(vtkObject *caller, unsigned long eventId, void* data)
{
if(eventId == vtkCommand::LeftButtonReleaseEvent)
{
int pickPosition[2];
sceneRenderWindowInteractor->GetEventPosition(pickPosition);
sceneRenderWindowInteractor->GetPicker()->Pick(pickPosition[0], pickPosition[1], 0, sceneRenderer);
vtkCellPicker *cellPicker = reinterpret_cast<vtkCellPicker*>(picker.GetPointer());
if(cellPicker)
{
// Check if correct actor was picked
if(cellPicker->GetActor() == actorToPick.GetPointer())
{
vtkDataArray *inputIds = glyphsToPick->GetOutput()->GetPointData()->GetArray("InputPointIds");
if(inputIds)
{
vtkCell *cell = glyphsToPick->GetOutput()->GetCell(cellPicker->GetCellId());
if(cell && cell->GetNumberOfPoints() > 0)
{
// get first PointId from picked cell
vtkIdType inputId = cell->GetPointId(0);
// get matching Id from "InputPointIds" array
vtkIdType selectedPointId = inputIds->GetTuple1(inputId);
if(selectedPointId >= 0)
{
// POINT PICKED!
// selectedPointId = Picked PointID (original input points)
}
}
}
}
else
{
// NONE PICKED
}
}
}
}
Allan James
High Performance Computing & Research Support
Queensland University of Technology
(07) 3138 9264
ar.james at qut.edu.au<mailto:ar.james at qut.edu.au>
http://www.qut.edu.au/its/hpc
<(((º> ._.·´¯`·.. >++(((º> ._.·´¯`·.. >++(((º>
-----Original Message-----
From: Gomez, Alberto [mailto:alberto.gomez at kcl.ac.uk]
Sent: Friday, 30 April 2010 8:53 PM
To: Allan James
Cc: vtkusers at vtk.org<mailto:vtkusers at vtk.org>
Subject: Re: [vtkusers] vtkPointPicker / vtkGlyph3D problem
Hi all,
I am trying to select a vector from a vector field with the
mouse. The
vector field is a glyph of vectors and it is generated in the
following
way (1). Then I use a custom interaction (subclassing
vtkInteractionStyleTrackballCamera) so that I pick points
when I press
the mouse button (2). When I click the left button, a
callback (3) does
some processing. The problem is that the position I get does
not match
the real vector position (i.e. I plot a vector at the 3D point I get
with the picker through the method picker->GetPickPosition()
and it does
not match). Anyone has a clue on why? I have played around with the
tolerance with no success.
Another question, how can I get the point information (vector and
position) from the point id??
Thanks,
Alberto
(1) Vector field generation :
//positions
vtkSmartPointer<vtkPoints> pts =
vtkSmartPointer<vtkPoints>::New();
pts->SetNumberOfPoints(num_pts);
//directions
vtkSmartPointer<vtkDoubleArray> vecArr =
vtkSmartPointer<vtkDoubleArray>::New();
vecArr->SetNumberOfComponents(3);
vecArr->SetNumberOfTuples(num_pts);
for (int i = 0; i < num_pts; i++) {
pts->InsertNextPoint(positions[i][0], positions[i][1],
positions[i][2]);
float tuple[3] = {(float) directions[i][0] , (float)
directions[i][1], (float) directions[i][2]};
vecArr->InsertNextTuple(tuple);
}
// put vectors and positions into a grid which will be the
glyph's input
vtkSmartPointer<vtkUnstructuredGrid> uGrid = vtkSmartPointer<
vtkUnstructuredGrid>::New();
uGrid->SetPoints(pts);
uGrid->GetPointData()->SetVectors(vecArr);
// glyph construction
vtkSmartPointer<vtkArrowSource> arrow =
vtkSmartPointer<vtkArrowSource>::New();
vtkSmartPointer<vtkGlyph3D> glyph =
vtkSmartPointer<vtkGlyph3D>::New();
glyph->SetInput(uGrid);
glyph->SetSource(arrow->GetOutput());
glyph->SetScaleModeToScaleByVector();
glyph->GeneratePointIdsOn();
//Mapper and actor
vtkSmartPointer<vtkPolyDataMapper> gMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
gMapper->SetInput(glyph->GetOutput());
gMapper->ScalarVisibilityOff();
gMapper->SetScalarRange(uGrid->GetScalarRange());
vtkSmartPointer<vtkActor> gactor = vtkSmartPointer<vtkActor>::New();
gactor->SetMapper(gMapper);
gactor->GetProperty()->SetColor(color);
ren->AddActor(gactor);
(2) Detail of my subclass for custom interactor style:
virtual void OnLeftButtonDown()
{
if (this->Interactor->GetControlKey() ){
int* pos = this->GetInteractor()->GetEventPosition();
pointPicker->Pick(pos[0], pos[1], 0,
this->GetDefaultRenderer());
} else{
vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}
}
(3) Callback class (detail)
// Callback thats get called for a picking event.
class PickCallback : public vtkCommand
{
public:
static PickCallback* New()
{
return new PickCallback();
}
void Execute(vtkObject* caller, unsigned long eventId,
void* callData)
{
vtkPointPicker *picker = static_cast< vtkPointPicker* >(caller);
if(picker->GetPointId() < 1)
{
// Nothing is picked.
}
else
{
double* pos = picker->GetPickPosition();
std::cout << pos[0]<< ","<< pos[1]<< ","<< pos[2]<< std::endl;
actor = generateVectorActor(picker);
ren->AddViewProp(actor);
}
}
Allan James wrote:
Hi all,
I have an issue with code that is using vtkPointPicker to
pick points displayed using vtkGlyph3D.
Now I have the picking working great for most of the glyphs
- using vtkGlyph3D->GeneratePointIdsOn(); and I am able to
select glyphs and display a sphere at the selected glyph location.
My problem is that while this works perfectly 99% of the
time - there are certain glyphs that are either very
difficult to pick (sometimes impossible it seems) or I have
to click about 20 pixels or so above or next to the glyph for
the pick to work. Has anyone seen this issue and/or can suggest a fix?
Why would picking work perfectly for most glyphs but not
for some others - when all of the glyphs are generated from
the same simple pointset using the same vtkGlyph3D filter?
Any help would be muchly appreciated - thanks
Allan James
High Performance Computing & Research Support
Queensland University of Technology
(07) 3138 9264
ar.james at qut.edu.au<mailto:ar.james at qut.edu.au><mailto:ar.james at qut.edu.au><mailto:ar.james at qut.edu.au>
http://www.qut.edu.au/its/hpc
<(((º> ._.·´¯`·.. >++(((º> ._.·´¯`·.. >++(((º>
--
Alberto Gómez
/Division of Imaging Sciences
The Rayne Institute
4th Floor, Lambeth Wing
St Thomas' Hospital
London SE1 7EH /
phone: +44 (0) 20 718 88364
email: alberto.gomez at kcl.ac.uk<mailto:alberto.gomez at kcl.ac.uk> <mailto:alberto.gomez at kcl.ac.uk><mailto:alberto.gomez at kcl.ac.uk>
_______________________________________________
Powered by www.kitware.com<http://www.kitware.com>
Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ
Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers
--
Alberto Gómez
Division of Imaging Sciences
The Rayne Institute
4th Floor, Lambeth Wing
St Thomas' Hospital
London SE1 7EH
phone: +44 (0) 20 718 88364
email: alberto.gomez at kcl.ac.uk<mailto:alberto.gomez at kcl.ac.uk>
More information about the vtkusers
mailing list