1 // This is brl/bseg/bvpl/kernels/bvpl_kernel_factory.h
2 #ifndef bvpl_kernel_base_h
3 #define bvpl_kernel_base_h
4 //:
5 // \file
6 // \brief  A base class for 3D kernel. The kernel is fully described by a rotation axis and an angle
7 //  The children of this classes must create a kernel on a "canonical form" i.e. with a default
8 //  axis of rotation and a complementary vector here called canonical_paralle_axis_.
9 //
10 //  If this two vector are seen as points on the unit sphere, then they lie on the same
11 //  parallel (constant polar angle). These vectors determine the zero rotation position as follows:
12 //  *  The rotation that transforms the canonical_rotation_axis to a new specified rotation axis,
13 //     is applied to the kernel (Lets call such rotation R).
14 //  *  The kernel is rotate around its new rotation such that R*canonical_parallel_axis achieves
15 //     the same polar angle as the new rotation axis
16 //
17 //  Usage:
18 //  - The user can create a kernel in its canonical form through children constructors
19 //  - Then, the user call set_rotation_axis(), set_angle() and create() and if one wishes to use
20 //    another angle with the same axis, it suffices to call set_angle(angle) and create().
21 //    This will save computation time since the rotation_axis has already been set.
22 //  - Alternatively, the user can call create(axis, angle). This transforms the canonical kernel according
23 //    to new parameters
24 //
25 // \author Isabel Restrepo mir@lems.brown.edu
26 // \date  May 29, 2009
27 //
28 // \verbatim
29 //  Modifications
30 //   <none yet>
31 // \endverbatim
32 
33 #include <iostream>
34 #include <map>
35 #include <utility>
36 #include "bvpl_kernel.h"
37 #include "bvpl_kernel_iterator.h"
38 #ifdef _MSC_VER
39 #  include <vcl_msvc_warnings.h>
40 #endif
41 #include <vnl/vnl_float_3.h>
42 #include <vgl/algo/vgl_rotation_3d.h>
43 #include <vbl/vbl_ref_count.h>
44 
45 class bvpl_kernel_factory;
46 typedef vbl_smart_ptr<bvpl_kernel_factory> bvpl_kernel_factory_sptr;
47 
48 
49 //: A factory of bvpl_kernels
50 class bvpl_kernel_factory: public vbl_ref_count
51 {
52  public:
53   //Default constructor. Initialize constant member variables
bvpl_kernel_factory()54   bvpl_kernel_factory(): canonical_rotation_axis_(vnl_float_3(1,0,0)), canonical_parallel_axis_(vnl_float_3(0,1,0)){}
55 
56   ~bvpl_kernel_factory() override = default;
57 
58   //: Returns a kernel described by class variables rotation_axis_, \p angle_
59   //  The user can modified the axis and angle using set_rotation_axis() and set_angle()
60   bvpl_kernel create();
61 
62   //: Returns a kernel described by inputs; rotation_axis and angle
63   bvpl_kernel create(vnl_float_3 rotation_axis, float angle);
64 
65   //: Sets the rotation axis of this kernel
66   void set_rotation_axis(vnl_float_3 rotation_axis);
67 
68   //: Sets rotation angle of this kernel
set_angle(float angle)69   void set_angle(float angle) { angle_ =angle; }
70 
71   //: Returns the current alignment axis
axis()72   vnl_float_3 axis() const { return rotation_axis_; }
73 
74   //: Return current rotation angle around axis()
angle()75   float angle() const { return angle_; }
76 
77   //: Returns angular resolution around rotation axis
angular_resolution()78   float angular_resolution() const { return angular_resolution_; }
79 
80   //: Return x-y-z maximum coordinate values
max_point()81   vgl_point_3d<int> max_point() const { return max_point_; }
82 
83   //: Return x-y-z minimum coordinate values
min_point()84   vgl_point_3d<int> min_point() const { return min_point_; }
85 
86   //: returns the rectangular dimensions around the kernel center
87   vgl_vector_3d<int> dim();
88 
89   //: Creates a vector of kernels as specified by func
90   template <class F>
91   bvpl_kernel_vector_sptr create_kernel_vector(F func);
92 
93   //: Return an xml element
xml_element()94   virtual bxml_data_sptr xml_element()
95   {
96     std::cout << "Calling xml write in parent class, xml data will be NULL" << std::endl;
97     return nullptr;
98   }
99 
self()100   virtual bvpl_kernel_factory_sptr self(){return this;}
101 
102  protected:
103 
104   typedef std::vector<std::pair<vgl_point_3d<float>, bvpl_kernel_dispatch> > kernel_type;
105 
106   //: The map of 3d positions and their symbols. This kernel has an axis of rotation, but it is always on zero-rotation position
107   std::vector<std::pair<vgl_point_3d<float>, bvpl_kernel_dispatch> > kernel_;
108 
109   //: The map of 3d positions and their symbols in their canonical form (As specified by children)
110   std::vector<std::pair<vgl_point_3d<float>, bvpl_kernel_dispatch> > canonical_kernel_;
111 
112   //: The rotation axis for canonical edge
113   const vnl_float_3 canonical_rotation_axis_;//(1,0,0);
114 
115   //: Rotation axis of kernel_
116   vnl_float_3 rotation_axis_;
117 
118   vnl_float_3 parallel_axis_;
119 
120   // parallel_axis_ define a coordinate system for each kernel.
121   // The vector (parallel_axis_ - rotation_axis_) defines the direction of the minor axis of the kernel
122   // The zero-rotation for any rotation axis is that for which parallel_axis_ and rotation_axis_ have constant polar angle
123   const vnl_float_3 canonical_parallel_axis_;//(0,1,0);
124 
125   //: Amounts rotation around rotation_axis_
126   float angle_;
127 
128   //: Dimensions of the 3D grid
129   vgl_point_3d<int> max_point_;
130 
131   //: Dimensions of the 3D grid
132   vgl_point_3d<int> min_point_;
133 
134   //: Angular resolutions
135   float angular_resolution_;
136 
137   //: Length of a voxel in global coordinates
138   double voxel_length_;
139 
140   //: Name that identifies the kernel e.g "edge3d", "gauss"
141   std::string factory_name_;
142 
143   //: Creates canonical(default) kernel.
144   //  It is described by a canonical axis of rotation and a canonical parallel axis
145   //  This is the main function implemented by the children.
146   virtual void create_canonical()=0;
147 
148   //: Rounds coordinates of kernel to the nearest integer
149   bvpl_kernel_iterator interpolate(kernel_type const& kernel);
150 
151   //: Rotates "class-kernel_" around "class-rotation_axis_"  by an "angle"
152   kernel_type rotate(float angle);
153 
154   //: Rotates "class-kernel_" using the given rotation matrix
155   kernel_type rotate(const vgl_rotation_3d<float>& R);
156 };
157 
158 
159 template <class F>
create_kernel_vector(F func)160 bvpl_kernel_vector_sptr bvpl_kernel_factory::create_kernel_vector(F func)
161 {
162   std::vector<vnl_float_3> axes=func.get_axes();
163   std::vector<float> angles = func.get_angles();
164 
165   bvpl_kernel_vector_sptr vec_kernel=new bvpl_kernel_vector();
166 
167   for (unsigned i=0;i<axes.size();i++)
168   {
169     this->set_rotation_axis(axes[i]);
170     this->set_angle(angles[i]);
171     vec_kernel->kernels_.push_back(new bvpl_kernel(this->create()));
172   }
173   return vec_kernel;
174 }
175 
176 #endif
177