1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** GUIX Component                                                        */
16 /**                                                                       */
17 /**   Utility (Utility)                                                   */
18 /**                                                                       */
19 /**************************************************************************/
20 
21 #define GX_SOURCE_CODE
22 
23 
24 /* Include necessary system files.  */
25 
26 #include "gx_api.h"
27 #include "gx_system.h"
28 #include "gx_utility.h"
29 
30 /**************************************************************************/
31 /*                                                                        */
32 /*  FUNCTION                                               RELEASE        */
33 /*                                                                        */
34 /*    _gx_utility_circle_point_get                        PORTABLE C      */
35 /*                                                           6.1          */
36 /*  AUTHOR                                                                */
37 /*                                                                        */
38 /*    Kenneth Maxwell, Microsoft Corporation                              */
39 /*                                                                        */
40 /*  DESCRIPTION                                                           */
41 /*                                                                        */
42 /*    This function gets the point on circle with specified angle         */
43 /*    and radius.                                                         */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    xcenter                               x-coord of center of circle   */
48 /*    ycenter                               y-coord of center of circle   */
49 /*    r                                     Radius of circle              */
50 /*    angle                                 The angle where the point is  */
51 /*    point                                 Return value of the point at  */
52 /*                                            the angle                   */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    None                                                                */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    _gx_utility_math_cos                  Compute cosine                */
61 /*    _gx_utility_math_sin                  Compute sine                  */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    Application Code                                                    */
66 /*    GUIX Internal Code                                                  */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
73 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*                                                                        */
76 /**************************************************************************/
_gx_utility_circle_point_get(INT xcenter,INT ycenter,UINT r,INT angle,GX_POINT * point)77 UINT _gx_utility_circle_point_get(INT xcenter, INT ycenter, UINT r, INT angle, GX_POINT *point)
78 {
79 
80 INT     x;
81 INT     y;
82 INT     d;
83 INT     x_sign;
84 INT     y_sign;
85 GX_BOOL swap = GX_FALSE;
86 
87     angle %= 360;
88 
89     if (angle < 0)
90     {
91         angle += 360;
92     }
93 
94     if (angle == 0)
95     {
96         point -> gx_point_x = (GX_VALUE)(xcenter + (INT)r);
97         point -> gx_point_y = (GX_VALUE)ycenter;
98     }
99     else if (angle == 90)
100     {
101         point -> gx_point_x = (GX_VALUE)xcenter;
102         point -> gx_point_y = (GX_VALUE)(ycenter - (INT)r);
103     }
104     else if (angle == 180)
105     {
106         point -> gx_point_x = (GX_VALUE)(xcenter - (INT)r);
107         point -> gx_point_y = (GX_VALUE)ycenter;
108     }
109     else if (angle == 270)
110     {
111         point -> gx_point_x = (GX_VALUE)xcenter;
112         point -> gx_point_y = (GX_VALUE)(ycenter + (INT)r);
113     }
114     else
115     {
116         point -> gx_point_x = (GX_VALUE)(GX_FIXED_VAL_TO_INT(r * _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle))));
117         point -> gx_point_y = (GX_VALUE)(GX_FIXED_VAL_TO_INT(r * _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle))));
118 
119         if (angle <= 90)
120         {
121             x_sign = 1;
122             y_sign = 1;
123 
124             if (angle < 45)
125             {
126                 swap = GX_TRUE;
127             }
128         }
129         else if (angle <= 180)
130         {
131             x_sign = -1;
132             y_sign = 1;
133 
134             if (angle > 135)
135             {
136                 swap = GX_TRUE;
137             }
138         }
139         else if (angle <= 270)
140         {
141             x_sign = -1;
142             y_sign = -1;
143 
144             if (angle < 225)
145             {
146                 swap = GX_TRUE;
147             }
148         }
149         else
150         {
151             x_sign = 1;
152             y_sign = -1;
153 
154             if (angle > 315)
155             {
156                 swap = GX_TRUE;
157             }
158         }
159 
160         x = 0;
161         y = (INT)r;
162         d = (INT)(5 - 4 * r);
163 
164         point -> gx_point_x = (GX_VALUE)(point -> gx_point_x * x_sign);
165         point -> gx_point_y = (GX_VALUE)(point -> gx_point_y * y_sign);
166 
167         if (swap)
168         {
169             GX_SWAP_VALS(point -> gx_point_x, point -> gx_point_y);
170         }
171 
172         while (x <= y)
173         {
174             if ((x > point -> gx_point_x) || (y < point -> gx_point_y))
175             {
176                 break;
177             }
178 
179             if (d < 0)
180             {
181                 d += 8 * x + 12;
182             }
183             else
184             {
185                 d += 8 * (x - y) + 20;
186                 y--;
187             }
188             x++;
189         }
190 
191         if (swap)
192         {
193             GX_SWAP_VALS(x, y);
194         }
195 
196         x *= x_sign;
197         y *= y_sign;
198 
199         point -> gx_point_x = (GX_VALUE)(xcenter + x);
200         point -> gx_point_y = (GX_VALUE)(ycenter - y);
201     }
202 
203     return GX_SUCCESS;
204 }
205 
206