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_arc.h"
17 namespace OHOS {
18 #if defined(GRAPHIC_ENABLE_ARC_FLAG) && GRAPHIC_ENABLE_ARC_FLAG
19 const int32_t CURVERENUMSTEP = 4;
GeometryArc(float centerX,float centerY,float rx,float ry,float start,float end,bool isClockwise)20 GeometryArc::GeometryArc(float centerX, float centerY,
21                          float rx, float ry,
22                          float start, float end,
23                          bool isClockwise)
24     : centerX_(centerX), centerY_(centerY), radiusX_(rx), radiusY_(ry), expansionRatio_(1.0)
25 {
26     Normalize(start, end, isClockwise);
27 }
28 
SetApproximationScale(float sale)29 void GeometryArc::SetApproximationScale(float sale)
30 {
31     expansionRatio_ = sale;
32     if (initialized_) {
33         Normalize(beginAngle_, endAngle_, isClockwise_);
34     }
35 }
36 
GenerateVertex(float * x,float * y)37 uint32_t GeometryArc::GenerateVertex(float* x, float* y)
38 {
39     // The current command is an end point with no vertices
40     if (IsStop(pathCommand_)) {
41         return PATH_CMD_STOP;
42     }
43     if ((currentAngle_ < endAngle_ - deltaAngle_ / CURVERENUMSTEP) != isClockwise_) {
44         *x = centerX_ + Cos(endAngle_ * RADIAN_TO_ANGLE) * radiusX_;
45         *y = centerY_ + Sin(endAngle_ * RADIAN_TO_ANGLE) * radiusY_;
46         pathCommand_ = PATH_CMD_STOP;
47         return PATH_CMD_LINE_TO;
48     }
49 
50     *x = centerX_ + Cos(currentAngle_ * RADIAN_TO_ANGLE) * radiusX_;
51     *y = centerY_ + Sin(currentAngle_ * RADIAN_TO_ANGLE) * radiusY_;
52 
53     currentAngle_ += deltaAngle_;
54 
55     uint32_t pf = pathCommand_;
56     pathCommand_ = PATH_CMD_LINE_TO;
57     return pf;
58 }
59 
Rewind(uint32_t)60 void GeometryArc::Rewind(uint32_t)
61 {
62     pathCommand_ = PATH_CMD_MOVE_TO;
63     currentAngle_ = beginAngle_;
64 }
65 
Normalize(float startAngle,float endAngle,bool isClockwise)66 void GeometryArc::Normalize(float startAngle, float endAngle, bool isClockwise)
67 {
68     float ra = (MATH_ABS(radiusX_) + MATH_ABS(radiusY_)) / FLOATNUM;
69     // Calculate the radian change rate
70     deltaAngle_ = Acos(ra / (ra + RADDALETAELPS / expansionRatio_)) * FLOATNUM;
71     if (isClockwise) {
72         while (endAngle < startAngle) {
73             endAngle += PI * FLOATNUM;
74         }
75     } else {
76         while (startAngle < endAngle) {
77             startAngle += PI * FLOATNUM;
78         }
79         deltaAngle_ = -deltaAngle_;
80     }
81     isClockwise_ = isClockwise;
82     beginAngle_ = startAngle;
83     endAngle_ = endAngle;
84     initialized_ = true;
85 }
86 
Init(float centerX,float centerY,float rx,float ry,float startAngle,float endAngle,bool isClockwise)87 void GeometryArc::Init(float centerX, float centerY, float rx, float ry,
88                        float startAngle, float endAngle, bool isClockwise)
89 {
90     centerX_ = centerX;
91     centerY_ = centerY;
92     radiusX_ = rx;
93     radiusY_ = ry;
94     Normalize(startAngle, endAngle, isClockwise);
95 }
96 #endif
97 } // namespace OHOS
98