Exemple #1
0
bool ccGenericMesh::laplacianSmooth(unsigned nbIteration, float factor, CCLib::GenericProgressCallback* progressCb/*=0*/)
{
    if (!m_associatedCloud)
        return false;

    //vertices
    unsigned vertCount = m_associatedCloud->size();
    //triangles
    unsigned faceCount = size();
    if (!vertCount || !faceCount)
        return false;

    GenericChunkedArray<3,PointCoordinateType>* verticesDisplacement = new GenericChunkedArray<3,PointCoordinateType>;
    if (!verticesDisplacement->resize(vertCount))
    {
        //not enough memory
        verticesDisplacement->release();
        return false;
    }

    //compute the number of edges to which belong each vertex
    unsigned* edgesCount = new unsigned[vertCount];
    if (!edgesCount)
    {
        //not enough memory
        verticesDisplacement->release();
        return false;
    }
    memset(edgesCount, 0, sizeof(unsigned)*vertCount);
    placeIteratorAtBegining();
    for(unsigned j=0; j<faceCount; j++)
    {
        const CCLib::TriangleSummitsIndexes* tri = getNextTriangleIndexes();
        edgesCount[tri->i1]+=2;
        edgesCount[tri->i2]+=2;
        edgesCount[tri->i3]+=2;
    }

    //progress dialog
    CCLib::NormalizedProgress* nProgress = 0;
    if (progressCb)
    {
        unsigned totalSteps = nbIteration;
        nProgress = new CCLib::NormalizedProgress(progressCb,totalSteps);
        progressCb->setMethodTitle("Laplacian smooth");
        progressCb->setInfo(qPrintable(QString("Iterations: %1\nVertices: %2\nFaces: %3").arg(nbIteration).arg(vertCount).arg(faceCount)));
        progressCb->start();
    }

    //repeat Laplacian smoothing iterations
    for(unsigned iter = 0; iter < nbIteration; iter++)
    {
        verticesDisplacement->fill(0);

        //for each triangle
        placeIteratorAtBegining();
        for(unsigned j=0; j<faceCount; j++)
        {
            const CCLib::TriangleSummitsIndexes* tri = getNextTriangleIndexes();

            const CCVector3* A = m_associatedCloud->getPoint(tri->i1);
            const CCVector3* B = m_associatedCloud->getPoint(tri->i2);
            const CCVector3* C = m_associatedCloud->getPoint(tri->i3);

            CCVector3 dAB = (*B-*A);
            CCVector3 dAC = (*C-*A);
            CCVector3 dBC = (*C-*B);

            CCVector3* dA = (CCVector3*)verticesDisplacement->getValue(tri->i1);
            (*dA) += dAB+dAC;
            CCVector3* dB = (CCVector3*)verticesDisplacement->getValue(tri->i2);
            (*dB) += dBC-dAB;
            CCVector3* dC = (CCVector3*)verticesDisplacement->getValue(tri->i3);
            (*dC) -= dAC+dBC;
        }

        if (nProgress && !nProgress->oneStep())
        {
            //cancelled by user
            break;
        }

        //apply displacement
        verticesDisplacement->placeIteratorAtBegining();
        for (unsigned i=0; i<vertCount; i++)
        {
            //this is a "persistent" pointer and we know what type of cloud is behind ;)
            CCVector3* P = const_cast<CCVector3*>(m_associatedCloud->getPointPersistentPtr(i));
            const CCVector3* d = (const CCVector3*)verticesDisplacement->getValue(i);
            (*P) += (*d)*(factor/(PointCoordinateType)edgesCount[i]);
        }
    }

    m_associatedCloud->updateModificationTime();

    if (hasNormals())
        computeNormals();

    if (verticesDisplacement)
        verticesDisplacement->release();
    verticesDisplacement=0;

    if (edgesCount)
        delete[] edgesCount;
    edgesCount=0;

    if (nProgress)
        delete nProgress;
    nProgress=0;

    return true;
}