//////////////////////////////////////////////////////////////////////////////////////// //GetBBox //-------- //Get a box which is twice as bigger as the boundding box of the object // void TMesh::GetBBox() { if(v_count() == 0 ) { _pmin = VECTOR3(); _pmax = VECTOR3(); return; } for(int i = 0; i < 3; i ++) { _pmin[i] = (vertex(0).coord())(i); _pmax[i] = (vertex(0).coord())(i); } for(unsigned int i = 1; i < v_count(); i ++) { for(int j = 0; j < 3; j ++) { if( (vertex(i).coord())(j) < _pmin[j] ) _pmin[j] = (vertex(i).coord())(j); else if((vertex(i).coord())(j) > _pmax[j]) _pmax[j] = (vertex(i).coord())(j); }//for j }//for i //cerr<<"BBox: min "<<_pmin[0]<<" "<<_pmin[1]<<" "<<_pmin[2] //<<" max "<<_pmax[0]<<" "<<_pmax[1]<<" "<<_pmax[2]<<endl; }
//================================================================ //begin: off file outpur function //================================================================ void TMesh::OutMeshOffFile(char *filename) { FILE *fp; if( (fp = fopen(filename, "w")) == NULL ) { std::cout<<"Failed to open file!"<<std::endl; return; } fprintf(fp, "LIST\n"); fprintf(fp, "appearance {linewidth 7}\n"); fprintf(fp, "{\n"); fprintf(fp, "OFF\n"); fprintf(fp, "%d %d 0\n", v_count(), f_count()); for(unsigned int i = 0; i < v_count(); i ++) { fprintf(fp, "%f %f %f\n", (vertex(i).coord())(0), (vertex(i).coord())(1), (vertex(i).coord())(2)); } for(unsigned int i = 0; i < f_count(); i ++) { if( vertex(facet(i).vert(0)).check_flag(VTMESH_FLAG_SELECTED) && vertex(facet(i).vert(1)).check_flag(VTMESH_FLAG_SELECTED) && vertex(facet(i).vert(2)).check_flag(VTMESH_FLAG_SELECTED)) fprintf(fp, "3 %d %d %d 0.2 0.2 0.2 1\n", facet(i).vert(0), facet(i).vert(1), facet(i).vert(2)); else fprintf(fp, "3 %d %d %d 1 1 1 1\n", facet(i).vert(0), facet(i).vert(1), facet(i).vert(2)); } fprintf(fp, "}\n"); fclose(fp); }
void TMesh::PrintMeshTopo() { cout<<"vertex top"<<endl; for(unsigned int i = 0; i < v_count(); i ++) { cout<<"vertex "<<i<<": "<<vertex(i).coord()<<endl; cout<<"\t incident vertex: "; for(unsigned int vit = 0; vit < vertex(i).n_verts(); vit ++) cout<<"\t"<<vertex(i).vert(vit)<<" "; cout<<endl; cout<<"\t incident triangle: "; for(unsigned int fit = 0; fit < vertex(i).n_facets(); fit ++) cout<<"\t"<<vertex(i).facet(fit)<<" "; cout<<endl; } cout<<endl; cout<<"triangle top"<<endl; for(unsigned int i = 0; i < f_count(); i ++) { cout<<"triangle "<<i<<endl; cout<<"\t vert: "; for(int j = 0; j < 3; j ++) cout<<"\t"<<facet(i).vert(j)<<" "; cout<<endl; cout<<"\t adj_facet: "; for(int j = 0; j < 3; j ++) cout<<"\t"<<facet(i).facet(j)<<" "; cout<<endl; } cout<<endl; }
void TMesh::OutMeshOffFile(FILE *fp, double r, double g, double b, double a) { if( fp == NULL ) { std::cout<<"Invalid FILE pointer"<<std::endl; return; } fprintf(fp, "{\n"); fprintf(fp, "OFF\n"); fprintf(fp, "%d %d 0\n", v_count(), f_count()); for(unsigned int i = 0; i < v_count(); i ++) { fprintf(fp, "%f %f %f\n", (vertex(i).coord())(0), (vertex(i).coord())(1), (vertex(i).coord())(2)); } for(unsigned int i = 0; i < f_count(); i ++) { if( facet(i).check_flag(FTMESH_FLAG_SELECT) ) fprintf(fp, "3 %d %d %d 1 0 0 1\n", facet(i).vert(0), facet(i).vert(1), facet(i).vert(2)); else fprintf(fp, "3 %d %d %d %f %f %f %f\n", facet(i).vert(0), facet(i).vert(1), facet(i).vert(2), r, g, b, a); } fprintf(fp, "}\n"); }
bool TMesh::CheckMeshTopo() { //check facet topo bool good = true; for(unsigned int i = 0; i < f_count(); i ++) { for(int j = 0; j < 3; j ++) { int fid = facet(i).facet(j); if(fid < 0) continue; int findex = facet(fid).findex(facet(i).vert((j + 1) % 3), facet(i).vert((j + 2) % 3)); if(findex < 0) { cerr<<"mesh topo check error!"<<endl; cerr<<"fid: "<<i<<" eid: "<<" fid_adj: "<<fid<<endl; good = false; } //assert(findex >= 0); } } //check vertex topo for(unsigned int i = 0; i < v_count(); i ++) { for(unsigned int j = 0; j < vertex(i).n_facets(); j ++) { unsigned int fid = vertex(i).facet(j); int vindex = facet(fid).index(i); if(vindex < 0) { cerr<<"mesh topo check error!"<<endl; cerr<< "vid: "<<i<<" fid: "<<fid<<endl; good = false; } //assert(vindex >= 0); } for(unsigned int j = 0; j < vertex(i).n_verts(); j ++) { unsigned int vid = vertex(i).vert(j); int vindex = vertex(vid).index(i); if(vindex < 0) { cerr<<"mesh topo check error!"<<endl; cerr<<"vid: "<<i<<" vid: "<<vid<<endl; good = false; } //assert(vindex >= 0); } } if(!good) { cerr<<"Warning: the input mesh is not a manifold, which MAY crash the successive computation."<<endl; } return true; }
//-------------------------------------------------- //MarkNonManifoldness: //---------------- //Check the non_manifoldness for each vertex and mark //the vertex and all the incident facets if it is a //non_manifold vertex. //-------------------------------------------------- void TMesh::MarkNonManifoldness() { unsigned int vid, fid, count; int ind, fid_circ, ind_circ, fid_pre; for(vid = 0; vid < v_count(); vid ++) { VTMesh vert = vertex(vid); if( vert.n_facets() == 0) continue; fid = vert.facet(0); ind = facet(fid).index(vid); assert(ind >= 0); facet(fid).set_flag(FTMESH_FLAG_VISITED); count = 1; #define UMBRELLAWALK(vid, fid, fid_circ) \ fid_pre = fid; \ while(fid_circ >= 0 && fid_circ != (int)fid){ \ if( facet(fid_circ).check_flag(FTMESH_FLAG_VISITED) ) break; \ facet(fid_circ).set_flag(FTMESH_FLAG_VISITED); \ count ++; \ ind_circ = facet(fid_circ).index(vid); \ assert(ind_circ >= 0); \ if( fid_pre != facet(fid_circ).facet( (ind_circ + 1) % 3 ) ){ \ fid_pre = fid_circ; \ fid_circ = facet(fid_circ).facet( (ind_circ + 1) % 3 ); \ } \ else{ \ fid_pre = fid_circ; \ fid_circ = facet(fid_circ).facet( (ind_circ + 2) % 3 ); \ } \ } fid_circ = facet(fid).facet( (ind + 1) % 3 ); UMBRELLAWALK(vid, fid, fid_circ); fid_circ = facet(fid).facet( (ind + 2) % 3 ); UMBRELLAWALK(vid, fid, fid_circ); //If the incident facets does not form an umbrella, then mark if( count < vert.n_facets() ) { vert.set_flag(VTMESH_FLAG_NMANIFOLD); for(unsigned int i = 0; i < vert.n_facets(); i ++) facet( vert.facet(i) ).un_set_flag(FTMESH_FLAG_NMANIFOLD); } //Unset FTMESH_FLAG_VISITED for(unsigned int i = 0; i < vert.n_facets(); i ++) facet( vert.facet(i) ).un_set_flag(FTMESH_FLAG_VISITED); } }
bool TMesh::ReadOffFile(char *filename, bool wcolor) { ifstream fin_temp; fin_temp.open(filename); if( !fin_temp.good() ) { return false; } ofstream fout_temp; fout_temp.open("temp.m"); if(!fout_temp.good()) { cerr<<"Failed to open file temp.m"<<endl; return false; } // Read the off file and skip the comments. // Write the comment-less off file to a file, called "temp.m". while(! fin_temp.eof()) { char line[90]; fin_temp.getline(line, 90); if(line[0] == 'O' || line[0] == '#') ; else fout_temp << line << endl; } fin_temp.close(); fout_temp.close(); FILE *fp; if( (fp = fopen("temp.m", "r")) == NULL ) { cerr<<"Failed to open file temp.m"<<endl; return false; } unsigned int n_ver, n_facet, n_edge; fscanf(fp, "%d %d %d", &n_ver, &n_facet, &n_edge); // cerr<<"n_ver: "<<n_ver<<" n_facet: "<<n_facet<<endl; float x, y, z; //vertex information for(unsigned int i = 0; i < n_ver; i ++) { fscanf(fp, "%f %f %f", &x, &y, &z); //cerr<<"x y z"<<x<<" "<<y<<" "<<z<<endl; //VTMesh v(x, y, z); add_vertex( VTMesh(x, y, z) ); } //cout<<"vertex done"<<endl; //facet information int nv, vid0, vid1, vid2; float r, g, b, a; for(unsigned int i = 0; i < n_facet; i ++) { fscanf(fp, "%d %d %d %d", &nv, &vid0, &vid1, &vid2); if(wcolor) fscanf(fp, "%f %f %f %f", &r, &g, &b, &a); unsigned int fid = add_facet( FTMesh(vid0, vid1, vid2) ); assert(fid == i); } //cerr<<"facet done"<<endl; assert(v_count() == n_ver); assert(f_count() == n_facet); //get the bounding box of mesh GetBBox(); //Delete the temp.m file system("rm temp.m"); //Generate the topology for tmesh GenerateMeshTopo(); //Mark the non_manifoldness MarkNonManifoldness(); //debug // PrintMeshTopo(); // getchar(); return true; }
/* * v_cmd -- * * The command structure for vi is less complex than ex (and don't think * I'm not grateful!) The command syntax is: * * [count] [buffer] [count] key [[motion] | [buffer] [character]] * * and there are several special cases. The motion value is itself a vi * command, with the syntax: * * [count] key [character] */ static gcret_t v_cmd( SCR *sp, VICMD *dp, VICMD *vp, VICMD *ismotion, /* Previous key if getting motion component. */ int *comcountp, int *mappedp) { enum { COMMANDMODE, ISPARTIAL, NOTPARTIAL } cpart; EVENT ev; VIKEYS const *kp; gcret_t gcret; u_int flags; CHAR_T key; char *s; /* * Get a key. * * <escape> cancels partial commands, i.e. a command where at least * one non-numeric character has been entered. Otherwise, it beeps * the terminal. * * !!! * POSIX 1003.2-1992 explicitly disallows cancelling commands where * all that's been entered is a number, requiring that the terminal * be alerted. */ cpart = ismotion == NULL ? COMMANDMODE : ISPARTIAL; if ((gcret = v_key(sp, ismotion == NULL, &ev, EC_MAPCOMMAND)) != GC_OK) { if (gcret == GC_EVENT) vp->ev = ev; return (gcret); } if (ev.e_value == K_ESCAPE) goto esc; if (F_ISSET(&ev.e_ch, CH_MAPPED)) *mappedp = 1; key = ev.e_c; if (ismotion == NULL) cpart = NOTPARTIAL; /* Pick up an optional buffer. */ if (key == '"') { cpart = ISPARTIAL; if (ismotion != NULL) { v_emsg(sp, NULL, VIM_COMBUF); return (GC_ERR); } KEY(vp->buffer, 0); F_SET(vp, VC_BUFFER); KEY(key, EC_MAPCOMMAND); } /* * Pick up an optional count, where a leading 0 is not a count, * it's a command. */ if (ISDIGIT(key) && key != '0') { if (v_count(sp, key, &vp->count)) return (GC_ERR); F_SET(vp, VC_C1SET); *comcountp = 1; KEY(key, EC_MAPCOMMAND); } else *comcountp = 0; /* Pick up optional buffer. */ if (key == '"') { cpart = ISPARTIAL; if (F_ISSET(vp, VC_BUFFER)) { msgq(sp, M_ERR, "234|Only one buffer may be specified"); return (GC_ERR); } if (ismotion != NULL) { v_emsg(sp, NULL, VIM_COMBUF); return (GC_ERR); } KEY(vp->buffer, 0); F_SET(vp, VC_BUFFER); KEY(key, EC_MAPCOMMAND); } /* Check for an OOB command key. */ cpart = ISPARTIAL; if (key > MAXVIKEY) { v_emsg(sp, KEY_NAME(sp, key), VIM_NOCOM); return (GC_ERR); } kp = &vikeys[vp->key = key]; /* * !!! * Historically, D accepted and then ignored a count. Match it. */ if (vp->key == 'D' && F_ISSET(vp, VC_C1SET)) { *comcountp = 0; vp->count = 0; F_CLR(vp, VC_C1SET); } /* Check for command aliases. */ if (kp->func == NULL && (kp = v_alias(sp, vp, kp)) == NULL) return (GC_ERR); /* The tildeop option makes the ~ command take a motion. */ if (key == '~' && O_ISSET(sp, O_TILDEOP)) kp = &tmotion; vp->kp = kp; /* * Find the command. The only legal command with no underlying * function is dot. It's historic practice that <escape> doesn't * just erase the preceding number, it beeps the terminal as well. * It's a common problem, so just beep the terminal unless verbose * was set. */ if (kp->func == NULL) { if (key != '.') { v_emsg(sp, KEY_NAME(sp, key), ev.e_value == K_ESCAPE ? VIM_NOCOM_B : VIM_NOCOM); return (GC_ERR); } /* If called for a motion command, stop now. */ if (dp == NULL) goto usage; /* * !!! * If a '.' is immediately entered after an undo command, we * replay the log instead of redoing the last command. This * is necessary because 'u' can't set the dot command -- see * vi/v_undo.c:v_undo for details. */ if (VIP(sp)->u_ccnt == sp->ccnt) { vp->kp = &vikeys['u']; F_SET(vp, VC_ISDOT); return (GC_OK); } /* Otherwise, a repeatable command must have been executed. */ if (!F_ISSET(dp, VC_ISDOT)) { msgq(sp, M_ERR, "208|No command to repeat"); return (GC_ERR); } /* Set new count/buffer, if any, and return. */ if (F_ISSET(vp, VC_C1SET)) { F_SET(dp, VC_C1SET); dp->count = vp->count; } if (F_ISSET(vp, VC_BUFFER)) dp->buffer = vp->buffer; *vp = *dp; return (GC_OK); } /* Set the flags based on the command flags. */ flags = kp->flags; /* Check for illegal count. */ if (F_ISSET(vp, VC_C1SET) && !LF_ISSET(V_CNT)) goto usage; /* Illegal motion command. */ if (ismotion == NULL) { /* Illegal buffer. */ if (!LF_ISSET(V_OBUF) && F_ISSET(vp, VC_BUFFER)) goto usage; /* Required buffer. */ if (LF_ISSET(V_RBUF)) { KEY(vp->buffer, 0); F_SET(vp, VC_BUFFER); } } /* * Special case: '[', ']' and 'Z' commands. Doesn't the fact that * the *single* characters don't mean anything but the *doubled* * characters do, just frost your shorts? */ if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') { /* * Historically, half entered [[, ]] or Z commands weren't * cancelled by <escape>, the terminal was beeped instead. * POSIX.2-1992 probably didn't notice, and requires that * they be cancelled instead of beeping. Seems fine to me. * * Don't set the EC_MAPCOMMAND flag, apparently ] is a popular * vi meta-character, and we don't want the user to wait while * we time out a possible mapping. This *appears* to match * historic vi practice, but with mapping characters, You Just * Never Know. */ KEY(key, 0); if (vp->key != key) { usage: if (ismotion == NULL) s = kp->usage; else if (ismotion->key == '~' && O_ISSET(sp, O_TILDEOP)) s = tmotion.usage; else s = vikeys[ismotion->key].usage; v_emsg(sp, s, VIM_USAGE); return (GC_ERR); } } /* Special case: 'z' command. */ if (vp->key == 'z') { KEY(vp->character, 0); if (ISDIGIT(vp->character)) { if (v_count(sp, vp->character, &vp->count2)) return (GC_ERR); F_SET(vp, VC_C2SET); KEY(vp->character, 0); } } /* * Commands that have motion components can be doubled to imply the * current line. */ if (ismotion != NULL && ismotion->key != key && !LF_ISSET(V_MOVE)) { msgq(sp, M_ERR, "210|%s may not be used as a motion command", KEY_NAME(sp, key)); return (GC_ERR); } /* Pick up required trailing character. */ if (LF_ISSET(V_CHAR)) KEY(vp->character, 0); /* Get any associated cursor word. */ if (F_ISSET(kp, V_KEYW) && v_curword(sp)) return (GC_ERR); return (GC_OK); esc: switch (cpart) { case COMMANDMODE: msgq(sp, M_BERR, "211|Already in command mode"); return (GC_ERR_NOFLUSH); case ISPARTIAL: break; case NOTPARTIAL: (void)sp->gp->scr_bell(sp); break; } return (GC_ERR); }