// create new vertex list // new vertex has same type with old vertex. // new edge vertex has same type with old edge, such as inner, ordinary and crease // new face vertex has same type with old face, such as inner, (ordinary) border // new cell vertex only has INNER type void hs_subdiv::create_vert_list(hs_model* pmodel , point_vector& vert_points , point_vector& edge_points , point_vector& face_points , point_vector& cell_points ) { point_vector_iter vert_iter; size_t idx = 0; vert_iter = vert_points.begin(); for (; vert_iter != vert_points.end(); ++vert_iter, ++idx) { pmodel->add_vert(*vert_iter, phexmodel->vert_at(idx).type() ); } idx = 0; vert_iter = edge_points.begin(); for (; vert_iter != edge_points.end(); ++vert_iter, ++idx) { pmodel->add_vert(*vert_iter, static_cast<vert_type>( phexmodel->edge_at(idx).type() )); } idx = 0; vert_iter = face_points.begin(); for (; vert_iter != face_points.end(); ++vert_iter, ++idx) { pmodel->add_vert(*vert_iter, static_cast<vert_type>( phexmodel->face_at(idx).type() ) ); } vert_iter = cell_points.begin(); for (; vert_iter != cell_points.end(); ++vert_iter) { pmodel->add_vert(*vert_iter, INNER_VERT); } }
/* * Algorithm for finding MST on a plane uses Prim's algorithm * to find the MST returns pairs representing indexes of the matched points * complexity: O(n^2 * log(n)) */ std::vector< std::pair<lint, lint> > naive_euclidean_mst( const point_vector & points) { ldouble cost = 0; lint n = points.size(); std::vector<bool> already_in_mst(n, false); already_in_mst[0] = true; std::vector< std::pair<lint, lint> > mst; std::priority_queue<edge> potential_edges; for(lint i = 1; i < n; i++) potential_edges.push(edge(0, i, dist(points[0], points[i]))); while(!potential_edges.empty()) { edge current = potential_edges.top(); potential_edges.pop(); if(!already_in_mst[current.end]) { cost += current.cost; already_in_mst[current.end] = true; mst.push_back(std::make_pair(current.begin, current.end)); for(lint i = 1; i < n; i++) if(!already_in_mst[i]) potential_edges.push(edge(current.end, i, dist(points[current.end], points[i]))); } } return mst; }
/*----------------------------------------------------------------*/ static void ConnectedComponent(unsigned char thresh, int marker, point_vector &inside, point_vector &boundary) { // simple connected component while (!inside.empty()) { t_offset ofs = inside.back().ofs; inside.pop_back(); add_if_inside(inside, boundary, thresh, ofs + g_cols, 4, marker); add_if_inside(inside, boundary, thresh, ofs - g_cols, 1, marker); add_if_inside(inside, boundary, thresh, ofs + 1, 2, marker); add_if_inside(inside, boundary, thresh, ofs - 1, 8, marker); } /* sort region's boundary */ std::sort(boundary.begin(), boundary.end()); }
// 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); } }