1 #ifndef ossim2dBilinearTransform_HEADER
2 #define ossim2dBilinearTransform_HEADER
3 #include <ossim/base/ossim2dTo2dTransform.h>
4 #include <algorithm>
5 /**
6  * ossim2dBilinearTransform allows one to specify a set of input points and output points
7  * and will fit a bilinear transform to those points.  Function of the form is solved for each
8  * output dimension.
9  *
10  * z(x,y) = a + b*x + c*y + d*x*y
11  *
12  * We use the ossimLeastSquareBilin solver to solve for the coefficients.
13  *
14  */
15 class OSSIM_DLL ossim2dBilinearTransform : public ossim2dTo2dTransform
16 {
17 public:
18    /**
19     * Initialize to the identity
20     */
21    ossim2dBilinearTransform();
22 
23    /**
24     * Initialize the transform that best fits the input and output arrays.
25     * If the input and output are well dispersed and are 4 points it should fit
26     * exactly.  Both arrays should be of equal number of points
27     *
28     * @param input the list of input points
29     * @param output the list of output points to transform the input to
30     * @param arraySize the number of points for the arrays.
31     */
32    ossim2dBilinearTransform(const ossimDpt* input,
33                             const ossimDpt* output,
34                             ossim_uint32 arraySize)
35    {
36       setFromPoints(input, output, arraySize);
37    }
38 
39    /**
40     * Mapping 4 corners to an output 4 corners.
41     *
42     */
43    ossim2dBilinearTransform(const ossimDpt& in1, const ossimDpt& in2, const ossimDpt& in3, const ossimDpt& in4,
44                             const ossimDpt& out1, const ossimDpt& out2, const ossimDpt& out3, const ossimDpt& out4)
45    {
46       setFromPoints(in1, in2, in3, in4, out1, out2, out3, out4);
47    }
48 
49    /**
50     * Copy constructor
51     */
52    ossim2dBilinearTransform(const ossim2dBilinearTransform& src);
53 
54    /**
55     * Duplication method that duplicates this object
56     */
57    virtual ossimObject* dup()const{return new ossim2dBilinearTransform(*this);}
58 
59    /**
60     * Overloaded operator equal that allows for assignment.
61     *
62     * @param src the src data to copy into this object.  It will call the base classes
63     * equal operator.
64     */
65    const ossim2dBilinearTransform& operator =(const ossim2dBilinearTransform& src)
66    {
67       if(this == &src) return *this;
68 
69       ossim2dTo2dTransform::operator =(*this); // call base classes equal operator
70       std::copy(src.m_coefficientsXTerm, src.m_coefficientsXTerm+4, m_coefficientsXTerm);
71       std::copy(src.m_coefficientsYTerm, src.m_coefficientsYTerm+4, m_coefficientsYTerm);
72       std::copy(src.m_inverseCoefficientsXTerm, src.m_inverseCoefficientsXTerm+4, m_inverseCoefficientsXTerm);
73       std::copy(src.m_inverseCoefficientsYTerm, src.m_inverseCoefficientsYTerm+4, m_inverseCoefficientsYTerm);
74 
75       return *this;
76    }
77 
78    /**
79     * Mapping 4 corners to an output 4 corners.  Will use the ossimLeastSquareBilin class to solve
80     * the bilinear coefficients that maps the given input points to the output points.
81     */
82    void setFromPoints(const ossimDpt& in1, const ossimDpt& in2, const ossimDpt& in3, const ossimDpt& in4,
83                       const ossimDpt& out1, const ossimDpt& out2, const ossimDpt& out3, const ossimDpt& out4);
84 
85    /**
86     * Initialize the transform that best fits the input and output arrays.
87     * If the input and output are well dispersed and are 4 points it should fit
88     * exactly.  Both arrays should be of equal number of points
89     *
90     * @param input the list of input points
91     * @param output the list of output points to transform the input to
92     * @param arraySize the number of points for the arrays.
93     */
94    void setFromPoints(const ossimDpt* input,
95                       const ossimDpt* output,
96                       ossim_uint32 arraySize);
97 
98    /**
99     * forward transform will transform an input point to the output.
100     */
101    virtual void forward(const ossimDpt& input,
102                         ossimDpt& output) const
103    {
104       output.x = (m_coefficientsXTerm[0] +
105                   m_coefficientsXTerm[1]*input.x +
106                   m_coefficientsXTerm[2]*input.y +
107                   m_coefficientsXTerm[3]*input.x*input.y);
108       output.y = (m_coefficientsYTerm[0] +
109                   m_coefficientsYTerm[1]*input.x +
110                   m_coefficientsYTerm[2]*input.y +
111                   m_coefficientsYTerm[3]*input.x*input.y);
112    }
113 
114    /**
115     * forward transform will transform an input point to the output and modify the passed in point
116     * to the new value
117     */
118    virtual void forward(ossimDpt&  modify_this) const
119    {
120       double saveX = modify_this.x;
121       modify_this.x = (m_coefficientsXTerm[0] +
122                        m_coefficientsXTerm[1]*modify_this.x +
123                        m_coefficientsXTerm[2]*modify_this.y +
124                        m_coefficientsXTerm[3]*modify_this.x*modify_this.y);
125       modify_this.y = (m_coefficientsYTerm[0] +
126                        m_coefficientsYTerm[1]*saveX +
127                        m_coefficientsYTerm[2]*modify_this.y +
128                        m_coefficientsYTerm[3]*saveX*modify_this.y);
129    }
130 
131    /**
132     * Inverts the point back to the original input value.
133     */
134    virtual void inverse(const ossimDpt& input,
135                         ossimDpt&       output) const
136    {
137       output.x = (m_inverseCoefficientsXTerm[0] +
138                   m_inverseCoefficientsXTerm[1]*input.x +
139                   m_inverseCoefficientsXTerm[2]*input.y +
140                   m_inverseCoefficientsXTerm[3]*input.x*input.y);
141       output.y = (m_inverseCoefficientsYTerm[0] +
142                   m_inverseCoefficientsYTerm[1]*input.x +
143                   m_inverseCoefficientsYTerm[2]*input.y +
144                   m_inverseCoefficientsYTerm[3]*input.x*input.y);
145    }
146 
147    /**
148     * Inverts the point back to the original input value and modifies the passed in point
149     * to the new value.
150     */
151    virtual void inverse(ossimDpt&  modify_this) const
152    {
153       double saveX = modify_this.x;
154       modify_this.x = (m_inverseCoefficientsXTerm[0] +
155                        m_inverseCoefficientsXTerm[1]*modify_this.x +
156                        m_inverseCoefficientsXTerm[2]*modify_this.y +
157                        m_inverseCoefficientsXTerm[3]*modify_this.x*modify_this.y);
158       modify_this.y = (m_inverseCoefficientsYTerm[0] +
159                        m_inverseCoefficientsYTerm[1]*saveX +
160                        m_inverseCoefficientsYTerm[2]*modify_this.y +
161                        m_inverseCoefficientsYTerm[3]*saveX*modify_this.y);
162    }
163 
164    /**
165     * Saves the state of this object.
166     */
167    virtual bool saveState(ossimKeywordlist& kwl,
168                           const char* prefix = 0)const;
169 
170    /**
171     * loads the state of this object from a keywordlist.
172     */
173    virtual bool loadState(const ossimKeywordlist& kwl,
174                           const char* prefix = 0);
175 
176    /**
177     * prints the contents of this object.  Will also cal the base classes
178     * print method.
179     */
180    virtual std::ostream& print(std::ostream& out) const
181    {
182       ossim2dTo2dTransform::print(out);
183       out << "xTerm: " << m_coefficientsXTerm[0] << ", " << m_coefficientsXTerm[1] << ", "
184           << m_coefficientsXTerm[2] << ", " << m_coefficientsXTerm[3] << "\n";
185       out << "yTerm: " << m_coefficientsYTerm[0] << ", " << m_coefficientsYTerm[1] << ", "
186           << m_coefficientsYTerm[2] << ", " << m_coefficientsYTerm[3] << "\n";
187 
188       out << "xInverseTerm: " << m_inverseCoefficientsXTerm[0] << ", " << m_inverseCoefficientsXTerm[1] << ", "
189           << m_inverseCoefficientsXTerm[2] << ", " << m_inverseCoefficientsXTerm[3] << "\n";
190       out << "yInverseTerm: " << m_inverseCoefficientsYTerm[0] << ", " << m_inverseCoefficientsYTerm[1] << ", "
191           << m_inverseCoefficientsYTerm[2] << ", " << m_inverseCoefficientsYTerm[3] << "\n";
192 
193       return out;
194    }
195 
196 protected:
197    ossim_float64 m_coefficientsXTerm[4]; // constant, linear x, linear y, cross xy
198    ossim_float64 m_coefficientsYTerm[4]; // constant, linear x, linear y, cross xy
199 
200    ossim_float64 m_inverseCoefficientsXTerm[4]; // constant, linear x, linear y, cross xy
201    ossim_float64 m_inverseCoefficientsYTerm[4]; // constant, linear x, linear y, cross xy
202    TYPE_DATA;
203 };
204 
205 #endif
206