codac 1.5.6
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 return (x1.lb() == x2._x.lb() || x1.lb() == Approx<double>(x2._x.lb(),x2._eps))
54 && (x1.ub() == x2._x.ub() || x1.ub() == Approx<double>(x2._x.ub(),x2._eps));
55 }
56
57 else if constexpr(std::is_same_v<T,Vector>
58 || std::is_same_v<T,IntervalVector>
59 || std::is_same_v<T,Row>
60 || std::is_same_v<T,IntervalRow>
61 || std::is_same_v<T,Matrix>
62 || std::is_same_v<T,IntervalMatrix>)
63 {
64 for(Index i = 0 ; i < x1.rows() ; i++)
65 for(Index j = 0 ; j < x1.cols() ; j++)
66 if(!(x1(i,j) == Approx<typename T::Scalar>(x2._x(i,j), x2._eps)))
67 return false;
68 return true;
69 }
70
71 else
72 {
73 assert_release(false && "Approx::operator== unhandled case");
74 return false;
75 }
76 }
77
78 friend std::ostream& operator<<(std::ostream& os, const Approx<T>& x)
79 {
80 os << "Approx(" << x._x << ")";
81 return os;
82 }
83
84 private:
85
86 const T _x;
87 const double _eps;
88 };
89
90 template<>
91 class Approx<Segment>
92 {
93 public:
94
95 explicit Approx(const Segment& x, double eps = DEFAULT_EPS)
96 : _x(x), _eps(eps)
97 { }
98
99 friend bool operator==(const Segment& p1, const Approx<Segment>& p2)
100 {
101 return (Approx<IntervalVector>(p1[0], p2._eps) == p2._x[0] && Approx<IntervalVector>(p1[1], p2._eps) == p2._x[1])
102 || (Approx<IntervalVector>(p1[1], p2._eps) == p2._x[0] && Approx<IntervalVector>(p1[0], p2._eps) == p2._x[1]);
103 }
104
105 friend std::ostream& operator<<(std::ostream& os, const Approx<Segment>& x)
106 {
107 os << "Approx(" << x._x << ")";
108 return os;
109 }
110
111 private:
112
113 const Segment _x;
114 const double _eps;
115 };
116
117 template<>
118 class Approx<Polygon>
119 {
120 public:
121
122 explicit Approx(const Polygon& x, double eps = DEFAULT_EPS)
123 : _x(x), _eps(eps)
124 { }
125
126 friend bool operator==(const Polygon& p1, const Approx<Polygon>& p2)
127 {
128 size_t n = p1.edges().size();
129 if(p2._x.edges().size() != n)
130 return false;
131
132 size_t i; // looking for same reference of first value
133 for(i = 0 ; i < n ; i++)
134 if(Approx<Segment>(p1.edges()[0], p2._eps) == p2._x.edges()[i])
135 break;
136
137 int way = 1;
138 if(n > 1)
139 way = (Approx<Segment>(p1.edges()[1], p2._eps) == p2._x.edges()[(i+1)%n]) ? 1 : -1;
140 assert(way == 1 || (way == -1 && p1.edges()[1] == p2._x.edges()[(i-1+2*n)%n]));
141
142 for(size_t j = 0 ; j < n ; j++)
143 if(Approx<Segment>(p1.edges()[j], p2._eps) != p2._x.edges()[(i+way*j+2*n)%n])
144 return false;
145
146 return true;
147 }
148
149 friend std::ostream& operator<<(std::ostream& os, const Approx<Polygon>& x)
150 {
151 os << "Approx(" << x._x << ")";
152 return os;
153 }
154
155 private:
156
157 const Polygon _x;
158 const double _eps;
159 };
160
161 Approx(const Polygon&, double) ->
162 Approx<Polygon>;
163}
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:27