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.
238 lines
6.9 KiB
C
238 lines
6.9 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 <execution>
|
||
|
|
#include <list>
|
||
|
|
#include <utility>
|
||
|
|
#include <vector>
|
||
|
|
|
||
|
|
#include "_Define.h"
|
||
|
|
#include "ASPoint.h"
|
||
|
|
#include "ASMatrix.h"
|
||
|
|
#include "core/Error.h"
|
||
|
|
|
||
|
|
namespace ais
|
||
|
|
{
|
||
|
|
/// Enum To describe an axis
|
||
|
|
enum class Axis3DType : int
|
||
|
|
{
|
||
|
|
X = 0,
|
||
|
|
Y,
|
||
|
|
Z
|
||
|
|
};
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// get point list for specified axis
|
||
|
|
/// @param pointList vector list for ais::Point or ais::PointXYZ
|
||
|
|
/// @param axis for target axis, must be Axis3DType::X, Axis3DType::Y, Axis3DType::Z
|
||
|
|
///
|
||
|
|
template <class PT = ais::Point>
|
||
|
|
AIS_EXPORT std::vector<double> getAxisValues(const std::vector<PT> &pointList, Axis3DType axis)
|
||
|
|
{
|
||
|
|
std::vector<double> axisValues;
|
||
|
|
for (auto &p : pointList)
|
||
|
|
{
|
||
|
|
if (axis == Axis3DType::Z)
|
||
|
|
{
|
||
|
|
if constexpr (ais::all_same_v<PT, ais::PointXYZ>)
|
||
|
|
{
|
||
|
|
axisValues.push_back(p.z);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
THROW_INVALID_ARGUMENT("PointList not contains z axis values.");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
axisValues.push_back(axis == Axis3DType::Y ? p.y : p.x);
|
||
|
|
}
|
||
|
|
return axisValues;
|
||
|
|
}
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// get min and max values from point list
|
||
|
|
/// @param points list of points
|
||
|
|
///
|
||
|
|
template <class dt>
|
||
|
|
AIS_EXPORT std::pair<dt, dt> getMinMax(const std::vector<dt> &points)
|
||
|
|
{
|
||
|
|
const auto [minp, maxp] = std::minmax_element(std::execution::par_unseq, points.begin(), points.end());
|
||
|
|
|
||
|
|
return std::pair<dt, dt>(*minp, *maxp);
|
||
|
|
}
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// get min and max values from point matrix
|
||
|
|
/// @param matrix matrix of point values
|
||
|
|
///
|
||
|
|
template <class dt = double>
|
||
|
|
AIS_EXPORT std::pair<dt, dt> getMinMax(const ais::Matrix<dt> &matrix)
|
||
|
|
{
|
||
|
|
const auto [minp, maxp] = std::minmax_element(std::execution::par_unseq, matrix.begin(), matrix.end());
|
||
|
|
|
||
|
|
return std::pair<dt, dt>(*minp, *maxp);
|
||
|
|
}
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// get average values from list
|
||
|
|
/// @param matrix matrix of point values
|
||
|
|
///
|
||
|
|
template <typename DC>
|
||
|
|
AIS_EXPORT double getAverage(const DC &list)
|
||
|
|
{
|
||
|
|
double ret = INFINITY;
|
||
|
|
double sum = 0.0;
|
||
|
|
size_t count = 0;
|
||
|
|
|
||
|
|
for (auto &value : list)
|
||
|
|
{
|
||
|
|
if (!std::isnan(value) && !std::isinf(value))
|
||
|
|
{
|
||
|
|
count++;
|
||
|
|
sum += value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = count == 0 ? INFINITY : sum / count;
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// get inverse distance weighting average values from list
|
||
|
|
/// @param matrix matrix of point values
|
||
|
|
///
|
||
|
|
template <typename DC>
|
||
|
|
AIS_EXPORT double get_idw(const DC &list)
|
||
|
|
{
|
||
|
|
double ret = INFINITY;
|
||
|
|
double sum = 0.0;
|
||
|
|
double denominator = 0.0;
|
||
|
|
|
||
|
|
std::pair<double, double> nearestWeight{1e+10, 0};
|
||
|
|
for (auto &dv_pair : list)
|
||
|
|
{
|
||
|
|
if (nearestWeight.first > dv_pair.first)
|
||
|
|
nearestWeight = dv_pair;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (auto &dv_pair : list)
|
||
|
|
{
|
||
|
|
auto [distance, value] = dv_pair;
|
||
|
|
if (std::abs(distance) < 1e-6)
|
||
|
|
return value;
|
||
|
|
|
||
|
|
double weight = 1 / (distance * distance);
|
||
|
|
sum += weight * value;
|
||
|
|
denominator += weight;
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = std::abs(denominator) < 1e-6 ? INFINITY : sum / denominator;
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// get mean values from list
|
||
|
|
/// @param matrix matrix of point values
|
||
|
|
///
|
||
|
|
template <typename DC>
|
||
|
|
AIS_EXPORT double get_mean(const DC &list, size_t top = 0)
|
||
|
|
{
|
||
|
|
double ret = INFINITY;
|
||
|
|
double sum = 0.0;
|
||
|
|
double denominator = 0.0;
|
||
|
|
|
||
|
|
std::pair<double, double> nearestWeight{1e+10, 0};
|
||
|
|
for (auto &dv_pair : list)
|
||
|
|
{
|
||
|
|
if (nearestWeight.first > dv_pair.first)
|
||
|
|
nearestWeight = dv_pair;
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t count = 0;
|
||
|
|
for (auto &dv_pair : list)
|
||
|
|
{
|
||
|
|
if (top > 0 && count > top)
|
||
|
|
break;
|
||
|
|
|
||
|
|
auto [distance, value] = dv_pair;
|
||
|
|
if (std::abs(distance) < 1e-6)
|
||
|
|
return value;
|
||
|
|
|
||
|
|
if (std::isnan(value) || std::isinf(value))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
sum += value;
|
||
|
|
denominator += 1;
|
||
|
|
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = std::abs(denominator) < 1e-6 ? INFINITY : sum / denominator;
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// get mean values from list
|
||
|
|
/// @param matrix matrix of point values
|
||
|
|
///
|
||
|
|
template <typename DC>
|
||
|
|
AIS_EXPORT double get_weight_mean(const DC &list, size_t top = 0)
|
||
|
|
{
|
||
|
|
double ret = INFINITY;
|
||
|
|
double sum = 0.0;
|
||
|
|
double denominator = 0.0;
|
||
|
|
|
||
|
|
size_t count = 0;
|
||
|
|
for (auto &dv_pair : list)
|
||
|
|
{
|
||
|
|
if (top > 0 && count > top)
|
||
|
|
break;
|
||
|
|
|
||
|
|
auto [weight, value] = dv_pair;
|
||
|
|
|
||
|
|
if (std::isnan(value) || std::isinf(value))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
sum += value * weight;
|
||
|
|
denominator += weight;
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = std::abs(denominator) < 1e-6 ? INFINITY : sum / denominator;
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// generate axis values from start to end, point count = grid count + 1
|
||
|
|
///
|
||
|
|
AIS_EXPORT std::vector<double> generateAxisPoints(double start, double end, size_t pointCount);
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// filter sample points which include in the target area points, out of the range will be erased
|
||
|
|
///
|
||
|
|
AIS_EXPORT std::vector<ais::PointXYZ> filter_points(const std::vector<ais::Point> &areaPoints, const std::vector<ais::PointXYZ> &samplePoints);
|
||
|
|
|
||
|
|
//================================================================
|
||
|
|
//
|
||
|
|
/// filter and copy sample points which include in the target area points
|
||
|
|
///
|
||
|
|
AIS_EXPORT void filter_copy_points(const std::pair<double, double> &minPos, const std::pair<double, double> &maxPos,
|
||
|
|
const std::vector<ais::PointXYZ> &samplePoints,
|
||
|
|
std::vector<ais::PointXYZ> &outputPoints);
|
||
|
|
}
|