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;
}
Пример #2
0
//-------------------------------------------------------------------------------------
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;
}