Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
TPiecewiseLinear1D.h
Go to the documentation of this file.
1#pragma once
2
3#include "Math/TVector2.h"
4
5#include <Common/assertion.h>
6
7#include <vector>
8#include <algorithm>
9#include <functional>
10#include <iterator>
11
12namespace ph::math
13{
14
15// A class defining a piecewise linear function, where points (x, y) are
16// connected by straight lines; function values between two nearby points
17// are evaluated by linearly interpolating their y-coordinates. Function
18// values beyond the domain of specified x coordinates are evaluated with
19// its nearest point's y value. If the function have got no points,
20// evaluation results in zero no matter the inputs.
21//
22// Notice that update() must be called before feeding this function into
23// any other methods.
24template<typename T>
26{
27public:
28 // Evaluates function value at <x>.
29 T evaluate(T x) const;
30
31 // Evaluates function value at <x> by linearly interpolating two points.
32 // Note that the two points may not be neighbors.
33 T evaluate(T x, std::size_t p0Index, std::size_t p1Index) const;
34
35 // TODO: eliminate the need for update
36 void update();
37
38 void addPoint(const TVector2<T>& point);
39 void addPoints(const TPiecewiseLinear1D& points);
40 TPiecewiseLinear1D getMirrored(T pivotX) const;
41 std::size_t numPoints() const;
42 TVector2<T> getPoint(std::size_t pointIndex) const;
43 std::string toString() const;
44
45private:
46 std::vector<TVector2<T>> m_points;
47
48 static bool pointDomainComparator(const TVector2<T>& pA, const TVector2<T>& pB);
49};
50
51// implementations:
52
53template<typename T>
54inline T TPiecewiseLinear1D<T>::evaluate(const T x) const
55{
56 if(m_points.empty())
57 {
58 return 0;
59 }
60
61 // handling out-of-domain situation
62 // (this also handles if there's only 1 unique point)
63 if (x <= m_points.front().x()) return m_points.front().y();
64 else if(x >= m_points.back().x()) return m_points.back().y();
65
66 const auto& result = std::lower_bound(m_points.begin(), m_points.end(), TVector2<T>(x),
67 &TPiecewiseLinear1D::pointDomainComparator);
68 PH_ASSERT(result != m_points.begin() && result != m_points.end());
69 const std::size_t i1 = result - m_points.begin();
70 const std::size_t i0 = i1 - 1;
71
72 return evaluate(x, i0, i1);
73}
74
75template<typename T>
77 const std::size_t p0Index,
78 const std::size_t p1Index) const
79{
80 PH_ASSERT(p0Index < m_points.size() && p1Index < m_points.size());
81
82 const TVector2<T>& p0 = m_points[p0Index];
83 const TVector2<T>& p1 = m_points[p1Index];
84 return p0.x() != p1.x() ? (x - p0.x()) / (p1.x() - p0.x()) * (p1.y() - p0.y()) + p0.y()
85 : (p0.y() + p1.y()) / 2;
86}
87
88template<typename T>
90{
91 std::stable_sort(m_points.begin(), m_points.end(),
92 &TPiecewiseLinear1D::pointDomainComparator);
93}
94
95template<typename T>
97{
98 m_points.push_back(point);
99}
100
101template<typename T>
103{
104 m_points.insert(std::end(m_points),
105 std::begin(points.m_points), std::end(points.m_points));
106}
107
108template<typename T>
110{
111 TPiecewiseLinear1D mirrored;
112 for(const auto& point : m_points)
113 {
114 mirrored.addPoint({static_cast<T>(2) * pivotX - point.x(), point.y()});
115 }
116 mirrored.update();
117 return mirrored;
118}
119
120template<typename T>
121inline std::size_t TPiecewiseLinear1D<T>::numPoints() const
122{
123 return m_points.size();
124}
125
126template<typename T>
127inline TVector2<T> TPiecewiseLinear1D<T>::getPoint(const std::size_t pointIndex) const
128{
129 return m_points[pointIndex];
130}
131
132template<typename T>
133inline std::string TPiecewiseLinear1D<T>::toString() const
134{
135 std::string result("piecewise linear function, composed of following points: ");
136 for(const auto& point : m_points)
137 {
138 result += point.toString();
139 }
140 return result;
141}
142
143template<typename T>
145 const TVector2<T>& pB)
146{
147 return pA.x() < pB.x();
148}
149
150}// end namespace ph::math
Definition TPiecewiseLinear1D.h:26
TPiecewiseLinear1D getMirrored(T pivotX) const
Definition TPiecewiseLinear1D.h:109
TVector2< T > getPoint(std::size_t pointIndex) const
Definition TPiecewiseLinear1D.h:127
std::size_t numPoints() const
Definition TPiecewiseLinear1D.h:121
T evaluate(T x) const
Definition TPiecewiseLinear1D.h:54
void addPoint(const TVector2< T > &point)
Definition TPiecewiseLinear1D.h:96
std::string toString() const
Definition TPiecewiseLinear1D.h:133
void update()
Definition TPiecewiseLinear1D.h:89
void addPoints(const TPiecewiseLinear1D &points)
Definition TPiecewiseLinear1D.h:102
Represents a 2-D vector.
Definition TVector2.h:19
T & x()
Definition TVector2.ipp:38
T & y()
Definition TVector2.ipp:44
Math functions and utilities.
Definition TransformInfo.h:10