1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef GRAPHIC_LTE_TRANS_AFFINE_H
16 #define GRAPHIC_LTE_TRANS_AFFINE_H
17 
18 #include <cmath>
19 
20 #include "gfx_utils/diagram/common/common_basics.h"
21 #include "gfx_utils/graphic_math.h"
22 namespace OHOS {
23 const float affineEpsilon = 1e-14;
24 const uint16_t parlIndexSize = 6;
25 /**
26  * @brief Map source transformation
27  * @since 1.0
28  * @version 1.0
29  */
30 class TransAffine : public Matrix3<float> {
31 public:
32     /**
33      * @brief Initialize to identity matrix
34      * @since 1.0
35      * @version 1.0
36      */
TransAffine()37     TransAffine() : Matrix3<float>() {}
38     /**
39      * @brief Custom matrix
40      * @since 1.0
41      * @version 1.0
42      */
TransAffine(float v0,float v1,float v2,float v3,float v4,float v5)43     TransAffine(float v0, float v1, float v2, float v3, float v4, float v5)
44         : Matrix3<float>(v0, v2, v4, v1, v3, v5, 0, 0, 1) {}
45     /**
46      * @brief Converts a rectangle to a parallelogram
47      * @since 1.0
48      * @version 1.0
49      */
TransAffine(float x1,float y1,float x2,float y2,const float * parl)50     TransAffine(float x1, float y1, float x2, float y2, const float* parl)
51     {
52         RectToParl(x1, y1, x2, y2, parl);
53     }
SetData(int32_t index,float value)54     void SetData(int32_t index, float value)
55     {
56         data_[index] = value;
57     }
58     /**
59      * @brief Convert the original parallelogram to the target parallelogram
60      * @param x1 x-axis coordinate of the upper left corner of the rectangle
61      * @param y1 y-axis coordinate of the upper left corner of the rectangle
62      * @param x2 x-axis coordinates of the lower right corner of the rectangle
63      * @param y2 y-axis coordinates of the lower right corner of the rectangle
64      * @param parl Target parallelogram
65      * @since 1.0
66      * @version 1.0
67      */
68     const TransAffine& RectToParl(float x1, float y1,
69                                   float x2, float y2,
70                                   const float* parl);
71 
72     /**
73      * @brief reset TransAffine
74      * @since 1.0
75      * @version 1.0
76      */
77     const TransAffine& Reset();
78 
79     /**
80      * @brief Element offset
81      * @param deltaX x-axis offset
82      * @param deltaY y-axis offset
83      * @since 1.0
84      * @version 1.0
85      */
86     const TransAffine& Translate(float x, float y);
87     /**
88      * @brief Element rotation
89      * @param angle Rotate angle
90      * @since 1.0
91      * @version 1.0
92      */
93     const TransAffine& Rotate(float angle);
94     /**
95      * @brief Element Scale
96      * @param scale Overall amplification factor
97      * @since 1.0
98      * @version 1.0
99      */
100     const TransAffine& Scale(float scale);
101     /**
102      * @brief Element Scale
103      * @param x x-axis magnification factor
104      * @param y y-axis magnification factor
105      * @since 1.0
106      * @version 1.0
107      */
108     const TransAffine& Scale(float x, float y);
109 
110     /**
111      * @brief Transformation matrix multiplication
112      * @param metrix
113      * @since 1.0
114      * @version 1.0
115      */
116     const TransAffine& Multiply(const TransAffine& metrix);
117 
118     /**
119      * @brief Matrix flip
120      * @since 1.0
121      * @version 1.0
122      */
123     const TransAffine& Invert();
124 
125     const TransAffine& operator*=(const TransAffine& metrix)
126     {
127         return Multiply(metrix);
128     }
129 
130     /**
131      * @brief Convert x, y
132      * @param x x-coordinate
133      * @param y y-coordinate
134      * @since 1.0
135      * @version 1.0
136      */
137     void Transform(float* x, float* y) const;
138 
139     /**
140      * @brief inverse transformation
141      * @param x x-coordinate
142      * @param y y-coordinate
143      * @since 1.0
144      * @version 1.0
145      */
146     void InverseTransform(float* x, float* y) const;
147 
148     /**
149      * @brief Computes the reciprocal of a determinant
150      * @since 1.0
151      * @version 1.0
152      */
DeterminantReciprocal()153     float DeterminantReciprocal() const
154     {
155         float reciprocal = data_[0] * data_[4] - data_[3] * data_[1];
156         if (reciprocal == 0) {
157             return VERTEX_DIST_EPSILON;
158         }
159         return 1.0f / reciprocal;
160     }
161 
162     /**
163      * @brief Check the matrix for degradation
164      * @since 1.0
165      * @version 1.0
166      */
167     bool IsValid(float epsilon = affineEpsilon) const;
168 
169     /**
170      * @brief Check whether it is an identity matrix
171      * @since 1.0
172      * @version 1.0
173      */
174     bool IsIdentity() const;
175 
176     /**
177      * @brief zoom
178      * @param x x-coordinate
179      * @param y y-coordinate
180      * @since 1.0
181      * @version 1.0
182      */
183     void ScalingAbs(float* x, float* y) const;
184 
185     /**
186      * @brief Set rotation matrix
187      * @since 1.0
188      * @version 1.0
189      */
TransAffineRotation(float angle)190     static TransAffine TransAffineRotation(float angle)
191     {
192         return TransAffine(std::cos(angle), std::sin(angle), -std::sin(angle), std::cos(angle), 0.0f, 0.0f);
193     }
194 
195     /**
196      * @brief Set scaling matrix
197      * @since 1.0
198      * @version 1.0
199      */
TransAffineScaling(float x,float y)200     static TransAffine TransAffineScaling(float x, float y)
201     {
202         return TransAffine(x, 0.0f, 0.0f, y, 0.0f, 0.0f);
203     }
204 
205     /**
206      * @brief Set scaling matrix
207      * @since 1.0
208      * @version 1.0
209      */
TransAffineScaling(float scale)210     static TransAffine TransAffineScaling(float scale)
211     {
212         return TransAffine(scale, 0.0f, 0.0f, scale, 0.0f, 0.0f);
213     }
214     /**
215      * @brief Set translation matrix
216      * @since 1.0
217      * @version 1.0
218      */
TransAffineTranslation(float x,float y)219     static TransAffine TransAffineTranslation(float x, float y)
220     {
221         return TransAffine(1.0f, 0.0f, 0.0f, 1.0f, x, y);
222     }
223 };
224 
Transform(float * x,float * y)225 inline void TransAffine::Transform(float* x, float* y) const
226 {
227     float tmp = *x;
228     *x = tmp * data_[0] + *y * data_[1] + data_[2];
229     *y = tmp * data_[3] + *y * data_[4] + data_[5];
230 }
231 
InverseTransform(float * x,float * y)232 inline void TransAffine::InverseTransform(float* x, float* y) const
233 {
234     float reciprocal = DeterminantReciprocal();
235     float a = (*x - data_[2]) * reciprocal;
236     float b = (*y - data_[5]) * reciprocal;
237     *x = a * data_[4] - b * data_[1];
238     *y = b * data_[0] - a * data_[3];
239 }
240 
Translate(float deltaX,float deltaY)241 inline const TransAffine& TransAffine::Translate(float deltaX, float deltaY)
242 {
243     data_[2] += deltaX;
244     data_[5] += deltaY;
245     return *this;
246 }
247 
Rotate(float angle)248 inline const TransAffine& TransAffine::Rotate(float angle)
249 {
250     float scaleXTemp = data_[0] * std::cos(angle) - data_[3] * std::sin(angle);
251     float shearXTemp = data_[1] * std::cos(angle) - data_[4] * std::sin(angle);
252     float translateXTemp = data_[2] * std::cos(angle) - data_[5] * std::sin(angle);
253     data_[3] = data_[0] * std::sin(angle) + data_[3] * std::cos(angle);
254     data_[4] = data_[1] * std::sin(angle) + data_[4] * std::cos(angle);
255     data_[5] = data_[2] * std::sin(angle) + data_[5] * std::cos(angle);
256     data_[0] = scaleXTemp;
257     data_[1] = shearXTemp;
258     data_[2] = translateXTemp;
259     return *this;
260 }
261 
Scale(float scaleX,float scaleY)262 inline const TransAffine& TransAffine::Scale(float scaleX, float scaleY)
263 {
264     data_[0] *= scaleX;
265     data_[1] *= scaleX;
266     data_[2] *= scaleX;
267     data_[3] *= scaleY;
268     data_[4] *= scaleY;
269     data_[5] *= scaleY;
270     return *this;
271 }
272 
Scale(float scale)273 inline const TransAffine& TransAffine::Scale(float scale)
274 {
275     data_[0] *= scale;
276     data_[1] *= scale;
277     data_[2] *= scale;
278     data_[3] *= scale;
279     data_[4] *= scale;
280     data_[5] *= scale;
281     return *this;
282 }
283 
ScalingAbs(float * x,float * y)284 inline void TransAffine::ScalingAbs(float* x, float* y) const
285 {
286     *x = Sqrt(data_[0] * data_[0] + data_[1] * data_[1]);
287     *y = Sqrt(data_[3] * data_[3] + data_[4] * data_[4]);
288 }
289 } // namespace OHOS
290 #endif
291