cgv
Loading...
Searching...
No Matches
plane.h
1#pragma once
2#include <cgv/math/vec.h>
3#include <cgv/math/point_operations.h>
4#include <cgv/math/eig.h>
5#include <cgv/math/ray.h>
6#include <algorithm>
7
8namespace cgv{
9 namespace math{
10
18template <typename T>
19T plane_val(const vec<T>& plane,const vec<T>& x)
20{
21
22 assert(plane.size()-1 == x.size());
23
24 T val=0;
25 for(unsigned i = 0;i< x.size(); i++)
26 val += plane(i)*x(i);
27
28 return val+plane(plane.size()-1);
29}
30
32template <typename T>
33vec<T> plane_val(const vec<T>& plane,const mat<T>& xs)
34{
35
36 assert(plane.size()-1 == xs.nrows());
37
38 vec<T> vals(xs.ncols());
39 for(unsigned i = 0;i< xs.ncols(); i++)
40 vals(i) = plane_val(plane,xs.col(i));
41
42
43 return vals;
44}
45
46
47//construct implicit plane from 3 points
48template <typename T>
49vec<T> plane_fit(const vec<T>& p1,const vec<T>& p2,const vec<T>& p3)
50{
51 vec<T> plane(4);
52 double l_nml;
53
54 vec<T> nml = cross(normalize(p2-p1),normalize(p3-p1));
55 l_nml = length(nml);
56 assert(l_nml != 0);
57
58 nml/=l_nml;
59 plane.set(nml(0),nml(1),nml(2),-dot(p1,nml));
60 return plane;
61}
62
63//fit implicit plane into multiple points (total least squares)
64template <typename T>
65vec<T> tls_plane_fit(const mat<T>& points)
66{
67 vec<T> plane(4);
68 mat<T> covmat,v;
69 diag_mat<T> d;
70 vec<T> mean;
71
72 covmat_and_mean(points,covmat, mean);
73 eig_sym(covmat,v,d);
74
75// T l_nml;
76
77 vec<T> nml = normalize(v.col(2));
78
79 plane.set(nml(0),nml(1),nml(2),-dot(mean,nml));
80 return plane;
81}
82
83
84
85
92template <typename T>
93vec<T> ransac_plane_fit(const mat<T>& points,const T p_out=0.8, const T d_max=0.001, const T p_surety = 0.99, bool msac=true)
94{
95 assert(points.nrows == 3);
96 vec<T> plane(4);
97
98 vec<unsigned int> ind;
99 vec<T> p1,p2,p3,dists(points.ncols());
101 unsigned n = points.ncols;
102 unsigned max_iter = num_ransac_iterations(3,p_out,psurety);
103 unsigned num_inlier = (unsigned)::ceil((1-p_out)*points.ncols());
104
105 T error = std::numeric_limits<T>::max();
106
107 for(unsigned i = 0; i < max_iter; i++)
108 {
109 //random sample
110 do
111 {
112 rg.uniform_nchoosek(n,3,ind);
113 p1 = points.col(ind(0));
114 p2 = points.col(ind(1));
115 p3 = points.col(ind(2));
116 }
117 while(fabs(length(cross(q2-q1,q3-q1)))<0.001);
118
119 //fit
120 vec<T> pl = plane_fit(p1,p2,p3);
121
122 //consensus
123 int n_inlier=0;
124 T e = 0;
125
126 for(unsigned i = 0; i < points.ncols(); i++)
127 {
128 dists(i) = std::abs(plane_val(pl,points.col(i)));
129 if(dists(i) < d_max)
130 {
131 n_inlier++;
132 if(msac)
133 e += dists(i);
134 }
135 else
136 {
137 e += dmax;
138 }
139 }
140
141 //local reoptimize
142 if(loransac && n_inlier > 3)
143 {
144 mat<T> inliers(3,n_inlier);
145 int j=0;
146 n_inlier=0;
147 for(unsigned i = 0; i < points.ncols(); i++)
148 {
149 if(dists(i) < d_max)
150 {
151 n_inlier++;
152 inliers.set_col(j,points.col(i));
153 j++;
154 }
155 }
156 pl = plane_fit(inliers)
157
158 //recompute error
159 for(unsigned i = 0; i < points.ncols(); i++)
160 {
161 dists(i) = std::abs(plane_val(pl,points.col(i)));
162 if(dists(i) < d_max)
163 {
164
165 if(msac)
166 e += dists(i);
167 }
168 else
169 {
170 e += dmax;
171 }
172 }
173 }
174
175 //remember best plane
176 if(error > e)
177 {
178 error = e;
179 plane = pl;
180 }
181
182 if(n_inlier >= num_inlier)
183 {
184 p_out = (T)1-(T)n_inlier/(T)points.ncols();
185 max_iter = num_ransac_iterations(3,p_out,psurety);
186 }
187 }
188 return plane;
189}
190
200template <typename T>
201int ray_plane_intersection_nd(const ray<T>& ray, const vec<T>& plane, T& out_t) {
202 out_t = T(0);
203 T s = T(0);
204 for(unsigned i = 0; i < ray.origin.dim(); i++) {
205 t += plane[i] * ray.origin[i];
206 s += plane[i] * ray.direction[i];
207 }
208 if(s == 0)
209 return 0;
210
211 t += plane[ray.origin.dim()];
212 t /= -s;
213 return 1;
214}
215
216
217
218
219
220
221 }
222}
223
the cgv namespace
Definition print.h:11
High quality random number generator, which is a little bit slower than typical random number generat...
Definition random.h:28
void uniform_nchoosek(unsigned n, unsigned k, vec< unsigned > &indices)
creates a vector of k unique indices drawn from 0 to n-1
Definition random.h:507