/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkPointPicker.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkPointPicker.h" #include "vtkImageData.h" #include "vtkMath.h" #include "vtkMapper.h" #include "vtkAbstractVolumeMapper.h" #include "vtkObjectFactory.h" vtkCxxRevisionMacro(vtkPointPicker, "$Revision: 1.34 $"); vtkStandardNewMacro(vtkPointPicker); vtkPointPicker::vtkPointPicker() { this->PointId = -1; } double vtkPointPicker::IntersectWithLine(double p1[3], double p2[3], double tol, vtkAssemblyPath *path, vtkProp3D *p, vtkAbstractMapper3D *m) { vtkIdType numPts; vtkIdType ptId, minPtId; int i; double ray[3], rayFactor, tMin, x[3], t, projXYZ[3], minXYZ[3]; vtkDataSet *input; vtkMapper *mapper; vtkAbstractVolumeMapper *volumeMapper; // Get the underlying dataset // if ( (mapper=vtkMapper::SafeDownCast(m)) != NULL ) { input = mapper->GetInput(); } else if ( (volumeMapper=vtkAbstractVolumeMapper::SafeDownCast(m)) != NULL ) { input = volumeMapper->GetDataSetInput(); } else { return 2.0; } if ( (numPts = input->GetNumberOfPoints()) < 1 ) { return 2.0; } // Determine appropriate info // for (i=0; i<3; i++) { ray[i] = p2[i] - p1[i]; } if (( rayFactor = vtkMath::Dot(ray,ray)) == 0.0 ) { vtkErrorMacro("Cannot process points"); return 2.0; } // Project each point onto ray. Keep track of the one within the // tolerance and closest to the eye (and within the clipping range). // double dist, maxDist, minPtDist=VTK_DOUBLE_MAX; for (minPtId=(-1),tMin=VTK_DOUBLE_MAX,ptId=0; ptIdGetPoint(ptId,x); t = (ray[0]*(x[0]-p1[0]) + ray[1]*(x[1]-p1[1]) + ray[2]*(x[2]-p1[2])) / rayFactor; // If we find a point closer than we currently have, see whether it // lies within the pick tolerance and clipping planes. We keep track // of the point closest to the line (use a fudge factor for points // nearly the same distance away.) // if ( t >= 0.0 && t <= 1.0 && t <= (tMin+this->Tolerance) ) { for(maxDist=0.0, i=0; i<3; i++) { projXYZ[i] = p1[i] + t*ray[i]; dist = fabs(x[i]-projXYZ[i]); if ( dist > maxDist ) { maxDist = dist; } } if ( maxDist <= tol && maxDist < minPtDist ) // within tolerance { minPtId = ptId; minXYZ[0]=x[0]; minXYZ[1]=x[1]; minXYZ[2]=x[2]; minPtDist = maxDist; tMin = t; } } } // Now compare this against other actors. // if ( minPtId>(-1) && tMin < this->GlobalTMin ) { this->MarkPicked(path, p, m, tMin, minXYZ); this->PointId = minPtId; vtkDebugMacro("Picked point id= " << minPtId); } return tMin; } void vtkPointPicker::Initialize() { this->PointId = (-1); this->vtkPicker::Initialize(); } void vtkPointPicker::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Point Id: " << this->PointId << "\n"; }