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_RectPicker.cxx
25 // Author : Natalia KOPNOVA
28 #include <VTKViewer_RectPicker.h>
31 #include "vtkAssemblyNode.h"
32 #include "vtkAssemblyPath.h"
33 #include "vtkCamera.h"
34 #include "vtkCommand.h"
35 #include "vtkImageData.h"
36 #include "vtkLODProp3D.h"
37 #include "vtkMapper.h"
39 #include "vtkObjectFactory.h"
40 #include "vtkPoints.h"
41 #include "vtkProp3DCollection.h"
42 #include "vtkProperty.h"
43 #include "vtkRenderWindow.h"
44 #include "vtkRenderer.h"
45 #include "vtkTransform.h"
46 #include "vtkVertex.h"
47 #include "vtkVolume.h"
48 #include "vtkVolumeMapper.h"
52 //----------------------------------------------------------------------------
53 vtkStandardNewMacro(VTKViewer_RectPicker);
55 //----------------------------------------------------------------------------
56 /*!Constructor. Do nothing*/
57 VTKViewer_RectPicker::VTKViewer_RectPicker()
61 //----------------------------------------------------------------------------
62 /*!Perform pick operation with selection rectangle provided. Normally the
63 * first two values for the selection top-left and right-bottom points are
64 * x-y pixel coordinate, and the third value is =0.
65 * \retval Return non-zero if something was successfully picked.
67 int VTKViewer_RectPicker::Pick(float selectionX1, float selectionY1, float selectionZ1,
68 float selectionX2, float selectionY2, float selectionZ2,
69 vtkRenderer *renderer)
74 vtkAbstractMapper3D *mapper = NULL;
75 float p1World[4][4], p2World[4][4], p1Mapper[4][4], p2Mapper[4][4];
81 float cameraPos[4], cameraFP[4];
82 float *displayCoords, *worldCoords;
83 float pickPosition[4][3];
85 float ray[4][3], rayLength[4];
88 float windowLowerLeft[4], windowUpperRight[4];
94 // Initialize picking process
96 this->Renderer = renderer;
98 /* Selection point is not defined for the rectangle
99 this->SelectionPoint[0] =
100 this->SelectionPoint[1] =
101 this->SelectionPoint[2] =
104 // Invoke start pick method if defined
105 this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
107 if ( renderer == NULL )
109 vtkErrorMacro(<<"Must specify renderer!");
113 // Get camera focal point and position. Convert to display (screen)
114 // coordinates. We need a depth value for z-buffer.
116 camera = renderer->GetActiveCamera();
117 camera->GetPosition((float *)cameraPos); cameraPos[3] = 1.0;
118 camera->GetFocalPoint((float *)cameraFP); cameraFP[3] = 1.0;
120 renderer->SetWorldPoint(cameraFP);
121 renderer->WorldToDisplay();
122 displayCoords = renderer->GetDisplayPoint();
123 selectionZ1 = selectionZ2 = displayCoords[2];
125 // Convert the selection rectangle into world coordinates.
127 renderer->SetDisplayPoint(selectionX1, selectionY1, selectionZ1);
128 renderer->DisplayToWorld();
129 worldCoords = renderer->GetWorldPoint();
130 if ( worldCoords[3] == 0.0 )
132 vtkErrorMacro(<<"Bad homogeneous coordinates");
135 for (i=0; i < 3; i++)
137 pickPosition[0][i] = worldCoords[i] / worldCoords[3];
140 renderer->SetDisplayPoint(selectionX1, selectionY2, (selectionZ1+selectionZ2)/2);
141 renderer->DisplayToWorld();
142 worldCoords = renderer->GetWorldPoint();
143 if ( worldCoords[3] == 0.0 )
145 vtkErrorMacro(<<"Bad homogeneous coordinates");
148 for (i=0; i < 3; i++)
150 pickPosition[1][i] = worldCoords[i] / worldCoords[3];
153 renderer->SetDisplayPoint(selectionX2, selectionY2, selectionZ2);
154 renderer->DisplayToWorld();
155 worldCoords = renderer->GetWorldPoint();
156 if ( worldCoords[3] == 0.0 )
158 vtkErrorMacro(<<"Bad homogeneous coordinates");
161 for (i=0; i < 3; i++)
163 pickPosition[2][i] = worldCoords[i] / worldCoords[3];
166 renderer->SetDisplayPoint(selectionX2, selectionY1, (selectionZ1+selectionZ2)/2);
167 renderer->DisplayToWorld();
168 worldCoords = renderer->GetWorldPoint();
169 if ( worldCoords[3] == 0.0 )
171 vtkErrorMacro(<<"Bad homogeneous coordinates");
174 for (i=0; i < 3; i++)
176 pickPosition[3][i] = worldCoords[i] / worldCoords[3];
179 // Compute the ray endpoints. The ray is along the line running from
180 // the camera position to the selection point, starting where this line
181 // intersects the front clipping plane, and terminating where this
182 // line intersects the back clipping plane.
183 for (k=0; k < 4; k++) {
186 ray[k][i] = pickPosition[k][i] - cameraPos[i];
191 cameraDOP[i] = cameraFP[i] - cameraPos[i];
194 vtkMath::Normalize(cameraDOP);
196 for (k=0; k < 4; k++) {
197 if (( rayLength[k] = vtkMath::Dot(cameraDOP,ray[k])) == 0.0 )
199 vtkWarningMacro("Cannot process points");
204 clipRange = camera->GetClippingRange();
206 if ( camera->GetParallelProjection() )
208 for (k=0; k < 4; k++) {
209 tF = clipRange[0] - rayLength[k];
210 tB = clipRange[1] - rayLength[k];
213 p1World[k][i] = pickPosition[k][i] + tF*cameraDOP[i];
214 p2World[k][i] = pickPosition[k][i] + tB*cameraDOP[i];
216 p1World[k][3] = p2World[k][3] = 1.0;
221 for (k=0; k < 4; k++) {
222 tF = clipRange[0] / rayLength[k];
223 tB = clipRange[1] / rayLength[k];
226 p1World[k][i] = cameraPos[i] + tF*ray[k][i];
227 p2World[k][i] = cameraPos[i] + tB*ray[k][i];
229 p1World[k][3] = p2World[k][3] = 1.0;
233 // Compute the center points of ray rectangle
234 for (i=0; i<3; i++) {
236 for (k=0; k<4; k++) {
237 c1[i] += p1World[k][i];
238 c2[i] += p2World[k][i];
244 // Compute the tolerance in world coordinates. Do this by
245 // determining the world coordinates of the diagonal points of the
246 // window, computing the width of the window in world coordinates, and
247 // multiplying by the tolerance.
249 viewport = renderer->GetViewport();
250 winSize = renderer->GetRenderWindow()->GetSize();
251 x = winSize[0] * viewport[0];
252 y = winSize[1] * viewport[1];
253 renderer->SetDisplayPoint(x, y, selectionZ1);
254 renderer->DisplayToWorld();
255 renderer->GetWorldPoint(windowLowerLeft);
257 x = winSize[0] * viewport[2];
258 y = winSize[1] * viewport[3];
259 renderer->SetDisplayPoint(x, y, selectionZ2);
260 renderer->DisplayToWorld();
261 renderer->GetWorldPoint(windowUpperRight);
263 for (tol=0.0,i=0; i<3; i++)
265 tol += (windowUpperRight[i] - windowLowerLeft[i]) *
266 (windowUpperRight[i] - windowLowerLeft[i]);
269 tol = sqrt (tol) * this->Tolerance;
271 // Loop over all props. Transform ray (defined from position of
272 // camera to selection point) into coordinates of mapper (not
273 // transformed to actors coordinates! Reduces overall computation!!!).
274 // Note that only vtkProp3D's can be picked by vtkPicker.
276 vtkPropCollection *props;
277 vtkProp *propCandidate;
278 if ( this->PickFromList )
280 props = this->GetPickList();
284 props = renderer->GetProps();
288 vtkLODProp3D *prop3D;
290 vtkAssemblyPath *path;
291 vtkProperty *tempProperty;
292 this->Transform->PostMultiply();
293 for ( props->InitTraversal(); (prop=props->GetNextProp()); )
295 for ( prop->InitPathTraversal(); (path=prop->GetNextPath()); )
299 propCandidate = path->GetLastNode()->GetProp();
300 if ( propCandidate->GetPickable() && propCandidate->GetVisibility() )
303 if ( (actor=vtkActor::SafeDownCast(propCandidate)) != NULL )
305 mapper = actor->GetMapper();
306 if ( actor->GetProperty()->GetOpacity() <= 0.0 )
311 else if ( (prop3D=vtkLODProp3D::SafeDownCast(propCandidate)) != NULL )
313 LODId = prop3D->GetPickLODID();
314 mapper = prop3D->GetLODMapper(LODId);
316 // if the mapper is a vtkMapper (as opposed to a vtkVolumeMapper),
317 // then check the transparency to see if the object is pickable
318 if ( vtkMapper::SafeDownCast(mapper) != NULL)
320 prop3D->GetLODProperty(LODId, &tempProperty);
321 if ( tempProperty->GetOpacity() <= 0.0 )
327 else if ( (volume=vtkVolume::SafeDownCast(propCandidate)) != NULL )
329 mapper = volume->GetMapper();
333 pickable = 0; //only vtkProp3D's (actors and volumes) can be picked
336 // If actor can be picked, get its composite matrix, invert it, and
337 // use the inverted matrix to transform the ray points into mapper
339 if ( pickable && mapper != NULL )
341 vtkMatrix4x4 *LastMatrix = path->GetLastNode()->GetMatrix();
342 if (LastMatrix == NULL)
344 vtkErrorMacro (<< "Pick: Null matrix.");
347 this->Transform->SetMatrix(LastMatrix);
348 this->Transform->Push();
349 this->Transform->Inverse();
351 for (k=0; k < 4; k++) {
352 this->Transform->TransformPoint(p1World[k],p1Mapper[k]);
353 this->Transform->TransformPoint(p2World[k],p2Mapper[k]);
357 ray[k][i] = p2Mapper[k][i] - p1Mapper[k][i];
361 this->Transform->Pop();
363 // Have the ray endpoints in mapper space, now need to compare this
364 // with the mapper bounds to see whether intersection is possible.
366 // Get the bounding box of the modeller. Note that the tolerance is
367 // added to the bounding box to make sure things on the edge of the
368 // bounding box are picked correctly.
369 mapper->GetBounds(bounds);
370 bounds[0] -= tol; bounds[1] += tol;
371 bounds[2] -= tol; bounds[3] += tol;
372 bounds[4] -= tol; bounds[5] += tol;
373 if ( HitBBox(bounds, p1Mapper, ray) ) {
374 t = this->IntersectWithHex(p1Mapper, p2Mapper, tol, path,
375 (vtkProp3D *)propCandidate, mapper);
376 if ( t >= 0.0 && t <= 1.0 /*t < VTK_LARGE_FLOAT*/ ) {
378 this->Prop3Ds->AddItem((vtkProp3D *)prop);
379 this->PickedPositions->InsertNextPoint
380 ((1.0 - t)*c1[0] + t*c2[0],
381 (1.0 - t)*c1[1] + t*c2[1],
382 (1.0 - t)*c1[2] + t*c2[2]);
384 // backwards compatibility: also add to this->Actors
386 this->Actors->AddItem(actor);
391 }//if visible and pickable not transparent and has mapper
395 // Invoke end pick method if defined
396 this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
403 #define SIDE_MIDDLE 2
405 float GetParameterValue(float start, float end, float point)
407 if (start == end) return -VTK_LARGE_FLOAT;
408 return (point-start)/(end-start);
411 void GetPointCoord(const float start[3], const float end[3], float t, float point[3])
414 for (i = 0; i < 3; i++) {
415 point[i] = start[i] + t*(end[i]-start[i]);
419 char GetIntersectionPoint(const float start[3], const float end[3],
420 const int& index, const float p, float point[3])
422 float t = GetParameterValue(start[index], end[index], p);
424 if (t >= 0.0 && t <= 1.0) {
426 GetPointCoord(start, end, t, point);
431 //----------------------------------------------------------------------------
432 /*! Bounding box intersection with hexahedron. Origin[4][4] starts the ray from corner points,
433 * dir[4][3] is the vector components of the ray in the x-y-z directions.
434 * (Notes: the intersection ray dir[4][3] is NOT normalized.)
435 * \retval The method returns a non-zero value, if the bounding box is hit.
437 char VTKViewer_RectPicker::HitBBox (float bounds[6], float origin[4][4], float dir[4][3])
442 for (k = 0; k < 4; k++) {
443 for (i = 0; i < 3; i++) {
444 endray[k][i] = origin[k][i] + dir[k][i];
448 // Compute hex bounding box, center point and center direction
449 float hbounds[6], center[3], ray[3];
450 for (i = 0; i < 3; i++) {
451 hbounds[2*i] = hbounds[2*i+1] = origin[0][i];
452 center[i] = ray[i] = 0;
453 for (k = 0; k < 4; k++) {
454 center[i] += origin[k][i];
455 ray[i] += endray[k][i];
456 if (origin[k][i] < hbounds[2*i]) {
457 hbounds[2*i] = origin[k][i];
459 else if (origin[k][i] > hbounds[2*i+1])
460 hbounds[2*i+1] = origin[k][i];
461 if (endray[k][i] < hbounds[2*i])
462 hbounds[2*i] = endray[k][i];
463 else if (endray[k][i] > hbounds[2*i+1])
464 hbounds[2*i+1] = endray[k][i];
466 center[i] = center[i]/4;
468 ray[i] = ray[i] - center[i];
471 // Check for intersection between bouning boxes
472 for (i = 0; i < 3; i++) {
473 if (bounds[2*i+1] < hbounds[2*i] || bounds[2*i] > hbounds[2*i+1])
477 // Check if one of the origin point lays inside bbox
479 for (k = 0; k < 4; k++) {
481 for (i = 0; i < 3; i++) {
482 if (origin[k][i] < bounds[2*i] || origin[k][i] > bounds[2*i+1]) {
487 if (inside) return 1;
490 // Find the closest coord plane for the center point
494 for (i = 0; i < 3; i++) {
495 if (center[i] < bounds[2*i]) {
497 coordPlane[i] = bounds[2*i];
500 else if (center[i] > bounds[2*i+1]) {
502 coordPlane[i] = bounds[2*i+1];
503 side[i] = SIDE_RIGHT;
506 coordPlane[i] = (ray[i]<0.0) ? bounds[2*i] : bounds[2*i+1];
507 side[i] = SIDE_MIDDLE;
510 if (inside) return 1;
512 // Calculate parametric distances to the planes and find the max
516 for (i = 0; i < 3; i++) {
517 if (side[i] != SIDE_MIDDLE && ray[i] != 0.0) {
518 maxT[i] = (coordPlane[i]-center[i])/ray[i];
524 for (i = 0; i < 3; i++) {
525 if (maxT[whichPlane] < maxT[i])
529 // Check for intersection along the center ray
531 if (maxT[whichPlane] <= 1.0 && maxT[whichPlane] >= 0.0) {
533 for (i = 0; i < 3; i++) {
534 if (i != whichPlane) {
535 coord = center[i] + maxT[whichPlane]*ray[i];
536 if (coord < bounds[2*i] || coord > bounds[2*i+1])
540 if (inside) return 1;
543 // Define the intersection plane
545 for (i = 0; i < 3; i++) {
547 maxT[i] = (coordPlane[i]-center[i])/ray[i];
550 maxT[i] = VTK_LARGE_FLOAT;
552 for (i = 0; i < 3; i++) {
553 if (maxT[whichPlane] > maxT[i])
558 // Compute the intersection between hex and coord plane
560 for (k = 0; k < 4; k++) {
561 if (dir[k][whichPlane] != 0.0) {
562 t[k] = (coordPlane[whichPlane]-origin[k][whichPlane])/dir[k][whichPlane];
565 t[k] = VTK_LARGE_FLOAT;
569 vtkPoints* aPoints = vtkPoints::New();
570 float p[3], q[3], t1;
571 for (k = 0; k < 4; k++) {
572 n = (k+1)%4; // next point
575 // find intersection point
576 t1 = GetParameterValue(endray[k][whichPlane], endray[n][whichPlane], coordPlane[whichPlane]);
577 if (t1 > 0.0 && t1 < 1.0) {
578 GetPointCoord(endray[k], endray[n], t1, p);
579 aPoints->InsertNextPoint(p[0], p[1], p[2]);
583 // find second intersection point
584 t1 = GetParameterValue(origin[k][whichPlane], origin[n][whichPlane], coordPlane[whichPlane]);
585 if (t1 > 0.0 && t1 < 1.0) {
586 GetPointCoord(origin[k], origin[n], t1, p);
587 aPoints->InsertNextPoint(p[0], p[1], p[2]);
591 else if (t[k] < 0.0) {
593 // find intersection point
594 t1 = GetParameterValue(origin[k][whichPlane], origin[n][whichPlane], coordPlane[whichPlane]);
595 if (t1 > 0.0 && t1 < 1.0) {
596 GetPointCoord(origin[k], origin[n], t1, p);
597 aPoints->InsertNextPoint(p[0], p[1], p[2]);
602 // find intersection point
603 GetPointCoord(origin[k], endray[k], t[k], p);
604 aPoints->InsertNextPoint(p[0], p[1], p[2]);
607 // find second intersection point
608 t1 = GetParameterValue(origin[k][whichPlane], origin[n][whichPlane], coordPlane[whichPlane]);
609 if (t1 > 0.0 && t1 < 1.0) {
610 GetPointCoord(origin[k], origin[n], t1, p);
611 aPoints->InsertNextPoint(p[0], p[1], p[2]);
614 else if (t[n] > 1.0) {
615 // find second intersection point
616 t1 = GetParameterValue(endray[k][whichPlane], endray[n][whichPlane], coordPlane[whichPlane]);
617 if (t1 > 0.0 && t1 < 1.0) {
618 GetPointCoord(endray[k], endray[n], t1, p);
619 aPoints->InsertNextPoint(p[0], p[1], p[2]);
624 n = aPoints->GetNumberOfPoints();
631 aPoints->GetPoint(0, p);
633 for (i = 0; i < 3; i++) {
634 if (i != whichPlane) {
635 if (p[i] < bounds[2*i] || p[i] > bounds[2*i+1]) {
644 // Analize intersection
645 int nearPlane, boundPlane = -1;
646 float boundCoord, boundMin, boundMax;
648 for (k = 0; k < n; k++) {
649 aPoints->GetPoint(k, p);
650 j = k+1; if (j == n) j = 0;
651 aPoints->GetPoint(j, q);
654 // if the point is inside bbox
655 for (i = 0; i < 3; i++) {
656 if (i != whichPlane) {
657 if (p[i] < bounds[2*i]) {
659 maxT[i] = GetParameterValue(p[i], q[i], bounds[2*i]);
662 else if (p[i] > bounds[2*i+1]) {
663 side[i] = SIDE_RIGHT;
664 maxT[i] = GetParameterValue(p[i], q[i], bounds[2*i+1]);
668 side[i] = SIDE_MIDDLE;
673 if (maxT[i] > maxT[nearPlane]) nearPlane = i;
676 // if segment intersects bbox
677 if (maxT[nearPlane] >= 0.0 && maxT[nearPlane] <= 1.0) {
678 for (i = 0; i < 3; i++) {
679 if (i != whichPlane && i != nearPlane) {
680 coord = p[i] + maxT[nearPlane]*(q[i]-p[i]);
681 if (coord >= bounds[2*i] && coord <= bounds[2*i+1]) {
682 intersect = 1; break;
686 // intersect with boundPlane
687 if (boundPlane == -1) {
688 boundCoord = p[nearPlane] + maxT[nearPlane]*(q[nearPlane]-p[nearPlane]);
689 boundPlane = nearPlane;
690 for (i = 0; i < 3; i++) {
691 if (i != whichPlane && i != boundPlane) {
692 coord = p[i] + maxT[nearPlane]*(q[i]-p[i]);
693 boundMin = boundMax = coord;
698 t1 = GetParameterValue(p[boundPlane], q[boundPlane], boundCoord);
699 if (t1 >= 0.0 && t1 <= 1.0) {
700 for (i = 0; i < 3; i++) {
701 if (i != whichPlane && i != boundPlane) {
702 coord = p[i] + t1*(q[i]-p[i]);
703 if (coord < boundMin) boundMin = coord;
704 if (coord > boundMax) boundMax = coord;
710 if (intersect) break;
713 if (inside || intersect) {
718 for (i = 0; i < 3; i++) {
719 if (i != whichPlane && i != boundPlane) {
720 if (boundMin > bounds[2*i+1] || boundMax < bounds[2*i])
728 //----------------------------------------------------------------------------
729 /*! Position of point relative to hexahedron. p1[4][4] is the corner points of top face,
730 * p2[4][4] is the corner points of bottom face.
731 * \retval The method returns a non-zero value, if the point is inside.
733 char VTKViewer_RectPicker::PointInside (float p[3], float p1[4][4], float p2[4][4], float tol)
738 // Fix one coordinate (x, for example) and
739 // compute intersection with coordinate plane
740 vtkPoints* aPoints = vtkPoints::New();
742 for (k = 0; k < 4; k++) {
743 j = k+1; if (j == 4) j = 0;
746 if (GetIntersectionPoint(p1[k], p1[j], 0, p[0], coord)) {
747 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
750 if (GetIntersectionPoint(p1[k], p2[k], 0, p[0], coord)) {
751 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
754 if (GetIntersectionPoint(p2[k], p2[j], 0, p[0], coord)) {
755 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
759 if ((p1[k][0]-p[0])*(p2[k][0]-p[0]) <= 0) {
760 t = GetParameterValue(p1[k][0], p2[k][0], p[0]);
761 if (t >= 0.0 && t <= 1.0) {
762 GetPointCoord(p1[k], p2[k], t, coord);
763 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
769 if (GetIntersectionPoint(p1[k], p2[k], 0, p[0], coord)) {
770 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
773 if (GetIntersectionPoint(p2[k], p2[j], 0, p[0], coord)) {
774 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
777 if (GetIntersectionPoint(p1[k], p1[j], 0, p[0], coord)) {
778 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
782 if ((p1[k][0]-p[0])*(p1[j][0]-p[0]) <= 0) {
783 t = GetParameterValue(p1[k][0], p1[j][0], p[0]);
784 if (t > 0.0 && t < 1.0) {
785 GetPointCoord(p1[k], p1[j], t, coord);
786 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
792 if (GetIntersectionPoint(p2[k], p2[j], 0, p[0], coord)) {
793 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
796 if (GetIntersectionPoint(p1[k], p2[k], 0, p[0], coord)) {
797 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
800 if (GetIntersectionPoint(p1[k], p1[j], 0, p[0], coord)) {
801 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
805 if ((p2[k][0]-p[0])*(p2[j][0]-p[0]) <= 0) {
806 t = GetParameterValue(p2[k][0], p2[j][0], p[0]);
807 if (t > 0.0 && t < 1.0) {
808 GetPointCoord(p2[k], p2[j], t, coord);
809 aPoints->InsertNextPoint(coord[0], coord[1], coord[2]);
816 int n = aPoints->GetNumberOfPoints();
817 //cout << "---> Points in X projection " << n << endl;
823 // Fix the second coord and define bounds
824 float zMin = VTK_LARGE_FLOAT, zMax = -VTK_LARGE_FLOAT, z, ncoord[3];
826 for (k = 0; k < n; k++) {
827 aPoints->GetPoint(k, coord);
828 //cout << " P" << k << " (" << coord[0] << ", " << coord[1] << ", " << coord[2] << ")";
829 j = k+1; if (j == n) j = 0;
831 if (p[1] == coord[1] && p[2] == coord[2]) {
836 aPoints->GetPoint(j, ncoord);
837 t = GetParameterValue(coord[1], ncoord[1], p[1]);
838 if (t >= 0.0 && t <= 1) {
839 z = coord[2] + t*(ncoord[2]-coord[2]);
840 if (z < zMin) zMin = z;
841 if (z > zMax) zMax = z;
844 //cout << endl << " Zmin = " << zMin << ", Zmax = " << zMax << endl;
846 if (p[2] <= (zMax+tol) && p[2] >= (zMin-tol))
854 //----------------------------------------------------------------------------
855 float VTKViewer_RectPicker::IntersectWithHex(float p1[4][4], float p2[4][4], float tol,
856 vtkAssemblyPath *path, vtkProp3D *prop3D,
857 vtkAbstractMapper3D *mapper)
860 float *center, p0[3], ray[3], rayFactor, t;
862 // Get the data from the modeler
864 center = mapper->GetCenter();
866 if (!PointInside(center, p1, p2)) {
870 // Determine appropriate info
872 for (i = 0; i < 3; i++) {
874 for (k = 0; k < 4; k++) {
880 ray[i] = ray[i] - p0[i];
882 if (( rayFactor = vtkMath::Dot(ray,ray)) == 0.0 ) {
883 vtkErrorMacro("Cannot process points");
887 // Project the center point onto the ray and determine its parametric value
889 t = (ray[0]*(center[0]-p0[0]) + ray[1]*(center[1]-p0[1])
890 + ray[2]*(center[2]-p0[2])) / rayFactor;
892 if ( t >= 0.0 && t <= 1.0 && t < this->GlobalTMin ) {
893 this->MarkPicked(path, prop3D, mapper, t, center);