You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
652 lines
21 KiB
C
652 lines
21 KiB
C
|
1 month ago
|
/*------------------------------------------------------------------------------
|
||
|
|
* Copyright (c) 2023 by Bai Bing (seread@163.com)
|
||
|
|
* See COPYING file for copying and redistribution conditions.
|
||
|
|
*
|
||
|
|
* Alians IT Studio.
|
||
|
|
*----------------------------------------------------------------------------*/
|
||
|
|
#pragma once
|
||
|
|
|
||
|
|
#include <algorithm>
|
||
|
|
#include <cstring>
|
||
|
|
#include <numeric>
|
||
|
|
#include <set>
|
||
|
|
#include <utility>
|
||
|
|
#include <vector>
|
||
|
|
|
||
|
|
#include "ASMatrix.h"
|
||
|
|
#include "ASSlice.h"
|
||
|
|
|
||
|
|
namespace ais
|
||
|
|
{
|
||
|
|
// Quick value access for ais::FMatrix while interpolating
|
||
|
|
template <typename dtype = double, class Allocator = std::allocator<dtype>>
|
||
|
|
struct GridInterpolatorBlock
|
||
|
|
{
|
||
|
|
GridInterpolatorBlock()
|
||
|
|
{
|
||
|
|
clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
//============================================================================
|
||
|
|
// Method Description:
|
||
|
|
/// Build a block of values from matrix, and center point at row and col
|
||
|
|
///
|
||
|
|
/// @param value
|
||
|
|
///
|
||
|
|
GridInterpolatorBlock(dtype &value)
|
||
|
|
{
|
||
|
|
clear();
|
||
|
|
for (int i = 0; i < 25; i++)
|
||
|
|
{
|
||
|
|
values[i] = value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//============================================================================
|
||
|
|
// Method Description:
|
||
|
|
/// Build a block of values from matrix, and center point at row and col
|
||
|
|
///
|
||
|
|
/// @param matrix, source extended matrix
|
||
|
|
/// @param row, col block center point in extended matrix positions (uj, ui) = (j+2, i+2)
|
||
|
|
///
|
||
|
|
GridInterpolatorBlock(const ais::Matrix<dtype> &matrixExtended, size_t uj, size_t ui)
|
||
|
|
{
|
||
|
|
copy(matrixExtended, uj, ui);
|
||
|
|
}
|
||
|
|
|
||
|
|
//============================================================================
|
||
|
|
// Method Description:
|
||
|
|
/// copy matrix values to block, and center point at row and col
|
||
|
|
///
|
||
|
|
/// @param matrix, source extended matrix
|
||
|
|
/// @param row, col block center point in extended matrix positions (uj, ui) = (j+2, i+2)
|
||
|
|
///
|
||
|
|
GridInterpolatorBlock ©(const ais::Matrix<dtype> &matrixExtended, size_t uj, size_t ui)
|
||
|
|
{
|
||
|
|
clear();
|
||
|
|
|
||
|
|
for (size_t j = uj - 2; j != uj + 3; ++j)
|
||
|
|
{
|
||
|
|
auto begin = j * matrixExtended.columns() + ui - 2;
|
||
|
|
auto end = begin + 5;
|
||
|
|
for (size_t pos = begin; pos < end; pos++)
|
||
|
|
{
|
||
|
|
size_t boxPos = (j - uj + 2) * 5 + pos - begin;
|
||
|
|
values[boxPos] = matrixExtended[pos];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline void clear() { std::memset(values, 0, 25 * sizeof(dtype)); }
|
||
|
|
|
||
|
|
//============================================================================
|
||
|
|
// Method Description:
|
||
|
|
/// Get the value at the specified offset position, center point of this block is (0, 0)
|
||
|
|
/// 2 top (2, 0) (row, col)
|
||
|
|
/// 1
|
||
|
|
/// -2 -1 0 1 2 left (0, -2) center (0, 0) right (0, 2)
|
||
|
|
/// -1
|
||
|
|
/// -2 bottom (-2, 0)
|
||
|
|
///
|
||
|
|
/// @param row, col
|
||
|
|
///
|
||
|
|
dtype &operator()(int8_t row, int8_t col) noexcept
|
||
|
|
{
|
||
|
|
size_t pos = (row + 2) * 5 + (col + 2);
|
||
|
|
return values[pos];
|
||
|
|
}
|
||
|
|
const dtype &operator()(int8_t row, int8_t col) const noexcept
|
||
|
|
{
|
||
|
|
size_t pos = (row + 2) * 5 + (col + 2);
|
||
|
|
return values[pos];
|
||
|
|
}
|
||
|
|
|
||
|
|
dtype &operator[](size_t pos)
|
||
|
|
{
|
||
|
|
return values[pos];
|
||
|
|
}
|
||
|
|
|
||
|
|
const dtype &operator[](size_t pos) const
|
||
|
|
{
|
||
|
|
return values[pos];
|
||
|
|
}
|
||
|
|
|
||
|
|
inline const size_t index(int8_t row, int8_t col) const
|
||
|
|
{
|
||
|
|
size_t index = (row + 2) * 5 + (col + 2);
|
||
|
|
if (index > 24)
|
||
|
|
{
|
||
|
|
std::string msg = "Out of range";
|
||
|
|
THROW_INVALID_ARGUMENT(msg);
|
||
|
|
}
|
||
|
|
|
||
|
|
return index;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline const std::pair<int8_t, int8_t> &pos_pair(size_t index) const
|
||
|
|
{
|
||
|
|
if (index > 24)
|
||
|
|
{
|
||
|
|
std::string msg = "Out of range";
|
||
|
|
THROW_INVALID_ARGUMENT(msg);
|
||
|
|
}
|
||
|
|
|
||
|
|
auto row = int8_t(index / 5) - 2;
|
||
|
|
auto col = int8_t(index % 5) - 2;
|
||
|
|
|
||
|
|
std::pair<int8_t, int8_t> ret = std::make_pair(row, col);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double avg()
|
||
|
|
{
|
||
|
|
double sum = 0.0;
|
||
|
|
size_t count = 0;
|
||
|
|
for (auto &d : values)
|
||
|
|
{
|
||
|
|
if ((!std::isnan(d)) && (!std::isinf(d)))
|
||
|
|
{
|
||
|
|
sum += d;
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return count == 0 ? 0 : sum / count;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double mock_value(long mask)
|
||
|
|
{
|
||
|
|
double sum = 0.0;
|
||
|
|
size_t count = 0;
|
||
|
|
for (int i = 0; i < 25; i++)
|
||
|
|
{
|
||
|
|
if ((mask & (1 << i)) == 0)
|
||
|
|
{
|
||
|
|
sum += values[i];
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return count == 0 ? 0 : sum / count;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline static const std::set<std::pair<int32_t, int32_t>> validPos = {
|
||
|
|
{0, 0},
|
||
|
|
{0, 1},
|
||
|
|
{-1, 0},
|
||
|
|
{1, 0},
|
||
|
|
{0, -1},
|
||
|
|
{-1, 1},
|
||
|
|
{-1, -1},
|
||
|
|
{1, 1},
|
||
|
|
{1, -1},
|
||
|
|
{0, 2},
|
||
|
|
{-2, 0},
|
||
|
|
{2, 0},
|
||
|
|
{0, -2}};
|
||
|
|
|
||
|
|
inline static const std::set<std::pair<int32_t, int32_t>> validPos1 = {
|
||
|
|
{0, 1},
|
||
|
|
{-1, 0},
|
||
|
|
{1, 0},
|
||
|
|
{0, -1}};
|
||
|
|
|
||
|
|
inline static const std::set<std::pair<int32_t, int32_t>> validPos2 = {
|
||
|
|
{-1, 1},
|
||
|
|
{-1, -1},
|
||
|
|
{1, 1},
|
||
|
|
{1, -1}};
|
||
|
|
|
||
|
|
inline static const std::set<std::pair<int32_t, int32_t>> validPos3 = {
|
||
|
|
{0, 2},
|
||
|
|
{-2, 0},
|
||
|
|
{2, 0},
|
||
|
|
{0, -2}};
|
||
|
|
|
||
|
|
inline double mock_value2(long mask, int pos, double originValue = 0.0)
|
||
|
|
{
|
||
|
|
double sum = 0.0;
|
||
|
|
size_t count = 0;
|
||
|
|
|
||
|
|
for (int index = 0; index < 25; index++)
|
||
|
|
{
|
||
|
|
int32_t j = int32_t(index / 5) - 2;
|
||
|
|
int32_t i = index % 5 - 2;
|
||
|
|
std::pair<int32_t, int32_t> ppos = std::make_pair(i, j);
|
||
|
|
|
||
|
|
if ((mask & (1 << pos)) == 0 && validPos.find(ppos) != validPos.end())
|
||
|
|
{
|
||
|
|
sum += values[i];
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return count == 0 ? originValue : sum / count;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double mock_value3(long mask, int pos)
|
||
|
|
{
|
||
|
|
double origin = values[pos];
|
||
|
|
double temp = std::nan("1");
|
||
|
|
double weight = 0.0;
|
||
|
|
|
||
|
|
for (int index = 0; index < 25; index++)
|
||
|
|
{
|
||
|
|
// use inverse distance weight to get mock value
|
||
|
|
int32_t j = int32_t(index / 5) - 2;
|
||
|
|
int32_t i = index % 5 - 2;
|
||
|
|
std::pair<int32_t, int32_t> ipos = std::make_pair(i, j);
|
||
|
|
|
||
|
|
if (((mask & (1 << index)) == 0) && validPos.find(ipos) != validPos.end())
|
||
|
|
{
|
||
|
|
// use valid block values to build the invalid node mock value.
|
||
|
|
if (index == 12)
|
||
|
|
{
|
||
|
|
temp += 2 * values[index];
|
||
|
|
weight += 2;
|
||
|
|
}
|
||
|
|
else if (validPos1.find(ipos) != validPos1.end())
|
||
|
|
{
|
||
|
|
temp += values[index];
|
||
|
|
weight += 1;
|
||
|
|
}
|
||
|
|
else if (validPos2.find(ipos) != validPos2.end())
|
||
|
|
{
|
||
|
|
temp += .7071 * values[index];
|
||
|
|
weight += .7071;
|
||
|
|
}
|
||
|
|
else if (validPos3.find(ipos) != validPos3.end())
|
||
|
|
{
|
||
|
|
temp += 0.5 * values[index];
|
||
|
|
weight += .5;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return std::isnan(temp) ? origin : (temp / weight);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double nodeInverseDistanceWeight(const std::pair<int32_t, int32_t> &ppos, const std::pair<int32_t, int32_t> &ipos)
|
||
|
|
{
|
||
|
|
double temp = std::nan("1");
|
||
|
|
if (ppos != ipos)
|
||
|
|
temp = std::sqrt((ppos.first - ipos.first) * (ppos.first - ipos.first) + (ppos.second - ipos.second) * (ppos.second - ipos.second));
|
||
|
|
|
||
|
|
return std::isnan(temp) ? 2 : 1 / temp;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double mock_value4(long mask, int pos, double weightLimit = 0.2)
|
||
|
|
{
|
||
|
|
// use the trand between p(0,0) and mirror point to build the mock value for point at pos
|
||
|
|
double origin = values[pos];
|
||
|
|
double temp = 0.0;
|
||
|
|
double weight = 0.0;
|
||
|
|
|
||
|
|
int32_t pj = int32_t(pos / 5) - 2;
|
||
|
|
int32_t pi = pos % 5 - 2;
|
||
|
|
std::pair<int32_t, int32_t> ppos = std::make_pair(pi, pj);
|
||
|
|
|
||
|
|
// use valid block values to build the invalid node mock value.
|
||
|
|
|
||
|
|
for (int index = 0; index < 25; index++)
|
||
|
|
{
|
||
|
|
// use inverse distance weight to get mock value
|
||
|
|
int32_t j = int32_t(index / 5) - 2;
|
||
|
|
int32_t i = index % 5 - 2;
|
||
|
|
std::pair<int32_t, int32_t> ipos = std::make_pair(i, j);
|
||
|
|
|
||
|
|
if (((mask & (1 << index)) == 0) && validPos.find(ipos) != validPos.end())
|
||
|
|
{
|
||
|
|
auto pweight = nodeInverseDistanceWeight(ppos, ipos);
|
||
|
|
if (pweight >= weightLimit)
|
||
|
|
{
|
||
|
|
temp += pweight * values[index];
|
||
|
|
weight += pweight;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return weight != 0.0 ? (temp / weight) : origin;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double mock_value5(long mask, int pos)
|
||
|
|
{
|
||
|
|
// use the trend between p(0,0) and mirror point to build the mock value for point at pos
|
||
|
|
double origin = values[pos];
|
||
|
|
double temp = 0.0;
|
||
|
|
double weight = 0.0;
|
||
|
|
|
||
|
|
int32_t pj = int32_t(pos / 5) - 2;
|
||
|
|
int32_t pi = pos % 5 - 2;
|
||
|
|
std::pair<int32_t, int32_t> ppos = std::make_pair(pi, pj);
|
||
|
|
|
||
|
|
// build mock node by nearest valid point mean
|
||
|
|
for (int i = -1; i < 2; i++)
|
||
|
|
{
|
||
|
|
int32_t ii = pi + i;
|
||
|
|
if (std::abs(ii) > 2)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
for (int j = -1; j < 2; j++)
|
||
|
|
{
|
||
|
|
// loop the nearest point
|
||
|
|
int32_t ij = pj + j;
|
||
|
|
if (std::abs(ij) > 2)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
auto index = (ij + 2) * 5 + (ii + 2);
|
||
|
|
if ((mask & (1 << index)) == 0)
|
||
|
|
{
|
||
|
|
temp += values[index];
|
||
|
|
weight++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return weight != 0.0 ? (temp / weight) : origin;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double mock_value6(long mask, int pos)
|
||
|
|
{
|
||
|
|
// use the trend between p(0,0) and mirror point to build the mock value for point at pos
|
||
|
|
double origin = values[pos];
|
||
|
|
double temp = 0.0;
|
||
|
|
double weight = 0.0;
|
||
|
|
|
||
|
|
int32_t pj = int32_t(pos / 5) - 2;
|
||
|
|
int32_t pi = pos % 5 - 2;
|
||
|
|
std::pair<int32_t, int32_t> ppos = std::make_pair(pi, pj);
|
||
|
|
|
||
|
|
double mock_p_0_0 = mock_value3(mask, 12);
|
||
|
|
|
||
|
|
if (pos == 12)
|
||
|
|
{
|
||
|
|
// use mock 4 to build center value
|
||
|
|
temp = mock_p_0_0;
|
||
|
|
weight = 1;
|
||
|
|
}
|
||
|
|
else if (validPos3.find(ppos) != validPos3.end() || validPos1.find(ppos) != validPos1.end())
|
||
|
|
{
|
||
|
|
// build mirror point index
|
||
|
|
auto mi = pi, mj = pj;
|
||
|
|
if (std::abs(pj) > 0)
|
||
|
|
{
|
||
|
|
// for pj = +/- 2 or +/- 1
|
||
|
|
mj = -pj;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// for pi = +/- 2 or +/- 1
|
||
|
|
mi = -pi;
|
||
|
|
}
|
||
|
|
auto index = (mj + 2) * 5 + (mi + 2);
|
||
|
|
if ((mask & (1 << 12)) > 0 && (mask & (1 << index)) > 0)
|
||
|
|
{
|
||
|
|
// only make mock value while there p(0,0) and mirror point are valid
|
||
|
|
temp = 2 * values[12] - values[index];
|
||
|
|
weight = 1;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// use mock 3 to build center value
|
||
|
|
temp = mock_value3(mask, pos);
|
||
|
|
weight = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (validPos2.find(ppos) != validPos2.end())
|
||
|
|
{
|
||
|
|
auto mi = -pi, mj = -pj;
|
||
|
|
auto index = (mj + 2) * 5 + (mi + 2);
|
||
|
|
if ((mask & (1 << 12)) > 0 && (mask & (1 << index)) > 0)
|
||
|
|
{
|
||
|
|
// only make mock value while there p(0,0) and mirror point are valid
|
||
|
|
temp = 2 * values[12] - values[index];
|
||
|
|
weight = 1;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// use mock 4 to build center value
|
||
|
|
temp = mock_value3(mask, pos);
|
||
|
|
weight = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return weight != 0.0 ? (temp / weight) : origin;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double mock_value7(long mask, int pos)
|
||
|
|
{
|
||
|
|
double origin = values[pos];
|
||
|
|
double med;
|
||
|
|
|
||
|
|
std::vector<dtype> validData;
|
||
|
|
for (int i = 0; i < 25; i++)
|
||
|
|
{
|
||
|
|
if ((mask & (1 << i)) == 0)
|
||
|
|
{
|
||
|
|
validData.push_back(values[i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
auto s = validData.size();
|
||
|
|
if (s == 0)
|
||
|
|
med = std::nan("-1");
|
||
|
|
else
|
||
|
|
{
|
||
|
|
auto m = validData.begin() + s / 2;
|
||
|
|
std::partial_sort(std::execution::par, validData.begin(), m, validData.end());
|
||
|
|
|
||
|
|
med = validData[s / 2];
|
||
|
|
}
|
||
|
|
|
||
|
|
return std::isnan(med) ? origin : med;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double mock_value8(long mask, int pos)
|
||
|
|
{
|
||
|
|
double origin = values[pos];
|
||
|
|
|
||
|
|
return mask & (1 << 12) ? origin : values[12];
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double mock_value9(long mask, int pos, double alpha)
|
||
|
|
{
|
||
|
|
// make the origin data as input value
|
||
|
|
double temp = std::nan("1");
|
||
|
|
auto [row, col] = pos_pair(pos);
|
||
|
|
std::pair<int32_t, int32_t> ppos = std::make_pair(row, col);
|
||
|
|
|
||
|
|
if (pos == index(0, 0))
|
||
|
|
{
|
||
|
|
// for center point, use avg to smooth the isoline
|
||
|
|
temp = mock_value(mask);
|
||
|
|
}
|
||
|
|
else if (validPos1.find(ppos) != validPos1.end())
|
||
|
|
{
|
||
|
|
// inner extension edge (0, 1), (0, -1), (1, 0), (-1, 0)
|
||
|
|
auto centerIndex = index(0, 0);
|
||
|
|
auto mirrorIndex = (std::abs(row) != 0) ? index(-row, col) : index(row, -col);
|
||
|
|
|
||
|
|
temp = 2 * values[centerIndex] - values[mirrorIndex];
|
||
|
|
}
|
||
|
|
else if (validPos2.find(ppos) != validPos2.end())
|
||
|
|
{
|
||
|
|
// inner corners (1, 1), (-1, -1), (1, -1), (-1, 1)
|
||
|
|
auto supportIndex1 = index(-row, col);
|
||
|
|
auto supportIndex2 = index(row, -col);
|
||
|
|
auto mirrorIndex = index(-row, -col);
|
||
|
|
|
||
|
|
temp = values[supportIndex1] + values[supportIndex2] - values[mirrorIndex];
|
||
|
|
}
|
||
|
|
else if (validPos3.find(ppos) != validPos3.end())
|
||
|
|
{
|
||
|
|
// exterior extension edge (2, 0), (-2, 0), (0, -2), (0, 2)
|
||
|
|
double alpha1 = alpha * alpha;
|
||
|
|
double alpha2 = -2 * (1 + alpha1);
|
||
|
|
|
||
|
|
double beta = 1 / alpha;
|
||
|
|
double beta1 = beta * beta;
|
||
|
|
double beta2 = -2 * (1 + beta1);
|
||
|
|
|
||
|
|
auto mirrorIndex = (std::abs(row) != 0) ? index(-row, col) : index(row, -col);
|
||
|
|
|
||
|
|
double innerCornersValue = values[index(1, 1)] - values[index(-1, -1)];
|
||
|
|
double innerEdgeValue = 0.0;
|
||
|
|
|
||
|
|
double adjustValue = 0;
|
||
|
|
if (std::abs(row) != 0)
|
||
|
|
{
|
||
|
|
// top & bottom (2, 0), (-2, 0)
|
||
|
|
innerCornersValue += values[index(-1, 1)] - values[index(1, -1)];
|
||
|
|
innerCornersValue *= alpha1;
|
||
|
|
innerEdgeValue = alpha2 * (values[index(0, 1)] - values[index(0, -1)]);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// left & right (0, -2), (0, 2)
|
||
|
|
innerCornersValue += values[index(1, -1)] - values[index(1, -1)];
|
||
|
|
innerCornersValue *= beta1;
|
||
|
|
innerEdgeValue = beta2 * (values[index(1, 0)] - values[index(-1, 0)]);
|
||
|
|
}
|
||
|
|
|
||
|
|
adjustValue = innerCornersValue + innerEdgeValue;
|
||
|
|
adjustValue = (row + col) > 0 ? -adjustValue : adjustValue;
|
||
|
|
|
||
|
|
temp = values[mirrorIndex] + adjustValue;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
temp = mock_value(mask);
|
||
|
|
}
|
||
|
|
|
||
|
|
return temp;
|
||
|
|
}
|
||
|
|
|
||
|
|
int get_fault_point_type(long mask, int pos)
|
||
|
|
{
|
||
|
|
// make the origin data as input value
|
||
|
|
double temp = std::nan("1");
|
||
|
|
auto [row, col] = pos_pair(pos);
|
||
|
|
|
||
|
|
if (std::abs(row) == std::abs(col))
|
||
|
|
{
|
||
|
|
// corner points
|
||
|
|
}
|
||
|
|
else if (std::abs(row) < std::abs(col))
|
||
|
|
{
|
||
|
|
// left or right
|
||
|
|
}
|
||
|
|
else if (std::abs(row) > std::abs(col))
|
||
|
|
{
|
||
|
|
// top or bottom
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline double mock_value10(long mask, int pos, double alpha)
|
||
|
|
{
|
||
|
|
// make the origin data as input value
|
||
|
|
double temp = std::nan("1");
|
||
|
|
auto [row, col] = pos_pair(pos);
|
||
|
|
std::pair<int32_t, int32_t> ppos = std::make_pair(row, col);
|
||
|
|
|
||
|
|
if (pos == index(0, 0))
|
||
|
|
{
|
||
|
|
// for center point, use avg to smooth the isoline
|
||
|
|
temp = mock_value(mask);
|
||
|
|
}
|
||
|
|
|
||
|
|
// else if (validPos1.find(ppos) != validPos1.end())
|
||
|
|
//{
|
||
|
|
// // inner extension edge (0, 1), (0, -1), (1, 0), (-1, 0)
|
||
|
|
// auto centerIndex = index(0, 0);
|
||
|
|
// auto mirrorIndex = (std::abs(row) != 0) ? index(-row, col) : index(row, -col);
|
||
|
|
|
||
|
|
// temp = 2 * values[centerIndex] - values[mirrorIndex];
|
||
|
|
//}
|
||
|
|
// else if (validPos2.find(ppos) != validPos2.end())
|
||
|
|
//{
|
||
|
|
// // inner corners (1, 1), (-1, -1), (1, -1), (-1, 1)
|
||
|
|
// auto supportIndex1 = index(-row, col);
|
||
|
|
// auto supportIndex2 = index(row, -col);
|
||
|
|
// auto mirrorIndex = index(-row, -col);
|
||
|
|
|
||
|
|
// temp = values[supportIndex1] + values[supportIndex2] - values[mirrorIndex];
|
||
|
|
//}
|
||
|
|
// else if (validPos3.find(ppos) != validPos3.end())
|
||
|
|
//{
|
||
|
|
// // exterior extension edge (2, 0), (-2, 0), (0, -2), (0, 2)
|
||
|
|
// double alpha1 = alpha * alpha;
|
||
|
|
// double alpha2 = -2 * (1 + alpha1);
|
||
|
|
|
||
|
|
// double beta = 1 / alpha;
|
||
|
|
// double beta1 = beta * beta;
|
||
|
|
// double beta2 = -2 * (1 + beta1);
|
||
|
|
|
||
|
|
// auto mirrorIndex = (std::abs(row) != 0) ? index(-row, col) : index(row, -col);
|
||
|
|
|
||
|
|
// double innerCornersValue = values[index(1, 1)] - values[index(-1, -1)];
|
||
|
|
// double innerEdgeValue = 0.0;
|
||
|
|
|
||
|
|
// double adjustValue = 0;
|
||
|
|
// if (std::abs(row) != 0)
|
||
|
|
// {
|
||
|
|
// // top & bottom (2, 0), (-2, 0)
|
||
|
|
// innerCornersValue += values[index(-1, 1)] - values[index(1, -1)];
|
||
|
|
// innerCornersValue *= alpha1;
|
||
|
|
// innerEdgeValue = alpha2 * (values[index(0, 1)] - values[index(0, -1)]);
|
||
|
|
|
||
|
|
// }
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// // left & right (0, -2), (0, 2)
|
||
|
|
// innerCornersValue += values[index(1, -1)] - values[index(1, -1)];
|
||
|
|
// innerCornersValue *= beta1;
|
||
|
|
// innerEdgeValue = beta2 * (values[index(1, 0)] - values[index(-1, 0)]);
|
||
|
|
// }
|
||
|
|
|
||
|
|
// adjustValue = innerCornersValue + innerEdgeValue;
|
||
|
|
// adjustValue = (row + col) > 0 ? -adjustValue : adjustValue;
|
||
|
|
|
||
|
|
// temp = values[mirrorIndex] + adjustValue;
|
||
|
|
//}
|
||
|
|
// else
|
||
|
|
//{
|
||
|
|
// temp = mock_value(mask);
|
||
|
|
//}
|
||
|
|
|
||
|
|
return temp;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string str() const
|
||
|
|
{
|
||
|
|
std::stringstream ss;
|
||
|
|
for (size_t j = 0; j < 5; j++)
|
||
|
|
{
|
||
|
|
for (size_t i = 0; i < 5; i++)
|
||
|
|
{
|
||
|
|
ss << values[j * 5 + i] << " ";
|
||
|
|
}
|
||
|
|
ss << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ss.str();
|
||
|
|
}
|
||
|
|
|
||
|
|
void print() const
|
||
|
|
{
|
||
|
|
std::cout << *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
friend std::ostream &operator<<(std::ostream &stream, const GridInterpolatorBlock<dtype> &block)
|
||
|
|
{
|
||
|
|
stream << block.str();
|
||
|
|
return stream;
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
dtype values[25];
|
||
|
|
};
|
||
|
|
} // namespace ais
|