Blender  V2.93
BLI_dial_2d.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include "BLI_dial_2d.h"
22 #include "BLI_math.h"
23 
24 #include "MEM_guardedalloc.h"
25 
26 struct Dial {
27  /* center of the dial */
28  float center[2];
29 
30  /* threshold of the dial. Distance of current position has to be greater
31  * than the threshold to be used in any calculations */
33 
34  /* the direction of the first dial position exceeding the threshold. This
35  * is later used as the basis against which rotation angle is calculated */
37 
38  /* cache the last angle to detect rotations bigger than -/+ PI */
39  float last_angle;
40 
41  /* number of full rotations */
42  int rotations;
43 
44  /* has initial_direction been initialized */
46 };
47 
48 Dial *BLI_dial_init(const float start_position[2], float threshold)
49 {
50  Dial *dial = MEM_callocN(sizeof(Dial), "dial");
51 
52  copy_v2_v2(dial->center, start_position);
53  dial->threshold_squared = threshold * threshold;
54 
55  return dial;
56 }
57 
58 float BLI_dial_angle(Dial *dial, const float current_position[2])
59 {
60  float current_direction[2];
61 
62  sub_v2_v2v2(current_direction, current_position, dial->center);
63 
64  /* only update when we have enough precision,
65  * by having the mouse adequately away from center */
66  if (len_squared_v2(current_direction) > dial->threshold_squared) {
67  float angle;
68  float cosval, sinval;
69 
70  normalize_v2(current_direction);
71 
72  if (!dial->initialized) {
73  copy_v2_v2(dial->initial_direction, current_direction);
74  dial->initialized = true;
75  }
76 
77  /* calculate mouse angle between initial and final mouse position */
78  cosval = dot_v2v2(current_direction, dial->initial_direction);
79  sinval = cross_v2v2(current_direction, dial->initial_direction);
80 
81  /* clamp to avoid nans in #acos */
83 
84  /* change of sign, we passed the 180 degree threshold. This means we need to add a turn.
85  * to distinguish between transition from 0 to -1 and -PI to +PI,
86  * use comparison with PI/2 */
87  if ((angle * dial->last_angle < 0.0f) && (fabsf(dial->last_angle) > (float)M_PI_2)) {
88  if (dial->last_angle < 0.0f) {
89  dial->rotations--;
90  }
91  else {
92  dial->rotations++;
93  }
94  }
95  dial->last_angle = angle;
96 
97  return angle + 2.0f * (float)M_PI * dial->rotations;
98  }
99 
100  return dial->last_angle;
101 }
typedef float(TangentPoint)[2]
Dial * BLI_dial_init(const float start_position[2], float threshold)
Definition: BLI_dial_2d.c:48
float BLI_dial_angle(Dial *dial, const float current_position[2])
Definition: BLI_dial_2d.c:58
#define M_PI_2
Definition: BLI_math_base.h:41
#define M_PI
Definition: BLI_math_base.h:38
MINLINE float len_squared_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v2(float r[2])
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
static const float sinval[CIRCLE_RESOL]
Definition: drawobject.c:55
static const float cosval[CIRCLE_RESOL]
Definition: drawobject.c:64
#define atan2f(x, y)
#define fabsf(x)
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
float center[2]
Definition: BLI_dial_2d.c:28
float initial_direction[2]
Definition: BLI_dial_2d.c:36
float last_angle
Definition: BLI_dial_2d.c:39
float threshold_squared
Definition: BLI_dial_2d.c:32
bool initialized
Definition: BLI_dial_2d.c:45
int rotations
Definition: BLI_dial_2d.c:42