commit
						a1efe768ea
					
				 6 changed files with 359 additions and 0 deletions
			
			
		@ -0,0 +1,36 @@ | 
				
			|||||
 | 
					# ---> C++ | 
				
			||||
 | 
					# Prerequisites | 
				
			||||
 | 
					*.d | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Compiled Object files | 
				
			||||
 | 
					*.slo | 
				
			||||
 | 
					*.lo | 
				
			||||
 | 
					*.o | 
				
			||||
 | 
					*.obj | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Precompiled Headers | 
				
			||||
 | 
					*.gch | 
				
			||||
 | 
					*.pch | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Compiled Dynamic libraries | 
				
			||||
 | 
					*.so | 
				
			||||
 | 
					*.dylib | 
				
			||||
 | 
					*.dll | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Fortran module files | 
				
			||||
 | 
					*.mod | 
				
			||||
 | 
					*.smod | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Compiled Static libraries | 
				
			||||
 | 
					*.lai | 
				
			||||
 | 
					*.la | 
				
			||||
 | 
					*.a | 
				
			||||
 | 
					*.lib | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Executables | 
				
			||||
 | 
					*.exe | 
				
			||||
 | 
					*.out | 
				
			||||
 | 
					*.app | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					cmake-build-debug/ | 
				
			||||
 | 
					.idea/ | 
				
			||||
@ -0,0 +1,9 @@ | 
				
			|||||
 | 
					cmake_minimum_required(VERSION 3.21) | 
				
			||||
 | 
					project(LoopDetector) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					set(CMAKE_CXX_STANDARD 14) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					add_executable(LoopDetector main.cpp src/loop_detector.cpp include/loop_detector.h) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					include_directories(E:/CLib/tinynurbs/include E:/CLib/glm) | 
				
			||||
 | 
					include_directories(include) | 
				
			||||
@ -0,0 +1,3 @@ | 
				
			|||||
 | 
					# GaussMap | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					A Gauss mapping tool for Nurbs surfaces on CPUs. | 
				
			||||
@ -0,0 +1,64 @@ | 
				
			|||||
 | 
					#ifndef LOOPDETECTOR_LOOP_DETECTOR_H | 
				
			||||
 | 
					#define LOOPDETECTOR_LOOP_DETECTOR_H | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include "tinynurbs/tinynurbs.h" | 
				
			||||
 | 
					#include "glm/glm.hpp" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					using namespace std; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class LoopDetector { | 
				
			||||
 | 
					public: | 
				
			||||
 | 
					    // 两个曲面
 | 
				
			||||
 | 
					    tinynurbs::RationalSurface<float> s; | 
				
			||||
 | 
					    tinynurbs::RationalSurface<float> f; | 
				
			||||
 | 
					    // 细分采样的总层数(最高与BVH的总层数相等)。从第二层开始,每一层都表示把原来的一个小sub patch分成了更小的四份
 | 
				
			||||
 | 
					    int maxSplitLayer; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // 采样点的求值和求切向量先设为public,因为这些因该是算好的,LoopDetector不用重复计算
 | 
				
			||||
 | 
					    // 曲面s和f的采样点。
 | 
				
			||||
 | 
					    vector<vector<glm::vec3>> s_evaluation; | 
				
			||||
 | 
					    vector<vector<glm::vec3>> f_evaluation; | 
				
			||||
 | 
					    // 曲面s和f的切向量。
 | 
				
			||||
 | 
					    vector<vector<glm::vec3>> s_tangent_u; | 
				
			||||
 | 
					    vector<vector<glm::vec3>> s_tangent_v; | 
				
			||||
 | 
					    vector<vector<glm::vec3>> f_tangent_u; | 
				
			||||
 | 
					    vector<vector<glm::vec3>> f_tangent_v; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					//    int subPatchEdgeSampleCnt;  // 在一个sub patch的采样网格中,边上的采样点个数
 | 
				
			||||
 | 
					//    void init(tinynurbs::RationalSurface<float> _s, tinynurbs::RationalSurface<float> _f, int _maxSplitLayer);
 | 
				
			||||
 | 
					    vector<pair<int, int>> detect(pair<int, int> _s_subPatchIdxRange_u, pair<int, int> _s_subPatchIdxRange_v, | 
				
			||||
 | 
					                                  pair<int, int> _f_subPatchIdxRange_u, pair<int, int> _f_subPatchIdxRange_v); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					private: | 
				
			||||
 | 
					    // 需要做Loop检测的sub patch在最后一层上的下标的范围(每个范围都真包含于[0, 2^(maxSplitLayer-1)-1])
 | 
				
			||||
 | 
					    pair<int, int> s_subPatchIdxRange_u; | 
				
			||||
 | 
					    pair<int, int> s_subPatchIdxRange_v; | 
				
			||||
 | 
					    pair<int, int> f_subPatchIdxRange_u; | 
				
			||||
 | 
					    pair<int, int> f_subPatchIdxRange_v; | 
				
			||||
 | 
					    // subPatch每条边上的采样点个数
 | 
				
			||||
 | 
					    // 这四个值根据subPatchRange的范围得到,不可被外部修改
 | 
				
			||||
 | 
					    int s_subPatchEdgeSampleCnt_u; | 
				
			||||
 | 
					    int s_subPatchEdgeSampleCnt_v; | 
				
			||||
 | 
					    int f_subPatchEdgeSampleCnt_u; | 
				
			||||
 | 
					    int f_subPatchEdgeSampleCnt_v; | 
				
			||||
 | 
					    // 整个曲面一条边上的采样点个数
 | 
				
			||||
 | 
					    int edgeSampleCnt; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // 有向距离计算结果。有向距离通过采样的方式计算,其结果与s曲面sub patch中的采样网格规模相同,即与s_evaluation大小一致
 | 
				
			||||
 | 
					//    vector<vector<glm::vec3>> distance;
 | 
				
			||||
 | 
					    // 确定有向距离后,对应的f曲面上的最短距离点的位置
 | 
				
			||||
 | 
					    vector<vector<pair<int, int>>> selectedPointsIdx; | 
				
			||||
 | 
					    // vector fields, 即有向距离关于u、v的导数
 | 
				
			||||
 | 
					    vector<vector<glm::vec2>> vectorFields; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    void initEvaluation(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    void initOrientedDistance(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    void initVectorField(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    void getRotationNumber(); | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#endif //LOOPDETECTOR_LOOP_DETECTOR_H
 | 
				
			||||
@ -0,0 +1,77 @@ | 
				
			|||||
 | 
					#include <iostream> | 
				
			||||
 | 
					#include "loop_detector.h" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					int main() { | 
				
			||||
 | 
					    LoopDetector loopDetector; | 
				
			||||
 | 
					    tinynurbs::RationalSurface<float> s; | 
				
			||||
 | 
					    tinynurbs::RationalSurface<float> f; | 
				
			||||
 | 
					    s.degree_u = 3; | 
				
			||||
 | 
					    s.degree_v = 3; | 
				
			||||
 | 
					    s.knots_u = {0, 0, 0, 0, 1, 1, 1, 1}; | 
				
			||||
 | 
					    s.knots_v = {0, 0, 0, 0, 1, 1, 1, 1}; | 
				
			||||
 | 
					    s.control_points = {4, 4, { | 
				
			||||
 | 
					            glm::vec3(0, 0.3, 0.9), glm::vec3(0, 0.6, 1), glm::vec3(0, 0.9, 1.1), glm::vec3(0, 1.2, 1), | 
				
			||||
 | 
					            glm::vec3(0.33, 0.3, 0.12), glm::vec3(0.33, 0.6, 0.12), glm::vec3(0.33, 0.9, 0.12), | 
				
			||||
 | 
					            glm::vec3(0.33, 1.2, 0.12), | 
				
			||||
 | 
					            glm::vec3(0.66, 0.3, 0.12), glm::vec3(0.66, 0.6, 0.12), glm::vec3(0.66, 0.9, 0.12), | 
				
			||||
 | 
					            glm::vec3(0.66, 1.2, 0.12), | 
				
			||||
 | 
					            glm::vec3(1, 0.3, 0.8), glm::vec3(1, 0.6, 1), glm::vec3(1, 0.9, 1.1), glm::vec3(1, 1.2, 1) | 
				
			||||
 | 
					    }}; | 
				
			||||
 | 
					    s.weights = {4, 4, | 
				
			||||
 | 
					                 { | 
				
			||||
 | 
					                         1, 1, 1, 1, | 
				
			||||
 | 
					                         1, 1, 1, 1, | 
				
			||||
 | 
					                         1, 1, 1, 1, | 
				
			||||
 | 
					                         1, 1, 1, 1, | 
				
			||||
 | 
					                 } | 
				
			||||
 | 
					    }; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    f.degree_u = 3; | 
				
			||||
 | 
					    f.degree_v = 3; | 
				
			||||
 | 
					    f.knots_u = {0, 0, 0, 0, 1, 1, 1, 1}; | 
				
			||||
 | 
					    f.knots_v = {0, 0, 0, 0, 1, 1, 1, 1}; | 
				
			||||
 | 
					    f.control_points = {4, 4, { | 
				
			||||
 | 
					            glm::vec3(0, 0.2, 0.9), glm::vec3(0, 0.5, 1.8), glm::vec3(0, 0.8, 1.1), glm::vec3(0, 1.2, 1), | 
				
			||||
 | 
					            glm::vec3(0.33, 0.2, 0.12), glm::vec3(0.33, 0.5, 0.42), glm::vec3(0.33, 0.9, -0.62), | 
				
			||||
 | 
					            glm::vec3(0.33, 1.1, -1.756), | 
				
			||||
 | 
					            glm::vec3(0.66, 0.2, 0.12), glm::vec3(0.66, 0.5, 0.42), glm::vec3(0.66, 0.9, -0.62), | 
				
			||||
 | 
					            glm::vec3(0.66, 1.0, -1.756), | 
				
			||||
 | 
					            glm::vec3(1, 0.2, 0.8), glm::vec3(1, 0.5, 1), glm::vec3(1, 0.9, 1.1), glm::vec3(1, 1.2, 1) | 
				
			||||
 | 
					    }}; | 
				
			||||
 | 
					    f.weights = {4, 4, | 
				
			||||
 | 
					                 { | 
				
			||||
 | 
					                         1, 1, 1, 1, | 
				
			||||
 | 
					                         1, 1, 1, 1, | 
				
			||||
 | 
					                         1, 1, 1, 1, | 
				
			||||
 | 
					                         1, 1, 1, 1, | 
				
			||||
 | 
					                 } | 
				
			||||
 | 
					    }; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    loopDetector.s = s; | 
				
			||||
 | 
					    loopDetector.f = f; | 
				
			||||
 | 
					    loopDetector.maxSplitLayer = 6; | 
				
			||||
 | 
					    // 需要做Loop检测的sub patch在最后一层上的下标的范围(每个范围都真包含于[0, 2^(maxSplitLayer-1)-1])
 | 
				
			||||
 | 
					    // 这里范围真包含于[0, 31]
 | 
				
			||||
 | 
					    loopDetector.detect({3, 11}, {4, 11}, {2, 7}, {6, 15}); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    glm::vec3 a(2, 3, 4); | 
				
			||||
 | 
					    glm::vec3 b(3, 7, 1); | 
				
			||||
 | 
					    auto nab = glm::normalize(a - b); | 
				
			||||
 | 
					    auto res = nab * (a - b); | 
				
			||||
 | 
					    auto ab = a * b; | 
				
			||||
 | 
					    cout << res.x << ", " << res.y << ", " << res.z << endl; | 
				
			||||
 | 
					    cout << nab.x << ", " << nab.y << ", " << nab.z << endl; | 
				
			||||
 | 
					    cout << ab.x << ", " << ab.y << ", " << ab.z << endl; | 
				
			||||
 | 
					    std::cout << "Hello, World!" << std::endl; | 
				
			||||
 | 
					    auto m = glm::mat2x2(1, 2, 3, 4); | 
				
			||||
 | 
					    cout << m[0][0] << " " << m[0][1] << endl; | 
				
			||||
 | 
					    auto dotRes = glm::dot(a, b); | 
				
			||||
 | 
					    cout << dotRes << endl; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    cout<<isnan(glm::normalize(glm::vec3(0, 0, 0)).x)<<endl; | 
				
			||||
 | 
					    cout<<isnan(1.)<<endl; | 
				
			||||
 | 
					//    auto m1 = glm::mat2(1., 2.);
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    cout<<round(3.7)<<" "<<round(3.5657567658)<<" "<<round(3.2)<<" "<<round(3.0)<<endl; | 
				
			||||
 | 
					    return 0; | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,170 @@ | 
				
			|||||
 | 
					#include "loop_detector.h" | 
				
			||||
 | 
					#include <utility> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const float PI = 3.1415927; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void LoopDetector::initEvaluation() { | 
				
			||||
 | 
					    // 初始化subPatch上所有采样点的值,以及它们的切向量,并存储
 | 
				
			||||
 | 
					    // 当该工具集成到系统中后,这一部分应该是可以直接全部去掉的
 | 
				
			||||
 | 
					    // 因为在GPU上已经做过对每个点的最细粒度的evaluation了,只需要从整个曲面把需要的subPatch找出来即可
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // subPatch每条边上的采样点个数。边上的格子个数=range.second-range.first+1,采样点个数=格子个数+1
 | 
				
			||||
 | 
					    s_subPatchEdgeSampleCnt_u = s_subPatchIdxRange_u.second - s_subPatchIdxRange_u.first + 2; | 
				
			||||
 | 
					    s_subPatchEdgeSampleCnt_v = s_subPatchIdxRange_v.second - s_subPatchIdxRange_v.first + 2; | 
				
			||||
 | 
					    f_subPatchEdgeSampleCnt_u = f_subPatchIdxRange_u.second - f_subPatchIdxRange_u.first + 2; | 
				
			||||
 | 
					    f_subPatchEdgeSampleCnt_v = f_subPatchIdxRange_v.second - f_subPatchIdxRange_v.first + 2; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    edgeSampleCnt = int(pow(2, maxSplitLayer - 1)) + 1; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    s_evaluation = vector<vector<glm::vec3>>(s_subPatchEdgeSampleCnt_u, vector<glm::vec3>(s_subPatchEdgeSampleCnt_v)); | 
				
			||||
 | 
					    f_evaluation = vector<vector<glm::vec3>>(f_subPatchEdgeSampleCnt_u, vector<glm::vec3>(f_subPatchEdgeSampleCnt_v)); | 
				
			||||
 | 
					    // 曲面s和f的切向量。
 | 
				
			||||
 | 
					    s_tangent_u = vector<vector<glm::vec3>>(s_subPatchEdgeSampleCnt_u, vector<glm::vec3>(s_subPatchEdgeSampleCnt_v)); | 
				
			||||
 | 
					    s_tangent_v = vector<vector<glm::vec3>>(s_subPatchEdgeSampleCnt_u, vector<glm::vec3>(s_subPatchEdgeSampleCnt_v)); | 
				
			||||
 | 
					    f_tangent_u = vector<vector<glm::vec3>>(f_subPatchEdgeSampleCnt_u, vector<glm::vec3>(f_subPatchEdgeSampleCnt_v)); | 
				
			||||
 | 
					    f_tangent_v = vector<vector<glm::vec3>>(f_subPatchEdgeSampleCnt_u, vector<glm::vec3>(f_subPatchEdgeSampleCnt_v)); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    auto s_first_u = *(s.knots_u.begin()); | 
				
			||||
 | 
					    auto s_first_v = *(s.knots_v.begin()); | 
				
			||||
 | 
					    auto s_step_u = (*(s.knots_u.end() - 1) - s_first_u) / float(edgeSampleCnt - 1); | 
				
			||||
 | 
					    auto s_step_v = (*(s.knots_v.end() - 1) - s_first_v) / float(edgeSampleCnt - 1); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    auto f_first_u = *(f.knots_u.begin()); | 
				
			||||
 | 
					    auto f_first_v = *(f.knots_v.begin()); | 
				
			||||
 | 
					    auto f_step_u = (*(f.knots_u.end() - 1) - f_first_u) / float(edgeSampleCnt - 1); | 
				
			||||
 | 
					    auto f_step_v = (*(f.knots_v.end() - 1) - f_first_v) / float(edgeSampleCnt - 1); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    for (int i = 0; i < s_subPatchEdgeSampleCnt_u; i++) { | 
				
			||||
 | 
					        auto u = s_first_u + s_step_u * float(s_subPatchIdxRange_u.first + i); | 
				
			||||
 | 
					        for (int j = 0; j < s_subPatchEdgeSampleCnt_v; j++) { | 
				
			||||
 | 
					            auto v = s_first_v + s_step_v * float(s_subPatchIdxRange_v.first + j); | 
				
			||||
 | 
					            s_evaluation[i][j] = tinynurbs::surfacePoint(s, u, v); | 
				
			||||
 | 
					            auto der = tinynurbs::surfaceDerivatives(s, 1, u, v); | 
				
			||||
 | 
					            s_tangent_u[i][j] = der(1, 0); | 
				
			||||
 | 
					            s_tangent_v[i][j] = der(0, 1); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    for (int i = 0; i < f_subPatchEdgeSampleCnt_u; i++) { | 
				
			||||
 | 
					        auto u = f_first_u + f_step_u * float(f_subPatchIdxRange_u.first + i); | 
				
			||||
 | 
					        for (int j = 0; j < f_subPatchEdgeSampleCnt_v; j++) { | 
				
			||||
 | 
					            auto v = f_first_v + f_step_v * float(f_subPatchIdxRange_v.first + j); | 
				
			||||
 | 
					            f_evaluation[i][j] = tinynurbs::surfacePoint(f, u, v); | 
				
			||||
 | 
					            auto der = tinynurbs::surfaceDerivatives(f, 1, u, v); | 
				
			||||
 | 
					            f_tangent_u[i][j] = der(1, 0); | 
				
			||||
 | 
					            f_tangent_v[i][j] = der(0, 1); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void LoopDetector::initOrientedDistance() { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    selectedPointsIdx = vector<vector<pair<int, int>>>(s_subPatchEdgeSampleCnt_u, | 
				
			||||
 | 
					                                                       vector<pair<int, int>>(s_subPatchEdgeSampleCnt_v)); | 
				
			||||
 | 
					//    distance = vector<vector<glm::vec3>>(s_subPatchEdgeSampleCnt_u, vector<glm::vec3>(s_subPatchEdgeSampleCnt_v));
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    for (int i = 0; i < s_subPatchEdgeSampleCnt_u; i++) { | 
				
			||||
 | 
					        for (int j = 0; j < s_subPatchEdgeSampleCnt_v; j++) { | 
				
			||||
 | 
					            float minDis = FLT_MAX; | 
				
			||||
 | 
					            int minDisFIdx_u = -1, minDisFIdx_v = -1; | 
				
			||||
 | 
					            for (int k = 0; k < f_subPatchEdgeSampleCnt_u; k++) { | 
				
			||||
 | 
					                for (int l = 0; l < f_subPatchEdgeSampleCnt_v; l++) { | 
				
			||||
 | 
					                    auto dis = glm::distance(s_evaluation[i][j], f_evaluation[k][l]); | 
				
			||||
 | 
					                    // 确定f上的对应点时,依据的最小欧氏距离,而不是有向距离
 | 
				
			||||
 | 
					                    if (dis < minDis) { | 
				
			||||
 | 
					                        minDis = dis; | 
				
			||||
 | 
					                        minDisFIdx_u = k; | 
				
			||||
 | 
					                        minDisFIdx_v = l; | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					//            auto N = glm::normalize(s_evaluation[i][j] - f_evaluation[minDisFIdx_u][minDisFIdx_v]);
 | 
				
			||||
 | 
					//            // 直接normalize得到的单位向量总是与SF同向,但实际上N应当总是与f的一侧法向量成锐角
 | 
				
			||||
 | 
					//            auto testAngle = N * glm::cross(f_tangent_u[minDisFIdx_u][minDisFIdx_v], f_tangent_v[minDisFIdx_u][minDisFIdx_v]);
 | 
				
			||||
 | 
					//            N = testAngle.x + testAngle.y + testAngle.z > 0 ? N : -N;
 | 
				
			||||
 | 
					//            distance[i][j] = N * (s_evaluation[i][j] - f_evaluation[minDisFIdx_u][minDisFIdx_v]);
 | 
				
			||||
 | 
					            selectedPointsIdx[i][j] = {minDisFIdx_u, minDisFIdx_v}; | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void LoopDetector::initVectorField() { | 
				
			||||
 | 
					    vectorFields = vector<vector<glm::vec2>>(s_subPatchEdgeSampleCnt_u, vector<glm::vec2>(s_subPatchEdgeSampleCnt_v)); | 
				
			||||
 | 
					    for (int i = 0; i < s_subPatchEdgeSampleCnt_u; i++) { | 
				
			||||
 | 
					        for (int j = 0; j < s_subPatchEdgeSampleCnt_v; j++) { | 
				
			||||
 | 
					            auto fPointIdx = selectedPointsIdx[i][j]; | 
				
			||||
 | 
					            auto N = glm::normalize(s_evaluation[i][j] - f_evaluation[fPointIdx.first][fPointIdx.second]); | 
				
			||||
 | 
					            if (isnan(N.x) || isnan(N.y) || isnan(N.z)) { | 
				
			||||
 | 
					                // 绝了,曲面s和f的交线正好经过采样点,此时就无法定义向量N
 | 
				
			||||
 | 
					                // 这里取两个曲面在交点的法向量的平均做近似
 | 
				
			||||
 | 
					                auto tmp1 = glm::cross(s_tangent_u[i][j], s_tangent_v[i][j]); | 
				
			||||
 | 
					                auto tmp2 = glm::cross(f_tangent_u[fPointIdx.first][fPointIdx.second], | 
				
			||||
 | 
					                                         f_tangent_v[fPointIdx.first][fPointIdx.second]); | 
				
			||||
 | 
					                N = glm::normalize(glm::cross(s_tangent_u[i][j], s_tangent_v[i][j]) + | 
				
			||||
 | 
					                                   glm::cross(f_tangent_u[fPointIdx.first][fPointIdx.second], | 
				
			||||
 | 
					                                              f_tangent_v[fPointIdx.first][fPointIdx.second])); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            // u1、u2两个向量构成和N垂直的曲面
 | 
				
			||||
 | 
					            glm::vec3 u1(1, 1, 1); | 
				
			||||
 | 
					            if (N.z != 0)u1.z = (-N.x - N.y) / N.z; | 
				
			||||
 | 
					            else if (N.y != 0)u1.y = (-N.x - N.z) / N.y; | 
				
			||||
 | 
					            else u1.x = (-N.y - N.z) / N.x; | 
				
			||||
 | 
					            u1 = glm::normalize(u1); | 
				
			||||
 | 
					            auto u2 = glm::normalize(glm::cross(N, u1)); | 
				
			||||
 | 
					            // s,f曲面在两个方向上的偏导
 | 
				
			||||
 | 
					            auto ps_pu = s_tangent_u[i][j], ps_pv = s_tangent_v[i][j]; | 
				
			||||
 | 
					            auto pf_pp = f_tangent_u[fPointIdx.first][fPointIdx.second], pf_pq = f_tangent_v[fPointIdx.first][fPointIdx.second]; | 
				
			||||
 | 
					            // 构造Aij矩阵,见<Detection of loops and singularities of surface intersections> APPENDIX (A7)
 | 
				
			||||
 | 
					            auto inverseAij = glm::inverse( | 
				
			||||
 | 
					                    glm::mat2x2(glm::dot(u1, pf_pp), glm::dot(u1, pf_pq), glm::dot(u2, pf_pp), glm::dot(u2, pf_pq)) | 
				
			||||
 | 
					            ); | 
				
			||||
 | 
					            auto mBmn = glm::mat2x2(glm::dot(u1, ps_pu), glm::dot(u1, ps_pv), glm::dot(u2, ps_pu), glm::dot(u2, ps_pv)); | 
				
			||||
 | 
					            auto tmp = glm::vec2(glm::dot(N, pf_pp), glm::dot(N, pf_pq)); | 
				
			||||
 | 
					            auto vNfpNfq_inverseAij = glm::vec2(glm::dot(N, pf_pp), glm::dot(N, pf_pq)) * inverseAij; | 
				
			||||
 | 
					            auto pd_pu = glm::dot(N, ps_pu) - | 
				
			||||
 | 
					                         glm::dot(vNfpNfq_inverseAij, glm::vec2(glm::dot(u1, ps_pu), glm::dot(u2, ps_pu))); | 
				
			||||
 | 
					            auto pd_pv = glm::dot(N, ps_pv) - | 
				
			||||
 | 
					                         glm::dot(vNfpNfq_inverseAij, glm::vec2(glm::dot(u1, ps_pv), glm::dot(u2, ps_pv))); | 
				
			||||
 | 
					            vectorFields[i][j] = glm::vec2(pd_pu, pd_pv); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    int a = 1; | 
				
			||||
 | 
					    int b = 2; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void LoopDetector::getRotationNumber() { | 
				
			||||
 | 
					    // 以小格子为单位遍历
 | 
				
			||||
 | 
					    for (int i = 0; i < s_subPatchEdgeSampleCnt_u - 1; i++) { | 
				
			||||
 | 
					        for (int j = 0; j < s_subPatchEdgeSampleCnt_v - 1; j++) { | 
				
			||||
 | 
					            auto rotationNumber = 0.; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            for (int biasI = 0; biasI < 2; biasI++) { | 
				
			||||
 | 
					                for (int biasJ = 0; biasJ < 2; biasJ++) { | 
				
			||||
 | 
					                    auto v = vectorFields[i + biasI][j + biasJ]; | 
				
			||||
 | 
					                    rotationNumber += atan(double(v.x / v.y)); | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            auto v00 = vectorFields[i][j]; | 
				
			||||
 | 
					            auto v01 = vectorFields[i][j + 1]; | 
				
			||||
 | 
					            auto v11 = vectorFields[i + 1][j + 1]; | 
				
			||||
 | 
					            auto v10 = vectorFields[i + 1][j]; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            rotationNumber = 2 * atan(double (v11.x/v11.y)) - 2 * atan(double(v00.x/v00.y)); | 
				
			||||
 | 
					            rotationNumber /= (2 * PI); | 
				
			||||
 | 
					            printf("rotationNumber: %lf\n", rotationNumber); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					vector<pair<int, int>> LoopDetector::detect(pair<int, int> _s_subPatchIdxRange_u, pair<int, int> _s_subPatchIdxRange_v, | 
				
			||||
 | 
					                                            pair<int, int> _f_subPatchIdxRange_u, | 
				
			||||
 | 
					                                            pair<int, int> _f_subPatchIdxRange_v) { | 
				
			||||
 | 
					    s_subPatchIdxRange_u = _s_subPatchIdxRange_u; | 
				
			||||
 | 
					    s_subPatchIdxRange_v = _s_subPatchIdxRange_v; | 
				
			||||
 | 
					    f_subPatchIdxRange_u = _f_subPatchIdxRange_u; | 
				
			||||
 | 
					    f_subPatchIdxRange_v = _f_subPatchIdxRange_v; | 
				
			||||
 | 
					    initEvaluation();  // 当evaluation已经完成,这一步就不用了,直接传入两个evaluation矩阵和四个tangent矩阵的值即可
 | 
				
			||||
 | 
					    initOrientedDistance(); | 
				
			||||
 | 
					    initVectorField(); | 
				
			||||
 | 
					    getRotationNumber(); | 
				
			||||
 | 
					    return {}; | 
				
			||||
 | 
					} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue