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