示例#1
0
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);
}
示例#2
0
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());
}
示例#3
0
 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;
 }