1 // SALOME VTKViewer : build VTK viewer into Salome desktop
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : VTKViewer_CellRectPicker.cxx
25 // Author : Natalia KOPNOVA
28 #include <VTKViewer_CellRectPicker.h>
30 #include "vtkGenericCell.h"
31 #include "vtkAssemblyNode.h"
32 #include "vtkAssemblyPath.h"
33 #include "vtkObjectFactory.h"
34 #include "vtkImageData.h"
35 #include "vtkMapper.h"
36 #include "vtkVolumeMapper.h"
40 #include "vtkPoints.h"
46 //----------------------------------------------------------------------------
47 vtkStandardNewMacro(VTKViewer_CellRectPicker);
48 //----------------------------------------------------------------------------
50 VTKViewer_CellRectPicker::VTKViewer_CellRectPicker()
52 this->Cell = vtkGenericCell::New();
53 this->Quad1 = vtkQuad::New();
54 this->Quad2 = vtkQuad::New();
57 VTKViewer_CellRectPicker::~VTKViewer_CellRectPicker()
60 this->Quad1->Delete();
61 this->Quad2->Delete();
64 void VTKViewer_CellRectPicker::Initialize()
67 this->VTKViewer_RectPicker::Initialize();
70 //----------------------------------------------------------------------------
71 float VTKViewer_CellRectPicker::IntersectWithHex(float p1[4][4], float p2[4][4], float tol,
72 vtkAssemblyPath *path, vtkProp3D *prop3D,
73 vtkAbstractMapper3D *m)
77 vtkVolumeMapper *volumeMapper;
79 // Get the underlying dataset
80 if ( (mapper=vtkMapper::SafeDownCast(m)) != NULL ) {
81 input = mapper->GetInput();
83 else if ( (volumeMapper=vtkVolumeMapper::SafeDownCast(m)) != NULL ) {
84 input = volumeMapper->GetInput();
87 return VTK_LARGE_FLOAT;
91 if ( (numCells = input->GetNumberOfCells()) < 1 ) {
96 float bounds[6], center[3], cp1[3], cp2[3];
97 float pcoord[3], weight[4], dist;
98 float t1[2], t2[2], x[3], t;
100 for (k = 0; k < 4; k++) {
101 this->Quad1->PointIds->SetId(k, k);
102 this->Quad1->Points->SetPoint(k, p1[k]);
103 this->Quad2->PointIds->SetId(k, k);
104 this->Quad2->Points->SetPoint(k, p2[k]);
108 cout << "---> Selection area:" << endl;
109 for (k = 0; k < 4; k++)
110 cout << "\t(" << p1[k][0] << ", " << p1[k][1] << ", " << p1[k][2] << ")";
112 for (k = 0; k < 4; k++)
113 cout << "\t(" << p2[k][0] << ", " << p2[k][1] << ", " << p2[k][2] << ")";
118 VTKViewer_CellData cellData;
119 VTKViewer_CellDataSet dataList;
121 char inside; int n; float *point;
122 float tMin = VTK_LARGE_FLOAT, xMin[3];
123 for (cellId = 0; cellId < numCells; cellId++) {
124 input->GetCell(cellId, this->Cell);
126 this->Cell->GetBounds(bounds);
127 for (i = 0; i < 3; i++)
128 center[i] = (bounds[2*i]+bounds[2*i+1])/2;
131 if (!VTKViewer_RectPicker::PointInside(center, p1, p2, 0.01))
136 n = this->Cell->Points->GetNumberOfPoints();
137 //cout << "---> Info cell " << cellId << " (" << n << "): " << endl;
138 for (k = 0; k < n; k++) {
139 point = this->Cell->Points->GetPoint(k);
140 //cout << " P (" << point[0] << ", " << point[1] << ", " << point[2] << ")";
141 if (!VTKViewer_RectPicker::PointInside(point, p1, p2)) {
146 if (!inside) continue;
148 //cout << "---> Inside cell " << cellId << endl;
150 this->Quad1->EvaluatePosition(center, 0, subId, pcoord, dist, weight);
151 t1[0] = pcoord[0]; t1[1] = pcoord[1];
152 this->Quad2->EvaluatePosition(center, 0, subId, pcoord, dist, weight);
153 t2[0] = pcoord[0]; t2[1] = pcoord[1];
155 pcoord[0] = (t1[0]+t2[0])/2; pcoord[1] = (t1[1]+t2[1])/2; pcoord[2] = 0;
157 this->Quad1->EvaluateLocation(subId, pcoord, cp1, weight);
158 this->Quad2->EvaluateLocation(subId, pcoord, cp2, weight);
160 if (this->Cell->IntersectWithLine(cp1, cp2, tol, t, x, pcoord, subId)) {
161 cellData.cellId = cellId;
162 cellData.subId = subId;
164 for (i = 0; i < 3; i++) {
165 cellData.p1[i] = cp1[i];
166 cellData.p2[i] = cp2[i];
169 cout << "---> Include cell " << cellId << ", depth = " << t << endl;
170 cout << " P1 = (" << cp1[0] << ", " << cp1[1] << ", " << cp1[2] << ")" << endl;
171 cout << " P2 = (" << cp2[0] << ", " << cp2[1] << ", " << cp2[2] << ")" << endl;
173 IncludeCell(input, cellData, dataList);
176 for (i = 0; i < 3; i++)
182 if (!dataList.empty()) {
183 // compare against other actors
184 IncludeActor(prop3D, input, dataList);
185 if (tMin < this->GlobalTMin) {
186 this->MarkPicked(path, prop3D, m, tMin, xMin);
194 //----------------------------------------------------------------------------
195 void VTKViewer_CellRectPicker::IncludeCell(vtkDataSet* input,
196 VTKViewer_CellData cellData,
197 VTKViewer_CellDataSet& dataList)
199 vtkGenericCell* cell1 = vtkGenericCell::New();
200 vtkGenericCell* cell2 = vtkGenericCell::New();
204 input->GetCell(cellData.cellId, cell1);
205 if (cell1->GetNumberOfFaces() > 0)
206 sub1 = cell1->GetFace(cellData.subId);
209 float p1[3], p2[3], dir[3];
212 VTKViewer_CellData curData;
213 VTKViewer_CellDataSet::iterator it;
214 for (it = dataList.begin(); it != dataList.end();) {
216 for (i = 0; i < 3; i++) {
217 p1[i] = (cellData.p1[i]+curData.p1[i])/2;
218 p2[i] = (cellData.p2[i]+curData.p2[i])/2;
219 dir[i] = p2[i] - p1[i];
222 input->GetCell(curData.cellId, cell2);
224 if (cell2->GetNumberOfFaces() > 0)
225 sub2 = cell2->GetFace(curData.subId);
229 result = IntersectCells(sub1, cellData.depth,
230 sub2, curData.depth, dir);
232 result = IntersectCells(sub1, cellData.depth,
233 cell2, curData.depth, dir);
237 result = IntersectCells(cell1, cellData.depth,
238 sub2, curData.depth, dir);
240 result = IntersectCells(cell1, cellData.depth,
241 cell2, curData.depth, dir);
244 cout << " Direction = (" << dir[0] << ", " << dir[1] << ", " << dir[2] << ")";
245 cout << " depth = " << cellData.depth << ", " << curData.depth << ", " << result << endl;
249 it = dataList.erase(it);
260 //cout << " add " << endl;
261 dataList.push_back(cellData);
268 //----------------------------------------------------------------------------
269 void VTKViewer_CellRectPicker::IncludeActor(vtkProp3D* prop,
271 VTKViewer_CellDataSet& dataList)
273 vtkGenericCell* cell1 = vtkGenericCell::New();
274 vtkGenericCell* cell2 = vtkGenericCell::New();
277 float p1[3], p2[3], dir[3];
280 VTKViewer_CellDataSet actorData;
281 VTKViewer_CellData curData, cellData;
282 VTKViewer_CellDataSet::iterator it1, it2;
283 VTKViewer_ActorDataMap::iterator it;
285 for (it1 = dataList.begin(); it1 != dataList.end();) {
287 input->GetCell(cellData.cellId, cell1);
290 for (it = ActorData.begin(); it != ActorData.end(); ++it) {
291 vtkActor* actor = (*it).first;
292 actorData = (*it).second;
294 for (it2 = actorData.begin(); it2 != actorData.end();) {
296 for (i = 0; i < 3; i++) {
297 p1[i] = (cellData.p1[i]+curData.p1[i])/2;
298 p2[i] = (cellData.p2[i]+curData.p2[i])/2;
299 dir[i] = p2[i] - p1[i];
302 actor->GetMapper()->GetInput()->GetCell(curData.cellId, cell2);
303 result = IntersectCells(cell1, cellData.depth,
304 cell2, curData.depth, dir);
307 it2 = actorData.erase(it2);
312 it1 = dataList.erase(it1);
324 if (!dataList.empty()) {
326 if ((actor = vtkActor::SafeDownCast(prop)) != NULL)
327 ActorData[actor] = dataList;
334 int VTKViewer_CellRectPicker::IntersectCells(vtkCell* c1, float d1, vtkCell* c2, float d2, float dir[3])
337 float *orig, cp[3], bounds[6];
341 // define the central point and cell for projection
342 if (fabs(d1-d2) < 1.e-7) return 0;
345 orig = c1->Points->GetPoint(0);
348 c2->GetBounds(bounds);
349 for (i = 0; i < 3; i++)
350 cp[i] = (bounds[2*i] + bounds[2*i+1])/2;
353 orig = c2->Points->GetPoint(0);
356 c1->GetBounds(bounds);
357 for (i = 0; i < 3; i++)
358 cp[i] = (bounds[2*i] + bounds[2*i+1])/2;
362 vtkPlane::GeneralizedProjectPoint(cp, orig, dir, proj);
365 vtkPoints* aPoints = vtkPoints::New();
366 for (k = 0; k < cell->Points->GetNumberOfPoints(); k++) {
367 p = cell->Points->GetPoint(k);
368 vtkPlane::GeneralizedProjectPoint(p, orig, dir, pp);
369 aPoints->InsertNextPoint(pp[0], pp[1], pp[2]);
373 if (PointInside(proj, aPoints)) {
374 result = (d1<d2) ? 1 : 2;
378 // test for boundary cells
379 for (k = 0; k < tcell->Points->GetNumberOfPoints(); k++) {
380 p = tcell->Points->GetPoint(k);
381 vtkPlane::GeneralizedProjectPoint(p, orig, dir, pp);
382 if (PointInside(pp, aPoints)) {
386 if (result && d2<d1) result = 2;
393 char VTKViewer_CellRectPicker::PointInside(float point[3], vtkPoints* list)
396 float x[3], *a1, *a2, v[3], p[3], q[3];
398 n = list->GetNumberOfPoints();
401 for (k = 0; k < n; k++) {
402 l = k+1; if (l == n) l = 0;
403 a1 = list->GetPoint(k);
404 a2 = list->GetPoint(l);
407 for (i = 0; i < 3; i++) {
408 x[i] = point[i] - a1[i];
412 // check if point coincides with vertex
413 if (x[0]*x[0] + x[1]*x[1] + x[2]*x[2] < 1.e-7) return 0;
416 vtkMath::Cross(x, v, p);
418 // check if point lays on edge
419 if (p[0]*p[0] + p[1]*p[1] + p[2]*p[2] < 1.e-7) return 0;
421 // check if normals are in the same direction
423 if (vtkMath::Dot(p, q) < 0.0) return 0;
426 // remember normal direction
427 for (i = 0; i < 3; i++) {