void Mesh::buildBasisCycles() { std::vector<BasisCycle> basisCycles; buildContractibleCycles(basisCycles); buildNonContractibleCycles(basisCycles); // build A Eigen::SparseMatrix<double> A((int)basisCycles.size(), (int)edges.size()); A.setZero(); std::vector<Eigen::Triplet<double>> ATriplet; for (int i = 0; i < (int)basisCycles.size(); i++) { for (int j = 0; j < (int)basisCycles[i].size(); j++) { HalfEdgeIter he = basisCycles[i][j]; int e = he->edge->index; double coefficient = sqrt((he->cotan() + he->flip->cotan()) * 0.5); if (coefficient != coefficient) coefficient = 0; // check for negative cotan weights if (he == he->edge->he) { ATriplet.push_back(Eigen::Triplet<double>(i, e, coefficient)); } else { ATriplet.push_back(Eigen::Triplet<double>(i, e, -coefficient)); } } } A.setFromTriplets(ATriplet.begin(), ATriplet.end()); solver.compute(A); }
void Mesh::buildNonContractibleCycles(std::vector<BasisCycle>& basisCycles) { generators.clear(); buildPrimalSpanningTree(); buildDualSpanningTree(); for (EdgeCIter e = edges.begin(); e != edges.end(); e++) { HalfEdgeIter he = e->he; if (!he->inPrimalSpanningTree() && !he->inDualSpanningTree()) { BasisCycle cycle; cycle.push_back(he); // trace loop in both directions BasisCycle temp1; FaceCIter f = he->flip->face; while (f != f->parent) { FaceCIter fp = f->parent; temp1.push_back(f->sharedEdge(fp)); f = fp; } BasisCycle temp2; f = he->face; while (f != f->parent) { FaceCIter fp = f->parent; temp2.push_back(f->sharedEdge(fp)); f = fp; } // remove common edges int t1 = (int)temp1.size()-1; int t2 = (int)temp2.size()-1; while (temp1[t1] == temp2[t2]) { t1--; t2--; } for (int i = 0; i <= t1; i++) { cycle.push_back(temp1[i]); } for (int i = t2; i >= 0; i--) { cycle.push_back(temp2[i]->flip); } generators.push_back(cycle); } } basisCycles.insert(basisCycles.end(), generators.begin(), generators.end()); }
double Mesh :: connectionOneForm(HalfEdgeIter h) const { double angle = 0.0; // coclosed term double star1 = 0.5 * ( h->cotan() + h->flip->cotan() ); double u0 = h->flip->vertex->potential; double u1 = h->vertex->potential; angle += star1*(u1 - u0); // harmonic term for(unsigned k = 0; k < h->harmonicBases.size(); ++k) angle += this->harmonicCoefs[k] * h->harmonicBases[k]; return angle; }