#include "loop_detector.h" #include const float PI = 3.1415927; LoopDetector:: LoopDetector(const vector> &s_evaluation_, const vector> &f_evaluation_, const vector> &s_tangent_u_, const vector> &f_tangent_u_, const vector> &s_tangent_v_, const vector> &f_tangent_v_, const vector> &s_normal_, const vector> &f_normal_, const tinynurbs::RationalSurface &s_) : s_evaluation(s_evaluation_), f_evaluation(f_evaluation_), s_tangent_u(s_tangent_u_), s_tangent_v(s_tangent_v_), f_tangent_u(f_tangent_u_), f_tangent_v(f_tangent_v_), s_normal(s_normal_), f_normal(f_normal_), s(s_) {} // old version void LoopDetector::initOrientedDistance() { selectedPointsIdx = vector>>(s_subPatchEdgeSampleCnt_u, vector>(s_subPatchEdgeSampleCnt_v)); // distance = vector>(s_subPatchEdgeSampleCnt_u, vector(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[s_subPatchIdxRange_u.first + i][s_subPatchIdxRange_v.first + j], f_evaluation[f_subPatchIdxRange_u.first + k][f_subPatchIdxRange_v.first + 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}; } } } // old version void LoopDetector::initOrientedDisAndVecFields(const vector, pair>> &intersectBoxPairs) { selectedPointsIdx = vector>>(s_subPatchEdgeSampleCnt_u, vector>(s_subPatchEdgeSampleCnt_v, {-1, -1})); vectorFields = vector>(s_subPatchEdgeSampleCnt_u, vector(s_subPatchEdgeSampleCnt_v)); int neighborIdxes[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; for (const auto &boxPair: intersectBoxPairs) { float minDis = FLT_MAX; int minDisFIdx_u = -1, minDisFIdx_v = -1; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { for (auto neighborIdx: neighborIdxes) { int idxI = boxPair.first.first + i + neighborIdx[0]; int idxJ = boxPair.first.second + j + neighborIdx[1]; if (idxI - s_subPatchIdxRange_u.first < 0 || idxI - s_subPatchIdxRange_u.first >= s_subPatchEdgeSampleCnt_u || idxJ - s_subPatchIdxRange_v.first < 0 || idxJ - s_subPatchIdxRange_v.first >= s_subPatchEdgeSampleCnt_v || selectedPointsIdx[idxI - s_subPatchIdxRange_u.first][idxJ - s_subPatchIdxRange_v.first] != pair(-1, -1)) { // 不重复计算 continue; } for (int k = 0; k < f_subPatchEdgeSampleCnt_u; k++) { for (int l = 0; l < f_subPatchEdgeSampleCnt_v; l++) { auto dis = glm::distance( s_evaluation[idxI][idxJ], f_evaluation[f_subPatchIdxRange_u.first + k][f_subPatchIdxRange_v.first + l]); // 确定f上的对应点时,依据的最小欧氏距离,而不是有向距离 if (dis < minDis) { minDis = dis; minDisFIdx_u = k; minDisFIdx_v = l; } } } selectedPointsIdx[idxI - s_subPatchIdxRange_u.first][idxJ - s_subPatchIdxRange_v.first] = {minDisFIdx_u, minDisFIdx_v}; // 计算vector fields auto fPtRelatedIdx = pair(minDisFIdx_u, minDisFIdx_v); auto n2 = f_normal[f_subPatchIdxRange_u.first + fPtRelatedIdx.first][f_subPatchIdxRange_v.first + fPtRelatedIdx.second]; auto ps_pu = s_tangent_u[idxI][idxJ]; auto ps_pv = s_tangent_v[idxI][idxJ]; vectorFields[idxI - s_subPatchIdxRange_u.first][idxJ - s_subPatchIdxRange_v.first] = glm::vec2(glm::dot(n2, ps_pu), glm::dot(n2, ps_pv)); } } } } } void LoopDetector::initOrientedDisAndVecFields(const map, set>> &intersectBoxPairs) { selectedPointsIdx = vector>>(s_subPatchEdgeSampleCnt_u, vector>(s_subPatchEdgeSampleCnt_v, {-1, -1})); vectorFields = vector>(s_subPatchEdgeSampleCnt_u, vector(s_subPatchEdgeSampleCnt_v)); int neighborIdxes[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; int dirs[2][2][2] = {{{-1, 1}, {1, 1}}, {{-1, -1}, {1, -1}}}; // 必须是左上,右上,左下,右下的顺序 for (const auto &boxPair: intersectBoxPairs) { for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { for (auto neighborIdx: neighborIdxes) { float minDis = FLT_MAX; int minDisFIdx_u = -1, minDisFIdx_v = -1; int idxI = boxPair.first.first + i + neighborIdx[0]; int idxJ = boxPair.first.second + j + neighborIdx[1]; if (idxI - s_subPatchIdxRange_u.first < 0 || idxI - s_subPatchIdxRange_u.first >= s_subPatchEdgeSampleCnt_u || idxJ - s_subPatchIdxRange_v.first < 0 || idxJ - s_subPatchIdxRange_v.first >= s_subPatchEdgeSampleCnt_v || selectedPointsIdx[idxI - s_subPatchIdxRange_u.first][idxJ - s_subPatchIdxRange_v.first] != pair(-1, -1)) { // 不重复计算 continue; } for (auto relatedBox: boxPair.second) { for (int k = 0; k < 2; k++) { for (int l = 0; l < 2; l++) { for (int step_u = 0; step_u <= 2; step_u++) { for (int step_v = 0; step_v + step_u <= 2; step_v++) { int fIdx_u = relatedBox.first + k + step_u * dirs[k][l][0]; int fIdx_v = relatedBox.second + l + step_v * dirs[k][l][1]; if (fIdx_u < 0 || fIdx_u >= f_evaluation.size() || fIdx_v < 0 || fIdx_v >= f_evaluation[0].size()) continue; auto dis = glm::distance(s_evaluation[idxI][idxJ], f_evaluation[fIdx_u][fIdx_v]); if (dis < minDis) { minDis = dis; minDisFIdx_u = fIdx_u; minDisFIdx_v = fIdx_v; } } } } } } selectedPointsIdx[idxI - s_subPatchIdxRange_u.first][idxJ - s_subPatchIdxRange_v.first] = {minDisFIdx_u - f_subPatchIdxRange_u.first, minDisFIdx_v - f_subPatchIdxRange_v.first}; auto n2 = f_normal[minDisFIdx_u][minDisFIdx_v]; auto ps_pu = s_tangent_u[idxI][idxJ]; auto ps_pv = s_tangent_v[idxI][idxJ]; vectorFields[idxI - s_subPatchIdxRange_u.first][idxJ - s_subPatchIdxRange_v.first] = glm::vec2(glm::dot(n2, ps_pu), glm::dot(n2, ps_pv)); } } } } } // Yawei Ma的文章中的做法 // old version void LoopDetector::initVectorField0() { vectorFields = vector>(s_subPatchEdgeSampleCnt_u, vector(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[s_subPatchIdxRange_u.first + i][s_subPatchIdxRange_v.first + j] - f_evaluation[f_subPatchIdxRange_u.first + fPointIdx.first] [f_subPatchIdxRange_v.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(s_normal[s_subPatchIdxRange_u.first + i][s_subPatchIdxRange_v.first + j] + f_normal[f_subPatchIdxRange_u.first + fPointIdx.first] [f_subPatchIdxRange_v.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[s_subPatchIdxRange_u.first + i][s_subPatchIdxRange_v.first + j] , ps_pv = s_tangent_v[s_subPatchIdxRange_u.first + i][s_subPatchIdxRange_v.first + j]; auto pf_pp = f_tangent_u[f_subPatchIdxRange_u.first + fPointIdx.first] [f_subPatchIdxRange_v.first + fPointIdx.second], pf_pq = f_tangent_v[f_subPatchIdxRange_u.first + fPointIdx.first] [f_subPatchIdxRange_v.first + fPointIdx.second]; // 构造Aij矩阵,见 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; } // G A Kriezis的文章中的做法 // old version void LoopDetector::initVectorField() { vectorFields = vector>(s_subPatchEdgeSampleCnt_u, vector(s_subPatchEdgeSampleCnt_v)); for (int i = 0; i < s_subPatchEdgeSampleCnt_u; i++) { for (int j = 0; j < s_subPatchEdgeSampleCnt_v; j++) { auto fPtRelatedIdx = selectedPointsIdx[i][j]; auto n2 = f_normal[f_subPatchIdxRange_u.first + fPtRelatedIdx.first][f_subPatchIdxRange_v.first + fPtRelatedIdx.second]; // glm::vec3 n2(1.,0.,0.); auto ps_pu = s_tangent_u[s_subPatchIdxRange_u.first + i][s_subPatchIdxRange_v.first + j]; auto ps_pv = s_tangent_v[s_subPatchIdxRange_u.first + i][s_subPatchIdxRange_v.first + j]; vectorFields[i][j] = glm::vec2(glm::dot(n2, ps_pu), glm::dot(n2, ps_pv)); } } } // old version void LoopDetector::getRotationNumber() { // vectorFields的参数域是与s(第一个曲面)一致的 auto edgeSampleCnt = s_evaluation.size(); auto uParamCellSize = (*(s.knots_u.end() - 1) - *s.knots_u.begin()) / (float) edgeSampleCnt; auto vParamCellSize = (*(s.knots_v.end() - 1) - *s.knots_v.begin()) / (float) edgeSampleCnt; // vector> pu_pt = {{0., 1.}, // {-1., 0.}}; // vector> pv_pt = {{1., 0.}, // {0., -1.}}; rotationNumbers = vector>(s_subPatchEdgeSampleCnt_u, vector(s_subPatchEdgeSampleCnt_v)); // 以小格子为单位遍历 for (int i = 0; i < s_subPatchEdgeSampleCnt_u - 1; i++) { for (int j = 0; j < s_subPatchEdgeSampleCnt_v - 1; j++) { float F[2][2], G[2][2]; for (int biasI = 0; biasI < 2; biasI++) { for (int biasJ = 0; biasJ < 2; biasJ++) { auto idxI = i + biasI; auto idxJ = j + biasJ; auto v = vectorFields[idxI][idxJ]; auto vSquareSum = v.x * v.x + v.y * v.y; auto pTheta_pChi = -v.y / vSquareSum; auto pTheta_pPhi = v.x / vSquareSum; // auto pChi_pu = // (vectorFields[idxI + 1][idxJ].x - vectorFields[idxI - 1][idxJ].x) / (2 * uParamCellSize); // auto pChi_pv = // (vectorFields[idxI][idxJ + 1].x - vectorFields[idxI][idxJ - 1].x) / (2 * vParamCellSize); glm::vec2 pV_pu; glm::vec2 pV_pv; if (idxI == 0) pV_pu = (vectorFields[idxI + 1][idxJ] - vectorFields[idxI][idxJ]) / uParamCellSize; else if (idxI == s_subPatchEdgeSampleCnt_u - 1) pV_pu = (vectorFields[idxI][idxJ] - vectorFields[idxI - 1][idxJ]) / uParamCellSize; else pV_pu = (vectorFields[idxI + 1][idxJ] - vectorFields[idxI - 1][idxJ]) / (2 * uParamCellSize); if (idxJ == 0) pV_pv = (vectorFields[idxI][idxJ + 1] - vectorFields[idxI][idxJ]) / vParamCellSize; else if (idxJ == s_subPatchEdgeSampleCnt_v - 1) pV_pv = (vectorFields[idxI][idxJ] - vectorFields[idxI][idxJ - 1]) / vParamCellSize; else pV_pv = (vectorFields[idxI][idxJ + 1] - vectorFields[idxI][idxJ - 1]) / (2 * vParamCellSize); F[biasI][biasJ] = pTheta_pChi * pV_pu.x + pTheta_pPhi * pV_pu.y; G[biasI][biasJ] = pTheta_pChi * pV_pv.x + pTheta_pPhi * pV_pv.y; } } rotationNumbers[i][j] = int( round(((F[0][1] + F[1][1] - F[0][0] - F[1][0]) * uParamCellSize + (G[0][0] + G[0][1] - G[1][0] - G[1][1]) * vParamCellSize)) / 2.); } } // int a = 3; // int b = 1; } // old version void LoopDetector::getRotationNumber(const vector, pair>> &intersectBoxPairs) { // vectorFields的参数域是与s(第一个曲面)一致的 auto edgeSampleCnt = s_evaluation.size(); auto uParamCellSize = (*(s.knots_u.end() - 1) - *s.knots_u.begin()) / (float) edgeSampleCnt; auto vParamCellSize = (*(s.knots_v.end() - 1) - *s.knots_v.begin()) / (float) edgeSampleCnt; rotationNumbers = vector>(s_subPatchEdgeSampleCnt_u, vector(s_subPatchEdgeSampleCnt_v)); // 以小格子为单位遍历 for (const auto &boxPair: intersectBoxPairs) { float F[2][2], G[2][2]; for (int biasI = 0; biasI < 2; biasI++) { for (int biasJ = 0; biasJ < 2; biasJ++) { auto idxI = boxPair.first.first + biasI - s_subPatchIdxRange_u.first; auto idxJ = boxPair.first.second + biasJ - s_subPatchIdxRange_v.first; auto v = vectorFields[idxI][idxJ]; auto vSquareSum = v.x * v.x + v.y * v.y; auto pTheta_pChi = -v.y / vSquareSum; auto pTheta_pPhi = v.x / vSquareSum; // auto pChi_pu = // (vectorFields[idxI + 1][idxJ].x - vectorFields[idxI - 1][idxJ].x) / (2 * uParamCellSize); // auto pChi_pv = // (vectorFields[idxI][idxJ + 1].x - vectorFields[idxI][idxJ - 1].x) / (2 * vParamCellSize); glm::vec2 pV_pu; glm::vec2 pV_pv; if (idxI == 0) pV_pu = (vectorFields[idxI + 1][idxJ] - vectorFields[idxI][idxJ]) / uParamCellSize; else if (idxI == s_subPatchEdgeSampleCnt_u - 1) pV_pu = (vectorFields[idxI][idxJ] - vectorFields[idxI - 1][idxJ]) / uParamCellSize; else pV_pu = (vectorFields[idxI + 1][idxJ] - vectorFields[idxI - 1][idxJ]) / (2 * uParamCellSize); if (idxJ == 0) pV_pv = (vectorFields[idxI][idxJ + 1] - vectorFields[idxI][idxJ]) / vParamCellSize; else if (idxJ == s_subPatchEdgeSampleCnt_v - 1) pV_pv = (vectorFields[idxI][idxJ] - vectorFields[idxI][idxJ - 1]) / vParamCellSize; else pV_pv = (vectorFields[idxI][idxJ + 1] - vectorFields[idxI][idxJ - 1]) / (2 * vParamCellSize); F[biasI][biasJ] = pTheta_pChi * pV_pu.x + pTheta_pPhi * pV_pu.y; G[biasI][biasJ] = pTheta_pChi * pV_pv.x + pTheta_pPhi * pV_pv.y; } } rotationNumbers[boxPair.first.first - s_subPatchIdxRange_u.first][boxPair.first.second - s_subPatchIdxRange_v.first] = int( round(((F[0][1] + F[1][1] - F[0][0] - F[1][0]) * uParamCellSize + (G[0][0] + G[0][1] - G[1][0] - G[1][1]) * vParamCellSize)) / 2.); } } void LoopDetector::getRotationNumber(const map, set>> &intersectBoxPairs) { // vectorFields的参数域是与s(第一个曲面)一致的 auto edgeSampleCnt = s_evaluation.size(); auto uParamCellSize = (*(s.knots_u.end() - 1) - *s.knots_u.begin()) / (float) edgeSampleCnt; auto vParamCellSize = (*(s.knots_v.end() - 1) - *s.knots_v.begin()) / (float) edgeSampleCnt; rotationNumbers = vector>(s_subPatchEdgeSampleCnt_u, vector(s_subPatchEdgeSampleCnt_v)); targetCells = {}; // 以小格子为单位遍历 for (const auto &boxPair: intersectBoxPairs) { if (boxPair.first.first == 127 && boxPair.first.second == 0) { int haha = 1; } float F[2][2], G[2][2]; for (int biasI = 0; biasI < 2; biasI++) { for (int biasJ = 0; biasJ < 2; biasJ++) { auto idxI = boxPair.first.first + biasI - s_subPatchIdxRange_u.first; auto idxJ = boxPair.first.second + biasJ - s_subPatchIdxRange_v.first; auto v = vectorFields[idxI][idxJ]; auto vSquareSum = v.x * v.x + v.y * v.y; auto pTheta_pChi = -v.y / vSquareSum; auto pTheta_pPhi = v.x / vSquareSum; // auto pChi_pu = // (vectorFields[idxI + 1][idxJ].x - vectorFields[idxI - 1][idxJ].x) / (2 * uParamCellSize); // auto pChi_pv = // (vectorFields[idxI][idxJ + 1].x - vectorFields[idxI][idxJ - 1].x) / (2 * vParamCellSize); glm::vec2 pV_pu; glm::vec2 pV_pv; if (idxI == 0) pV_pu = (vectorFields[idxI + 1][idxJ] - vectorFields[idxI][idxJ]) / uParamCellSize; else if (idxI == s_subPatchEdgeSampleCnt_u - 1) pV_pu = (vectorFields[idxI][idxJ] - vectorFields[idxI - 1][idxJ]) / uParamCellSize; else pV_pu = (vectorFields[idxI + 1][idxJ] - vectorFields[idxI - 1][idxJ]) / (2 * uParamCellSize); if (idxJ == 0) pV_pv = (vectorFields[idxI][idxJ + 1] - vectorFields[idxI][idxJ]) / vParamCellSize; else if (idxJ == s_subPatchEdgeSampleCnt_v - 1) pV_pv = (vectorFields[idxI][idxJ] - vectorFields[idxI][idxJ - 1]) / vParamCellSize; else pV_pv = (vectorFields[idxI][idxJ + 1] - vectorFields[idxI][idxJ - 1]) / (2 * vParamCellSize); F[biasI][biasJ] = pTheta_pChi * pV_pu.x + pTheta_pPhi * pV_pu.y; G[biasI][biasJ] = pTheta_pChi * pV_pv.x + pTheta_pPhi * pV_pv.y; } } int rotationNumber = int(round(((F[0][1] + F[1][1] - F[0][0] - F[1][0]) * uParamCellSize + (G[0][0] + G[0][1] - G[1][0] - G[1][1]) * vParamCellSize)) / 2.); rotationNumbers[boxPair.first.first - s_subPatchIdxRange_u.first][boxPair.first.second - s_subPatchIdxRange_v.first] = rotationNumber; if (rotationNumber != 0) { targetCells.insert({{boxPair.first.first, boxPair.first.second}, rotationNumber}); } } } // old version vector> LoopDetector::detect(pair _s_subPatchIdxRange_u, pair _s_subPatchIdxRange_v, pair _f_subPatchIdxRange_u, pair _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; // 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; initOrientedDistance(); initVectorField(); getRotationNumber(); return {}; } vector> LoopDetector::detect(const map, set>> &intersectBoxPairs, pair _s_subPatchIdxRange_u, pair _s_subPatchIdxRange_v, pair _f_subPatchIdxRange_u, pair _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; // 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; initOrientedDisAndVecFields(intersectBoxPairs); getRotationNumber(intersectBoxPairs); return {}; }