codac 2.0.0
Loading...
Searching...
No Matches
codac2_Approx.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include <limits>
13#include "codac2_matrices.h"
14#include "codac2_Vector.h"
16#include "codac2_Row.h"
17#include "codac2_IntervalRow.h"
18#include "codac2_Matrix.h"
20#include "codac2_Polygon.h"
21
22namespace codac2
23{
24 #define DEFAULT_EPS std::numeric_limits<double>::epsilon()*10
25
26 template<typename T>
27 class Approx
28 {
29 public:
30
31 explicit Approx(const T& x, double eps = DEFAULT_EPS)
32 : _x(x), _eps(eps)
33 { }
34
35 template<typename OtherDerived>
36 explicit Approx(const Eigen::MatrixBase<OtherDerived>& x, double eps = DEFAULT_EPS)
37 : _x(x.eval()), _eps(eps)
38 { }
39
40 friend bool operator==(const T& x1, const Approx<T>& x2)
41 {
42 if constexpr(std::is_same_v<T,double>)
43 return std::fabs(x1-x2._x) < x2._eps;
44
45 else if(x1.size() != x2._x.size())
46 return false;
47
48 else if(x1 == x2._x)
49 return true;
50
51 else if constexpr(std::is_same_v<T,Interval>)
52 {
53 if((x1.is_empty() && !x2._x.is_empty()) || (!x1.is_empty() && x2._x.is_empty()))
54 return false;
55 return (x1.lb() == x2._x.lb() || x1.lb() == Approx<double>(x2._x.lb(),x2._eps))
56 && (x1.ub() == x2._x.ub() || x1.ub() == Approx<double>(x2._x.ub(),x2._eps));
57 }
58
59 else if constexpr(std::is_same_v<T,Vector>
60 || std::is_same_v<T,IntervalVector>
61 || std::is_same_v<T,Row>
62 || std::is_same_v<T,IntervalRow>
63 || std::is_same_v<T,Matrix>
64 || std::is_same_v<T,IntervalMatrix>)
65 {
66 for(Index i = 0 ; i < x1.rows() ; i++)
67 for(Index j = 0 ; j < x1.cols() ; j++)
68 if(!(x1(i,j) == Approx<typename T::Scalar>(x2._x(i,j), x2._eps)))
69 return false;
70 return true;
71 }
72
73 else
74 {
75 assert_release_constexpr(false && "Approx::operator== unhandled case");
76 return false;
77 }
78 }
79
80 friend std::ostream& operator<<(std::ostream& os, const Approx<T>& x)
81 {
82 os << "Approx(" << x._x << ")";
83 return os;
84 }
85
86 private:
87
88 const T _x;
89 const double _eps;
90 };
91
92 template<>
93 class Approx<Segment>
94 {
95 public:
96
97 explicit Approx(const Segment& x, double eps = DEFAULT_EPS)
98 : _x(x), _eps(eps)
99 { }
100
101 friend bool operator==(const Segment& p1, const Approx<Segment>& p2)
102 {
103 return (Approx<IntervalVector>(p1[0], p2._eps) == p2._x[0] && Approx<IntervalVector>(p1[1], p2._eps) == p2._x[1])
104 || (Approx<IntervalVector>(p1[1], p2._eps) == p2._x[0] && Approx<IntervalVector>(p1[0], p2._eps) == p2._x[1]);
105 }
106
107 friend std::ostream& operator<<(std::ostream& os, const Approx<Segment>& x)
108 {
109 os << "Approx(" << x._x << ")";
110 return os;
111 }
112
113 private:
114
115 const Segment _x;
116 const double _eps;
117 };
118
119 template<>
120 class Approx<Polygon>
121 {
122 public:
123
124 explicit Approx(const Polygon& x, double eps = DEFAULT_EPS)
125 : _x(x), _eps(eps)
126 { }
127
128 friend bool operator==(const Polygon& p1, const Approx<Polygon>& p2)
129 {
130 size_t n = p1.edges().size();
131 if(p2._x.edges().size() != n)
132 return false;
133
134 size_t i; // looking for same reference of first value
135 for(i = 0 ; i < n ; i++)
136 if(Approx<Segment>(p1.edges()[0], p2._eps) == p2._x.edges()[i])
137 break;
138
139 int way = 1;
140 if(n > 1)
141 way = (Approx<Segment>(p1.edges()[1], p2._eps) == p2._x.edges()[(i+1)%n]) ? 1 : -1;
142 assert(way == 1 || (way == -1 && p1.edges()[1] == p2._x.edges()[(i-1+2*n)%n]));
143
144 for(size_t j = 0 ; j < n ; j++)
145 if(Approx<Segment>(p1.edges()[j], p2._eps) != p2._x.edges()[(i+way*j+2*n)%n])
146 return false;
147
148 return true;
149 }
150
151 friend std::ostream& operator<<(std::ostream& os, const Approx<Polygon>& x)
152 {
153 os << "Approx(" << x._x << ")";
154 return os;
155 }
156
157 private:
158
159 const Polygon _x;
160 const double _eps;
161 };
162
163 template<typename T>
164 class Approx<std::pair<T,T>>
165 {
166 public:
167
168 explicit Approx(const std::pair<T,T>& x, double eps = DEFAULT_EPS)
169 : _x(x), _eps(eps)
170 { }
171
172 friend bool operator==(const std::pair<T,T>& p1, const Approx<std::pair<T,T>>& p2)
173 {
174 return Approx<T>(p2._x.first,p2._eps) == p1.first && Approx<T>(p2._x.second,p2._eps) == p1.second;
175 }
176
177 friend std::ostream& operator<<(std::ostream& os, const Approx<std::pair<T,T>>& x)
178 {
179 os << "Approx(" << x._x.first << "," << x._x.second << ")";
180 return os;
181 }
182
183 private:
184
185 const std::pair<T,T> _x;
186 const double _eps;
187 };
188
189 Approx(const Polygon&, double) ->
190 Approx<Polygon>;
191}
Represents a polygon (convex or non-convex) defined by its vertices enclosed in IntervalVectors.
Definition codac2_Polygon.h:29
Represents a geometric segment defined by two points enclosed in IntervalVectors.
Definition codac2_Segment.h:28
Definition codac2_OctaSym.h:21