2 #ifndef vgl_homg_operators_2d_hxx_ 3 #define vgl_homg_operators_2d_hxx_ 13 # include <vcl_msvc_warnings.h> 23 #include <vnl/vnl_vector_fixed.h> 24 #include <vnl/vnl_matrix.h> 25 #include <vnl/vnl_matrix_fixed.h> 26 #include <vnl/vnl_math.h> 27 #include <vnl/algo/vnl_scatter_3x3.h> 28 #include <vnl/algo/vnl_real_eigensystem.h> 29 #include <vnl/vnl_diag_matrix.h> 38 p1.
w() * p2.
x() - p1.
x() * p2.
w(),
39 p1.
x() * p2.
y() - p1.
y() * p2.
x());
47 l1.
c() * l2.
a() - l1.
a() * l2.
c(),
48 l1.
a() * l2.
b() - l1.
b() * l2.
a());
55 return l.a()*p.
x() +
l.b()*p.
y() +
l.c()*p.
w();
63 return vnl_vector_fixed<T,3>(p.
x(),p.
y(),p.
w());
69 return vnl_vector_fixed<T,3>(
l.a(),
l.b(),
l.c());
75 vnl_vector_fixed<T,6>
v;
91 double norm = std::sqrt (a.
x()*a.
x() + a.
y()*a.
y() + a.
w()*a.
w());
94 std::cerr <<
"vgl_homg_operators_2d<T>::unitize() -- Zero length vector\n";
98 a.
set(T(a.
x()*norm), T(a.
y()*norm), T(a.
w()*norm));
116 if (p1 == p2)
return T(0);
118 if (p1.
w() == 0 || p2.
w() == 0) {
119 std::cerr <<
"vgl_homg_operators_2d<T>::distance_squared() -- point at infinity\n";
120 return std::numeric_limits<T>::infinity();
123 return vnl_math::sqr (p1.
x() / p1.
w() - p2.
x() / p2.
w()) +
124 vnl_math::sqr (p1.
y() / p1.
w() - p2.
y() / p2.
w());
138 if ((line.
a()==0 && line.
b()== 0) || point.
w()==0) {
139 std::cerr <<
"vgl_homg_operators_2d<T>::perp_dist_squared() -- line or point at infinity\n";
143 T numerator = vnl_math::sqr (
dot(line,point) / point.
w());
144 if (numerator == 0)
return T(0);
145 T denominator = line.
a()*line.
a() + line.
b()*line.
b();
147 return numerator / denominator;
158 return std::atan2 (line.
b(), line.
a());
168 double angle1 = line_angle(line1);
169 double angle2 = line_angle(line2);
171 double diff = angle2 - angle1;
172 if (diff > vnl_math::pi_over_2) diff -= vnl_math::pi;
173 if (diff < -vnl_math::pi_over_2) diff += vnl_math::pi;
175 return std::fabs(diff);
191 return std::fmod(line_angle(line2)-line_angle(line1), vnl_math::twopi);
277 T x = p1.
x() * p2.
w() + p2.
x() * p1.
w();
278 T y = p1.
y() * p2.
w() + p2.
y() * p1.
w();
279 T w = p1.
w() * p2.
w() + p2.
w() * p1.
w();
288 vnl_vector_fixed<T,3>
291 vnl_scatter_3x3<T> scatter_matrix;
294 i != inpoints.end(); ++i)
295 scatter_matrix.add_outer_product(get_vector(*i));
297 return scatter_matrix.minimum_eigenvector();
300 #include <vnl/algo/vnl_svd.h> 303 vnl_vector_fixed<T,3>
306 vnl_matrix<T> D(lines.size(), 3);
308 typename std::vector<vgl_homg_line_2d<T> >::const_iterator i = lines.begin();
309 for (
unsigned j = 0; i != lines.end(); ++i,++j)
310 D.set_row(j, get_vector(*i).as_ref());
314 std::cout <<
"[movrank " << svd.W() <<
']';
317 return svd.nullvector();
331 assert(lines.size() >= 2);
333 #ifdef VGL_HOMG_OPERATORS_2D_LINES_TO_POINT_USE_SVD 334 vnl_vector_fixed<T,3> mov = most_orthogonal_vector_svd(lines);
336 vnl_vector_fixed<T,3> mov = most_orthogonal_vector(lines);
367 double x1 = a.
x(), y1 = a.
y(), w1 = a.
w();
368 double x2 = b.
x(), y2 = b.
y(), w2 = b.
w();
369 double x3 = c.
x(), y3 = c.
y(), w3 = c.
w();
370 double x4 = d.
x(), y4 = d.
y(), w4 = d.
w();
371 double x = x1 - x2;
if (x<0) x = -x;
372 double y = y1 - y2;
if (y<0) y = -y;
373 double n = (x>y) ? (x1*w3-x3*w1)*(x2*w4-x4*w2) : (y1*w3-y3*w1)*(y2*w4-y4*w2);
374 double m = (x>y) ? (x1*w4-x4*w1)*(x2*w3-x3*w2) : (y1*w4-y4*w1)*(y2*w3-y3*w2);
375 if (n == 0 && m == 0)
376 std::cerr <<
"cross ratio not defined: three of the given points coincide\n";
391 T x1 = a.
x(), y1 = a.
y(), w1 = a.
w();
392 T x2 = b.
x(), y2 = b.
y(), w2 = b.
w();
393 T x3 = c.
x(), y3 = c.
y(), w3 = c.
w();
394 T kx = x1*w3 - x3*w1, mx = x2*w3 - x3*w2, nx = T(kx*w2-cr*mx*w1);
395 T ky = y1*w3 - y3*w1, my = y2*w3 - y3*w2, ny = T(ky*w2-cr*my*w1);
409 return vgl_conic<T>(mat[0][0], mat[1][0]+mat[0][1], mat[1][1], mat[0][2]+mat[2][0], mat[1][2]+mat[2][1], mat[2][2]);
420 vnl_matrix_fixed<T,3,3>
423 vnl_matrix_fixed<T,3,3> mat;
424 T A = c.
a(), B = c.
b()/2, C = c.
c(), D = c.
d()/2, E = c.
e()/2, F = c.
f();
426 mat[0][0] = A; mat[0][1] = B; mat[0][2] = D;
427 mat[1][0] = B; mat[1][1] = C; mat[1][2] = E;
428 mat[2][0] = D; mat[2][1] = E; mat[2][2] = F;
438 vnl_matrix_fixed<T,3,3>
441 vnl_matrix_fixed<T,3,3> mat;
442 T A = c.
a(), B = c.
b()/2, C = c.
c(), D = c.
d()/2, E = c.
e()/2, F = c.
f();
444 mat[0][0] = C*F-E*E; mat[0][1] = E*D-B*F; mat[0][2] = B*E-C*D;
445 mat[1][0] = E*D-B*F; mat[1][1] = A*F-D*D; mat[1][2] = B*D-A*E;
446 mat[2][0] = B*E-C*D; mat[2][1] = B*D-A*E; mat[2][2] = A*C-B*B;
455 std::list<vgl_homg_point_2d<T> >
461 std::cerr << __FILE__
462 <<
"Warning: the intersection of two identical conics is not a finite set of points.\n" 463 <<
"Returning an empty list.\n";
464 return std::list<vgl_homg_point_2d<T> >();
466 T A=c1.
a(),B=c1.
b(),C=c1.
c(),D=c1.
d(),E=c1.
e(),F=c1.
f();
467 T a=c2.
a(),b=c2.
b(),c=c2.
c(),d=c2.
d(),e=c2.
e(),f=c2.
f();
469 T ab=a*B-A*b, ac=a*C-A*c, ad=a*D-A*d, ae=a*E-A*e, af=a*F-A*f, BD=b*D+B*d;
484 || (ac*ad*ad+af*ab*ab == ab*ad*ae))
488 vnl_vector_fixed<T,5> coef;
489 coef(0) = ac*ac-ab*(b*C-B*c);
490 coef(1) = 2*ac*ae-ab*(b*E-B*e)-BD*(a*C+A*c)+2*A*b*C*d+2*a*B*c*D;
491 coef(2) = ae*ae-ab*(b*F-B*f)+ad*(c*D-C*d)-BD*(a*E+A*e)+2*a*B*e*D+2*A*b*E*d+2*ac*af;
492 coef(3) = 2*ae*af-ad*(d*E-D*e)-BD*(a*F+A*f)+2*A*b*d*F+2*a*B*D*f;
493 coef(4) = af*af-ad*(d*F-D*f);
504 if (coef(0) == 0 && coef(1) == 0) {
506 T dis = coef(3)*coef(3)-4*coef(2)*coef(4);
507 if (dis < 0)
return std::list<vgl_homg_point_2d<T> >();
509 if (coef(2) == 0) dis=0, y = - coef(4) / coef(3);
510 else y = - coef(3) / coef(2) / 2;
512 T x = -(y*y*ac+y*ae+af);
513 if (x == 0 && w == 0) x = w = 1;
515 dis = std::sqrt(dis) / coef(2) / 2;
516 std::list<vgl_homg_point_2d<T> > solutions;
517 y -= dis; w = y*ab+ad; x = -(y*y*ac+y*ae+af);
518 if (x == 0 && w == 0) x = w = 1;
520 y += 2*dis; w = y*ab+ad; x = -(y*y*ac+y*ae+af);
521 if (x == 0 && w == 0) x = w = 1;
527 double data[]={coef(2),coef(3),coef(4), 1,0,0, 0,1,0};
528 vnl_matrix<double> M(data,3,3);
529 vnl_real_eigensystem eig(M);
530 vnl_diag_matrix<std::complex<double> > polysolutions = eig.D;
531 std::list<vgl_homg_point_2d<T> > solutions;
532 for (
int i=0;i<3;++i)
533 if (std::abs(std::imag(polysolutions(i))) < 1e-3) {
534 T y = (T)std::real(polysolutions(i));
536 T x = -(y*y*ac+y*ae+af);
537 if (x == 0 && w == 0) x = w = 1;
544 double data[]={coef(1),coef(2),coef(3),coef(4), 1,0,0,0, 0,1,0,0, 0,0,1,0};
545 vnl_matrix<double> M(data,4,4);
546 vnl_real_eigensystem eig(M);
548 vnl_diag_matrix<std::complex<double> > polysolutions = eig.D;
552 for (
int i=0;i<4;++i)
553 if (std::abs(std::imag(polysolutions(i))) < 1e-7)
554 yvals.push_back((T)std::real(polysolutions(i)));
559 std::list<vgl_homg_point_2d<T> > solutions;
562 typename std::list<T>::const_iterator it = yvals.begin();
564 if (yvals(0) == yvals(1) || yvals(1) == yvals(2) || yvals(2) == yvals(3))
569 for (it = yvals.begin(); it != yvals.end(); ++it) {
572 T x = -(y*y*ac+y*ae+af);
573 if (x == 0 && w == 0) x = w = 1;
583 std::list<vgl_homg_point_2d<T> >
587 T A=q.
a(), B=q.
b(), C=q.
c(), D=q.
d(), E=q.
e(), F=q.
f();
588 T a=
l.a(), b=
l.b(), c=
l.c();
594 if (d < 0)
return std::list<vgl_homg_point_2d<T> >();
603 T y = -c/b; B = B*y+D;
604 T d = B*B-4*A*(C*y*y+E*y+F);
605 if (d < 0)
return std::list<vgl_homg_point_2d<T> >();
606 if (d == 0 && A == 0)
622 B = 2*A*b*c+B*c+D*b+E;
623 T d = B*B-4*AA*(A*c*c+D*c+F);
624 if (d < 0)
return std::list<vgl_homg_point_2d<T> >();
625 if (d == 0 && AA == 0)
642 std::list<vgl_homg_point_2d<T> >
656 std::list<vgl_homg_point_2d<T> > list(2, p);
661 std::list<vgl_homg_point_2d<T> > list;
666 return do_intersect(c,
l);
670 std::list<vgl_homg_point_2d<T> >
676 return std::list<vgl_homg_point_2d<T> >(2, c1.
centre());
680 return std::list<vgl_homg_point_2d<T> >(2, c2.
centre());
693 l1.insert(l1.end(), l2.begin(), l2.end());
702 l1.insert(l1.end(), l2.begin(), l2.end());
706 return do_intersect(c1, c2);
718 std::list<vgl_homg_line_2d<T> >
724 std::list<vgl_homg_line_2d<T> >
v = c.
components();
727 if (
v.size() > 0 &&
dot(
v.front(),p) == 0)
728 return std::list<vgl_homg_line_2d<T> >(1,
v.front());
729 else if (
v.size() > 1 &&
dot(
v.back(),p) == 0)
730 return std::list<vgl_homg_line_2d<T> >(1,
v.back());
732 return std::list<vgl_homg_line_2d<T> >();
737 std::list<vgl_homg_point_2d<T> > dualpts =
intersection(C,
l);
738 std::list<vgl_homg_line_2d<T> >
v;
739 typename std::list<vgl_homg_point_2d<T> >::iterator it = dualpts.begin();
740 for (; !(it == dualpts.end()); ++it)
750 std::list<vgl_homg_line_2d<T> >
756 return std::list<vgl_homg_line_2d<T> >();
760 std::list<vgl_homg_point_2d<T> > dualpts =
intersection(C1,C2);
761 std::list<vgl_homg_line_2d<T> >
v;
762 typename std::list<vgl_homg_point_2d<T> >::iterator it = dualpts.begin();
763 for (; !(it == dualpts.end()); ++it)
780 std::list<vgl_homg_point_2d<T> > candidates;
785 -c.
c()*pt.
x()*2+c.
b()*pt.
y(),
786 c.
d()*pt.
y() -c.
e()*pt.
x());
788 if (candidates.size() == 0)
791 else return candidates.front();
793 else if (c.
b()==0 && c.
a()==c.
c())
804 pt.
w()*(c.
c()-c.
a())*2,
806 pt.
y()*c.
a()*2-pt.
x()*c.
b()+pt.
w()*c.
e(),
807 -pt.
x()*c.
c()*2+pt.
y()*c.
b()-pt.
w()*c.
d(),
808 pt.
y()*c.
d() -pt.
x()*c.
e());
812 if (candidates.size() == 0)
814 std::cerr <<
"Warning: vgl_homg_operators_2d<T>::closest_point: no intersection\n";
819 typename std::list<vgl_homg_point_2d<T> >::iterator it = candidates.begin();
822 for (++it; it != candidates.end(); ++it) {
823 if ((*it).w() == 0)
continue;
825 if (d < dist) { p = (*it); dist = d; }
849 if (c.
real_type() ==
"complex intersecting lines") {
857 c.
real_type() ==
"complex parallel lines")
860 if (c.
real_type() ==
"real parallel lines" ||
864 std::list<vgl_homg_line_2d<T> >
l = c.
components();
865 if (
l.front().a() == 0)
868 if (
l.front().b() == 0)
885 T y1 = - lx.front().c() / lx.front().b();
886 T y2 = - lx.back().c() / lx.back().b();
887 if (y1 > y2) { T t = y1; y1 = y2; y2 = t; }
888 T x1 = - ly.front().c() / ly.front().a();
889 T x2 = - ly.back().c() / ly.back().a();
890 if (x1 > x2) { T t = x1; x1 = x2; x2 = t; }
902 m(1,0)*p.
x()+m(1,1)*p.
y()+m(1,2)*p.
w(),
903 m(2,0)*p.
x()+m(2,1)*p.
y()+m(2,2)*p.
w());
913 m(1,0)*
l.a()+m(1,1)*
l.b()+m(1,2)*
l.c(),
914 m(2,0)*
l.a()+m(2,1)*
l.b()+m(2,2)*
l.c());
923 if (
l.a()*p.
x()+
l.b()*p.
y()+
l.c()*p.
w() == 0)
return p;
932 #undef VGL_HOMG_OPERATORS_2D_INSTANTIATE 933 #define VGL_HOMG_OPERATORS_2D_INSTANTIATE(T) \ 934 template class vgl_homg_operators_2d<T >; \ 935 template vgl_homg_point_2d<T > operator*(vnl_matrix_fixed<T,3,3> const& m, vgl_homg_point_2d<T > const& p); \ 936 template vgl_homg_line_2d<T > operator*(vnl_matrix_fixed<T,3,3> const& m, vgl_homg_line_2d<T > const& p) 938 #endif // vgl_homg_operators_2d_hxx_ static vgl_conic< T > vgl_conic_from_matrix(vnl_matrix_fixed< T, 3, 3 > const &mat)
returns the vgl_conic which has the given matrix as its matrix.
vgl_conic_type type() const
vgl_homg_point_1d< T > centre(vgl_homg_point_1d< T > const &p1, vgl_homg_point_1d< T > const &p2)
Return the point at the centre of gravity of two given points.
2D homogeneous operations
static vgl_homg_point_2d< T > conjugate(const vgl_homg_point_2d< T > &a, const vgl_homg_point_2d< T > &b, const vgl_homg_point_2d< T > &c, double cr=-1.0)
Conjugate point of three given collinear points.
a point in 2D nonhomogeneous space
T a() const
Parameter a of line a*x + b*y + c*w = 0.
static vnl_matrix_fixed< T, 3, 3 > matrix_from_conic(vgl_conic< T > const &)
returns 3x3 matrix containing conic coefficients.
Represents a homogeneous 2D line.
static vgl_homg_point_2d< T > intersection(const vgl_homg_line_2d< T > &line1, const vgl_homg_line_2d< T > &line2)
Get the intersection point of two lines (the cross-product).
T b() const
Parameter b of line a*x + b*y + c*w = 0.
bool contains(vgl_homg_point_2d< T > const &pt) const
Returns true if the point pt belongs to the conic.
static vgl_homg_line_2d< T > perp_line_through_point(const vgl_homg_line_2d< T > &line, const vgl_homg_point_2d< T > &point)
Get the perpendicular line to line which passes through point.
T f() const
Returns the coefficient of .
line in projective 2D space
static std::list< vgl_homg_point_2d< T > > do_intersect(vgl_conic< T > const &q, vgl_homg_line_2d< T > const &l)
This function is called from within intersection(vgl_conic<T>,vgl_homg_line_2d<T>).
T a() const
Returns the coefficient of .
static vgl_homg_point_2d< T > midpoint(const vgl_homg_point_2d< T > &p1, const vgl_homg_point_2d< T > &p2)
Return the midpoint of the line joining two homogeneous points.
static vgl_homg_point_2d< T > closest_point(vgl_homg_line_2d< T > const &l, vgl_homg_point_2d< T > const &p)
Return the point on the line closest to the given point.
static vnl_vector_fixed< T, 3 > most_orthogonal_vector(const std::vector< vgl_homg_line_2d< T > > &lines)
compute most orthogonal vector with vnl_symmetric_eigensystem.
T c() const
Returns the coefficient of .
vgl_homg_point_2d< T > centre() const
Returns the centre of the conic, or its point at infinity if a parabola.
static vnl_vector_fixed< T, 3 > get_vector(vgl_homg_point_2d< T > const &p)
get a vnl_vector_fixed representation of a homogeneous object.
2D homogeneous operations.
std::string real_type() const
Returns the type of the conic as a string.
bool is_central() const
Returns true if a central conic, i.e., an ellipse, circle, or hyperbola.
static vgl_homg_line_2d< T > join(const vgl_homg_point_2d< T > &point1, const vgl_homg_point_2d< T > &point2)
Get the line through two points (the cross-product).
General purpose support class for vgl_homg_ classes.
static void unitize(vgl_homg_point_2d< T > &a)
Normalize vgl_homg_point_2d<T> to unit magnitude.
T e() const
Returns the coefficient of .
vgl_conic dual_conic() const
Returns the dual or tangential representation of this conic.
static vgl_homg_point_2d< T > lines_to_point(const std::vector< vgl_homg_line_2d< T > > &lines)
Intersect a set of 2D lines to find the least-square point of intersection.
static double cross_ratio(const vgl_homg_point_2d< T > &p1, const vgl_homg_point_2d< T > &p2, const vgl_homg_point_2d< T > &p3, const vgl_homg_point_2d< T > &p4)
cross ratio of four collinear points.
point in projective 2D space
void set(T px, T py, T pw=(T) 1)
Set x,y,w.
T b() const
Returns the coefficient of .
Contains class to represent a cartesian 2D bounding box.
static vgl_homg_line_2d< T > join_oriented(const vgl_homg_point_2d< T > &point1, const vgl_homg_point_2d< T > &point2)
Get the line through two points (the cross-product).
static vnl_matrix_fixed< T, 3, 3 > matrix_from_dual_conic(vgl_conic< T > const &)
returns 3x3 matrix containing conic coefficients of dual conic.
static vgl_homg_point_2d< T > perp_projection(const vgl_homg_line_2d< T > &line, const vgl_homg_point_2d< T > &point)
Get the perpendicular projection of point onto line.
T d() const
Returns the coefficient of .
static vnl_vector_fixed< T, 3 > most_orthogonal_vector_svd(const std::vector< vgl_homg_line_2d< T > > &lines)
compute most orthogonal vector with SVD.
static T distance_squared(const vgl_homg_point_2d< T > &point1, const vgl_homg_point_2d< T > &point2)
Get the square of the 2D distance between the two points.
vgl_homg_point_3d< Type > intersection(l const &l1, l const &l2)
Return the intersection point of two concurrent lines.
vgl_homg_point_1d< T > operator *(vnl_matrix_fixed< T, 2, 2 > const &m, vgl_homg_point_1d< T > const &p)
Transform a point through a 2x2 projective transformation matrix.
static vgl_box_2d< T > compute_bounding_box(vgl_conic< T > const &c)
Compute the bounding box of an ellipse.
T c() const
Parameter c of line a*x + b*y + c*w = 0.
General purpose support class for vgl_homg_ classes.
static double angle_between_oriented_lines(const vgl_homg_line_2d< T > &line1, const vgl_homg_line_2d< T > &line2)
Get the angle between two lines, a number between -PI and PI.
static T distance(const vgl_homg_point_2d< T > &point1, const vgl_homg_point_2d< T > &point2)
Get the 2D distance between the two points.
std::list< vgl_homg_line_2d< T > > components() const
Returns the list of component lines, when degenerate and real components.
static double line_angle(const vgl_homg_line_2d< T > &line)
Get the anticlockwise angle between a line and the x axis.
static double abs_angle(const vgl_homg_line_2d< T > &line1, const vgl_homg_line_2d< T > &line2)
Get the 0 to pi/2 angle between two lines.
Represents a homogeneous 2D point.
static std::list< vgl_homg_line_2d< T > > common_tangents(vgl_conic< T > const &c1, vgl_conic< T > const &c2)
Return the list of common tangent lines of two conics.
static T perp_dist_squared(const vgl_homg_point_2d< T > &point, const vgl_homg_line_2d< T > &line)
Get the square of the perpendicular distance to a line.
bool is_degenerate() const
Returns true if this conic is degenerate, i.e., if it consists of 2 lines.
static std::list< vgl_homg_line_2d< T > > tangent_from(vgl_conic< T > const &c, vgl_homg_point_2d< T > const &p)
Return the (at most) two tangent lines that pass through p and are tangent to the conic.