예제 #1
0
파일: gui.cpp 프로젝트: ipa-nhg/kukadu
void Compute_Leaves( SWIFT_BV* piece )
{
    int i;

    if( piece == mesh->Root() ) {
        leaves.Destroy();
        leaves.Create( num_leaves );
        leaves.Set_Length( 0 );
    }

    if( piece->Is_Leaf() ) {
        leaves.Add( piece );
    } else {
        for( i = 0; i < piece->Num_Children(); i++ ) {
            Compute_Leaves( piece->Children()[i] );
        }
    }
}
예제 #2
0
파일: gui.cpp 프로젝트: ipa-nhg/kukadu
int Convex_Pieces_CB( Togl *togl, int argc, const char *argv[] )
{
    if( argv[2][0] == 'A' || argv[2][0] == 'a' ) {
        // Want to draw all pieces
        int i;
        which_cps.Set_Length( which_cps.Max_Length() );
        for( i = 0; i < which_cps.Length(); i++ ) {
            which_cps[i] = i;
        }
    } else {
        // Parse the string to determine which ones to draw
        long upper, lower;
        const char* str = argv[2];
        char* endp;
        int i;
        SWIFT_Array<int> which_cps_back = which_cps;

        which_cps.Set_Length( 0 );

        while( *str != '\0' && which_cps.Length() != which_cps.Max_Length() ) {
            if( isdigit( *str ) ) {
                // Read the next segment
                lower = strtol( str, &endp, 10 );
                str = endp;
                if( lower < 0 ) {
                    lower = 0;
                }
                if( lower >= which_cps.Max_Length() ) {
                    lower = which_cps.Max_Length()-1;
                }
                upper = lower;
                if( *str == '-' ) {
                    str++;
                    if( isdigit( *str ) ) {
                        upper = strtol( str, &endp, 10 );
                        str = endp;
                        if( upper < 0 ) {
                            upper = 0;
                        }
                        if( upper >= which_cps.Max_Length() ) {
                            upper = which_cps.Max_Length()-1;
                        }
                        if( upper < lower ) {
                            int j = lower;
                            lower = upper;
                            upper = j;
                        }
                    } else {
                        cerr << "Error: Expecting number after '-'" << endl;
                        which_cps = which_cps_back;
                        break;
                    }
                }

                // Save the segment
                for( i = lower; i <= upper &&
                     which_cps.Length() != which_cps.Max_Length(); i++
                ) {
                    which_cps.Add( i );
                }

                // Done this segment
                if( *str == ',' ) {
                    str++;
                } else {
                    // Assume that we found the end of the list
                    break;
                }
            } else {
                break;
            }
        }
    }

    Togl_PostRedisplay( t );
    return TCL_OK;
}
예제 #3
0
int Decompose_Cresting_BFS( SWIFT_Tri_Mesh* m, SWIFT_Array<int>& piece_ids,
                            SWIFT_Array< SWIFT_Array<int> >& mfs,
                            SWIFT_Array< SWIFT_Array<SWIFT_Tri_Face> >& vfs )
{
    // Start performing BFS on the dual graph maintaining a convex hull along
    // the way.

    cerr << endl << "Starting cresting BFS decomposition" << endl;

    const unsigned int max_faces_in_a_chull = (m->Num_Vertices() - 2) << 1;
    int i, j, k, l;
    int created_faces = 0;
    int front, id;
    bool add_children;
    SWIFT_Tri_Edge* e;
    SWIFT_Tri_Vertex* v;
    SWIFT_Array<SWIFT_Tri_Face*> qfs;   // The queue
    SWIFT_Array<SWIFT_Tri_Face*> qfs_parents;
    SWIFT_Array<int> qmap;
    SWIFT_Array<int> qmap_idx;
    SWIFT_Array<SWIFT_Tri_Face*> mark_failed;
    SWIFT_Array<SWIFT_Tri_Face> chull;
    SWIFT_Array<SWIFT_Tri_Face*> cfs;
    SWIFT_Array<bool> fallowed;
    SWIFT_Array<bool> cvs;
    SWIFT_Array<int> cvs_idx;
    SWIFT_Array<int> addedfs;
    SWIFT_Array<int> temp_mfs_1d;
    SWIFT_Array< SWIFT_Array<int> > temp_mfs_2d;

    // The priority queue
    SWIFT_Array<int> lengths( m->Num_Faces() );
    SWIFT_Array<int> bmap( m->Num_Faces() );
    SWIFT_Array<int> fmap( m->Num_Faces() );

    qfs.Create( m->Num_Faces() );
    qfs_parents.Create( m->Num_Faces() );
    qmap.Create( m->Num_Faces() );
    qmap_idx.Create( m->Num_Faces() );
    mark_failed.Create( m->Num_Faces() );
    chull.Create( max_faces_in_a_chull );
    cfs.Create( max_faces_in_a_chull );
    fallowed.Create( m->Num_Faces() );
    cvs.Create( m->Num_Vertices() );
    cvs_idx.Create( m->Num_Vertices() );
    addedfs.Create( m->Num_Faces() );
    temp_mfs_1d.Create( m->Num_Faces() );
    temp_mfs_2d.Create( m->Num_Faces() );

    vfs.Create( m->Num_Faces() );
    piece_ids.Create( m->Num_Faces() );

    Prepare_Mesh_For_Decomposition( m );

    cvs_idx.Set_Length( 0 );
    qmap_idx.Set_Length( 0 );
    for( i = 0; i < m->Num_Vertices(); i++ ) {
        cvs[i] = false;
    }
    for( i = 0; i < m->Num_Faces(); i++ ) {
        fallowed[i] = true;
        piece_ids[i] = -1;
        qmap[i] = -1;
        bmap[i] = fmap[i] = i;
        if( m->Faces()[i].Edge1().Unmarked() ||
            m->Faces()[i].Edge2().Unmarked() ||
            m->Faces()[i].Edge3().Unmarked()
        ) {
            lengths[i] = 0;
            qmap_idx.Add( i );
        } else {
            lengths[i] = -1;
        }
    }

    id = 0;

    // Calculate distances for each face and create priority queue
    if( !qmap_idx.Empty() ) {
        // This is a convex object
        for( i = 0; i < qmap_idx.Max_Length(); i++ ) {
            if( m->Faces()[qmap_idx[i]].Edge1().Twin() != NULL ) {
                k = m->Face_Id(
                        m->Faces()[qmap_idx[i]].Edge1().Twin()->Adj_Face() );
                if( lengths[k] == -1 ) {
                    lengths[k] = lengths[qmap_idx[i]]+1;
                    qmap_idx.Add( k );
                }
            }
            if( m->Faces()[qmap_idx[i]].Edge2().Twin() != NULL ) {
                k = m->Face_Id(
                        m->Faces()[qmap_idx[i]].Edge2().Twin()->Adj_Face() );
                if( lengths[k] == -1 ) {
                    lengths[k] = lengths[qmap_idx[i]]+1;
                    qmap_idx.Add( k );
                }
            }
            if( m->Faces()[qmap_idx[i]].Edge3().Twin() != NULL ) {
                k = m->Face_Id(
                        m->Faces()[qmap_idx[i]].Edge3().Twin()->Adj_Face() );
                if( lengths[k] == -1 ) {
                    lengths[k] = lengths[qmap_idx[i]]+1;
                    qmap_idx.Add( k );
                }
            }
        }

        Build_Heap( lengths, bmap, fmap );
    }
    qmap_idx.Set_Length( 0 );

    // Process the priority queue by doing BFS
    while( !lengths.Empty() ) {
        i = bmap[0];

        // Unset all the qmappings
        for( j = 0; j < qmap_idx.Length(); j++ ) { 
            qmap[qmap_idx[j]] = -1;
        }
        qmap_idx.Set_Length( 0 );
        qfs.Set_Length( 0 );
        qfs_parents.Set_Length( 0 );
        front = 0;

        if( m->Faces()[i].Edge1().Marked() &&
            m->Faces()[i].Edge1().Twin()->Adj_Face()->Unmarked()
        ) {
            j = m->Face_Id( m->Faces()[i].Edge1().Twin()->Adj_Face() );
            qmap_idx.Add( j );
            qmap[j] = qfs.Length();
            qfs.Add( m->Faces()(j) );
            m->Faces()(j)->Mark();
            qfs_parents.Add( m->Faces()(i) );
        }
        if( m->Faces()[i].Edge2().Marked() &&
            m->Faces()[i].Edge2().Twin()->Adj_Face()->Unmarked()
        ) {
            j = m->Face_Id( m->Faces()[i].Edge2().Twin()->Adj_Face() );
            qmap_idx.Add( j );
            qmap[j] = qfs.Length();
            qfs.Add( m->Faces()(j) );
            m->Faces()(j)->Mark();
            qfs_parents.Add( m->Faces()(i) );
        }
        if( m->Faces()[i].Edge3().Marked() &&
            m->Faces()[i].Edge3().Twin()->Adj_Face()->Unmarked()
        ) {
            j = m->Face_Id( m->Faces()[i].Edge3().Twin()->Adj_Face() );
            qmap_idx.Add( j );
            qmap[j] = qfs.Length();
            qfs.Add( m->Faces()(j) );
            m->Faces()(j)->Mark();
            qfs_parents.Add( m->Faces()(i) );
        }

        mark_failed.Set_Length( 0 );
        temp_mfs_1d.Set_Length( 0 );

        Create_First_Face( m->Faces()(i), chull, cfs );

        // Unset all the vertex membership flags
        for( j = 0; j < cvs_idx.Length(); j++ ) { 
            cvs[cvs_idx[j]] = false;
        }
        cvs_idx.Set_Length( 0 );

        // Mark the first three vertices as added to the hull
        cvs_idx.Add( m->Vertex_Id( m->Faces()[i].Edge1().Origin() ) );
        cvs_idx.Add( m->Vertex_Id( m->Faces()[i].Edge2().Origin() ) );
        cvs_idx.Add( m->Vertex_Id( m->Faces()[i].Edge3().Origin() ) );
        cvs[cvs_idx[0]] = true;
        cvs[cvs_idx[1]] = true;
        cvs[cvs_idx[2]] = true;

        // Add the first face
        piece_ids[i] = id;
        m->Faces()[i].Mark();
        temp_mfs_1d.Add( i );
        l = 1;
        addedfs.Set_Length( 1 );
        addedfs[0] = i;
        fallowed[i] = false;


        // The strategy here is a bit different from that of DFS.  Whatever
        // is at the front of the queue is tested for validity and if so, it
        // is added and the unmarked neighbors are placed at the end of the
        // queue.
        while( front < qfs.Length() ) {

            if( qmap[ m->Face_Id( qfs[front] ) ] >= 0 ) {
                if( qfs[front]->Edge1().Twin() != NULL &&
                    qfs_parents[front] == qfs[front]->Edge1().Twin()->Adj_Face()
                ) {
                    e = qfs[front]->Edge1().Twin();
                    v = qfs[front]->Edge3().Origin();
                } else if( qfs[front]->Edge2().Twin() != NULL &&
                    qfs_parents[front] == qfs[front]->Edge2().Twin()->Adj_Face()
                ) {
                    e = qfs[front]->Edge2().Twin();
                    v = qfs[front]->Edge1().Origin();
                } else {
                    e = qfs[front]->Edge3().Twin();
                    v = qfs[front]->Edge2().Origin();
                }
                add_children = Add_To_Convex_Hull( m, chull, cfs, fallowed,
                                                   cvs, addedfs,
                                                   qfs[front], e, v );
                if( add_children ) {
                    // Add the face to the current piece
                    cvs_idx.Add( m->Vertex_Id( v ) );
                    // Mark all the faces that were added to the chull
                    for( j = l; j < addedfs.Length(); j++ ) {
                        fallowed[addedfs[j]] = false;
                        if( piece_ids[addedfs[j]] == -1 ) {
                            // Remove faces that were added if they exist in q
                            if( qmap[addedfs[j]] == -1 ) {
                                qmap_idx.Add( addedfs[j] );
                            }
                            qmap[addedfs[j]] = -2;
                            piece_ids[addedfs[j]] = id;
                            temp_mfs_1d.Add( addedfs[j] );
                            Delete_From_Heap( lengths, bmap, fmap,
                                              fmap[addedfs[j]] );
                        }
                    }
                    l = addedfs.Length();
                }
            } else {
                add_children = true;
            }

            if( add_children ) {
                // Expand the front by adding unmarked neighbors to the queue
                if( qfs[front]->Edge1().Marked() &&
                    qfs[front]->Edge1().Twin()->Adj_Face()->Unmarked()
                ) {
                    j = m->Face_Id( qfs[front]->Edge1().Twin()->Adj_Face() );
                    if( qmap[j] == -2 ) {
                        qmap[j] = -1;
                    } else {
                        qmap[j] = qfs.Length();
                        qmap_idx.Add( j );
                    }
                    qfs.Add( m->Faces()(j) );
                    m->Faces()(j)->Mark();
                    qfs_parents.Add( qfs[front] );
                }
                if( qfs[front]->Edge2().Marked() &&
                    qfs[front]->Edge2().Twin()->Adj_Face()->Unmarked()
                ) {
                    j = m->Face_Id( qfs[front]->Edge2().Twin()->Adj_Face() );
                    if( qmap[j] == -2 ) {
                        qmap[j] = -1;
                    } else {
                        qmap[j] = qfs.Length();
                        qmap_idx.Add( j );
                    }
                    qfs.Add( m->Faces()(j) );
                    m->Faces()(j)->Mark();
                    qfs_parents.Add( qfs[front] );
                }
                if( qfs[front]->Edge3().Marked() &&
                    qfs[front]->Edge3().Twin()->Adj_Face()->Unmarked()
                ) {
                    j = m->Face_Id( qfs[front]->Edge3().Twin()->Adj_Face() );
                    if( qmap[j] == -2 ) {
                        qmap[j] = -1;
                    } else {
                        qmap[j] = qfs.Length();
                        qmap_idx.Add( j );
                    }
                    qfs.Add( m->Faces()(j) );
                    m->Faces()(j)->Mark();
                    qfs_parents.Add( qfs[front] );
                }
            } else {
                mark_failed.Add( qfs[front] );
            }
            front++;
        }

        // Unmark all the failed faces.
        for( j = 0; j < mark_failed.Length(); j++ ) {
            mark_failed[j]->Unmark();
        }

        // Copy the virtual faces for this piece
        for( j = 0, k = 0; j < chull.Length(); j++ ) {
            if( chull[j].Unmarked() && cfs[j] == NULL ) {
                k++;
            }
        }
        created_faces += k;

        vfs[id].Create( k );
        for( j = 0, k = 0; j < chull.Length(); j++ ) {
            if( chull[j].Unmarked() && cfs[j] == NULL ) {
                vfs[id][k].Set_Normal_N( chull[j].Normal() );
                vfs[id][k].Set_Distance( chull[j].Distance() );
                vfs[id][k].Edge1().Set_Direction_N(
                                                chull[j].Edge1().Direction() );
                vfs[id][k].Edge2().Set_Direction_N(
                                                chull[j].Edge2().Direction() );
                vfs[id][k].Edge3().Set_Direction_N(
                                                chull[j].Edge3().Direction() );
                vfs[id][k].Edge1().Set_Length( chull[j].Edge1().Length() );
                vfs[id][k].Edge2().Set_Length( chull[j].Edge2().Length() );
                vfs[id][k].Edge3().Set_Length( chull[j].Edge3().Length() );
                vfs[id][k].Edge1().Set_Origin( chull[j].Edge1().Origin() );
                vfs[id][k].Edge2().Set_Origin( chull[j].Edge2().Origin() );
                vfs[id][k].Edge3().Set_Origin( chull[j].Edge3().Origin() );
                vfs[id][k].Edge1().Set_Twin( chull[j].Edge1().Twin() );
                vfs[id][k].Edge2().Set_Twin( chull[j].Edge2().Twin() );
                vfs[id][k].Edge3().Set_Twin( chull[j].Edge3().Twin() );
                chull[j].Edge1().Twin()->Set_Twin( vfs[id][k].Edge1P() );
                chull[j].Edge2().Twin()->Set_Twin( vfs[id][k].Edge2P() );
                chull[j].Edge3().Twin()->Set_Twin( vfs[id][k].Edge3P() );
                k++;
            }
        }

        // Copy the model faces for this piece
        temp_mfs_2d[id].Copy_Length( temp_mfs_1d );

        id++;

        // Remove this face from the priority queue
        Delete_From_Heap( lengths, bmap, fmap, fmap[i] );
    }
    temp_mfs_2d.Set_Length( id );
    vfs.Set_Length( id );

    // Unmark all the faces and edges
    for( i = 0; i < m->Num_Faces(); i++ ) {
        m->Faces()[i].Unmark();
        m->Faces()[i].Edge1().Unmark();
        m->Faces()[i].Edge2().Unmark();
        m->Faces()[i].Edge3().Unmark();
    }

    // Copy the mfs
    mfs.Copy_Length( temp_mfs_2d );
    for( i = 0; i < temp_mfs_2d.Length(); i++ ) {
        temp_mfs_2d[i].Nullify();
    }

    cerr << "Created " << id << " pieces" << endl;
    cerr << "Original faces = " << m->Num_Faces() << endl;
    cerr << "Created virtual faces = " << created_faces << endl << endl;

    return id;
}