1 // This is core/vgl/algo/vgl_fit_cremona_2d.h
2 #ifndef vgl_compute_cremona_2d_h_
3 #define vgl_compute_cremona_2d_h_
4 //:
5 // \file
6 // \brief Fit a cremona transform in the plane given a set of corresponding points
7 //
8 // \verbatim
9 //  Modifications
10 //   Created November 22, 2019 - J.L. Mundy
11 // \endverbatim
12 //
13 // A cremona tranform is a generalization of the 2-d projective transformation
14 // where the map (X,Y) -> (x, y) in Euclidian coordinates is defined by ratios of polynomials.
15 //
16 //       P(X, Y)       R(X, Y)
17 //   x = -------   y = ------
18 //       Q(X, Y)       S(X, Y)
19 //
20 //   P, Q, R, S are polynomials of degree deg.
21 //
22 // In the case where the highest degree is one, the Cremona transformation with
23 // a common denominator is equivalent to the projective transformation.
24 //
25 // Various constraints on the generality of the transformation are available:
26 //
27 // BI_RATIONAL - full generality
28 // COMMON_DENOMINATOR - the maps to x and to y have the same bi-rational denominator
29 // UNITY_DENOMINATOR  - both denominators are 1 - so not a rational form (analogous to affine)
30 //
31 #include <iosfwd>
32 #include <vgl/algo/vgl_norm_trans_2d.h>
33 #include <vgl/vgl_homg_point_2d.h>
34 #ifdef _MSC_VER
35 #  include <vcl_msvc_warnings.h>
36 #endif
37 #include <vnl/vnl_matrix.h>
38 #include <vnl/vnl_vector.h>
39 #include "vgl_cremona_trans_2d.h"
40 template <class T, size_t deg>
41 class vgl_compute_cremona_2d
42 {
43  public:
44      enum constraint_t  {BI_RATIONAL, COMMON_DENOMINATOR, UNITY_DENOMINATOR, UNKNOWN};
45   // Constructors/Initializers/Destructors-------------------------------------
46 
vgl_compute_cremona_2d()47      vgl_compute_cremona_2d() : constr_type_(BI_RATIONAL) {}
48      ~vgl_compute_cremona_2d() = default;
49      ;
50 
51      // Operations----------------------------------------------------------------
52 
53      bool compute_linear(std::vector<vgl_homg_point_2d<T>> const &from_pts,
54                          std::vector<vgl_homg_point_2d<T>> const &to_pts,
55                          constraint_t ctype = BI_RATIONAL);
56      bool project_linear(T X, T Y, T &x, T &y) const;
linear_error()57      T linear_error() { return linear_error_; }
58 
59      //: the cremona transformation produced by the linear solution
linear_trans()60      vgl_cremona_trans_2d<T, deg> linear_trans() {
61        return vgl_cremona_trans_2d<T, deg>(tr_from_, tr_to_, linear_coeff_);
62  }
63  // internals
linear_coeff()64  vnl_vector<T> linear_coeff() const {return linear_coeff_;}
tr_from()65  vgl_norm_trans_2d<T> tr_from() const {return tr_from_;}
tr_to()66  vgl_norm_trans_2d<T> tr_to() const {return tr_to_;}
67 
68  protected :
69  bool normalize();
70  bool compute_linear_solution_error();
71  constraint_t constr_type_;
72  std::vector<vgl_homg_point_2d<T> > from_pts_;
73  std::vector<vgl_homg_point_2d<T> > to_pts_;
74  vgl_norm_trans_2d<T> tr_from_;
75  vgl_norm_trans_2d<T> tr_to_;
76  std::vector<vgl_homg_point_2d<T> > norm_from_pts_;
77  std::vector<vgl_homg_point_2d<T> > norm_to_pts_;
78  T linear_error_;
79  vnl_vector<T> linear_coeff_;
80  bool linear_solved_{false};
81 };
82 
83 #define VGL_COMPUTE_CREMONA_2D_INSTANTIATE(T, deg) extern "please include vgl/algo/vgl_compute_cremona_2d.hxx first"
84 
85 #endif // vgl_compute_cremona_2d_h_
86