1 #include <VTKViewer_CellRectPicker.h>
3 #include "vtkGenericCell.h"
4 #include "vtkAssemblyNode.h"
5 #include "vtkAssemblyPath.h"
6 #include "vtkObjectFactory.h"
7 #include "vtkImageData.h"
9 #include "vtkVolumeMapper.h"
13 #include "vtkPoints.h"
17 vtkStandardNewMacro(VTKViewer_CellRectPicker);
19 //****************************************************************
20 VTKViewer_CellRectPicker::VTKViewer_CellRectPicker()
22 this->Cell = vtkGenericCell::New();
23 this->Quad1 = vtkQuad::New();
24 this->Quad2 = vtkQuad::New();
27 //****************************************************************
28 VTKViewer_CellRectPicker::~VTKViewer_CellRectPicker()
31 this->Quad1->Delete();
32 this->Quad2->Delete();
35 //****************************************************************
36 void VTKViewer_CellRectPicker::Initialize()
39 this->VTKViewer_RectPicker::Initialize();
42 //****************************************************************
43 float VTKViewer_CellRectPicker::IntersectWithHex(float p1[4][4], float p2[4][4], float tol,
44 vtkAssemblyPath *path, vtkProp3D *prop3D,
45 vtkAbstractMapper3D *m)
49 vtkVolumeMapper *volumeMapper;
51 // Get the underlying dataset
52 if ( (mapper=vtkMapper::SafeDownCast(m)) != NULL ) {
53 input = mapper->GetInput();
55 else if ( (volumeMapper=vtkVolumeMapper::SafeDownCast(m)) != NULL ) {
56 input = volumeMapper->GetInput();
59 return VTK_LARGE_FLOAT;
63 if ( (numCells = input->GetNumberOfCells()) < 1 ) {
68 float bounds[6], center[3], cp1[3], cp2[3];
69 float pcoord[3], weight[4], dist;
70 float t1[2], t2[2], x[3], t;
72 for (k = 0; k < 4; k++) {
73 this->Quad1->PointIds->SetId(k, k);
74 this->Quad1->Points->SetPoint(k, p1[k]);
75 this->Quad2->PointIds->SetId(k, k);
76 this->Quad2->Points->SetPoint(k, p2[k]);
80 cout << "---> Selection area:" << endl;
81 for (k = 0; k < 4; k++)
82 cout << "\t(" << p1[k][0] << ", " << p1[k][1] << ", " << p1[k][2] << ")";
84 for (k = 0; k < 4; k++)
85 cout << "\t(" << p2[k][0] << ", " << p2[k][1] << ", " << p2[k][2] << ")";
90 VTKViewer_CellData cellData;
91 VTKViewer_CellDataSet dataList;
93 char inside; int n; float *point;
94 float tMin = VTK_LARGE_FLOAT, xMin[3];
95 for (cellId = 0; cellId < numCells; cellId++) {
96 input->GetCell(cellId, this->Cell);
98 this->Cell->GetBounds(bounds);
99 for (i = 0; i < 3; i++)
100 center[i] = (bounds[2*i]+bounds[2*i+1])/2;
103 if (!VTKViewer_RectPicker::PointInside(center, p1, p2, 0.01))
108 n = this->Cell->Points->GetNumberOfPoints();
109 //cout << "---> Info cell " << cellId << " (" << n << "): " << endl;
110 for (k = 0; k < n; k++) {
111 point = this->Cell->Points->GetPoint(k);
112 //cout << " P (" << point[0] << ", " << point[1] << ", " << point[2] << ")";
113 if (!VTKViewer_RectPicker::PointInside(point, p1, p2)) {
118 if (!inside) continue;
120 //cout << "---> Inside cell " << cellId << endl;
122 this->Quad1->EvaluatePosition(center, 0, subId, pcoord, dist, weight);
123 t1[0] = pcoord[0]; t1[1] = pcoord[1];
124 this->Quad2->EvaluatePosition(center, 0, subId, pcoord, dist, weight);
125 t2[0] = pcoord[0]; t2[1] = pcoord[1];
127 pcoord[0] = (t1[0]+t2[0])/2; pcoord[1] = (t1[1]+t2[1])/2; pcoord[2] = 0;
129 this->Quad1->EvaluateLocation(subId, pcoord, cp1, weight);
130 this->Quad2->EvaluateLocation(subId, pcoord, cp2, weight);
132 if (this->Cell->IntersectWithLine(cp1, cp2, tol, t, x, pcoord, subId)) {
133 cellData.cellId = cellId;
134 cellData.subId = subId;
136 for (i = 0; i < 3; i++) {
137 cellData.p1[i] = cp1[i];
138 cellData.p2[i] = cp2[i];
141 cout << "---> Include cell " << cellId << ", depth = " << t << endl;
142 cout << " P1 = (" << cp1[0] << ", " << cp1[1] << ", " << cp1[2] << ")" << endl;
143 cout << " P2 = (" << cp2[0] << ", " << cp2[1] << ", " << cp2[2] << ")" << endl;
145 IncludeCell(input, cellData, dataList);
148 for (i = 0; i < 3; i++)
154 if (!dataList.empty()) {
155 // compare against other actors
156 IncludeActor(prop3D, input, dataList);
157 if (tMin < this->GlobalTMin) {
158 this->MarkPicked(path, prop3D, m, tMin, xMin);
165 //****************************************************************
166 void VTKViewer_CellRectPicker::IncludeCell(vtkDataSet* input,
167 VTKViewer_CellData cellData,
168 VTKViewer_CellDataSet& dataList)
170 vtkGenericCell* cell1 = vtkGenericCell::New();
171 vtkGenericCell* cell2 = vtkGenericCell::New();
175 input->GetCell(cellData.cellId, cell1);
176 if (cell1->GetNumberOfFaces() > 0)
177 sub1 = cell1->GetFace(cellData.subId);
180 float p1[3], p2[3], dir[3];
183 VTKViewer_CellData curData;
184 VTKViewer_CellDataSet::iterator it;
185 for (it = dataList.begin(); it != dataList.end();) {
187 for (i = 0; i < 3; i++) {
188 p1[i] = (cellData.p1[i]+curData.p1[i])/2;
189 p2[i] = (cellData.p2[i]+curData.p2[i])/2;
190 dir[i] = p2[i] - p1[i];
193 input->GetCell(curData.cellId, cell2);
195 if (cell2->GetNumberOfFaces() > 0)
196 sub2 = cell2->GetFace(curData.subId);
200 result = IntersectCells(sub1, cellData.depth,
201 sub2, curData.depth, dir);
203 result = IntersectCells(sub1, cellData.depth,
204 cell2, curData.depth, dir);
208 result = IntersectCells(cell1, cellData.depth,
209 sub2, curData.depth, dir);
211 result = IntersectCells(cell1, cellData.depth,
212 cell2, curData.depth, dir);
215 cout << " Direction = (" << dir[0] << ", " << dir[1] << ", " << dir[2] << ")";
216 cout << " depth = " << cellData.depth << ", " << curData.depth << ", " << result << endl;
220 it = dataList.erase(it);
231 //cout << " add " << endl;
232 dataList.push_back(cellData);
239 //****************************************************************
240 void VTKViewer_CellRectPicker::IncludeActor(vtkProp3D* prop,
242 VTKViewer_CellDataSet& dataList)
244 vtkGenericCell* cell1 = vtkGenericCell::New();
245 vtkGenericCell* cell2 = vtkGenericCell::New();
248 float p1[3], p2[3], dir[3];
251 VTKViewer_CellDataSet actorData;
252 VTKViewer_CellData curData, cellData;
253 VTKViewer_CellDataSet::iterator it1, it2;
254 VTKViewer_ActorDataMap::iterator it;
256 for (it1 = dataList.begin(); it1 != dataList.end();) {
258 input->GetCell(cellData.cellId, cell1);
261 for (it = ActorData.begin(); it != ActorData.end(); ++it) {
262 //vtkActor* actor = (*it).first;
263 actorData = (*it).second;
265 for (it2 = actorData.begin(); it2 != actorData.end();) {
267 for (i = 0; i < 3; i++) {
268 p1[i] = (cellData.p1[i]+curData.p1[i])/2;
269 p2[i] = (cellData.p2[i]+curData.p2[i])/2;
270 dir[i] = p2[i] - p1[i];
273 input->GetCell(curData.cellId, cell2);
274 result = IntersectCells(cell1, cellData.depth,
275 cell2, curData.depth, dir);
278 it2 = actorData.erase(it2);
283 it1 = dataList.erase(it1);
295 if (!dataList.empty()) {
297 if ((actor = vtkActor::SafeDownCast(prop)) != NULL)
298 ActorData[actor] = dataList;
305 //****************************************************************
306 int VTKViewer_CellRectPicker::IntersectCells(vtkCell* c1, float d1, vtkCell* c2, float d2, float dir[3])
309 float *orig, cp[3], bounds[6];
313 // define the central point and cell for projection
314 if (fabs(d1-d2) < 1.e-7) return 0;
317 orig = c1->Points->GetPoint(0);
320 c2->GetBounds(bounds);
321 for (i = 0; i < 3; i++)
322 cp[i] = (bounds[2*i] + bounds[2*i+1])/2;
325 orig = c2->Points->GetPoint(0);
328 c1->GetBounds(bounds);
329 for (i = 0; i < 3; i++)
330 cp[i] = (bounds[2*i] + bounds[2*i+1])/2;
334 vtkPlane::GeneralizedProjectPoint(cp, orig, dir, proj);
337 vtkPoints* aPoints = vtkPoints::New();
338 for (k = 0; k < cell->Points->GetNumberOfPoints(); k++) {
339 p = cell->Points->GetPoint(k);
340 vtkPlane::GeneralizedProjectPoint(p, orig, dir, pp);
341 aPoints->InsertNextPoint(pp[0], pp[1], pp[2]);
345 if (PointInside(proj, aPoints)) {
346 result = (d1<d2) ? 1 : 2;
350 // test for boundary cells
351 for (k = 0; k < tcell->Points->GetNumberOfPoints(); k++) {
352 p = tcell->Points->GetPoint(k);
353 vtkPlane::GeneralizedProjectPoint(p, orig, dir, pp);
354 if (PointInside(pp, aPoints)) {
358 if (result && d2<d1) result = 2;
365 //****************************************************************
366 char VTKViewer_CellRectPicker::PointInside(float point[3], vtkPoints* list)
369 float x[3], *a1, *a2, v[3], p[3], q[3];
371 n = list->GetNumberOfPoints();
374 for (k = 0; k < n; k++) {
375 l = k+1; if (l == n) l = 0;
376 a1 = list->GetPoint(k);
377 a2 = list->GetPoint(l);
380 for (i = 0; i < 3; i++) {
381 x[i] = point[i] - a1[i];
385 // check if point coincides with vertex
386 if (x[0]*x[0] + x[1]*x[1] + x[2]*x[2] < 1.e-7) return 0;
389 vtkMath::Cross(x, v, p);
391 // check if point lays on edge
392 if (p[0]*p[0] + p[1]*p[1] + p[2]*p[2] < 1.e-7) return 0;
394 // check if normals are in the same direction
396 if (vtkMath::Dot(p, q) < 0.0) return 0;
399 // remember normal direction
400 for (i = 0; i < 3; i++) {