|
|
@ -8,15 +8,15 @@ LoopDetector(const vector<vector<glm::vec3>> &s_evaluation_, const vector<vector |
|
|
|
const vector<vector<glm::vec3> > &s_tangent_u_, const vector<vector<glm::vec3> > &f_tangent_u_, |
|
|
|
const vector<vector<glm::vec3> > &s_tangent_v_, const vector<vector<glm::vec3> > &f_tangent_v_, |
|
|
|
const vector<vector<glm::vec3> > &s_normal_, const vector<vector<glm::vec3> > &f_normal_, |
|
|
|
const tinynurbs::RationalSurface<float> &s_) |
|
|
|
const tinynurbs::RationalSurface<float> &s_, const tinynurbs::RationalSurface<float> &f_) |
|
|
|
: 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_) {} |
|
|
|
s_normal(s_normal_), f_normal(f_normal_), s(s_), f(f_) { |
|
|
|
} |
|
|
|
|
|
|
|
// old version
|
|
|
|
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));
|
|
|
@ -49,14 +49,17 @@ void LoopDetector::initOrientedDistance() { |
|
|
|
} |
|
|
|
|
|
|
|
// old version
|
|
|
|
void LoopDetector::initOrientedDisAndVecFields(const vector<pair<pair<int, int>, pair<int, int>>> &intersectBoxPairs) { |
|
|
|
void LoopDetector::initOrientedDisAndVecFields( |
|
|
|
const vector<pair<pair<int, int>, pair<int, int> > > &intersectBoxPairs) { |
|
|
|
selectedPointsIdx = vector<vector<pair<int, int> > >(s_subPatchEdgeSampleCnt_u, |
|
|
|
vector<pair<int, int> >(s_subPatchEdgeSampleCnt_v, {-1, -1})); |
|
|
|
vectorFields = vector<vector<glm::vec2> >(s_subPatchEdgeSampleCnt_u, vector<glm::vec2>(s_subPatchEdgeSampleCnt_v)); |
|
|
|
int neighborIdxes[4][2] = {{1, 0}, |
|
|
|
int neighborIdxes[4][2] = { |
|
|
|
{1, 0}, |
|
|
|
{0, 1}, |
|
|
|
{-1, 0}, |
|
|
|
{0, -1}}; |
|
|
|
{0, -1} |
|
|
|
}; |
|
|
|
for (const auto &boxPair: intersectBoxPairs) { |
|
|
|
float minDis = FLT_MAX; |
|
|
|
int minDisFIdx_u = -1, minDisFIdx_v = -1; |
|
|
@ -104,17 +107,23 @@ void LoopDetector::initOrientedDisAndVecFields(const vector<pair<pair<int, int>, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void LoopDetector::initOrientedDisAndVecFields(const map<pair<int, int>, set<pair<int, int>>> &intersectBoxPairs) { |
|
|
|
|
|
|
|
// without newton iteration and with wrong approximate
|
|
|
|
void LoopDetector::initOrientedDisAndVecFields_deprecated( |
|
|
|
const map<pair<int, int>, set<pair<int, int> > > &intersectBoxPairs) { |
|
|
|
selectedPointsIdx = vector<vector<pair<int, int> > >(s_subPatchEdgeSampleCnt_u, |
|
|
|
vector<pair<int, int> >(s_subPatchEdgeSampleCnt_v, {-1, -1})); |
|
|
|
vectorFields = vector<vector<glm::vec2> >(s_subPatchEdgeSampleCnt_u, vector<glm::vec2>(s_subPatchEdgeSampleCnt_v)); |
|
|
|
int neighborIdxes[4][2] = {{1, 0}, |
|
|
|
auto vectorFieldsCalculated = vector<vector<int> >(s_subPatchEdgeSampleCnt_u, vector<int>(0)); |
|
|
|
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}}}; // 必须是左上,右上,左下,右下的顺序
|
|
|
|
{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++) { |
|
|
@ -137,7 +146,6 @@ void LoopDetector::initOrientedDisAndVecFields(const map<pair<int, int>, set<pai |
|
|
|
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() || |
|
|
@ -168,6 +176,72 @@ void LoopDetector::initOrientedDisAndVecFields(const map<pair<int, int>, set<pai |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void LoopDetector::initOrientedDisAndVecFields(const map<pair<int, int>, set<pair<int, int> > > &intersectBoxPairs) { |
|
|
|
selectedPointsIdx = vector(s_subPatchEdgeSampleCnt_u, vector<pair<int, int> >(s_subPatchEdgeSampleCnt_v, {-1, -1})); |
|
|
|
vectorFields = vector(s_subPatchEdgeSampleCnt_u, vector<glm::vec2>(s_subPatchEdgeSampleCnt_v)); |
|
|
|
auto vectorFieldsCalculated = vector(s_subPatchEdgeSampleCnt_u, vector<int>(0)); |
|
|
|
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++) { |
|
|
|
float minDis = FLT_MAX; |
|
|
|
int minDisFIdx_u = -1, minDisFIdx_v = -1; |
|
|
|
int idxI = boxPair.first.first + i; |
|
|
|
int idxJ = boxPair.first.second + j; |
|
|
|
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<int, int>(-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 <= 4; step_u++) { |
|
|
|
for (int step_v = 0; step_v + step_u <= 4; 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}; |
|
|
|
pair<int, int> selectedIdx = {minDisFIdx_u - f_subPatchIdxRange_u.first, minDisFIdx_v - f_subPatchIdxRange_v.first}; |
|
|
|
pair<float, float> fURange = {f.knots_u[0], f.knots_u[f.knots_u.size() - 1]}; |
|
|
|
pair<float, float> fVRange = {f.knots_v[0], f.knots_v[f.knots_v.size() - 1]}; |
|
|
|
pair<float, float> selectedParam = { |
|
|
|
fURange.first + (fURange.second - fURange.first) / static_cast<float>(f_evaluation.size() - 1) * static_cast<float>(selectedIdx.first), |
|
|
|
fVRange.first + (fVRange.second - fVRange.first) / static_cast<float>(f_evaluation[0].size() - 1) * static_cast<float>(selectedIdx.second) |
|
|
|
}; |
|
|
|
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() { |
|
|
@ -261,7 +335,7 @@ void LoopDetector::getRotationNumber() { |
|
|
|
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 pTheta_pPsi = v.x / vSquareSum; |
|
|
|
// auto pChi_pu =
|
|
|
|
// (vectorFields[idxI + 1][idxJ].x - vectorFields[idxI - 1][idxJ].x) / (2 * uParamCellSize);
|
|
|
|
// auto pChi_pv =
|
|
|
@ -280,8 +354,8 @@ void LoopDetector::getRotationNumber() { |
|
|
|
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; |
|
|
|
F[biasI][biasJ] = pTheta_pChi * pV_pu.x + pTheta_pPsi * pV_pu.y; |
|
|
|
G[biasI][biasJ] = pTheta_pChi * pV_pv.x + pTheta_pPsi * pV_pv.y; |
|
|
|
} |
|
|
|
} |
|
|
|
rotationNumbers[i][j] = int( |
|
|
@ -311,7 +385,7 @@ void LoopDetector::getRotationNumber(const vector<pair<pair<int, int>, pair<int, |
|
|
|
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 pTheta_pPsi = v.x / vSquareSum; |
|
|
|
// auto pChi_pu =
|
|
|
|
// (vectorFields[idxI + 1][idxJ].x - vectorFields[idxI - 1][idxJ].x) / (2 * uParamCellSize);
|
|
|
|
// auto pChi_pv =
|
|
|
@ -330,8 +404,8 @@ void LoopDetector::getRotationNumber(const vector<pair<pair<int, int>, pair<int, |
|
|
|
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; |
|
|
|
F[biasI][biasJ] = pTheta_pChi * pV_pu.x + pTheta_pPsi * pV_pu.y; |
|
|
|
G[biasI][biasJ] = pTheta_pChi * pV_pv.x + pTheta_pPsi * pV_pv.y; |
|
|
|
} |
|
|
|
} |
|
|
|
rotationNumbers[boxPair.first.first - s_subPatchIdxRange_u.first][boxPair.first.second - |
|
|
@ -351,9 +425,6 @@ void LoopDetector::getRotationNumber(const map<pair<int, int>, set<pair<int, int |
|
|
|
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++) { |
|
|
@ -361,8 +432,12 @@ void LoopDetector::getRotationNumber(const map<pair<int, int>, set<pair<int, int |
|
|
|
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; |
|
|
|
float pTheta_pChi = -1e6; |
|
|
|
float pTheta_pPsi = 1e6; |
|
|
|
if (vSquareSum != 0) { |
|
|
|
pTheta_pChi = -v.y / vSquareSum; |
|
|
|
pTheta_pPsi = v.x / vSquareSum; |
|
|
|
} |
|
|
|
// auto pChi_pu =
|
|
|
|
// (vectorFields[idxI + 1][idxJ].x - vectorFields[idxI - 1][idxJ].x) / (2 * uParamCellSize);
|
|
|
|
// auto pChi_pv =
|
|
|
@ -381,19 +456,18 @@ void LoopDetector::getRotationNumber(const map<pair<int, int>, set<pair<int, int |
|
|
|
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; |
|
|
|
F[biasI][biasJ] = pTheta_pChi * pV_pu.x + pTheta_pPsi * pV_pu.y; |
|
|
|
G[biasI][biasJ] = pTheta_pChi * pV_pv.x + pTheta_pPsi * 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.); |
|
|
|
(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}); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -437,5 +511,3 @@ vector<pair<int, int>> LoopDetector::detect(const map<pair<int, int>, set<pair<i |
|
|
|
getRotationNumber(intersectBoxPairs); |
|
|
|
return {}; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|