// calculate face point coordinate by iterating each face // there are 2 classes face: // 1) border face, which has 1 adjacent cell; // 2) inner face, which has 2 adjacent cells. void hs_subdiv::calc_face_point(point_vector& face_points, point_vector& cell_points) { hs_point cent; face_vector_iter face_iter = phexmodel->first_face(); for (; face_iter != phexmodel->end_face(); ++face_iter) { cent.zero(); int_set_iter vert_iter = face_iter->first_vert(); for (; vert_iter != face_iter->end_vert(); ++vert_iter) { cent += phexmodel->vert_at(*vert_iter).coord(); } cent /= face_iter->vert_size(); //if (face_iter->fst_cell() != -1 && face_iter->snd_cell() != -1) { if ( face_iter->type() == INNER_FACE ) { // inner face cent = cent * 0.5 + (cell_points[face_iter->fst_cell()] + cell_points[face_iter->snd_cell()]) * 0.25; } else if ( face_iter->type() == BORDER_FACE ) { // boder face // find a vertex in the surface assert( NULL != face_iter->acis_face() ); SPAposition spa_pos( cent.x(), cent.y(), cent.z() ); const surface& csurf = face_iter->acis_face()->geometry()->equation(); SPAposition new_spa_pos( csurf.eval_position( csurf.param(spa_pos) ) ); cent.set_coord( new_spa_pos.x(), new_spa_pos.y(), new_spa_pos.z() ); } face_points.push_back(cent); } }
// calculate cell point coordinate by iterating each cell void hs_subdiv::calc_cell_point( point_vector& cell_points ) { hs_point cent; cell_vector_iter cell_iter = phexmodel->first_cell(); for (; cell_iter != phexmodel->end_cell(); ++cell_iter) { cent.zero(); int_set_iter vert_iter = cell_iter->first_vert(); for (; vert_iter != cell_iter->end_vert(); ++ vert_iter) { cent += phexmodel->vert_at(*vert_iter).coord(); } cent /= cell_iter->vert_size(); cell_points.push_back(cent); } }
// calculate edge point coordinate by iterating each edge in model // there are 3 classes edge: // 1) inner edge, whose number of adjacent faces is same with adjacent cells; // 2) crease edge, which has 2 adjacent border faces // 3) ordinary border edge( except crease ), // which has 2 adjacent border faces and other inner faces void hs_subdiv::calc_edge_point(point_vector& edge_points, point_vector& cell_points) { size_t idx = 0; hs_point cent; edge_vector_iter edge_iter = phexmodel->first_edge(); for (; edge_iter != phexmodel->end_edge(); ++edge_iter, ++idx) { // centroid of each edge cent = ( phexmodel->vert_at(edge_iter->start_vert()).coord() + phexmodel->vert_at(edge_iter->end_vert()).coord() ) * 0.5; if ( edge_iter->type() == INNER_EDGE ) { // inner edge hs_point avg_face_point; int_set_iter face_iter = edge_iter->first_face(); for (; face_iter != edge_iter->end_face(); ++face_iter) { hs_point avg_cent_face; hs_face& f = phexmodel->face_at(*face_iter); int_set_iter vitr = f.first_vert(); for (; vitr != f.end_vert(); ++vitr) { avg_cent_face += phexmodel->vert_at(*vitr).coord(); } avg_face_point += avg_cent_face / f.vert_size(); } avg_face_point /= edge_iter->face_size(); hs_point avg_cell_point; int_set_iter cell_iter = edge_iter->first_cell(); for (; cell_iter != edge_iter->end_cell(); ++cell_iter) { avg_cell_point += cell_points[*cell_iter]; } avg_cell_point /= edge_iter->cell_size(); // average of midpoint, face point and cell point size_t n = edge_iter->face_size(); cent = ((n - 3) * cent + 2 * avg_face_point + avg_cell_point) / n; } else if ( edge_iter->type() == CREASE_EDGE ) { // crease edge // find a vertex in the curve which is adjacent to crease edge assert( NULL != edge_iter->acis_edge() ); SPAposition spa_pos( cent.x(), cent.y(), cent.z()); const curve& ccurv = edge_iter->acis_edge()->geometry()->equation(); SPAposition new_spa_pos( ccurv.eval_position( ccurv.param(spa_pos) ) ); cent.set_coord( new_spa_pos.x(), new_spa_pos.y(), new_spa_pos.z() ); } else if ( edge_iter->type() == ORDINARY_EDGE ) { // ordinary border edge // find a vertex in the surface which is adjacent to edge std::set< const FACE* > face_set; int_set_iter face_iter = edge_iter->first_face(); for (; face_iter != edge_iter->end_face(); ++face_iter) { face_set.insert( phexmodel->face_at(*face_iter).acis_face() ); } // ordinary edge have 2 same adjacent surface face_set.erase(NULL); assert( 1 == face_set.size() ); const FACE* spa_face = *(face_set.begin()); const surface& csurf = spa_face->geometry()->equation(); SPAposition spa_pos( cent.x(), cent.y(), cent.z() ); SPAposition new_spa_pos( csurf.eval_position( csurf.param(spa_pos) ) ); cent.set_coord( new_spa_pos.x(), new_spa_pos.y(), new_spa_pos.z() ); } edge_points.push_back(cent); } }
// calculate vertex point by iterating each vertex // there are 4 classes vertex: // 1) inner vertex, // 2) corner point, // 3) point on crease // 4) ordinary border point on adjacent surface void hs_subdiv::calc_vert_point(point_vector& vert_points, point_vector& cell_points) { hs_point cent; vert_vector_iter vert_iter = phexmodel->first_vert(); for (; vert_iter != phexmodel->end_vert(); ++ vert_iter) { cent = vert_iter->coord(); if ( vert_iter->type() == INNER_VERT ) { // inner point hs_point avg_cell_point; int_set_iter cell_iter = vert_iter->first_cell(); for (; cell_iter != vert_iter->end_cell(); ++cell_iter) { avg_cell_point += cell_points[*cell_iter]; } avg_cell_point /= vert_iter->cell_size(); hs_point avg_face_point; int_set_iter face_iter = vert_iter->first_face(); for (; face_iter != vert_iter->end_face(); ++face_iter) { hs_point avg_cent_face; hs_face& f = phexmodel->face_at(*face_iter); int_set_iter vitr = f.first_vert(); for (; vitr != f.end_vert(); ++vitr) { avg_cent_face += phexmodel->vert_at(*vitr).coord(); } avg_face_point += avg_cent_face / f.vert_size(); } avg_face_point /= vert_iter->face_size(); hs_point avg_mid_edge; int_set_iter edge_iter = vert_iter->first_edge(); for (; edge_iter != vert_iter->end_edge(); ++edge_iter) { avg_mid_edge += ( phexmodel->vert_at(phexmodel->edge_at(*edge_iter).start_vert()).coord() + phexmodel->vert_at(phexmodel->edge_at(*edge_iter).end_vert()).coord() ) * 0.5; } avg_mid_edge /= vert_iter->edge_size(); cent = (cent + avg_mid_edge * 3 + avg_face_point * 3 + avg_cell_point) / 8; } else if ( vert_iter->type() == CREASE_VERT ){ // crease vertex // find the crease curve of crease vertex using set std::set< const EDGE* > edge_set; int_set_iter edge_iter = vert_iter->first_edge(); for (; edge_iter != vert_iter->end_edge(); ++edge_iter) { edge_set.insert( phexmodel->edge_at(*edge_iter).acis_edge() ); } edge_set.erase( NULL ); // crease vertex only have 2 same crease curve // and other adjacent edge is null assert( 1 == edge_set.size() ); SPAposition spa_pos( cent.x(), cent.y(), cent.z()); const EDGE* spa_edge = *(edge_set.begin()); const curve& ccurv = spa_edge->geometry()->equation(); SPAposition new_spa_pos( ccurv.eval_position( ccurv.param(spa_pos) ) ); cent.set_coord( new_spa_pos.x(), new_spa_pos.y(), new_spa_pos.z() ); } else if ( vert_iter->type() == ORDINARY_VERT ) { // ordinary vertex // find the unique adjacent border surface using set std::set< const FACE* > face_set; int_set_iter face_iter = vert_iter->first_face(); for (; face_iter != vert_iter->end_face(); ++face_iter) { face_set.insert( phexmodel->face_at(*face_iter).acis_face() ); } face_set.erase( NULL ); assert( 1 == face_set.size() ); const FACE* spa_face = *(face_set.begin()); const surface& csurf = spa_face->geometry()->equation(); SPAposition spa_pos( cent.x(), cent.y(), cent.z() ); SPAposition new_spa_pos( csurf.eval_position( csurf.param(spa_pos) ) ); cent.set_coord( new_spa_pos.x(), new_spa_pos.y(), new_spa_pos.z() ); } else { // corner vertex assert( vert_iter->type() == CORNER_VERT ); } vert_points.push_back(cent); } }