5#ifndef QWT_GRID_DATA_HPP
6#define QWT_GRID_DATA_HPP
90 typename XContainer = std::vector< T >,
91 typename YContainer = std::vector< T >,
92 typename DataColumn = std::vector< T >,
93 typename DataContainer = std::vector< DataColumn > >
102 using size_type =
typename DataColumn::size_type;
119 BilinearInterpolation,
129 : m_mode(NearestNeighbour), m_xMin(0.0), m_xMax(0.0), m_yMin(0.0), m_yMax(0.0), m_dataMax(0.0), m_dataMin(0.0)
153 m_xMin =
xAxis.front();
154 m_xMax =
xAxis.back();
155 m_yMin =
yAxis.front();
156 m_yMax =
yAxis.back();
193 m_xMin =
xAxis.front();
194 m_xMax =
xAxis.back();
195 m_yMin =
yAxis.front();
196 m_yMax =
yAxis.back();
223 return value(xy.first, xy.second);
237 case NearestNeighbour:
239 case BilinearInterpolation:
241 case BicubicInterpolation:
244 throw std::runtime_error(
"Unknown resampling mode.");
278 return m_xAxis.size();
287 return m_yAxis.size();
306 return m_xAxis.at(ix);
316 return m_yAxis.at(iy);
326 return m_data.at(ix).at(iy);
374 if (m_xAxis.empty() || m_yAxis.empty() || m_data.empty()) {
377 if (m_xAxis.size() != m_data.size()) {
380 for (
const auto& column : m_data) {
381 if (column.size() != m_yAxis.size()) {
385 if (!std::is_sorted(m_xAxis.begin(), m_xAxis.end())) {
388 if (!std::is_sorted(m_yAxis.begin(), m_yAxis.end())) {
401 if (m_xAxis.empty() || m_yAxis.empty() || m_data.empty()) {
402 throw std::invalid_argument(
"Axes or data cannot be empty.");
404 if (m_data.size() != m_xAxis.size()) {
405 throw std::invalid_argument(
"Number of columns in data must match x-axis size.");
407 for (
const auto& column : m_data) {
408 if (column.size() != m_yAxis.size()) {
409 throw std::invalid_argument(
"Number of rows in data must match y-axis size.");
412 if (!std::is_sorted(m_xAxis.begin(), m_xAxis.end())) {
413 std::sort(m_xAxis.begin(), m_xAxis.end());
415 if (!std::is_sorted(m_yAxis.begin(), m_yAxis.end())) {
416 std::sort(m_yAxis.begin(), m_yAxis.end());
456 template<
typename Container >
459 auto it = std::lower_bound(arr.begin(), arr.end(), val);
460 if (it == arr.begin())
463 return arr.size() - 1;
464 size_type idx = std::distance(arr.begin(), it);
465 return (std::abs(arr[ idx ] - val) < std::abs(arr[ idx - 1 ] - val)) ? idx : idx - 1;
477 template<
typename Container >
480 auto it = std::lower_bound(arr.begin(), arr.end(), val);
481 if (it == arr.begin())
483 return std::distance(arr.begin(), it) - 1;
486 template<
typename V >
487 static const V& clamp(
const V&
value,
const V& lo,
const V& hi)
502 m_dataMin = std::numeric_limits< T >::max();
503 m_dataMax = std::numeric_limits< T >::lowest();
504 for (
const auto& column : m_data) {
505 for (
const auto& val : column) {
506 m_dataMin = std::min(m_dataMin, val);
507 m_dataMax = std::max(m_dataMax, val);
525 return m_data[ xIdx ][ yIdx ];
540 size_type x1Idx = x0Idx + 1;
542 size_type y1Idx = y0Idx + 1;
544 T x0 = m_xAxis[ x0Idx ], x1 = m_xAxis[ x1Idx ];
545 T y0 = m_yAxis[ y0Idx ], y1 = m_yAxis[ y1Idx ];
547 T f00 = m_data[ x0Idx ][ y0Idx ];
548 T f10 = m_data[ x1Idx ][ y0Idx ];
549 T f01 = m_data[ x0Idx ][ y1Idx ];
550 T f11 = m_data[ x1Idx ][ y1Idx ];
552 T dx = (x - x0) / (x1 - x0);
553 T dy = (y - y0) / (y1 - y0);
555 return (1 - dx) * (1 - dy) * f00 + dx * (1 - dy) * f10 + (1 - dx) * dy * f01 + dx * dy * f11;
574 auto xIt = std::lower_bound(m_xAxis.begin(), m_xAxis.end(), x);
575 size_type x0, x1, x2, x3;
578 if (xIt == m_xAxis.begin()) {
584 }
else if (xIt == m_xAxis.end()) {
585 x0 = m_xAxis.size() - 3;
586 x1 = m_xAxis.size() - 2;
587 x2 = m_xAxis.size() - 1;
588 x3 = m_xAxis.size() - 1;
591 x0 = xIt - 2 - m_xAxis.begin();
594 x1 = xIt - 1 - m_xAxis.begin();
595 x2 = xIt - m_xAxis.begin();
596 x3 = xIt + 1 - m_xAxis.begin();
597 if (x3 >= m_xAxis.size())
598 x3 = m_xAxis.size() - 1;
599 xWeight =
static_cast< T
>(x - m_xAxis[ x1 ]) / (m_xAxis[ x2 ] - m_xAxis[ x1 ]);
603 auto yIt = std::lower_bound(m_yAxis.begin(), m_yAxis.end(), y);
604 size_type y0, y1, y2, y3;
607 if (yIt == m_yAxis.begin()) {
613 }
else if (yIt == m_yAxis.end()) {
614 y0 = m_yAxis.size() - 3;
615 y1 = m_yAxis.size() - 2;
616 y2 = m_yAxis.size() - 1;
617 y3 = m_yAxis.size() - 1;
620 y0 = yIt - 2 - m_yAxis.begin();
623 y1 = yIt - 1 - m_yAxis.begin();
624 y2 = yIt - m_yAxis.begin();
625 y3 = yIt + 1 - m_yAxis.begin();
626 if (y3 >= m_yAxis.size())
627 y3 = m_yAxis.size() - 1;
628 yWeight =
static_cast< T
>(y - m_yAxis[ y1 ]) / (m_yAxis[ y2 ] - m_yAxis[ y1 ]);
632 auto h00 = [](T t) {
return (1 + 2 * t) * (1 - t) * (1 - t); };
633 auto h10 = [](T t) {
return t * (1 - t) * (1 - t); };
634 auto h01 = [](T t) {
return t * t * (3 - 2 * t); };
635 auto h11 = [](T t) {
return t * t * (t - 1); };
639 for (
int i = 0; i < 4; ++i) {
642 v[ 0 ] = m_data[ x0 ][ y0 + i ];
643 v[ 1 ] = m_data[ x1 ][ y0 + i ];
644 v[ 2 ] = m_data[ x2 ][ y0 + i ];
645 v[ 3 ] = m_data[ x3 ][ y0 + i ];
648 values[ 0 ][ i ] = h00(xWeight) * v[ 1 ]
649 + h10(xWeight) * (m_xAxis[ x2 ] - m_xAxis[ x1 ])
650 * ((v[ 2 ] - v[ 1 ]) / (m_xAxis[ x2 ] - m_xAxis[ x1 ])
651 + (v[ 2 ] - v[ 1 ] - (v[ 1 ] - v[ 0 ]) / (m_xAxis[ x1 ] - m_xAxis[ x0 ]))
652 / (m_xAxis[ x2 ] - m_xAxis[ x0 ]) * (m_xAxis[ x2 ] - m_xAxis[ x1 ]))
653 + h01(xWeight) * v[ 2 ]
654 + h11(xWeight) * (m_xAxis[ x2 ] - m_xAxis[ x1 ])
655 * ((v[ 2 ] - v[ 1 ]) / (m_xAxis[ x2 ] - m_xAxis[ x1 ])
656 + (v[ 3 ] - v[ 2 ] - (v[ 2 ] - v[ 1 ]) / (m_xAxis[ x2 ] - m_xAxis[ x1 ]))
657 / (m_xAxis[ x3 ] - m_xAxis[ x1 ]) * (m_xAxis[ x2 ] - m_xAxis[ x1 ]));
662 v[ 0 ] = values[ 0 ][ 0 ];
663 v[ 1 ] = values[ 0 ][ 1 ];
664 v[ 2 ] = values[ 0 ][ 2 ];
665 v[ 3 ] = values[ 0 ][ 3 ];
667 return h00(yWeight) * v[ 1 ]
668 + h10(yWeight) * (m_yAxis[ y2 ] - m_yAxis[ y1 ])
669 * ((v[ 2 ] - v[ 1 ]) / (m_yAxis[ y2 ] - m_yAxis[ y1 ])
670 + (v[ 2 ] - v[ 1 ] - (v[ 1 ] - v[ 0 ]) / (m_yAxis[ y1 ] - m_yAxis[ y0 ]))
671 / (m_yAxis[ y2 ] - m_yAxis[ y0 ]) * (m_yAxis[ y2 ] - m_yAxis[ y1 ]))
672 + h01(yWeight) * v[ 2 ]
673 + h11(yWeight) * (m_yAxis[ y2 ] - m_yAxis[ y1 ])
674 * ((v[ 2 ] - v[ 1 ]) / (m_yAxis[ y2 ] - m_yAxis[ y1 ])
675 + (v[ 3 ] - v[ 2 ] - (v[ 2 ] - v[ 1 ]) / (m_yAxis[ y2 ] - m_yAxis[ y1 ]))
676 / (m_yAxis[ y3 ] - m_yAxis[ y1 ]) * (m_yAxis[ y2 ] - m_yAxis[ y1 ]));
700 T m_xMin, m_xMax, m_yMin, m_yMax, m_dataMin, m_dataMax;
A generic container class for storing 2D grid data and providing resampling methods.
Definition qwt_grid_data.hpp:95
T value(T x, T y) const
Query value at (x, y).
Definition qwt_grid_data.hpp:234
void setValue(const x_container_type &xAxis, const y_container_type &yAxis, const data_container_type &data)
Set new x-axis, y-axis, and data matrix.
Definition qwt_grid_data.hpp:186
size_type xSize() const
x的尺寸
Definition qwt_grid_data.hpp:276
std::pair< size_type, size_type > valueSize() const
value矩阵的尺寸
Definition qwt_grid_data.hpp:294
T atY(size_type iy) const
y值对应的内容
Definition qwt_grid_data.hpp:314
size_type ySize() const
y的尺寸
Definition qwt_grid_data.hpp:285
ResampleMode resampleMode() const
Get the current resampling mode.
Definition qwt_grid_data.hpp:267
QwtGridData()
Default constructor.
Definition qwt_grid_data.hpp:128
XContainer x_container_type
Type of the x-axis container / x 轴容器的类型
Definition qwt_grid_data.hpp:98
void validate()
Validate the data.
Definition qwt_grid_data.hpp:399
T value_type
Type of the stored values / 存储值的类型
Definition qwt_grid_data.hpp:97
void findValueRange()
Get the minimum & maximum value in the data matrix.
Definition qwt_grid_data.hpp:500
T operator[](const std::pair< T, T > &xy) const
operator []
Definition qwt_grid_data.hpp:221
const y_container_type & yAxis() const
Get the y-axis values.
Definition qwt_grid_data.hpp:348
void setResampleMode(ResampleMode mode)
Set the resampling mode.
Definition qwt_grid_data.hpp:255
T bilinearInterpolation(T x, T y) const
Bilinear interpolation.
Definition qwt_grid_data.hpp:537
T atValue(size_type ix, size_type iy) const
value值对应的内容
Definition qwt_grid_data.hpp:324
T nearestNeighbour(T x, T y) const
Nearest neighbor interpolation.
Definition qwt_grid_data.hpp:521
YContainer y_container_type
Type of the y-axis container / y 轴容器的类型
Definition qwt_grid_data.hpp:99
static size_type findClosestIndex(const Container &arr, T val)
Find the closest index in a sorted array.
Definition qwt_grid_data.hpp:457
const data_container_type & data() const
Get the data matrix.
Definition qwt_grid_data.hpp:360
const x_container_type & xAxis() const
Get the x-axis values.
Definition qwt_grid_data.hpp:336
DataColumn data_column_type
Type of a single column in the data matrix / 数据矩阵中单列的类型
Definition qwt_grid_data.hpp:100
T operator()(T x, T y) const
Operator to query value at (x, y).
Definition qwt_grid_data.hpp:208
QwtGridData(const x_container_type &xAxis, const y_container_type &yAxis, const data_container_type &data, ResampleMode mode=NearestNeighbour)
Constructor with initial data.
Definition qwt_grid_data.hpp:145
bool valid() const
Check if the object is valid.
Definition qwt_grid_data.hpp:372
static size_type findLowerIndex(const Container &arr, T val)
Find the lower bound index in a sorted array.
Definition qwt_grid_data.hpp:478
ResampleMode
Enumeration for resampling methods.
Definition qwt_grid_data.hpp:117
T atX(size_type ix) const
x 值对应的内容
Definition qwt_grid_data.hpp:304
DataContainer data_container_type
Type of the data matrix / 数据矩阵的类型
Definition qwt_grid_data.hpp:101
T bicubicInterpolation(T x, T y) const
Perform bicubic interpolation.
Definition qwt_grid_data.hpp:571