1 /*
2 * Copyright (c) 2022 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
16 #include "gfx_utils/diagram/vertexprimitive/geometry_curves.h"
17 #include "gfx_utils/graphic_math.h"
18 #include "gfx_utils/diagram/common/common_math.h"
19 namespace OHOS {
20 const float CURVE_COLLINEARITY_EPSILON = 1e-30;
21 const float CURVE_ANGLE_TO_LERANCE_EPSILON = 0.01f;
22 const int32_t CURVE_RECURSION_LIMIT = 32;
23 const float CURVES_NUM_STEP_LEN = 0.25f;
ApproximationScale() const24 float QuadBezierCurveIncr::ApproximationScale() const
25 {
26 return approximationScale_;
27 }
28
ApproximationScale(float scale)29 void QuadBezierCurveIncr::ApproximationScale(float scale)
30 {
31 approximationScale_ = scale;
32 }
33
Init(float x1,float y1,float x2,float y2,float x3,float y3)34 void QuadBezierCurveIncr::Init(float x1, float y1,
35 float x2, float y2,
36 float x3, float y3)
37 {
38 startCoordinate_.x = x1;
39 startCoordinate_.y = y1;
40 endCoordinate_.x = x3;
41 endCoordinate_.y = y3;
42
43 float deltaX1 = x2 - x1;
44 float deltaY1 = y2 - y1;
45 float deltaX2 = x3 - x2;
46 float deltaY2 = y3 - y2;
47
48 float len = Sqrt(deltaX1 * deltaX1 + deltaY1 * deltaY1) +
49 Sqrt(deltaX2 * deltaX2 + deltaY2 * deltaY2);
50
51 numberSteps_ = MATH_UROUND(len * CURVES_NUM_STEP_LEN * approximationScale_);
52 const int32_t numStepsMax = 4;
53 if (numberSteps_ < numStepsMax) {
54 numberSteps_ = numStepsMax;
55 }
56 if (numberSteps_ == 0) {
57 return;
58 }
59 float subdivideStep = 1.0f / numberSteps_;
60 float subdivideStep2 = subdivideStep * subdivideStep;
61
62 float tmpX = (x1 - x2 * FLOATNUM + x3) * subdivideStep2;
63 float tmpY = (y1 - y2 * FLOATNUM + y3) * subdivideStep2;
64
65 savedFinalCoordinate_.x = x1;
66 finalCoordinate_.x = x1;
67 savedFinalCoordinate_.y = y1;
68 finalCoordinate_.y = y1;
69
70 savedDeltaFinalCoordinate_.x = tmpX + (x2 - x1) * (FLOATNUM * subdivideStep);
71 deltaFinalCoordinate_.x = tmpX + (x2 - x1) * (FLOATNUM * subdivideStep);
72 savedDeltaFinalCoordinate_.y = tmpY + (y2 - y1) * (FLOATNUM * subdivideStep);
73 deltaFinalCoordinate_.y = tmpY + (y2 - y1) * (FLOATNUM * subdivideStep);
74
75 copyDeltaFinalCoordinate_.x = tmpX * FLOATNUM;
76 copyDeltaFinalCoordinate_.y = tmpY * FLOATNUM;
77
78 currentStep_ = numberSteps_;
79 }
80
Reset()81 void QuadBezierCurveIncr::Reset()
82 {
83 numberSteps_ = 0;
84 currentStep_ = -1;
85 }
86
ApproximationMethod() const87 CurveApproximationMethod QuadBezierCurveIncr::ApproximationMethod() const
88 {
89 return CURVEINCREMENT;
90 }
91
AngleTolerance() const92 float QuadBezierCurveIncr::AngleTolerance() const
93 {
94 return 0.0f;
95 }
96
CuspLimit() const97 float QuadBezierCurveIncr::CuspLimit() const
98 {
99 return 0.0f;
100 }
101
Rewind(uint32_t)102 void QuadBezierCurveIncr::Rewind(uint32_t)
103 {
104 if (numberSteps_ == 0) {
105 currentStep_ = -1;
106 return;
107 }
108
109 currentStep_ = numberSteps_;
110 finalCoordinate_.x = savedFinalCoordinate_.x;
111 finalCoordinate_.y = savedFinalCoordinate_.y;
112 deltaFinalCoordinate_.x = savedDeltaFinalCoordinate_.x;
113 deltaFinalCoordinate_.y = savedDeltaFinalCoordinate_.y;
114 }
115
GenerateVertex(float * x,float * y)116 uint32_t QuadBezierCurveIncr::GenerateVertex(float* x, float* y)
117 {
118 if (currentStep_ < 0) {
119 return PATH_CMD_STOP;
120 }
121 if (currentStep_ == numberSteps_) {
122 *x = startCoordinate_.x;
123 *y = startCoordinate_.y;
124 --currentStep_;
125 return PATH_CMD_MOVE_TO;
126 }
127 if (currentStep_ == 0) {
128 *x = endCoordinate_.x;
129 *y = endCoordinate_.y;
130 --currentStep_;
131 return PATH_CMD_LINE_TO;
132 }
133
134 finalCoordinate_.x += deltaFinalCoordinate_.x;
135 finalCoordinate_.y += deltaFinalCoordinate_.y;
136 deltaFinalCoordinate_.x += copyDeltaFinalCoordinate_.x;
137 deltaFinalCoordinate_.y += copyDeltaFinalCoordinate_.y;
138 *x = finalCoordinate_.x;
139 *y = finalCoordinate_.y;
140 --currentStep_;
141 return PATH_CMD_LINE_TO;
142 }
143
Init(float x1,float y1,float x2,float y2,float x3,float y3)144 void QuadrBezierCurveDividOp::Init(float x1, float y1,
145 float x2, float y2,
146 float x3, float y3)
147 {
148 points_.Clear();
149 distanceToleranceSquare_ = HALFNUM / approximationScale_;
150 distanceToleranceSquare_ *= distanceToleranceSquare_;
151 Bezier(x1, y1, x2, y2, x3, y3);
152 count_ = 0;
153 }
154
Reset()155 void QuadrBezierCurveDividOp::Reset()
156 {
157 points_.Clear();
158 count_ = 0;
159 }
160
ApproximationMethod() const161 CurveApproximationMethod QuadrBezierCurveDividOp::ApproximationMethod() const
162 {
163 return CURVEDIVIDOPERATE;
164 }
165
ApproximationScale(float scale)166 void QuadrBezierCurveDividOp::ApproximationScale(float scale)
167 {
168 approximationScale_ = scale;
169 }
170
ApproximationScale() const171 float QuadrBezierCurveDividOp::ApproximationScale() const
172 {
173 return approximationScale_;
174 }
175
AngleTolerance(float angle)176 void QuadrBezierCurveDividOp::AngleTolerance(float angle)
177 {
178 angleTolerance_ = angle;
179 }
180
AngleTolerance() const181 float QuadrBezierCurveDividOp::AngleTolerance() const
182 {
183 return angleTolerance_;
184 }
185
CuspLimit() const186 float QuadrBezierCurveDividOp::CuspLimit() const
187 {
188 return 0.0f;
189 }
190
Rewind(uint32_t)191 void QuadrBezierCurveDividOp::Rewind(uint32_t)
192 {
193 count_ = 0;
194 }
195
GenerateVertex(float * x,float * y)196 uint32_t QuadrBezierCurveDividOp::GenerateVertex(float* x, float* y)
197 {
198 if (count_ >= points_.Size()) {
199 return PATH_CMD_STOP;
200 }
201 const PointF& point = points_[count_++];
202 *x = point.x;
203 *y = point.y;
204 return (count_ == 1) ? PATH_CMD_MOVE_TO : PATH_CMD_LINE_TO;
205 }
206
Recursive(float x1,float y1,float x2,float y2,float x3,float y3,uint32_t level)207 void QuadrBezierCurveDividOp::Recursive(float x1, float y1,
208 float x2, float y2,
209 float x3, float y3,
210 uint32_t level)
211 {
212 if (level > CURVE_RECURSION_LIMIT) {
213 return;
214 }
215
216 // Calculates All Midpoints Of a Segment
217 float x12 = (x1 + x2) / FLOATNUM;
218 float y12 = (y1 + y2) / FLOATNUM;
219 float x23 = (x2 + x3) / FLOATNUM;
220 float y23 = (y2 + y3) / FLOATNUM;
221 float x123 = (x12 + x23) / FLOATNUM;
222 float y123 = (y12 + y23) / FLOATNUM;
223 float deltaX = x3 - x1;
224 float deltaY = y3 - y1;
225 float distance = MATH_ABS(((x2 - x3) * deltaY - (y2 - y3) * deltaX));
226 float da;
227 if (distance > CURVE_COLLINEARITY_EPSILON) {
228 if (distance * distance <= distanceToleranceSquare_ * (deltaX * deltaX + deltaY * deltaY)) {
229 // If The Curvature Does Not Exceed The Distance Tolerance Value
230 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
231 points_.PushBack(PointF(x123, y123));
232 return;
233 }
234
235 da = MATH_ABS(FastAtan2F(y3 - y2, x3 - x2) - FastAtan2F(y2 - y1, x2 - x1));
236 if (da >= PI) {
237 da = TWO_TIMES * PI - da;
238 }
239
240 if (da < angleTolerance_) {
241 points_.PushBack(PointF(x123, y123));
242 return;
243 }
244 }
245 } else {
246 da = deltaX * deltaX + deltaY * deltaY;
247 if (da == 0) {
248 distance = CalcSqDistance(x1, y1, x2, y2);
249 } else {
250 distance = ((x2 - x1) * deltaX + (y2 - y1) * deltaY) / da;
251 if (distance > 0 && distance < 1) {
252 // Simple Collinear Case,1---2---3
253 // We Can Leave Only Two Endpoints
254 return;
255 }
256 if (distance <= 0) {
257 distance = CalcSqDistance(x2, y2, x1, y1);
258 } else if (distance >= 1) {
259 distance = CalcSqDistance(x2, y2, x3, y3);
260 } else {
261 distance = CalcSqDistance(x2, y2, x1 + distance * deltaX, y1 + distance * deltaY);
262 }
263 }
264 if (distance < distanceToleranceSquare_) {
265 points_.PushBack(PointF(x2, y2));
266 return;
267 }
268 }
269
270 // Continue Subdivision
271 Recursive(x1, y1, x12, y12, x123, y123, level + 1);
272 Recursive(x123, y123, x23, y23, x3, y3, level + 1);
273 }
274
Bezier(float x1,float y1,float x2,float y2,float x3,float y3)275 void QuadrBezierCurveDividOp::Bezier(float x1, float y1,
276 float x2, float y2,
277 float x3, float y3)
278 {
279 points_.PushBack(PointF(x1, y1));
280 Recursive(x1, y1, x2, y2, x3, y3, 0);
281 points_.PushBack(PointF(x3, y3));
282 }
283
ApproximationScale(float scale)284 void CubicBezierCurveIncrement::ApproximationScale(float scale)
285 {
286 approximationScale_ = scale;
287 }
288
ApproximationScale() const289 float CubicBezierCurveIncrement::ApproximationScale() const
290 {
291 return approximationScale_;
292 }
293
Init(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)294 void CubicBezierCurveIncrement::Init(float x1, float y1,
295 float x2, float y2,
296 float x3, float y3,
297 float x4, float y4)
298 {
299 startCoordinate_.x = x1;
300 startCoordinate_.y = y1;
301 endCoordinate_.x = x4;
302 endCoordinate_.y = y4;
303
304 float deltaX1 = x2 - x1;
305 float deltaY1 = y2 - y1;
306 float deltaX2 = x3 - x2;
307 float deltaY2 = y3 - y2;
308 float deltaX3 = x4 - x3;
309 float deltaY3 = y4 - y3;
310
311 float len = (Sqrt(deltaX1 * deltaX1 + deltaY1 * deltaY1) +
312 Sqrt(deltaX2 * deltaX2 + deltaY2 * deltaY2) +
313 Sqrt(deltaX3 * deltaX3 + deltaY3 * deltaY3)) *
314 CURVES_NUM_STEP_LEN * approximationScale_;
315
316 numberSteps_ = MATH_UROUND(len);
317 const int32_t cuvereNumStep = 4;
318 if (numberSteps_ < cuvereNumStep) {
319 numberSteps_ = cuvereNumStep;
320 }
321 if (numberSteps_ == 0) {
322 return;
323 }
324 float subdivideStep = 1.0f / numberSteps_;
325 float subdivideStep2 = subdivideStep * subdivideStep;
326 float subdivideStep3 = subdivideStep * subdivideStep * subdivideStep;
327 const float prelMin = 3.0f;
328 const float prelMax = 6.0f;
329
330 float pre1 = prelMin * subdivideStep;
331 float pre2 = prelMin * subdivideStep2;
332 float pre4 = prelMax * subdivideStep2;
333 float pre5 = prelMax * subdivideStep3;
334
335 float tmp1X = x1 - x2 * FLOATNUM + x3;
336 float tmp1Y = y1 - y2 * FLOATNUM + y3;
337
338 float tmp2X = (x2 - x3) * prelMin - x1 + x4;
339 float tmp2Y = (y2 - y3) * prelMin - y1 + y4;
340
341 savedFinalCoordinate_.x = x1;
342 finalCoordinate_.x = x1;
343 savedFinalCoordinate_.y = y1;
344 finalCoordinate_.y = y1;
345
346 savedDeltaFinalCoordinate_.x = (x2 - x1) * pre1 + tmp1X * pre2 + tmp2X * subdivideStep3;
347 deltaFinalCoordinate_.x = (x2 - x1) * pre1 + tmp1X * pre2 + tmp2X * subdivideStep3;
348 savedDeltaFinalCoordinate_.y = (y2 - y1) * pre1 + tmp1Y * pre2 + tmp2Y * subdivideStep3;
349 deltaFinalCoordinate_.y = (y2 - y1) * pre1 + tmp1Y * pre2 + tmp2Y * subdivideStep3;
350
351 savedCopyDeltaFinalCoordinate_.x = tmp1X * pre4 + tmp2X * pre5;
352 copyDeltaFinalCoordinate_.x = tmp1X * pre4 + tmp2X * pre5;
353 savedCopyDeltaFinalCoordinate_.y = tmp1Y * pre4 + tmp2Y * pre5;
354 copyDeltaFinalCoordinate_.y = tmp1Y * pre4 + tmp2Y * pre5;
355
356 repeatCopyDeltaFinalCoordinate_.x = tmp2X * pre5;
357 repeatCopyDeltaFinalCoordinate_.y = tmp2Y * pre5;
358
359 currentStep_ = numberSteps_;
360 }
361
Reset()362 void CubicBezierCurveIncrement::Reset()
363 {
364 numberSteps_ = 0;
365 currentStep_ = -1;
366 }
367
ApproximationMethod() const368 CurveApproximationMethod CubicBezierCurveIncrement::ApproximationMethod() const
369 {
370 return CURVEINCREMENT;
371 }
372
AngleTolerance() const373 float CubicBezierCurveIncrement::AngleTolerance() const
374 {
375 return 0.0f;
376 }
377
CuspLimit() const378 float CubicBezierCurveIncrement::CuspLimit() const
379 {
380 return 0.0f;
381 }
382
Rewind(uint32_t)383 void CubicBezierCurveIncrement::Rewind(uint32_t)
384 {
385 if (numberSteps_ == 0) {
386 currentStep_ = -1;
387 return;
388 }
389
390 currentStep_ = numberSteps_;
391 finalCoordinate_.x = savedFinalCoordinate_.x;
392 finalCoordinate_.y = savedFinalCoordinate_.y;
393 deltaFinalCoordinate_.x = savedDeltaFinalCoordinate_.x;
394 deltaFinalCoordinate_.y = savedDeltaFinalCoordinate_.y;
395 copyDeltaFinalCoordinate_.x = savedCopyDeltaFinalCoordinate_.x;
396 copyDeltaFinalCoordinate_.y = savedCopyDeltaFinalCoordinate_.y;
397 }
398
GenerateVertex(float * x,float * y)399 uint32_t CubicBezierCurveIncrement::GenerateVertex(float* x, float* y)
400 {
401 if (currentStep_ < 0) {
402 return PATH_CMD_STOP;
403 }
404 if (currentStep_ == numberSteps_) {
405 *x = startCoordinate_.x;
406 *y = startCoordinate_.y;
407 --currentStep_;
408 return PATH_CMD_MOVE_TO;
409 }
410
411 if (currentStep_ == 0) {
412 *x = endCoordinate_.x;
413 *y = endCoordinate_.y;
414 --currentStep_;
415 return PATH_CMD_LINE_TO;
416 }
417
418 finalCoordinate_.x += deltaFinalCoordinate_.x;
419 finalCoordinate_.y += deltaFinalCoordinate_.y;
420 deltaFinalCoordinate_.x += copyDeltaFinalCoordinate_.x;
421 deltaFinalCoordinate_.y += copyDeltaFinalCoordinate_.y;
422 copyDeltaFinalCoordinate_.x += repeatCopyDeltaFinalCoordinate_.x;
423 copyDeltaFinalCoordinate_.y += repeatCopyDeltaFinalCoordinate_.y;
424
425 *x = finalCoordinate_.x;
426 *y = finalCoordinate_.y;
427 --currentStep_;
428 return PATH_CMD_LINE_TO;
429 }
430
Init(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)431 void CubicBezierCurveDividOperate::Init(float x1, float y1,
432 float x2, float y2,
433 float x3, float y3,
434 float x4, float y4)
435 {
436 points_.Clear();
437 distanceToleranceSquare_ = HALFNUM / approximationScale_;
438 distanceToleranceSquare_ *= distanceToleranceSquare_;
439 Bezier(x1, y1, x2, y2, x3, y3, x4, y4);
440 count_ = 0;
441 }
442
Reset()443 void CubicBezierCurveDividOperate::Reset()
444 {
445 points_.Clear();
446 count_ = 0;
447 }
448
ApproximationMethod() const449 CurveApproximationMethod CubicBezierCurveDividOperate::ApproximationMethod() const
450 {
451 return CURVEDIVIDOPERATE;
452 }
453
ApproximationScale(float scale)454 void CubicBezierCurveDividOperate::ApproximationScale(float scale)
455 {
456 approximationScale_ = scale;
457 }
458
ApproximationScale() const459 float CubicBezierCurveDividOperate::ApproximationScale() const
460 {
461 return approximationScale_;
462 }
463
AngleTolerance(float angleValue)464 void CubicBezierCurveDividOperate::AngleTolerance(float angleValue)
465 {
466 angleTolerance_ = angleValue;
467 }
468
AngleTolerance() const469 float CubicBezierCurveDividOperate::AngleTolerance() const
470 {
471 return angleTolerance_;
472 }
473
CuspLimit(float angleValue)474 void CubicBezierCurveDividOperate::CuspLimit(float angleValue)
475 {
476 cuspLimit_ = (angleValue == 0.0f) ? 0.0f : PI - angleValue;
477 }
478
CuspLimit() const479 float CubicBezierCurveDividOperate::CuspLimit() const
480 {
481 return (cuspLimit_ == 0.0f) ? 0.0f : PI - cuspLimit_;
482 }
483
Rewind(uint32_t)484 void CubicBezierCurveDividOperate::Rewind(uint32_t)
485 {
486 count_ = 0;
487 }
488
GenerateVertex(float * x,float * y)489 uint32_t CubicBezierCurveDividOperate::GenerateVertex(float* x, float* y)
490 {
491 if (count_ >= points_.Size()) {
492 return PATH_CMD_STOP;
493 }
494 const PointF& p = points_[count_++];
495 *x = p.x;
496 *y = p.y;
497 return (count_ == 1) ? PATH_CMD_MOVE_TO : PATH_CMD_LINE_TO;
498 }
499
Recursive(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,uint32_t level)500 void CubicBezierCurveDividOperate::Recursive(float x1, float y1,
501 float x2, float y2,
502 float x3, float y3,
503 float x4, float y4,
504 uint32_t level)
505 {
506 if (level > CURVE_RECURSION_LIMIT) {
507 return;
508 }
509
510 /** Calculates All Midpoints Of a Segment */
511 float x12 = (x1 + x2) / FLOATNUM;
512 float y12 = (y1 + y2) / FLOATNUM;
513 float x23 = (x2 + x3) / FLOATNUM;
514 float y23 = (y2 + y3) / FLOATNUM;
515 float x34 = (x3 + x4) / FLOATNUM;
516 float y34 = (y3 + y4) / FLOATNUM;
517 float x123 = (x12 + x23) / FLOATNUM;
518 float y123 = (y12 + y23) / FLOATNUM;
519 float x234 = (x23 + x34) / FLOATNUM;
520 float y234 = (y23 + y34) / FLOATNUM;
521 float x1234 = (x123 + x234) / FLOATNUM;
522 float y1234 = (y123 + y234) / FLOATNUM;
523 /** Try to Approximate the Entire Cubic Curve With a Straight Line */
524 float delta41X = x4 - x1;
525 float delta41Y = y4 - y1;
526 float delta2 = MATH_ABS(((x2 - x4) * delta41Y - (y2 - y4) * delta41X));
527 float delta3 = MATH_ABS(((x3 - x4) * delta41Y - (y3 - y4) * delta41X));
528 float dxTemp;
529 float dyTemp;
530 float delta41;
531
532 bool isEnabled = true;
533 switch ((int32_t(delta2 > CURVE_COLLINEARITY_EPSILON) << 1) + int32_t(delta3 > CURVE_COLLINEARITY_EPSILON)) {
534 case COLLINEAR:
535 /** All are Collinear or p1 == p4 */
536 delta41 = delta41X * delta41X + delta41Y * delta41Y;
537 if (delta41 == 0) {
538 delta2 = CalcSqDistance(x1, y1, x2, y2);
539 delta3 = CalcSqDistance(x4, y4, x3, y3);
540 } else {
541 delta41 = 1 / delta41;
542 dxTemp = x2 - x1;
543 dyTemp = y2 - y1;
544 delta2 = delta41 * (dxTemp * delta41X + dyTemp * delta41Y);
545 dxTemp = x3 - x1;
546 dyTemp = y3 - y1;
547 delta3 = delta41 * (dxTemp * delta41X + dyTemp * delta41Y);
548 if (delta2 > 0 && delta2 < 1 && delta3 > 0 && delta3 < 1) {
549 /** Simple Collinear Case,1--2--3--4 */
550 /** We Can Leave Only Two Endpoints */
551 return;
552 }
553
554 if (delta2 <= 0) {
555 delta2 = CalcSqDistance(x2, y2, x1, y1);
556 } else if (delta2 >= 1) {
557 delta2 = CalcSqDistance(x2, y2, x4, y4);
558 } else {
559 delta2 = CalcSqDistance(x2, y2, x1 + delta2 * delta41X, y1 + delta2 * delta41Y);
560 }
561 if (delta3 <= 0) {
562 delta3 = CalcSqDistance(x3, y3, x1, y1);
563 } else if (delta3 >= 1) {
564 delta3 = CalcSqDistance(x3, y3, x4, y4);
565 } else {
566 delta3 = CalcSqDistance(x3, y3, x1 + delta3 * delta41X, y1 + delta3 * delta41Y);
567 }
568 }
569
570 if (delta2 > delta3) {
571 if (delta2 < distanceToleranceSquare_) {
572 points_.PushBack(PointF(x2, y2));
573 isEnabled = false;
574 }
575 } else {
576 if (delta3 < distanceToleranceSquare_) {
577 points_.PushBack(PointF(x3, y3));
578 isEnabled = false;
579 }
580 }
581 break;
582 case COLLINEAR1:
583 /** p1、p2、p4 is Collinear */
584 if (delta3 * delta3 <= distanceToleranceSquare_ * (delta41X * delta41X + delta41Y * delta41Y)) {
585 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
586 points_.PushBack(PointF(x23, y23));
587 isEnabled = false;
588 }
589 if (isEnabled) {
590 dxTemp = MATH_ABS(FastAtan2F(y4 - y3, x4 - x3) - FastAtan2F(y3 - y2, x3 - x2));
591 if (dxTemp >= PI) {
592 dxTemp = FLOATNUM * PI - dxTemp;
593 }
594 if (dxTemp < angleTolerance_) {
595 points_.PushBack(PointF(x2, y2));
596 points_.PushBack(PointF(x3, y3));
597 isEnabled = false;
598 }
599 if (isEnabled && cuspLimit_ != 0.0f && dxTemp > cuspLimit_) {
600 points_.PushBack(PointF(x3, y3));
601 isEnabled = false;
602 }
603 }
604 }
605 break;
606 case COLLINEAR2:
607 /** p1、p3、p4 is Collinear. */
608 if (delta2 * delta2 <= distanceToleranceSquare_ * (delta41X * delta41X + delta41Y * delta41Y)) {
609 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
610 points_.PushBack(PointF(x23, y23));
611 isEnabled = false;
612 }
613 if (isEnabled) {
614 dxTemp = MATH_ABS(FastAtan2F(y3 - y2, x3 - x2) - FastAtan2F(y2 - y1, x2 - x1));
615 if (dxTemp >= PI) {
616 dxTemp = FLOATNUM * PI - dxTemp;
617 }
618 if (dxTemp < angleTolerance_) {
619 points_.PushBack(PointF(x2, y2));
620 points_.PushBack(PointF(x3, y3));
621 isEnabled = false;
622 }
623 if (isEnabled && cuspLimit_ != 0.0f && dxTemp > cuspLimit_) {
624 points_.PushBack(PointF(x2, y2));
625 isEnabled = false;
626 }
627 }
628 }
629 break;
630 case COLLINEAR3:
631 if ((delta2 + delta3) * (delta2 + delta3) <=
632 distanceToleranceSquare_ * (delta41X * delta41X + delta41Y * delta41Y)) {
633 if (angleTolerance_ < CURVE_ANGLE_TO_LERANCE_EPSILON) {
634 points_.PushBack(PointF(x23, y23));
635 isEnabled = false;
636 }
637 delta41 = FastAtan2F(y3 - y2, x3 - x2);
638 dxTemp = MATH_ABS(delta41 - FastAtan2F(y2 - y1, x2 - x1));
639 dyTemp = MATH_ABS(FastAtan2F(y4 - y3, x4 - x3) - delta41);
640 if (dxTemp >= PI) {
641 dxTemp = FLOATNUM * PI - dxTemp;
642 }
643 if (dyTemp >= PI) {
644 dyTemp = FLOATNUM * PI - dyTemp;
645 }
646 if (isEnabled) {
647 if (dxTemp + dyTemp < angleTolerance_) {
648 points_.PushBack(PointF(x23, y23));
649 isEnabled = false;
650 }
651 if (isEnabled && cuspLimit_ != 0.0f && dxTemp > cuspLimit_) {
652 points_.PushBack(PointF(x2, y2));
653 isEnabled = false;
654 }
655 if (isEnabled && cuspLimit_ != 0.0f && dyTemp > cuspLimit_) {
656 points_.PushBack(PointF(x3, y3));
657 isEnabled = false;
658 }
659 }
660 }
661 break;
662 }
663 if (!isEnabled) {
664 return;
665 }
666 Recursive(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
667 Recursive(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
668 }
669
Bezier(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)670 void CubicBezierCurveDividOperate::Bezier(float x1, float y1,
671 float x2, float y2,
672 float x3, float y3,
673 float x4, float y4)
674 {
675 points_.PushBack(PointF(x1, y1));
676 Recursive(x1, y1, x2, y2, x3, y3, x4, y4, 0);
677 points_.PushBack(PointF(x4, y4));
678 }
679 } // namespace OHOS
680