/*========================================================================= Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: ImageRayIntersectionFinder.txx,v $ Language: C++ Date: $Date: 2003/10/02 13:45:07 $ Version: $Revision: 1.2 $ Copyright (c) 2003 Insight Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information. =========================================================================*/ #include "itkImage.h" template int ImageRayIntersectionFinder ::FindIntersection(ImageType *image,Vector3d point, Vector3d ray,Vector3i &hit) const { typename ImageType::IndexType lIndex; typename ImageType::SizeType size = image->GetLargestPossibleRegion().GetSize(); double delta[3][3], dratio[3]; int signrx, signry, signrz; double rayLen = ray.two_norm(); if(rayLen == 0) return -1; ray /= rayLen; double rx = ray[0];double ry = ray[1];double rz = ray[2]; if (rx >=0) signrx = 1; else signrx = -1; if (ry >=0) signry = 1; else signry = -1; if (rz >=0) signrz = 1; else signrz = -1; // offset everything by (.5, .5) [becuz samples are at center of voxels] // this offset will put borders of voxels at integer values // we will work with this offset grid and offset back to check samples // we really only need to offset "point" double px = point[0]+0.5; double py = point[1]+0.5; double pz = point[2]+0.5; // get the starting point within data extents int c = 0; while ( (px < 0 || px >= size[0]|| py < 0 || py >= size[1]|| pz < 0 || pz >= size[2]) && c < 10000) { px += rx; py += ry; pz += rz; c++; } if (c >= 9999) return -1; // walk along ray to find intersection with any voxel with val > 0 while ( (px >= 0 && px < size[0]&& py >= 0 && py < size[1] && pz >= 0 && pz < size[2]) ) { // offset point by (-.5, -.5) [to account for earlier offset] and // get the nearest sample voxel within unit cube around (px,py,pz) // lx = my_round(px-0.5); // ly = my_round(py-0.5); // lz = my_round(pz-0.5); lIndex[0] = (int)px; lIndex[1] = (int)py; lIndex[2] = (int)pz; // Get the pixel TPixel hitPixel = image->GetPixel(lIndex); // Test if the pixel is a hit if(m_HitTester(hitPixel)) { hit[0] = lIndex[0]; hit[1] = lIndex[1]; hit[2] = lIndex[2]; return 1; } // BEGIN : walk along ray to border of next voxel touched by ray // compute path to YZ-plane surface of next voxel if (rx == 0) { // ray is parallel to 0 axis delta[0][0] = 9999; } else { delta[0][0] = (int)(px+signrx) - px; } // compute path to XZ-plane surface of next voxel if (ry == 0) { // ray is parallel to 1 axis delta[1][0] = 9999; } else { delta[1][1] = (int)(py+signry) - py; dratio[1] = delta[1][1]/ry; delta[1][0] = dratio[1] * rx; } // compute path to XY-plane surface of next voxel if (rz == 0) { // ray is parallel to 2 axis delta[2][0] = 9999; } else { delta[2][2] = (int)(pz+signrz) - pz; dratio[2] = delta[2][2]/rz; delta[2][0] = dratio[2] * rx; } // choose the shortest path if ( fabs(delta[0][0]) <= fabs(delta[1][0]) && fabs(delta[0][0]) <= fabs(delta[2][0]) ) { dratio[0] = delta[0][0]/rx; delta[0][1] = dratio[0] * ry; delta[0][2] = dratio[0] * rz; px += delta[0][0]; py += delta[0][1]; pz += delta[0][2]; } else if ( fabs(delta[1][0]) <= fabs(delta[0][0]) && fabs(delta[1][0]) <= fabs(delta[2][0]) ) { delta[1][2] = dratio[1] * rz; px += delta[1][0]; py += delta[1][1]; pz += delta[1][2]; } else { //if (fabs(delta[2][0] <= fabs(delta[0][0] && fabs(delta[2][0] <= fabs(delta[0][0]) delta[2][1] = dratio[2] * ry; px += delta[2][0]; py += delta[2][1]; pz += delta[2][2]; } // END : walk along ray to border of next voxel touched by ray } // while ( (px return 0; }