HRESULT CIsochartMesh::InitializeBarycentricEquation( CSparseMatrix<double>& A, CVector<double>& BU, CVector<double>& BV, const std::vector<double>& boundTable, const std::vector<uint32_t>& vertMap) { HRESULT hr = S_OK; CSparseMatrix<double> orgA; CVector<double> orgBU, orgBV; // 1. Allocate memory size_t dwOrgADim = m_dwVertNumber - boundTable.size()/2; try { orgA.resize(dwOrgADim, dwOrgADim); orgBU.resize(dwOrgADim); orgBV.resize(dwOrgADim); } catch (std::bad_alloc&) { return E_OUTOFMEMORY; } // 2. Fill the linear equation for (size_t ii=0; ii<m_dwVertNumber; ii++) { if (m_pVerts[ii].bIsBoundary) { continue; } auto& adjacent = m_pVerts[ii].vertAdjacent; double bu = 0, bv = 0; orgA.setItem(vertMap[ii], vertMap[ii], double(adjacent.size())); for (size_t jj=0; jj<adjacent.size(); jj++) { uint32_t dwAdj = adjacent[jj]; if (m_pVerts[dwAdj].bIsBoundary) { bu += boundTable[vertMap[dwAdj]*2]; bv += boundTable[vertMap[dwAdj]*2+1]; } else { orgA.setItem(vertMap[ii], vertMap[dwAdj], double(-1)); } } orgBU[vertMap[ii]] = bu; orgBV[vertMap[ii]] = bv; } // 3. get Symmetric matrix // A' = A^T * A if (!CSparseMatrix<double>::Mat_Trans_MUL_Mat(A, orgA)) { return E_OUTOFMEMORY; } // B' = A^T * b if (!CSparseMatrix<double>::Mat_Trans_Mul_Vec(BU, orgA, orgBU)) { return E_OUTOFMEMORY; } if (!CSparseMatrix<double>::Mat_Trans_Mul_Vec(BV, orgA, orgBV)) { return E_OUTOFMEMORY; } return hr; }
//------------------------------------------------------------------------------------- HRESULT CIsochartMesh::AddFaceWeight( uint32_t dwFaceID, CSparseMatrix<double>& A, CSparseMatrix<double>& M, uint32_t dwBaseVertId1, uint32_t dwBaseVertId2) { HRESULT hr = S_OK; assert(dwBaseVertId1 < dwBaseVertId2); ISOCHARTFACE& face = m_pFaces[dwFaceID]; XMFLOAT2 v2d[3]; XMFLOAT3 axis[2]; IsochartCaculateCanonicalCoordinates( m_baseInfo.pVertPosition + m_pVerts[face.dwVertexID[0]].dwIDInRootMesh, m_baseInfo.pVertPosition + m_pVerts[face.dwVertexID[1]].dwIDInRootMesh, m_baseInfo.pVertPosition + m_pVerts[face.dwVertexID[2]].dwIDInRootMesh, v2d, v2d+1, v2d+2, axis); double t = (v2d[0].x*v2d[1].y - v2d[0].y*v2d[1].x) + (v2d[1].x*v2d[2].y - v2d[1].y*v2d[2].x) + (v2d[2].x*v2d[0].y - v2d[2].y*v2d[0].x); t = static_cast<double>(IsochartSqrt(t)); if (IsInZeroRange2(static_cast<float>(t))) { return hr; } CSparseMatrix<double>* pA = nullptr; for (size_t ii=0; ii<3; ii++) { ISOCHARTVERTEX& vert = m_pVerts[face.dwVertexID[ii]]; double w_r = v2d[(ii+2)%3].x - v2d[(ii+1)%3].x; double w_i = v2d[(ii+2)%3].y - v2d[(ii+1)%3].y; size_t dwCol1; size_t dwCol2; if ( IN_CONSTANT == GetPosInMatrix( vert.dwID, m_dwVertNumber, dwBaseVertId1, dwBaseVertId2, dwCol1, dwCol2)) { pA = &M; } else { pA = &A; } if (!pA->setItem(dwFaceID, dwCol1, w_r/t)) { return E_OUTOFMEMORY; } if (!pA->setItem(dwFaceID, dwCol2, -w_i/t)) { return E_OUTOFMEMORY; } if (!pA->setItem(dwFaceID+m_dwFaceNumber, dwCol1, w_i/t)) { return E_OUTOFMEMORY; } if (!pA->setItem(dwFaceID+m_dwFaceNumber, dwCol2, w_r/t)) { return E_OUTOFMEMORY; } } return hr; }