//##################################################################### // Function Intersection //##################################################################### template<class TV> bool DYADIC_IMPLICIT_OBJECT<TV>:: Intersection(RAY<TV>& ray,const T thickness,const ARRAY<T>& phi_nodes,const bool verbose) const { bool save_semi_infinite=ray.semi_infinite;T save_t_max=ray.t_max;int save_aggregate=ray.aggregate_id; T t_start,t_end; bool exit_intersection=false;int exit_aggregate=0;T exit_t_max=0; int intersect_box=INTERSECTION::Intersects(ray,box,thickness); int outside_box=box.Outside(ray.endpoint,thickness); if(outside_box && !intersect_box) return false; // missed the box else if(outside_box){ // intersected the box from the outside TV point=ray.Point(ray.t_max); // intersection point with the box if((*this)(point) <= 0) return true; // test the levelset right at the box point=box.Thickened(-4*thickness).Clamp(point); // moves the point inside the box if((*this)(point) <= 0) return true; // level set is on the edge of the box else{ // level set is not on the edge of the box t_start=ray.t_max; // intersection with the box ray.semi_infinite=save_semi_infinite;ray.t_max=save_t_max;ray.aggregate_id=save_aggregate; // box intersection doesn't count RAY<TV> new_ray(point,ray.direction);INTERSECTION::Intersects(new_ray,box,thickness); if(ray.semi_infinite) t_end=t_start+new_ray.t_max; else t_end=min(t_start+new_ray.t_max,ray.t_max);}} else if(!intersect_box){t_start=0;t_end=ray.t_max;} // intersected some object inside the box else{ // intersects the box from inside t_start=0;t_end=ray.t_max; exit_intersection=true;exit_t_max=ray.t_max;exit_aggregate=ray.aggregate_id; // save for exiting rays ray.semi_infinite=save_semi_infinite;ray.t_max=save_t_max;ray.aggregate_id=save_aggregate;} // box intersection doesn't count // set up marching DYADIC_IMPLICIT_OBJECT_ON_A_RAY<T_GRID> implicit_surface_on_a_ray(*this,ray); ITERATIVE_SOLVER<T> iterative_solver;iterative_solver.tolerance=Iterative_Solver_Tolerance<T>()*thickness; // start marching T t1=t_start+thickness; TV p1(ray.Point(t1));T_CELL* current_cell=levelset.grid.Leaf_Cell(p1); T phi1=levelset.Phi_From_Close_Cell(current_cell,p1,&phi_nodes),t2=t1+Integration_Step(phi1); // march through the line segment while(t2 <= t_end){ TV p2(ray.Point(t2)); if(!levelset.grid.Inside_Cell(current_cell,p2)){ if(phi1<current_cell->DX().x*20) // 20 is a hack to avoid looking for neighbors current_cell=levelset.grid.Leaf_Cell_By_Neighbor_Path(current_cell,p2); else current_cell=levelset.grid.Leaf_Cell(p2);} else if(current_cell->Has_Children()) current_cell=levelset.grid.Leaf_Cell(p2); T phi2=levelset.Phi_From_Close_Cell(current_cell,p2,&phi_nodes); if(LEVELSET_UTILITIES<T>::Interface(phi1,phi2)){ T_CELL* base_cell=levelset.grid.Base_Cell_By_Neighbor_Path(current_cell,p1);assert(base_cell); implicit_surface_on_a_ray.phi_nodes=&phi_nodes; implicit_surface_on_a_ray.last_block=new BLOCK_DYADIC<T_GRID>(levelset.grid,base_cell); // optimization ray.semi_infinite=false;ray.t_max=iterative_solver.Bisection_Secant_Root(implicit_surface_on_a_ray,t1,t2);ray.aggregate_id=-1; if(implicit_surface_on_a_ray.last_block){delete implicit_surface_on_a_ray.last_block;implicit_surface_on_a_ray.last_block=0;} return true;} else{t1=t2;phi1=phi2;t2=t1+Integration_Step(phi1);}} // check the last piece of the line segment t2=t_end;T phi2=(*this)(ray.Point(t_end)); if(LEVELSET_UTILITIES<T>::Interface(phi1,phi2)){ray.semi_infinite=false;ray.t_max=iterative_solver.Bisection_Secant_Root(implicit_surface_on_a_ray,t1,t2);ray.aggregate_id=-1;return true;} else if(exit_intersection && phi2 <= 0){ray.semi_infinite=false;ray.t_max=exit_t_max; ray.aggregate_id=exit_aggregate; return true;} // exiting ray else return false; }
//##################################################################### // Function Closest_Non_Intersecting_Point //##################################################################### template<class T> bool Closest_Non_Intersecting_Point(RAY<VECTOR<T,3> >& ray,const TRIANGULATED_SURFACE<T>& surface, const T thickness_over_two) { assert(surface.hierarchy);assert(surface.bounding_box);assert(surface.triangle_list); bool hit=false;T start_t,end_t;if(!INTERSECTION::Get_Intersection_Range(ray,*surface.bounding_box,start_t,end_t))return false; RANGE<VECTOR<T,3> > ray_box(ray.Point(start_t));ray_box.Enlarge_To_Include_Point(ray.Point(end_t)); ARRAY<int> triangles_to_check;surface.hierarchy->Intersection_List(ray_box,triangles_to_check,4*thickness_over_two); for(int i=1;i<=triangles_to_check.m;i++){int k=triangles_to_check(i);if(INTERSECTION::Closest_Non_Intersecting_Point(ray,(*surface.triangle_list)(k),thickness_over_two)){ray.aggregate_id=k;hit=true;}} return hit; }
//##################################################################### // Function Intersects //##################################################################### template<class T> bool Rectangle_Intersects(RAY<VECTOR<T,3> >& ray,const PLANE<T>& plane,const PLANE<T>& bounding_plane1,const PLANE<T>& bounding_plane2,const PLANE<T>& bounding_plane3,const PLANE<T>& bounding_plane4,const T thickness_over_two) { RAY<VECTOR<T,3> > ray_temp;ray.Save_Intersection_Information(ray_temp); if(INTERSECTION::Intersects(ray,plane,thickness_over_two)){ VECTOR<T,3> point=ray.Point(ray.t_max); if(!bounding_plane1.Outside(point,thickness_over_two) && !bounding_plane2.Outside(point,thickness_over_two) && !bounding_plane3.Outside(point,thickness_over_two) && !bounding_plane4.Outside(point,thickness_over_two)) return true; else ray.Restore_Intersection_Information(ray_temp);} return false; }
//##################################################################### // Function Intersection //##################################################################### template<class TV> bool IMPLICIT_OBJECT<TV>:: Intersection(RAY<TV>& ray,const T thickness) const { bool save_semi_infinite=ray.semi_infinite;T save_t_max=ray.t_max;int save_aggregate=ray.aggregate_id; T t_start,t_end; bool exit_intersection=false;int exit_aggregate=0;T exit_t_max=0; int intersect_box=INTERSECTION::Intersects(ray,box,thickness); int outside_box=box.Outside(ray.endpoint,thickness); if(outside_box && !intersect_box) return false; // missed the box else if(outside_box){ // intersected the box from the outside TV point=ray.Point(ray.t_max); // intersection point with the box point=box.Thickened(-4*thickness).Clamp(point); // moves the point inside the box if((*this)(point) <= 0) return true; // level set is on the edge of the box else{ // level set is not on the edge of the box t_start=ray.t_max; // intersection with the box ray.semi_infinite=save_semi_infinite;ray.t_max=save_t_max;ray.aggregate_id=save_aggregate; // box intersection doesn't count RAY<TV> new_ray(point,ray.direction);INTERSECTION::Intersects(new_ray,box,thickness); if(ray.semi_infinite) t_end=t_start+new_ray.t_max; else t_end=min(t_start+new_ray.t_max,ray.t_max);}} else if(!intersect_box){t_start=0;t_end=ray.t_max;} // intersected some object inside the box else{ // intersects the box from inside t_start=0;t_end=ray.t_max; exit_intersection=true;exit_t_max=ray.t_max;exit_aggregate=ray.aggregate_id; // save for exiting rays ray.semi_infinite=save_semi_infinite;ray.t_max=save_t_max;ray.aggregate_id=save_aggregate;} // box intersection doesn't count if(!use_secondary_interpolation){ // set up marching IMPLICIT_OBJECT_ON_A_RAY<IMPLICIT_OBJECT> implicit_surface_on_a_ray(*this,ray); ITERATIVE_SOLVER<T> iterative_solver;iterative_solver.tolerance=Iterative_Solver_Tolerance<T>()*thickness; // start marching T t1=t_start+thickness,phi1=(*this)(ray.Point(t1)),t2=t1+Integration_Step(phi1); // march through the line segment while(t2 <= t_end){ T phi2=(*this)(ray.Point(t2)); if(LEVELSET_UTILITIES<T>::Interface(phi1,phi2)){ray.semi_infinite=false;ray.t_max=iterative_solver.Bisection_Secant_Root(implicit_surface_on_a_ray,t1,t2);ray.aggregate_id=-1;return true;} else{t1=t2;phi1=phi2;t2=t1+Integration_Step(phi1);}} // check the last piece of the line segment t2=t_end;T phi2=(*this)(ray.Point(t_end)); if(LEVELSET_UTILITIES<T>::Interface(phi1,phi2)){ray.semi_infinite=false;ray.t_max=iterative_solver.Bisection_Secant_Root(implicit_surface_on_a_ray,t1,t2);ray.aggregate_id=-1;return true;} else if(exit_intersection && phi2 <= 0){ray.semi_infinite=false;ray.t_max=exit_t_max;ray.aggregate_id=exit_aggregate;return true;} // exiting ray else return false;} else{ // use_secondary_interpolation // set up marching //IMPLICIT_OBJECT_ON_A_RAY_SECONDARY_INTERPOLATION<T> implicit_surface_on_a_ray(*this,ray); // TODO: we should probably be using this instead IMPLICIT_OBJECT_ON_A_RAY<IMPLICIT_OBJECT> implicit_surface_on_a_ray(*this,ray); ITERATIVE_SOLVER<T> iterative_solver;iterative_solver.tolerance=Iterative_Solver_Tolerance<T>()*thickness; // start marching T t1=t_start+thickness,phi1=(*this)(ray.Point(t1)),t2=t1+Integration_Step(phi1); // march through the line segment while(t2 <= t_end){ T phi2=(*this)(ray.Point(t2)); if(LEVELSET_UTILITIES<T>::Interface(phi1,phi2)){ phi1=this->Phi_Secondary(ray.Point(t1)); phi2=this->Phi_Secondary(ray.Point(t2)); if(LEVELSET_UTILITIES<T>::Interface(phi1,phi2)){ ray.semi_infinite=false; ray.t_max=iterative_solver.Bisection_Secant_Root(implicit_surface_on_a_ray,t1,t2); ray.aggregate_id=-1;return true;} else{t1=t2;phi1=phi2;t2=t1+Integration_Step(phi1);}} else{t1=t2;phi1=phi2;t2=t1+Integration_Step(phi1);}} // check the last piece of the line segment t2=t_end;T phi2=(*this)(ray.Point(t2)); if(LEVELSET_UTILITIES<T>::Interface(phi1,phi2)){ phi1=this->Phi_Secondary(ray.Point(t1)); phi2=this->Phi_Secondary(ray.Point(t2)); if(LEVELSET_UTILITIES<T>::Interface(phi1,phi2)){ ray.semi_infinite=false; ray.t_max=iterative_solver.Bisection_Secant_Root(implicit_surface_on_a_ray,t1,t2); ray.aggregate_id=-1;return true;}} if(exit_intersection && phi2 <= 0){ray.semi_infinite=false;ray.t_max=exit_t_max;ray.aggregate_id=exit_aggregate;return true;} // exiting ray else return false;} }