//#####################################################################
// 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;
}
Ejemplo n.º 4
0
//#####################################################################
// 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;}
}