/* Calculates the signed supplement of an angle*/
double calculateSupplement(double theta){
	return findSign(theta)*(PI-abs(theta));	
}
Ejemplo n.º 2
0
void HoleRepairer::computeSignedDistanceField()
{
    // distance field from the mesh
    std::cout << "Computing mesh distance field..." << std::endl;
    computeUDFmesh(&m_distanceGrid);

    // distance field from the hole
    std::cout << "Computing holes distance field..." << std::endl;
    computeUDFhole(&m_holeDistance);

    // compute the mask and final distance field
    std::cout << "Computing mask..." << std::endl;
    for (int i = 0; i < VOX_SAMPLES; i++) {
        for (int j = 0; j < VOX_SAMPLES; j++) {
            for (int k = 0; k < VOX_SAMPLES; k++) {
                float mdist = m_distanceGrid.get(i, j, k);
                float hdist = m_holeDistance.get(i, j, k);
                if (hdist < mdist + 0.5*glm::length(m_voxelSize)) {
                    m_triangleMask.set(i, j, k, true);
                    m_distanceGrid.set(i, j, k, mdist);
                }
                else {
                    m_triangleMask.set(i, j, k, false);
                    m_distanceGrid.set(i, j, k, mdist);
                }
            }
        }
    }

    std::cout << "Generating signed distance field..." << std::endl;

    // compute regions in the mask to propagate the sign
    Grid3D<int> regionGrid(VOX_SAMPLES, 0);
    int numRegions = 0;
    bool foundRegion = true;
    while (foundRegion) {
        foundRegion = false;
        for (int i = 0; i < VOX_SAMPLES; i++) {
            for (int j = 0; j < VOX_SAMPLES; j++) {
                for (int k = 0; k < VOX_SAMPLES; k++) {
                    if (!m_triangleMask.get(i, j, k) && regionGrid.get(i, j, k) == 0) {
                        numRegions++;
                        foundRegion = true;
                        floodRegion(&regionGrid, &m_triangleMask, m_surfaceSticks, i, j, k, numRegions);
                    }
                }
            }
        }
    }

    // votes based on sticks
    std::vector<int> positiveVotes(numRegions+1, 0);
    std::vector<int> negativeVotes(numRegions+1, 0);
    for (std::set<std::pair<int, int> >::const_iterator it = m_surfaceSticks.begin(); it != m_surfaceSticks.end(); it++) {
        int v1id = it->first;
        int v2id = it->second;
        int i1 =  v1id/(VOX_SAMPLES*VOX_SAMPLES);
        int j1 = (v1id%(VOX_SAMPLES*VOX_SAMPLES))/VOX_SAMPLES;
        int k1 = (v1id%(VOX_SAMPLES*VOX_SAMPLES))%VOX_SAMPLES;
        int i2 =  v2id/(VOX_SAMPLES*VOX_SAMPLES);
        int j2 = (v2id%(VOX_SAMPLES*VOX_SAMPLES))/VOX_SAMPLES;
        int k2 = (v2id%(VOX_SAMPLES*VOX_SAMPLES))%VOX_SAMPLES;
        int r1 = regionGrid.get(i1, j1, k1);
        int r2 = regionGrid.get(i2, j2, k2);

        // if both endpoints are marked as positive, this is not a safe sign sample
        if (m_positivePoints.find(v1id) != m_positivePoints.end() && m_positivePoints.find(v2id) == m_positivePoints.end()) {
            positiveVotes[r1]++;
            negativeVotes[r2]++;
        }
        else if (m_positivePoints.find(v2id) != m_positivePoints.end() && m_positivePoints.find(v1id) == m_positivePoints.end()) {
            positiveVotes[r2]++;
            negativeVotes[r1]++;
        }
    }

    // define sign to regions according to votes
    std::vector<bool> setSign(numRegions+1, false);
    std::vector<bool> posRegion(numRegions+1, false);
    for (int i = 1; i <= numRegions; i++) {
        if (positiveVotes[i] != negativeVotes[i]) {
            setSign[i] = true;
            posRegion[i] = positiveVotes[i] > negativeVotes[i];
        }
    }

    // assign sign
    for (int i = 0; i < VOX_SAMPLES; i++) {
        for (int j = 0; j < VOX_SAMPLES; j++) {
            for (int k = 0; k < VOX_SAMPLES; k++) {
                int rid = regionGrid.get(i, j, k);
                if (rid > 0) {
                    float dist = m_distanceGrid.get(i, j, k);

                    if (!setSign[rid]) {
                        bool positive;
                        findSign(&regionGrid, setSign, posRegion, m_surfaceSticks, i, j, k, positive);
                        posRegion[rid] = positive;
                        setSign[rid] = true;
                    }

                    if (!posRegion[rid]) {
                        m_distanceGrid.set(i, j, k, -dist);
                    }
                }
            }
        }
    }
}