Point Face::norm() { HalfEdge * he = m_halfedge; Point p1 = he->target ()->point () - he->source ()->point (); Point p2 = he->he_next ()->target ()->point () - he->target ()->point (); Point n = p1 ^ p2; n /= n.norm (); return n; }
bool Curve::RobustTraceBoundaryLoop(HalfEdge* startHe, int & loopSize) { HalfEdge * che = startHe; if (!che->source()->boundary() || !che->target()->boundary()) { std::cerr << "Error: the input halfedge is not on the boundary!" << std::endl; loopSize=0; return false; } bool ccw; Vertex * ver = che->source(); HalfEdge * the = ver->most_ccw_out_halfedge(); if (the == che) { //Possiblly ccw is right, except the case that there is only one out halfedge starting from ver //in that case, check one more step forward is enough HalfEdge * tempthe = the->target()->most_ccw_out_halfedge(); if (tempthe->edge()->boundary()) ccw = true; else { assert(ver->most_ccw_out_halfedge() == ver->most_clw_out_halfedge()); ccw = false; } } else { ccw = false; the = ver->most_clw_out_halfedge(); assert(the == che); } the = che; std::vector<HalfEdge *>::iterator finditer; while (the->target() != ver) { finditer = std::find(helist.begin(), helist.end(), the); if (finditer != helist.end()) {//found std::cerr << "Possible Error: not go back to the starting point!" << std::endl; helist.erase(helist.begin(), finditer-1); loopSize = helist.size(); return false; } else {//not found helist.push_back(the); } if (ccw) the = the->target()->most_ccw_out_halfedge(); else the = the->target()->most_clw_out_halfedge(); } helist.push_back(the); loopSize = helist.size(); return true; }
void SolidDelegate::removeFace (Solid * pS, Face * f) { int i; HalfEdge * he = f->halfedge (); for(i=0; i<3; i++) { he = he->he_next (); Vertex * v = he->target (); if(v->halfedge () == he) { for(SolidEdgeIterator eiter(pS); !eiter.end (); ++eiter) { Edge * e = *eiter; HalfEdge * hhe = e->halfedge (0); if(hhe->target () == v && hhe != he) { v->halfedge () = hhe; break; } else if (e->halfedge (1) != NULL && e->halfedge (1)->target () == v && e->halfedge (1) != he) { v->halfedge () = e->halfedge (1); break; } } } if(v->halfedge () == he) v->halfedge () = NULL; } for(i=0; i<3; i++) { HalfEdge * nhe = he->he_next (); // Vertex * v = he->target (); Edge * e = he->edge (); if(e->halfedge (1) == NULL) { removeEdge(pS, e); delete e; delete he; } else { if(e->halfedge (0) == he) e->halfedge (0) = e->halfedge (1); delete he; e->halfedge(1) = NULL; } he = nhe; } pS->m_faces.remove(f); }
void Curve::ReplaceSections(Vertex * startV, Vertex * endV, std::vector<HalfEdge *> & replaceList) { int i,j; int startInd, endInd; startInd = endInd = -1; for (i=0;i<helist.size(); ++i) { HalfEdge * he = helist[i]; if (he->source() == startV) { startInd = i; break; } } assert(startInd != -1); for (j=i; j<helist.size();++j) { HalfEdge * he = helist[j]; if (he->target() == endV) { endInd = j; break; } } assert(endInd != -1); ReplaceSections(startInd, endInd, replaceList); }
int Curve::TraceFeatureCurve(Mesh * mesh, HalfEdge * heStart) { helist.clear(); MeshUtility::MarkSharpEdges(mesh); HalfEdge * che = heStart; Edge * ce = che->edge(); if (!ce->sharp()) { std::cerr << "Error: the input halfedge is not a feature edge!" << std::endl; return 0; } helist.push_back(che); Vertex * startV = che->source(); Vertex * cv = che->target(); while (cv!=startV) { bool flag = false; for (VertexOutHalfedgeIterator vhe(mesh, cv); !vhe.end(); ++vhe) { HalfEdge * he = *vhe; if (he->edge()->sharp() && he->edge() != ce) { che = he; cv = che->target(); ce = che->edge(); flag = true; break; } } if (!flag) { std::cerr << "Cannot find a circle!" << std::endl; helist.clear(); return 0; } helist.push_back(che); if (che->target() == startV) { //succeed return helist.size(); } } return helist.size(); }
bool Face::include_vertex(Vertex *v) { HalfEdge * he = m_halfedge; if(he->target () == v || he->source () == v || he->he_next ()->target () == v) return true; return false; }
int superMi::assign_kuv_to_edge(Solid* mesh) { for (SolidEdgeIterator seiter(mesh); !seiter.end(); ++seiter){ Edge* se = *seiter; se->kuv_h() = 0.0; //Point p1 = mesh->edgeVertex1(se)->point(); //Point p3 = mesh->edgeVertex2(se)->point(); //HalfEdge* he2 = se->halfedge(0)->ccw_rotate_about_source(); //HalfEdge* he4 = se->halfedge(0)->clw_rotate_about_source(); //Point p2 = he2->target()->point(); //Point p4 = he4->target()->point(); //double alpha = ((p3 - p2)*(p1 - p2) / ((p3 - p2) ^ (p1 - p2)).norm()) / 2.0; //double beta = ((p3 - p4)*(p1 - p4) / ((p3 - p4) ^ (p1 - p4)).norm()) / 2.0; //se->kuv_h() = alpha + beta; HalfEdge* he = se->halfedge(0); HalfEdge* nhe = he->he_next(); HalfEdge* phe = he->he_prev(); Face* hef = he->face(); double nhel = (nhe->target()->point() - nhe->source()->point()).norm(); double phel = (phe->target()->point() - phe->source()->point()).norm(); double hel = (he->target()->point() - he->source()->point()).norm(); se->kuv_h() += (nhel*nhel + phel*phel - hel*hel) / hef->area() / 8.0; he = se->halfedge(1); nhe = he->he_next(); phe = he->he_prev(); hef = he->face(); nhel = (nhe->target()->point() - nhe->source()->point()).norm(); phel = (phe->target()->point() - phe->source()->point()).norm(); se->kuv_h() += (nhel*nhel + phel*phel - hel*hel) / hef->area() / 8.0; se->kuv_t() = 1.0; //std::cout << se->kuv() << std::endl; } return 0; }
void Curve::TraceBoundary(HalfEdge * startHe, Vertex * endV) { HalfEdge * che = startHe; if (!che->source()->boundary() || !che->target()->boundary()) { std::cerr << "Error: the input halfedge is not on the boundary!" << std::endl; return; } bool ccw; Vertex * ver = che->source(); HalfEdge * the = ver->most_ccw_out_halfedge(); if (the == che) { //Possiblly ccw is right, except the case that there is only one out halfedge starting from ver //in that case, check one more step forward is enough HalfEdge * tempthe = the->target()->most_ccw_out_halfedge(); if (tempthe->edge()->boundary()) ccw = true; else { assert(ver->most_ccw_out_halfedge() == ver->most_clw_out_halfedge()); ccw = false; } } else { ccw = false; the = ver->most_clw_out_halfedge(); assert(the == che); } the = che; std::vector<HalfEdge *>::iterator finditer; while (the->vertex() != endV) { helist.push_back(the); if (ccw) the = the->target()->most_ccw_out_halfedge(); else the = the->target()->most_clw_out_halfedge(); if (helist.size()>10000000) { assert(0); } } }
bool Curve::WriteToFile(const char file[]) { //if (!valid) //{ // std::cerr << "Error: The curve is invalid" << std::endl; // return false; //} std::ofstream fp; fp.open(file); if (!fp.good()) { std::cerr << "I/O Error: Cannot write into file " << file << " !" << std::endl; return false; } fp << helist.size() << std::endl; for (int i=0;i<helist.size(); ++i) { HalfEdge * he = helist[i]; fp << he->source()->id() << " " << he->target()->id() << std::endl; } fp.close(); return true; }
void main(int argc, char *argv[]) { // Read in the obj file Solid mesh; OBJFileReader of; std::ifstream in(argv[1]); of.readToSolid(&mesh, in); SolidDelegate sodel; SolidVertexIterator viter(&mesh); SolidFaceIterator faceiter(&mesh); Point deltaPL[2502]; Point Normal[2502]; Point tuettePoint[2502]; Point harmonicPoint[2502]; double innerProduct; Point normalComp; Point aDerv; for (int i = 0; i < 2502; i++) { deltaPL[i][0] = 0.0; deltaPL[i][1] = 0.0; deltaPL[i][2] = 0.0; Normal[i][0] = 0.0; Normal[i][1] = 0.0; Normal[i][2] = 0.0; tuettePoint[i][0] = 0.0; tuettePoint[i][1] = 0.0; tuettePoint[i][2] = 0.0; harmonicPoint[i] = { 0.0, 0.0, 0.0 }; } for (; !viter.end(); ++viter) { Vertex *vertmp = *viter; //VertexOutHalfedgeIterator voh(&mesh, vertmp); Point norm;//calc new Norm double totalArea = 0.0; norm[0] = norm[1] = norm[2] = 0.0; VertexFaceIterator vf(vertmp); for (; !vf.end(); ++vf){ double area = 0.0; Face *f = *vf; Point v1 = f->halfedge()->source()->point(); Point v2 = f->halfedge()->target()->point(); Point v3 = f->halfedge()->he_next()->target()->point(); area = ((v3 - v1) ^ (v2 - v1)).norm(); Point n = f->norm(); norm += n * area; totalArea += area; } Point newNorm; norm = norm / totalArea; double normN = norm.norm(); newNorm = norm / normN; //Normal & Gauss Map Normal[vertmp->id() - 1] = newNorm; } SolidEdgeIterator edgeiter(&mesh); double tuetteEnergy = 0.0; double newTEnergy = 0.0; double harmoincEnergy = 0.0; double newHEnergy = 0.0; double stepLength = 0.01; double eThreshold = 0.00001; for (; !edgeiter.end(); ++edgeiter) { Edge *e = *edgeiter; Vertex *s = mesh.edgeVertex1(e); Vertex *t = mesh.edgeVertex2(e); tuetteEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2(); } //harmonic K double K, cota, cotb; edgeiter.reset(); for (; !edgeiter.end(); ++edgeiter) { Edge *e = *edgeiter; Vertex *s = mesh.edgeVertex1(e); Vertex *t = mesh.edgeVertex2(e); HalfEdge *he = e->halfedge(1); he = he->ccw_rotate_about_source(); Vertex *v1 = he->target(); he = he->clw_rotate_about_source()->clw_rotate_about_source(); Vertex *v2 = he->target(); cota = (s->point() - v1->point())*(t->point() - v1->point()) / ((s->point() - v1->point()) ^ (t->point() - v1->point())).norm(); cotb = (s->point() - v2->point())*(t->point() - v2->point()) / ((s->point() - v2->point()) ^ (t->point() - v2->point())).norm(); K = (cota + cotb) / 2.0; edgemap.insert({ e, K }); } viter.reset(); //Gauss map update for (; !viter.end(); ++viter) { Vertex *vertmp = *viter; vertmp->point() = Normal[vertmp->id() - 1] ; } viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; VertexOutHalfedgeIterator voh(&mesh, vertmp); Point u = vertmp->point(); int id = vertmp->id()-1; double num = 0.0; for (; !voh.end(); ++voh) { HalfEdge *he1 = *voh; Vertex *v1 = he1->target(); Point v = v1->point(); deltaPL[id] += v - u; num = num + 1.0; } deltaPL[id] = deltaPL[id] / num; } //absolute derivatives viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; VertexOutHalfedgeIterator voh(&mesh, vertmp); Point u = vertmp->point(); int id = vertmp->id() - 1; innerProduct = deltaPL[id] * Normal[id]; normalComp[0] = innerProduct * Normal[id][0]; normalComp[1] = innerProduct * Normal[id][1]; normalComp[2] = innerProduct * Normal[id][2]; Point aDerv = deltaPL[id] - normalComp; Point tuetteUpdate = aDerv * stepLength; tuettePoint[id] = tuetteUpdate; //step 3 } viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; int id = vertmp->id() - 1; Normal[id] += tuettePoint[id]; Normal[id] = Normal[id] / Normal[id].norm(); } edgeiter.reset(); for (; !edgeiter.end(); ++edgeiter) { Edge *e = *edgeiter; Vertex *s = mesh.edgeVertex1(e); Vertex *t = mesh.edgeVertex2(e); newTEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2(); } viter.reset(); //tuette map update for (; !viter.end(); ++viter) { Vertex *vertmp = *viter; vertmp->point() =Normal[vertmp->id() - 1]; } //while(1==0) while (!(fabs(newTEnergy - tuetteEnergy) < eThreshold*1000)) {//step 5 tuetteEnergy = newTEnergy; newTEnergy = 0.0; //printf("%f\n", tuetteEnergy); viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; VertexOutHalfedgeIterator voh(&mesh, vertmp); Point u = vertmp->point(); int id = vertmp->id() - 1; double num = 0.0; for (; !voh.end(); ++voh) { HalfEdge *he1 = *voh; Vertex *v1 = he1->target(); Point v = v1->point(); deltaPL[id] += v - u; num = num + 1.0; } deltaPL[id] = deltaPL[id] / num; } viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; VertexOutHalfedgeIterator voh(&mesh, vertmp); Point u = vertmp->point(); int id = vertmp->id() - 1; innerProduct = deltaPL[id] * Normal[id]; normalComp[0] = innerProduct * Normal[id][0]; normalComp[1] = innerProduct * Normal[id][1]; normalComp[2] = innerProduct * Normal[id][2]; Point aDerv = deltaPL[id] - normalComp; Point tuetteUpdate = aDerv * stepLength; tuettePoint[id] = tuetteUpdate; //step 3 } viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; int id = vertmp->id() - 1; Normal[id] += tuettePoint[id]; Normal[id] = Normal[id] / Normal[id].norm(); } edgeiter.reset(); for (; !edgeiter.end(); ++edgeiter) { Edge *e = *edgeiter; Vertex *s = mesh.edgeVertex1(e); Vertex *t = mesh.edgeVertex2(e); newTEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2(); } viter.reset(); //tuette map update for (; !viter.end(); ++viter) { Vertex *vertmp = *viter; vertmp->point() = Normal[vertmp->id() - 1]; } } tuetteEnergy = newTEnergy; harmoincEnergy = tuetteEnergy; //harmonic viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; VertexOutHalfedgeIterator voh(&mesh, vertmp); Point u = vertmp->point(); int id = vertmp->id() - 1; double num = 0.0; for (; !voh.end(); ++voh) { HalfEdge *he1 = *voh; Edge *e = he1->edge(); Vertex *v1 = he1->target(); Point v = v1->point(); std::unordered_map<Edge*,double>::const_iterator got = edgemap.find(e); double K = got->second; deltaPL[id] += (v - u) * K; num = num + 1.0; } deltaPL[id] = deltaPL[id] / num; } //absolute derivatives viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; VertexOutHalfedgeIterator voh(&mesh, vertmp); Point u = vertmp->point(); int id = vertmp->id() - 1; innerProduct = deltaPL[id] * Normal[id]; normalComp[0] = innerProduct * Normal[id][0]; normalComp[1] = innerProduct * Normal[id][1]; normalComp[2] = innerProduct * Normal[id][2]; Point aDerv = deltaPL[id] - normalComp; Point hUpdate = aDerv * stepLength; harmonicPoint[id] =hUpdate; //step 3 } // compute mass center Point mass = { 0.0, 0.0, 0.0 }; viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; mass += vertmp->point(); } mass = mass / 2502; // h update w/ mass viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; int id = vertmp->id() - 1; Normal[id] +=harmonicPoint[id]; Normal[id] -= mass; Normal[id] = Normal[id] / Normal[id].norm(); } //h energy edgeiter.reset(); for (; !edgeiter.end(); ++edgeiter) { Edge *e = *edgeiter; Vertex *s = mesh.edgeVertex1(e); Vertex *t = mesh.edgeVertex2(e); std::unordered_map<Edge*, double>::const_iterator got = edgemap.find(e); double K = got->second; newHEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2()*K; } viter.reset(); //h map update for (; !viter.end(); ++viter) { Vertex *vertmp = *viter; vertmp->point() = Normal[vertmp->id() - 1]; } while (!(fabs(newHEnergy - harmoincEnergy) < eThreshold)) { harmoincEnergy = newHEnergy; newHEnergy = 0.0; //printf("%f\n", harmoincEnergy); viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; VertexOutHalfedgeIterator voh(&mesh, vertmp); Point u = vertmp->point(); int id = vertmp->id() - 1; double num = 0.0; for (; !voh.end(); ++voh) { HalfEdge *he1 = *voh; Edge *e = he1->edge(); Vertex *v1 = he1->target(); Point v = v1->point(); std::unordered_map<Edge*, double>::const_iterator got = edgemap.find(e); double K = got->second; deltaPL[id] += (v - u) * K; num = num + 1.0; } deltaPL[id] = deltaPL[id] / num; } //absolute derivatives viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; VertexOutHalfedgeIterator voh(&mesh, vertmp); Point u = vertmp->point(); int id = vertmp->id() - 1; innerProduct = deltaPL[id] * Normal[id]; normalComp[0] = innerProduct * Normal[id][0]; normalComp[1] = innerProduct * Normal[id][1]; normalComp[2] = innerProduct * Normal[id][2]; Point aDerv = deltaPL[id] - normalComp; Point hUpdate = aDerv * stepLength; harmonicPoint[id] = hUpdate; //step 3 } // compute mass center Point mass = { 0.0, 0.0, 0.0 }; viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; mass += vertmp->point(); } mass = mass / 2502; // h update w/ mass viter.reset(); for (; !viter.end(); ++viter)//step2 { Vertex *vertmp = *viter; int id = vertmp->id() - 1; Normal[id] += harmonicPoint[id]; Normal[id] -= mass; Normal[id] = Normal[id] / Normal[id].norm(); } //h energy edgeiter.reset(); for (; !edgeiter.end(); ++edgeiter) { Edge *e = *edgeiter; Vertex *s = mesh.edgeVertex1(e); Vertex *t = mesh.edgeVertex2(e); std::unordered_map<Edge*, double>::const_iterator got = edgemap.find(e); double K = got->second; newHEnergy += (Normal[s->id() - 1] - Normal[t->id() - 1]).norm2()*K; } viter.reset(); //h map update for (; !viter.end(); ++viter) { Vertex *vertmp = *viter; vertmp->point() = Normal[vertmp->id() - 1]; } } /***conformal****/ // Write out the resultant obj file int vObjID = 1; std::map<int, int> vidToObjID; std::ofstream os(argv[2]); SolidVertexIterator iter(&mesh); for (; !iter.end(); ++iter) { Vertex *v = *iter; Point p = v->point(); os << "v " << p[0] << " " << p[1] << " " << p[2] << std::endl; vidToObjID[v->id()] = vObjID++; } os << "# " << (unsigned int)mesh.numVertices() << " vertices" << std::endl; //texture float u = 0.0, v = 0.0; for (iter.reset(); !iter.end(); ++iter) { Vertex *vv = *iter; std::string key("uv"); std::string s = Trait::getTraitValue(vv->string(), key); if (s.length() > 0) { sscanf(s.c_str(), "%f %f", &u, &v); } os << "vt " << u << " " << v << std::endl; } os << "# " << (unsigned int)mesh.numVertices() << " texture coordinates" << std::endl; SolidFaceIterator fiter(&mesh); for (; !fiter.end(); ++fiter) { Face *f = *fiter; FaceVertexIterator viter(f); os << "f "; for (; !viter.end(); ++viter) { Vertex *v = *viter; os << vidToObjID[v->id()] << "/" << vidToObjID[v->id()] << " "; } os << std::endl; } os.close(); }
void Curve::BuildList(std::list<Edge *> edges, Vertex * startV) { // first we find the startV; valid = false; HalfEdge * startHE; std::list<Edge *>::iterator listEiter; for (listEiter=edges.begin(); listEiter!=edges.end(); ++listEiter) { //Edge * e = edges[i]; Edge * e = *listEiter; if (e->halfedge(0)->source() == startV) { valid = true; startHE = e->halfedge(0); break; } else if (e->halfedge(1) && e->halfedge(1)->source() == startV) { valid = true; startHE = e->halfedge(1); break; } } if (!valid) return; HalfEdge * che = startHE; helist.push_back(che); edges.erase(listEiter); while (edges.size()>0) { valid = false; for (listEiter=edges.begin(); listEiter!=edges.end(); ++listEiter) { Edge * e = *listEiter; HalfEdge * he1 = e->halfedge(0); //HalfEdge * he2 = e->halfedge(1); if (he1->source() == che->target()) { // use he1 valid = true; che = he1; helist.push_back(che); break; } else if (he1->target() == che->target()) { // he1 che = e->halfedge(1); if (!che) { valid = false; return; } else { valid = true; helist.push_back(che); break; } } } if (valid) edges.erase(listEiter); else return; } }