• off 表面三角网格翻转问题解决


    简介

    参考链接 https://gamedev.stackexchange.com/questions/26974/repairing-back-facing-triangles-without-user-input
    缺陷, 对于非流形的网格会失败

    code

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <map>
    #include <vector>
    #include <queue>
    #include <set>
    #include <algorithm>
    using namespace std;
    struct triangle{
        int pv1;
        int pv2;
        int pv3;
        triangle(int pv1_, int pv2_, int pv3_):pv1(pv1_), pv2(pv2_), pv3(pv3_){};
        bool operator == (const triangle &rhs){
            return pv1 == rhs.pv1 && pv2 == rhs.pv2 && pv3 == rhs.pv3;
        }
        bool operator < (const triangle &rhs) {
            return (pv1 + pv2 + pv3) < (rhs.pv1 + rhs.pv2 + rhs.pv3);
        }
            bool operator < (const triangle &rhs) const {
            return (pv1 + pv2 + pv3) < (rhs.pv1 + rhs.pv2 + rhs.pv3);
        }
    };
    int pointNum;
    int faceNum;
    std::queue<int> triQ;
    std::vector<bool> check;
    std::vector<triangle> allTriangle;
    std::map<int, std::vector<int> > mm;
    // 检查a和b的公共边是否序列相等
    bool isFlip(triangle b, int a1, int a2){
        if(b.pv1 == a1 && b.pv2 == a2){
            return true;
        }
        if(b.pv2 == a1 && b.pv3 == a2){
            return true;
        }
        if(b.pv3 == a1 && b.pv1 == a2){
            return true;
        }
        return false;
    }
    void fixFlip(triangle &a){
        int a1 = a.pv1;
        int a2 = a.pv2;
        int a3 = a.pv3;
        a.pv1 = a3;
        a.pv3 = a1;
    }
    
    /**
     * @description: 
     * @param {set<int> &s1, std::set<int>} &s2
     * @param {int} a1
     * @param {int} a2
     * @return 是否修复了, 或者除了一种情况两个三角形都是true的情况
     */
    bool refine(std::set<int> &s1, std::set<int> &s2, int a1, int a2, int &falseTri){
        std::set<int> c;
        std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), inserter(c, c.begin()));
        if(c.size() != 2) { // 对于封闭的曲面而言是对的
            std::cout << "[ERROR] c size not equal 2 " << c.size() << "
    ";
            return false;
        }
        std::vector<int> cv;
        for(auto it:c){
            cv.push_back(it);
        }
        int trueTri = -1;
        falseTri = -1;
        if(check[cv[0]] == true && check[cv[1]] == false){
            trueTri = cv[0];
            falseTri = cv[1];
        }
        else if(check[cv[0]] == false && check[cv[1]] == true) {
            trueTri = cv[1];
            falseTri = cv[0];
        }else{
            std::cout << "[DEBUG] maybe this two triangle is true??
    ";
            return false;
        }
        if(falseTri != -1) {
            if(isFlip(allTriangle[falseTri], a1, a2)){
                fixFlip(allTriangle[falseTri]);
            }
        }
        return true;
    }
    void BFS(int i){
        check[i] = true;
        triQ.push(i);
        while(!triQ.empty()){
            int front = triQ.front();
            triQ.pop();
            triangle t = allTriangle[front];
            std::set<int> s1;
            std::set<int> s2;
            std::set<int> s3;
            std::set<int> c;
            for(auto it : mm[t.pv1]) {
                s1.insert(it);
            }
            for(auto it : mm[t.pv2]) {
                s2.insert(it);
            }
            for(auto it : mm[t.pv3]) {
                s3.insert(it);
            }
            int falseTri;
            if(refine(s1, s2, t.pv1, t.pv2, falseTri)){
                triQ.push(falseTri);
                check[falseTri] = true;
            }
            if(refine(s2, s3, t.pv2, t.pv3, falseTri)){
                triQ.push(falseTri);
                check[falseTri] = true;
            }
            if(refine(s3, s1, t.pv3, t.pv1, falseTri)){
                triQ.push(falseTri);
                check[falseTri] = true;
            }
        }
    }
    void BFSTraverse(){
        // 访问数组初始化
        for(int i=0; i<faceNum; i++){
            if(!check[i]){
                BFS(i);
            }
        }
    }
    int main() {
        std::string filename;
        filename = "test.off";
        std::string filenameOut;
        filenameOut = "testOut.off";
        std::ifstream iff = std::ifstream(filename.c_str(), std::ios::in);
        std::ofstream off = std::ofstream(filenameOut.c_str(), std::ios::out);
        // Write header
        off << "OFF" << std::endl;
        if (!off.good()) {
            std::cout << "[Error] Could not open file " << filenameOut << " for writing!" << std::endl;
            off.close();
            return false;
        }
        if(!iff.good()) {
            std::cout << "[ERROR] could not open file " << filename << " for reading!" << std::endl;
            iff.close();
            return false;
        }
        std::string line;
        getline(iff, line);
        if(line != "OFF") {
            std::cout << "[ERROR] format not supported" << std::endl;
            return false;
        }
        getline(iff, line);
        stringstream sstr;
        sstr.str(line);
        
        sstr >> pointNum;
        sstr >> faceNum;
        sstr.clear();
    
        off << line << "
    ";
        for(int i=0; i<pointNum; i++){
            getline(iff, line);
            off << line << "
    ";
        }
        
        
        std::map<triangle, int> mi;
        int tmp;
        int pv1;
        int pv2;
        int pv3;
        for(int i=0; i<faceNum; i++){
            getline(iff, line);
            sstr.str(line);
            sstr >> tmp;
            if(tmp != 3) {
                std::cout << "[ERROR] format not supported_" << std::endl;
                return false;
            }
            sstr >> pv1;
            sstr >> pv2;
            sstr >> pv3;
            triangle t(pv1, pv2, pv3);
            sstr.clear();
            mm[pv1].push_back(i);
            mm[pv2].push_back(i);
            mm[pv3].push_back(i);
            allTriangle.push_back(t);
            mi[t] = i;
        }
        check.resize(allTriangle.size(), false);
        BFSTraverse();
        for(auto it : allTriangle){
            off << "3 " << it.pv1 << " " << it.pv2 << " " << it.pv3 << "
    ";
        }
        off.close();
        iff.close();
        return 0;
    }
    
    Hope is a good thing,maybe the best of things,and no good thing ever dies.----------- Andy Dufresne
  • 相关阅读:
    Java基础模拟LinkedList的双向链表结构
    对thrift版本降级(mac)
    通信技术类网站
    Arista和他的EOS
    程序员的英文能力培养
    挖掘时间的价值
    写作的方法论
    SRv6相关资源汇总
    你不必有自己的写作优势领域
    20192416汇编语言学习总结
  • 原文地址:https://www.cnblogs.com/eat-too-much/p/14747471.html
Copyright © 2020-2023  润新知