[vtkusers] Pick a point...
Jonathan.Bailleul
Jonathan.Bailleul at greyc.ismra.fr
Thu Jan 8 18:21:47 EST 2004
ted lee wrote:
>
> hi all..,
> if i wanna to pick a 3d coordinates from the render window after press "P"+Lbuttomdown .., how can i do that.., can any body write a somall sample code to pick this point..
> any help will be appreciated..,
> Lee..,
>
I've got something that roughly does the trick, even if it is poorly
coded. If anyone has suggestions about it, you're welcome!
You can select a triangle, and get vertices indexes and coordinates on
the console.
(PS: you might need header files in
http://www.greyc.ismra.fr/~bailleul/Ressources/OpenSource-tarball.tgz,
because of included Vector.h)
--
-----------------------------------
Jonathan BAILLEUL, Doctorant
GREYC Image - Université de Caen
http://www.greyc.ismra.fr/~bailleul
-------------- next part --------------
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkActor2D.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkPointPicker.h"
#include "vtkCellPicker.h"
#include "vtkPicker.h"
#include "vtkPolyDataReader.h"
#include "vtkPolyData.h"
#include "vtkProperty.h"
#include "vtkCamera.h"
#include "vtkCommand.h"
#include "vtkCallbackCommand.h"
#include "vtkIdList.h"
#include "vtkConeSource.h"
#include "vtkSphereSource.h"
#include "vtkGlyph3D.h"
#include "vtkCellArray.h"
#include "vtkTextSource.h"
#include "vtkTextProperty.h"
#include "vtkTextMapper.h"
#include "vtkVectorText.h"
#include "vtkCoordinate.h"
/* GLOS (Graphic Library in Open Source), an ANSI Common Lisp OpenGL subset.
Copyright (C) 2000 the GLOS development team (http://glos.sourceforge.net) */
// using namespace std;
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include "Vector.h"
/* -------------------------------------------------------------------------- */
/* Global vars / functions */
/* -------------------------------------------------------------------------- */
#define ANNOTATE_KEY 'g'
#define NUMBER_KEY 'n'
#define UNUMBER_KEY 'u'
#define BG_R 0.2
#define BG_G 0.3
#define BG_B 0.4
#define DEBUG 0
// scale the actors (text & glyph) to match size of structure
float G_SIZESCALE = 0.1;
vtkRenderer* G_REN;
vtkRenderWindow* G_WREN;
vtkRenderWindowInteractor* G_IREN;
vtkPointPicker* G_PPICKER;
vtkCellPicker* G_CPICKER;
vtkPolyData* G_POLY; // last polydata source
vtkGlyph3D* G_SELGLYPH;
vtkActor* G_SELGLYPHACT;
vtkActor *G_txtActor1; vtkActor *G_txtActor2; vtkActor *G_txtActor3;
vtkPolyDataMapper* G_SELGLYPHMAP;
// vtkPolyDataMapper* G_MAP;
char* G_FILENAME;
vtkPoints *G_POINTS; // points of polydata object
int G_NBPOINTS;
vtkActor2D** G_NUMACTORS; // 2d actors for landmark annotation
void
recall_keybindings()
{
cout << endl << "Standard VTK intercation:";
cout << endl << "r: reset view; s: solid rendering; w: wireframe rendering; e: exit; a: move actor separately; c: back in common mode; f: move camera towards item under mouse";
cout << endl << "Custom VTK intercation:";
cout << endl << ANNOTATE_KEY << ": select polygon under mouse";
cout << endl << NUMBER_KEY << "/" << UNUMBER_KEY << ": toggle on/off display number of landmarks";
}
static void
usage(int argc, char **argv)
{
if ((((argc - 1) % 4) != 0) || (argc <= 1))
{
printf("Display .vtk object files for annotation purposes \n");
printf("Usage: %s [ <vtk object filename> <object color components from 0-255: R G B> ] + \n", argv[0]);
printf("Behaviour undefined if several objects loaded");
recall_keybindings();
exit(1);
}
}
/* -------------------------------------------------------------------------- */
/* actors creation for representing objects */
/* -------------------------------------------------------------------------- */
vtkActor*
makeTextActor(char *message)
{
vtkVectorText *txt = vtkVectorText::New();
txt -> SetText(message);
vtkPolyDataMapper *txtMapper = vtkPolyDataMapper::New();
vtkActor *txtActor = vtkActor::New();
txtMapper -> SetInput(txt -> GetOutput());
txtActor -> SetMapper(txtMapper);
txtActor -> SetScale(0.40 * G_SIZESCALE);
return txtActor;
}
vtkActor*
makeActor(char* filename, float r, float g, float b)
{
// create object geometry
vtkPolyDataReader *reader = vtkPolyDataReader::New();
reader -> SetFileName(filename);
reader -> Update();
G_POLY = reader -> GetOutput();
// map to graphics library
vtkPolyDataMapper *map = vtkPolyDataMapper::New();
map -> SetInput(reader -> GetOutput());
// retrieve size of object diagonal to adjust (global) scale factor
float ref_bounds[6]; map -> GetBounds(ref_bounds);
// retrieves norm of the diagonal of the bounding box of reference
double diagsize = Vector<float>(Point<float>(ref_bounds[0], ref_bounds[2], ref_bounds[4]),
Point<float>(ref_bounds[1], ref_bounds[3], ref_bounds[5])).norm();
G_SIZESCALE = diagsize / 30;
// actor coordinates geometry, properties, transformation
vtkActor *actor = vtkActor::New();
actor -> SetMapper(map);
actor -> GetProperty() -> SetDiffuseColor(r, g, b);
actor -> GetProperty() -> SetSpecularPower(50);
actor -> GetProperty() -> SetSpecular(0.5);
actor -> GetProperty() -> SetDiffuse(0.8);
actor -> GetProperty() -> SetInterpolationToFlat(); //Gouraud, Phong
vtkProperty *backprop = vtkProperty::New();
backprop -> SetDiffuseColor(r, g, b);
backprop -> SetDiffuse(0.2);
actor -> SetBackfaceProperty(backprop);
return actor;
}
vtkActor*
makeActor_255(char* filename, int r, int g, int b)
{
return makeActor(filename, (float) r / 255, (float) g / 255, (float) b / 255);
}
/* sets actor position to 2d projection of given 3d point */
void
Place2DActor(vtkRenderer *ren, vtkActor2D *act, float* pt)
{
float x, y, z;
int* coords = NULL;
// x = pt[0]; y = pt[1]; z = pt[2];
vtkCoordinate *c1 = vtkCoordinate::New();
c1 -> SetCoordinateSystemToWorld();
c1 -> SetValue(pt);
if (DEBUG) {cout << "before: " << x << " " << y << " " << z;}
coords = c1 -> GetComputedDisplayValue(ren);
x = coords[0]; y = coords[1];
if (DEBUG) {cout << " after:" << x << " " << y << " " << endl;}
act -> SetPosition(x, y);
}
/* -------------------------------------------------------------------------- */
/* Events */
/* -------------------------------------------------------------------------- */
void
PrintPoint(float* p, ostream &stream)
{
stream << " [" << p[0] << "; " << p[1] << "; " << p[2] << "] ";
}
void SelectCell(vtkRenderer* ren, vtkCellPicker *c_picker, int X, int Y)
{
float Point[3];
float* mypoint;
int CellId;
vtkIdType* ptsIds;
vtkIdType orig_index[3] = {0, 1, 2};
vtkIdType nbpts;
int i;
if ((c_picker -> Pick((float)X, (float)Y, (float)0, ren)) &&
(c_picker -> GetActors() -> GetNumberOfItems() == 1))
{
// id de la cellule. Attention, peut prendre celle du dessous.
CellId = c_picker -> GetCellId();
G_POLY -> GetCellPoints(CellId, nbpts, ptsIds); // seult 3 pts par cell (triangles)
assert(nbpts == 3);
vtkPolyData* selCell_poly = vtkPolyData::New();
vtkPoints* orig_pts = G_POLY -> GetPoints();
vtkPoints* selPoints = vtkPoints::New();
selPoints -> SetNumberOfPoints(3);
// selCell_poly is a polydata whose edges will be added glyphes
// polydata contains a triangle cell with point indexes 0 1 2
selCell_poly -> Allocate(2,2);
selCell_poly -> InsertNextCell(VTK_TRIANGLE, 3, orig_index);
// associate point list to polydata at correponding indexes
selPoints -> SetPoint(0, orig_pts -> GetPoint(ptsIds[0]));
selPoints -> SetPoint(1, orig_pts -> GetPoint(ptsIds[1]));
selPoints -> SetPoint(2, orig_pts -> GetPoint(ptsIds[2]));
selCell_poly -> SetPoints(selPoints);
// display selected cell
cout << " Cell Id: " << CellId;
cout << " PtsIds: " << ptsIds[0] << " " << ptsIds[1] << " " << ptsIds[2] << " ";
cout << " Pts: "; for (int i = 0; i < 3; i++) {PrintPoint(selPoints -> GetPoint(i), cout);}
G_txtActor1 -> SetPosition(selPoints -> GetPoint(0));
G_txtActor2 -> SetPosition(selPoints -> GetPoint(1));
G_txtActor3 -> SetPosition(selPoints -> GetPoint(2));
cout << "New actor 3 position: "; PrintPoint(G_txtActor1 -> GetPosition(), cout);
// display position of first point in different coordinate systems
vtkCoordinate *c1 = vtkCoordinate::New();
c1 -> SetValue(selPoints -> GetPoint(0));
c1 -> SetCoordinateSystemToDisplay();
cout << endl << "**pt as in file: "; PrintPoint(selPoints -> GetPoint(0), cout);
float* coords = NULL;
coords = c1 -> GetComputedWorldValue(ren);
cout << endl << "**point in world:"; PrintPoint(coords, cout);
// title modification
char* msg;
assert(msg = (char *)calloc(30, sizeof(char)));
sprintf(msg, "%s: %d %d %d", G_FILENAME, ptsIds[0], ptsIds[1], ptsIds[2]);
G_WREN -> SetWindowName(msg);
G_SELGLYPH -> SetInput(selCell_poly);
G_SELGLYPH -> Update();
}
}
void SelectPoint(vtkRenderer* ren, vtkPointPicker *p_picker, int X, int Y)
{
float Point[3];
float *pos;
if (p_picker -> Pick((float)X, (float)Y, (float)0, ren))
{
pos = p_picker -> GetPickPosition();
for(int i=0;i<3;i++)
Point[i] = pos[i];
cout << "Point(" << Point[0] << "," << Point[1] << "," << Point[2] << ")\n";
ren -> Render();
}
}
void
vectraEventHandler(vtkObject* caller, unsigned long eventId, void* ClientData, void* data)
{
vtkRenderer* ren = G_REN;
vtkRenderWindowInteractor* iren = G_IREN;
vtkPointPicker* p_picker = G_PPICKER;
vtkCellPicker* c_picker = G_CPICKER;
switch (eventId) {
case vtkCommand::TimerEvent:
cout << endl << "TimerEvent";
break;
case vtkCommand::KeyPressEvent:
{
int X, Y;
char keypressed = *(iren -> GetKeySym());
iren -> GetMousePosition(&X, &Y);
switch (keypressed)
{
// selection of a cell
case ANNOTATE_KEY:
cout << "|>|";
SelectCell(ren, c_picker, X, Y);
cout << "|<|" << endl ; fflush(stdout);
break;
/** */
// request to display number of each landmark
case NUMBER_KEY:
for (int i = 0; i < G_NBPOINTS; i++)
{
Place2DActor(G_REN, G_NUMACTORS[i], G_POINTS -> GetPoint(i));
G_NUMACTORS[i] -> SetVisibility(1);
}
break;
case UNUMBER_KEY:
for (int i = 0; i < G_NBPOINTS; i++)
G_NUMACTORS[i] -> VisibilityOff();
break;
/** */
default:
cerr << endl << "Unhandled Key";
}
}
break;
default:
cout << endl << "UnhandledEvent";
}
G_SELGLYPH -> Update();
G_SELGLYPHMAP -> Update();
G_IREN -> Render();
G_REN -> Render();
}
/* -------------------------------------------------------------------------- */
/* Main program */
/* -------------------------------------------------------------------------- */
int
main(int argc, char* argv[])
{
usage(argc, argv);
recall_keybindings();
int objects = (argc - 1) / 4;
int r, g, b, index;
// a renderer and render window
vtkRenderer *ren1 = vtkRenderer::New(); G_REN = ren1;
vtkRenderWindow *renWin = vtkRenderWindow::New();
G_WREN = renWin;
renWin -> AddRenderer(ren1);
renWin -> SetSize(450, 450);
renWin -> SetWindowName(argv[1]); G_FILENAME = argv[1];
//point picker object
vtkPointPicker *p_picker = vtkPointPicker::New(); G_PPICKER = p_picker;
vtkCellPicker *c_picker = vtkCellPicker::New(); G_CPICKER = c_picker;
// an interactor
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); G_IREN = iren;
iren -> SetRenderWindow(renWin);
vtkCallbackCommand *cbc = vtkCallbackCommand::New();
cbc -> SetCallback(vectraEventHandler);
iren -> AddObserver(vtkCommand::KeyPressEvent, cbc);
/* Create and attach actors for every input vtk file */
cout << endl << "Number of objects:" << objects;
// add the actor to the scene
for (int i = 0; i < objects; i++)
{
index = 1 + 4 * i;
r = atoi(argv[index + 1]);
g = atoi(argv[index + 2]);
b = atoi(argv[index + 3]);
ren1 -> AddActor(makeActor_255(argv[index], r, g, b));
cout << endl << "Object " << i << ": "<< argv[index] << " " << r << " " << g << " " << b;
}
cout << endl;
/* Generate cone glyphs for vertices */
vtkConeSource* cone = vtkConeSource::New();
vtkSphereSource *sphere = vtkSphereSource::New();
vtkGlyph3D* glyph = vtkGlyph3D::New();
vtkGlyph3D* selglyph = vtkGlyph3D::New(); G_SELGLYPH = selglyph;
vtkActor *spikeActor1 = vtkActor::New();
vtkActor *spikeActor2 = vtkActor::New(); G_SELGLYPHACT = spikeActor2;
vtkPolyDataMapper *spikeMapper1 = vtkPolyDataMapper::New();
vtkPolyDataMapper *spikeMapper2 = vtkPolyDataMapper::New(); G_SELGLYPHMAP = spikeMapper2;
selglyph -> SetSource(sphere -> GetOutput());
selglyph -> SetVectorModeToUseNormal();
selglyph -> SetScaleModeToScaleByVector();
selglyph -> SetScaleFactor(0.40 * G_SIZESCALE);
// the main characteristic of a glyph is its ability to
// automatically follow the attached points. all glyphs are copies
// of the same object.
glyph -> SetInput(G_POLY); // source points to glyph G_POLY: last vtkPolydata object read
glyph -> SetSource(cone -> GetOutput()); // glyph object
glyph -> ScalingOn();
glyph -> SetVectorModeToUseNormal();
glyph -> SetScaleModeToScaleByVector();
glyph -> SetScaleFactor(0.40 * G_SIZESCALE);
spikeMapper1 -> SetInput(glyph -> GetOutput());
spikeMapper2 -> SetInput(selglyph -> GetOutput());
spikeActor1 -> SetMapper(spikeMapper1);
spikeActor2 -> SetMapper(spikeMapper2);
// modify colors & co of spikes
spikeActor2 -> GetProperty() -> SetDiffuseColor(0.9, 0.1, 0.2);
spikeActor2 -> GetProperty() -> SetSpecularPower(50);
spikeActor2 -> GetProperty() -> SetSpecular(0.5);
spikeActor2 -> GetProperty() -> SetDiffuse(0.8);
/* create 3d text actors */
G_txtActor1 = makeTextActor("P1");
G_txtActor2 = makeTextActor("P2");
G_txtActor3 = makeTextActor("P3");
/* 2d actors for landmark annotation creation and attachment */
/** */
{
G_POINTS = G_POLY -> GetPoints();
G_NBPOINTS = G_POLY -> GetNumberOfPoints();
vtkTextProperty *tp = vtkTextProperty::New();
int i;
char msg[50];
vtkTextMapper** mappers;
assert(mappers = (vtkTextMapper**) calloc(G_NBPOINTS, sizeof(vtkTextMapper*)));
assert(G_NUMACTORS = (vtkActor2D**) calloc(G_NBPOINTS, sizeof(vtkActor2D*)));
for (i = 0; i < G_NBPOINTS; i++)
{
mappers[i] = vtkTextMapper::New();
tp = mappers[i] -> GetTextProperty();
tp -> SetFontFamilyToArial();
tp -> SetFontSize(10);
tp -> SetColor(1, 0, 0);
G_NUMACTORS[i] = vtkActor2D::New();
G_NUMACTORS[i] -> SetMapper(mappers[i]);
G_NUMACTORS[i] -> VisibilityOff();
G_NUMACTORS[i] -> SetPosition(0,0);
sprintf(msg, "%d", i);
mappers[i] -> SetInput(msg);
ren1 -> AddActor(G_NUMACTORS[i]);
}
}
/* rendering setup and actors association */
ren1 -> AddActor(G_txtActor1);
ren1 -> AddActor(G_txtActor2);
ren1 -> AddActor(G_txtActor3);
ren1 -> AddActor(spikeActor1);
ren1 -> AddActor(spikeActor2);
ren1 -> SetBackground(BG_R, BG_G, BG_B); // fixed background color
ren1 -> GetActiveCamera() -> SetViewUp(0, -1, 0);
ren1 -> GetActiveCamera() -> Azimuth(180);
// render an image (lights and cameras are created automatically)
renWin -> Render();
// begin mouse interaction
iren -> Initialize();
iren -> Start();
return EXIT_SUCCESS;
}
More information about the vtkusers
mailing list