//#####################################################################
// Function Compute_Level_Set
//#####################################################################
template<class T> void LEVELSET_MAKER_UNIFORM_2D<T>::
Compute_Level_Set(SEGMENTED_CURVE_2D<T>& curve,GRID<TV>& grid,int ghost_cells,ARRAY<T,TV_INT>& phi)
{
    phi.Fill(FLT_MAX);
    T dx=grid.dX.Max();

    ARRAY<bool,TV_INT> done(grid.Domain_Indices(ghost_cells+1));
    for(int i=1;i<=curve.mesh.elements.m;i++){
        SEGMENT_2D<T> segment(curve.particles.X(curve.mesh.elements(i).x),curve.particles.X(curve.mesh.elements(i).y));
        RANGE<TV_INT> box(grid.Cell(segment.x1,3));
        box.Enlarge_To_Include_Point(grid.Cell(segment.x2,3));
        box=box.Intersect(box,grid.Domain_Indices(ghost_cells-1));
        if(box.Empty()) continue;
        for(UNIFORM_ARRAY_ITERATOR<TV::m> it(box.Thickened(1));it.Valid();it.Next()){
            TV X=grid.X(it.index);
            T dist=segment.Distance_From_Point_To_Segment(X);
            if(dist<abs(phi(it.index))+dx*1e-4 && dist<dx){
                bool new_sign=TV::Dot_Product(X-segment.x1,segment.Normal())<0;
                if(abs(dist-abs(phi(it.index)))<dx*1e-4 && new_sign != (phi(it.index)<0))
                    new_sign=curve.Inside(grid.X(it.index));
                if(abs(dist)<abs(phi(it.index))) phi(it.index)=dist;
                phi(it.index)=abs(phi(it.index))*(new_sign?-1:1);
                done(it.index)=true;}}}

    ARRAY<TV_INT> todo,next_todo;
    for(UNIFORM_GRID_ITERATOR_CELL<TV> it(grid);it.Valid();it.Next())
        if(phi(it.index)!=FLT_MAX)
            todo.Append(it.index);
    for(int layer=1;todo.m;layer++){
        while(todo.m){
            TV_INT index=todo.Pop();
            T next=sign(phi(index))*layer*dx;
            Compute_Level_Set_Helper(index+TV_INT(1,0),next,next_todo,phi);
            Compute_Level_Set_Helper(index-TV_INT(1,0),next,next_todo,phi);
            Compute_Level_Set_Helper(index+TV_INT(0,1),next,next_todo,phi);
            Compute_Level_Set_Helper(index-TV_INT(0,1),next,next_todo,phi);}
        todo.Exchange(next_todo);}
/*
    for(UNIFORM_GRID_ITERATOR_CELL<TV> it(grid);it.Valid();it.Next()){
        VECTOR<T,3> color=phi(it.index)>0?VECTOR<T,3>(0,1,0):VECTOR<T,3>(1,0,0);
        if(done(it.index)) color/=(T)3;
        Add_Debug_Particle(grid.X(it.index),color);}*/
    PHYSBAM_DEBUG_WRITE_SUBSTEP("Compute Level Set",0,1);

    LEVELSET_2D<GRID<TV> > levelset(grid,phi);
    FAST_MARCHING_METHOD_UNIFORM<GRID<TV> > fmm(levelset,ghost_cells);
    fmm.Fast_Marching_Method(phi,done);
}
Exemplo n.º 2
0
LEVELSET<GRID<TV> >* createTriMeshAndLevelSet(const char* name) {
	string n = string(name);
    TRIANGULATED_SURFACE<float>* triangles = new TRIANGULATED_SURFACE<float>();
    triangles->loadOBJ(name);
    triangles->Update_Bounding_Box_And_Gravity_Center();
    RANGE<TV> range = triangles->bounding_box;
    range.min -= TV(0.2, 0.2, 0.2);
    range.max += TV(0.2, 0.2, 0.2);
    GRID<TV>* grid = new GRID<TV>(TV_INT(40,40,40), range);
    ARRAY<3,float>* phi = new ARRAY<3, float>(grid->Domain_Indices());
    LEVELSET<GRID<TV> >* implicit_object = new LEVELSET<GRID<TV> >(*grid, *phi);
    SimLib::LEVELSET_MAKER<float> level_maker;
    ARRAY<3, int> closest_index;
    level_maker.Compute_Level_Set(*triangles, *grid, *phi, closest_index);
    ((LEVELSET<GRID<TV> >*)implicit_object)->Fast_Marching_Method(*triangles, closest_index);
    return implicit_object;
}
//#####################################################################
// Function Fill_Level
//#####################################################################
template<class TV,class T2> void EXTRAPOLATION_HIGHER_ORDER<TV,T2>::
Fill_Level(const GRID<TV>& grid,const T_LEVELSET& phi,int ghost,MAPPING& m,ARRAY<TV>& normal,ARRAY<VECTOR<STENCIL,TV::m> >& stencil,int order,T distance)
{
    ARRAY<TV_INT> inside;
    m.node_to_index.Resize(grid.Domain_Indices(ghost+1)); // Need an extra ring for the sentinals
    m.index_to_node.Append(TV_INT::All_Ones_Vector()*INT_MAX); // First index is the "outside" index.
    normal.Append(TV::All_Ones_Vector()*INT_MAX);

    // Cells that must be solved for normally.
    for(UNIFORM_GRID_ITERATOR_NODE<TV> it(grid,ghost);it.Valid();it.Next()){
        T p=phi.Phi(it.Location());
        if(p<=0){
            if(p>-(T)2.1*grid.dX.Max()){inside.Append(it.index);m.node_to_index(it.index)=-1;}} // Register two levels to prevent the closure below from leaking inside.
        else if(p<=(distance+(T)1e-4)*grid.dX.Max()) m.node_to_index(it.index)=m.index_to_node.Append(it.index);}

    // Ensure that two upwind nodes are being solved for.
    for(int i=2;i<=m.index_to_node.m;i++){
        TV N=phi.Normal(grid.X(m.index_to_node(i)));
        normal.Append(N);
        for(int d=1;d<=TV::m;d++){
            int s=N(d)<0?1:-1;
            TV_INT ind=m.index_to_node(i);
            for(int j=1;j<=2;j++){
                ind(d)+=s;
                int& k=m.node_to_index(ind);
                if(!k) k=m.index_to_node.Append(ind);}}}
    m.max_solve_index(1)=m.index_to_node.m;

    // Register additional cells inside for derivatives.
    for(int o=1,i=1;o<=order*2;o++){
        int previous=m.index_to_node.m,mx=inside.m;
        for(;i<=mx;i++){
            bool added=false;
            for(int k=1;k<=TV::m*2;k++){
                TV_INT ind=grid.Node_Neighbor(inside(i),k);
                int& n=m.node_to_index(ind);
                if(!n){n=-1;inside.Append(ind);}
                else if(n>0 && n<=previous && !added){
                    m.node_to_index(inside(i))=m.index_to_node.Append(inside(i));
                    normal.Append(phi.Normal(grid.X(inside(i))));
                    added=true;}}
            if(!added) inside.Append(TV_INT(inside(i)));}  // Use a copy to avoid but on resize
        m.max_solve_index(o+1)=m.index_to_node.m;}

    // Register sentinal layer and precompute stencils.
    stencil.Resize(m.max_solve_index(order));
    for(int i=2;i<=m.max_solve_index(order);i++){
        TV N=normal(i);
        for(int d=1;d<=TV::m;d++){
            int s=N(d)<0?1:-1;
            STENCIL& st=stencil(i)(d);
            st.scale=s*N(d)*grid.one_over_dX(d);
            TV_INT ind=m.index_to_node(i);
            for(int j=1;j<=3;j++){
                st.nodes(j+1)=m.node_to_index(ind);
                ind(d)+=s;}
            ind(d)-=4*s;
            int& n=m.node_to_index(ind);
            if(!n) n=1;
            st.nodes(1)=n;}}
}