public void Build(TriMesh mesh) { int nBasisCycles = basisCycles.Count; //Build Matrix A A = BuildCycleMatrix(mesh, basisCycles); ApplyCotanWeights(ref A); //Factorize LinearSystemGenericByLib.Instance.FactorizationQR(ref A); K = new DenseMatrixDouble(basisCycles.Count, 1); b = new DenseMatrixDouble(basisCycles.Count, 1); //Add constraint of angle defect for (int i = 0; i < nContractibleCycles; i++) { K[i, 0] = -ComputeGeneratorDefect(basisCycles[i]); } //Add constraint of Generator int nGenerators = dualCycles.Count; for (int i = nContractibleCycles; i < nGenerators + nContractibleCycles; i++) { List <TriMesh.HalfEdge> generatorCycle = basisCycles[i]; //Boundary condition if (treeCotree.IsBoundaryGenerator(generatorCycle)) { K[i, 0] = -BoundaryLoopCurvature(generatorCycle); GeneratorOnBoundary[i - nContractibleCycles] = true; } //None-Boundary condition else { K[i, 0] = -ComputeGeneratorDefect(generatorCycle); GeneratorOnBoundary[i - nContractibleCycles] = false; } } //Copy to b for (int i = 0; i < nBasisCycles; i++) { b[i, 0] = K[i, 0]; } }
public void InitProcess(TriMesh mesh) { TreeCoTree treeCotree = new TreeCoTree(mesh); generatorLoops = treeCotree.ExtractHonologyGenerator(mesh); HarmonicBasis basis = new HarmonicBasis(mesh); HarmonicBasis = basis.BuildHarmonicBasis(generatorLoops); int numberOfHarmBases = basis.NumberOfHarmonicBases(generatorLoops); //Still need to built u = InitWithTrivalHolonmy(Laplace, mesh); HarmonicCoffition = new double[numberOfHarmBases]; if (numberOfHarmBases == 0) { return; } DenseMatrixDouble b = new DenseMatrixDouble(numberOfHarmBases, 1); SparseMatrixDouble H = new SparseMatrixDouble(numberOfHarmBases, numberOfHarmBases); int row = 0; bool skipBoundaryLoop = true; for (int i = 0; i < generatorLoops.Count; i++) { List <TriMesh.HalfEdge> cycle = generatorLoops[i]; if (skipBoundaryLoop && treeCotree.IsBoundaryGenerator(cycle)) { skipBoundaryLoop = false; continue; } foreach (TriMesh.HalfEdge hf in cycle) { for (int col = 0; col < numberOfHarmBases; col++) { H[row, col] += HarmonicBasis[hf.Index][col]; } } double value = -GeneratorHolomy(cycle, HarmonicBasis, HarmonicCoffition, u); b[row, 0] = value; row++; } DenseMatrixDouble x = null; if (b.F_Norm() > 1.0e-8) { x = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref H, ref b); } else { x = new DenseMatrixDouble(numberOfHarmBases, 1); } for (int i = 0; i < numberOfHarmBases; i++) { HarmonicCoffition[i] = x[i, 0]; } }
public List <double>[] BuildHarmonicBasis(List <List <TriMesh.HalfEdge> > generators) { List <double>[] HarmonicBasis; HarmonicBasis = new List <double> [mesh.HalfEdges.Count]; SparseMatrixDouble laplace = DECDouble.Instance.BuildLaplaceWithNeumannBoundary(mesh); SparseMatrixDouble star1 = DECDouble.Instance.Star1; if (star1 == null) { star1 = DECDouble.Instance.BuildHodgeStar1Form(mesh); } SparseMatrixDouble d0 = DECDouble.Instance.D0; if (d0 == null) { d0 = DECDouble.Instance.BuildExteriorDerivative0Form(mesh); } SparseMatrixDouble d1 = DECDouble.Instance.D1; if (d1 == null) { d1 = DECDouble.Instance.BuildExteriorDerivative1Form(mesh); } SparseMatrixDouble div = d0.Transpose() * star1; bool skipBoundary = true; foreach (List <TriMesh.HalfEdge> loopItem in generators) { if (skipBoundary && treeCoTree.IsBoundaryGenerator(loopItem)) { skipBoundary = false; continue; } DenseMatrixDouble W = BuildClosedPrimalOneForm(mesh, loopItem); DenseMatrixDouble divW = div * W; DenseMatrixDouble u = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref laplace, ref divW); DenseMatrixDouble h = star1 * (W - (d0 * u)); //Store correspond edge foreach (TriMesh.Edge edge in mesh.Edges) { double value = h[edge.Index, 0]; if (HarmonicBasis[edge.HalfEdge0.Index] == null) { HarmonicBasis[edge.HalfEdge0.Index] = new List <double>(); } HarmonicBasis[edge.HalfEdge0.Index].Add(value); if (HarmonicBasis[edge.HalfEdge1.Index] == null) { HarmonicBasis[edge.HalfEdge1.Index] = new List <double>(); } HarmonicBasis[edge.HalfEdge1.Index].Add(-value); } } return(HarmonicBasis); }
public void InitProcess(TriMesh mesh) { TreeCoTree treeCotree = new TreeCoTree(mesh); generatorLoops = treeCotree.ExtractHonologyGenerator(mesh); HarmonicBasis basis = new HarmonicBasis(mesh); HarmonicBasis = basis.BuildHarmonicBasis(generatorLoops); int numberOfHarmBases = basis.NumberOfHarmonicBases(generatorLoops); //Still need to built u = InitWithTrivalHolonmy(Laplace, mesh); HarmonicCoffition = new double[numberOfHarmBases]; if (numberOfHarmBases == 0) { return; } DenseMatrixDouble b = new DenseMatrixDouble(numberOfHarmBases, 1); SparseMatrixDouble H = new SparseMatrixDouble(numberOfHarmBases, numberOfHarmBases); int row = 0; bool skipBoundaryLoop = true; for (int i = 0; i < generatorLoops.Count; i++) { List<TriMesh.HalfEdge> cycle = generatorLoops[i]; if (skipBoundaryLoop && treeCotree.IsBoundaryGenerator(cycle)) { skipBoundaryLoop = false; continue; } foreach (TriMesh.HalfEdge hf in cycle) { for (int col = 0; col < numberOfHarmBases; col++) { H[row, col] += HarmonicBasis[hf.Index][col]; } } double value = -GeneratorHolomy(cycle, HarmonicBasis, HarmonicCoffition, u); b[row, 0] = value; row++; } DenseMatrixDouble x = null; if (b.F_Norm() > 1.0e-8) { x = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref H, ref b); } else { x = new DenseMatrixDouble(numberOfHarmBases, 1); } for (int i = 0; i < numberOfHarmBases; i++) { HarmonicCoffition[i] = x[i, 0]; } }