Skip to content

Commit 04026eb

Browse files
authored
Change direction of angles (#715)
* Add additional thick line tests * Change direction of angles
1 parent 11f3fde commit 04026eb

9 files changed

Lines changed: 254 additions & 102 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ Embedded Graphics is a `no_std` library for adding graphics features to display
8282
- **(breaking)** [#688](https://github.com/embedded-graphics/embedded-graphics/pull/688) `MonoFont` is now `Send + Sync`; implementations of `GlyphMapping` must be `Sync`.
8383
- **(breaking)** [#663](https://github.com/embedded-graphics/embedded-graphics/pull/663) Upgraded Cargo dependencies to their latest versions.
8484
- **(breaking)** [#689](https://github.com/embedded-graphics/embedded-graphics/pull/689) Bump Minimum Supported Rust Version (MSRV) to 1.61.
85+
- **(breaking)** [#715](https://github.com/embedded-graphics/embedded-graphics/pull/715) Changed the direction of angles. Positive angles are now clockwise.
8586

8687
### Fixed
8788

src/geometry/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub(crate) trait PointExt {
3636

3737
impl PointExt for Point {
3838
fn rotate_90(self) -> Self {
39-
Self::new(self.y, -self.x)
39+
Self::new(-self.y, self.x)
4040
}
4141

4242
fn dot_product(self, other: Point) -> i32 {
@@ -65,9 +65,9 @@ mod tests {
6565

6666
#[test]
6767
fn rotate_90() {
68-
assert_eq!(Point::new(1, 0).rotate_90(), Point::new(0, -1));
69-
assert_eq!(Point::new(0, -2).rotate_90(), Point::new(-2, 0));
70-
assert_eq!(Point::new(-3, 0).rotate_90(), Point::new(0, 3));
71-
assert_eq!(Point::new(0, 4).rotate_90(), Point::new(4, 0));
68+
assert_eq!(Point::new(1, 0).rotate_90(), Point::new(0, 1));
69+
assert_eq!(Point::new(0, -2).rotate_90(), Point::new(2, 0));
70+
assert_eq!(Point::new(-3, 0).rotate_90(), Point::new(0, -3));
71+
assert_eq!(Point::new(0, 4).rotate_90(), Point::new(-4, 0));
7272
}
7373
}

src/primitives/arc/styled.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ mod tests {
119119
fn tiny_arc() -> Result<(), core::convert::Infallible> {
120120
let mut display = MockDisplay::new();
121121

122-
Arc::new(Point::zero(), 7, 30.0.deg(), 120.0.deg())
122+
Arc::new(Point::zero(), 7, 210.0.deg(), 120.0.deg())
123123
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))
124124
.draw(&mut display)?;
125125

@@ -138,14 +138,14 @@ mod tests {
138138

139139
for &diameter in &[11, 12] {
140140
for &(angle_start, angle_sweep, anchor_point) in &[
141-
(0.0.deg(), 90.0.deg(), AnchorPoint::TopRight),
142-
(90.0.deg(), 90.0.deg(), AnchorPoint::TopLeft),
143-
(180.0.deg(), 90.0.deg(), AnchorPoint::BottomLeft),
144-
(270.0.deg(), 90.0.deg(), AnchorPoint::BottomRight),
145-
(0.0.deg(), -90.0.deg(), AnchorPoint::BottomRight),
146-
(90.0.deg(), -90.0.deg(), AnchorPoint::TopRight),
147-
(180.0.deg(), -90.0.deg(), AnchorPoint::TopLeft),
148-
(270.0.deg(), -90.0.deg(), AnchorPoint::BottomLeft),
141+
(0.0.deg(), 90.0.deg(), AnchorPoint::BottomRight),
142+
(90.0.deg(), 90.0.deg(), AnchorPoint::BottomLeft),
143+
(180.0.deg(), 90.0.deg(), AnchorPoint::TopLeft),
144+
(270.0.deg(), 90.0.deg(), AnchorPoint::TopRight),
145+
(0.0.deg(), -90.0.deg(), AnchorPoint::TopRight),
146+
(90.0.deg(), -90.0.deg(), AnchorPoint::BottomRight),
147+
(180.0.deg(), -90.0.deg(), AnchorPoint::BottomLeft),
148+
(270.0.deg(), -90.0.deg(), AnchorPoint::TopLeft),
149149
] {
150150
let circle = Circle::new(Point::new(1, 1), diameter).into_styled(style);
151151

src/primitives/common/line_join.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,7 @@ impl LineJoin {
214214
// Line segments overlap (degenerate)
215215
else {
216216
Self {
217-
kind: match outer_side {
218-
LineSide::Left => JoinKind::Degenerate { outer_side },
219-
LineSide::Right => JoinKind::Degenerate { outer_side },
220-
},
217+
kind: JoinKind::Degenerate { outer_side },
221218
first_edge_end: EdgeCorners {
222219
left: first_edge_left.end,
223220
right: first_edge_right.end,

src/primitives/common/linear_equation.rs

Lines changed: 146 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ impl LinearEquation {
6060
let distance = self.distance(point);
6161

6262
match side {
63-
LineSide::Right => distance <= 0,
64-
LineSide::Left => distance >= 0,
63+
LineSide::Left => distance <= 0,
64+
LineSide::Right => distance >= 0,
6565
}
6666
}
6767
}
@@ -79,12 +79,13 @@ impl OriginLinearEquation {
7979
// FIXME: angle.tan() for 180.0 degrees isn't exactly 0 which causes problems when drawing
8080
// a single quadrant. Is there a better solution to fix this?
8181
let normal_vector = if angle == Angle::from_degrees(180.0) {
82-
Point::new(0, NORMAL_VECTOR_SCALE)
82+
Point::new(0, -NORMAL_VECTOR_SCALE)
8383
} else {
84-
-Point::new(
85-
i32::from(angle.sin() * Real::from(NORMAL_VECTOR_SCALE)),
84+
Point::new(
8685
i32::from(angle.cos() * Real::from(NORMAL_VECTOR_SCALE)),
86+
i32::from(angle.sin() * Real::from(NORMAL_VECTOR_SCALE)),
8787
)
88+
.rotate_90()
8889
};
8990

9091
Self { normal_vector }
@@ -93,15 +94,15 @@ impl OriginLinearEquation {
9394
/// Creates a new horizontal linear equation.
9495
pub const fn new_horizontal() -> Self {
9596
Self {
96-
normal_vector: Point::new(0, -NORMAL_VECTOR_SCALE),
97+
normal_vector: Point::new(0, NORMAL_VECTOR_SCALE),
9798
}
9899
}
99100

100101
/// Returns the distance between the line and a point.
101102
///
102103
/// The scaling of the returned value depends on the length of the normal vector.
103-
/// Positive values will be returned for points on the left side of the line and negative
104-
/// values for points on the right.
104+
/// Positive values will be returned for points on the right side of the line and negative
105+
/// values for points on the left.
105106
pub fn distance(&self, point: Point) -> i32 {
106107
point.dot_product(self.normal_vector)
107108
}
@@ -113,8 +114,8 @@ impl OriginLinearEquation {
113114
let distance = self.distance(point);
114115

115116
match side {
116-
LineSide::Right => distance <= 0,
117-
LineSide::Left => distance >= 0,
117+
LineSide::Left => distance <= 0,
118+
LineSide::Right => distance >= 0,
118119
}
119120
}
120121
}
@@ -129,26 +130,26 @@ mod tests {
129130
assert_eq!(
130131
LinearEquation::from_line(&Line::new(Point::zero(), Point::new(1, 0))),
131132
LinearEquation {
132-
normal_vector: Point::new(0, -1),
133+
normal_vector: Point::new(0, 1),
133134
origin_distance: 0, // line goes through the origin
134135
}
135136
);
136137

137138
assert_eq!(
138139
LinearEquation::from_line(&Line::new(Point::zero(), Point::new(0, 1))),
139140
LinearEquation {
140-
normal_vector: Point::new(1, 0),
141+
normal_vector: Point::new(-1, 0),
141142
origin_distance: 0, // line goes through the origin
142143
}
143144
);
144145

145146
assert_eq!(
146147
LinearEquation::from_line(&Line::new(Point::new(2, 3), Point::new(-2, 3))),
147148
LinearEquation {
148-
normal_vector: Point::new(0, 4),
149+
normal_vector: Point::new(0, -4),
149150
// origin_distance = min. distance between line and origin * length of unit vector
150151
// = 3 * 4
151-
origin_distance: 12,
152+
origin_distance: -12,
152153
}
153154
);
154155
}
@@ -158,7 +159,7 @@ mod tests {
158159
assert_eq!(
159160
OriginLinearEquation::with_angle(0.0.deg()),
160161
OriginLinearEquation {
161-
normal_vector: Point::new(0, -NORMAL_VECTOR_SCALE),
162+
normal_vector: Point::new(0, NORMAL_VECTOR_SCALE),
162163
}
163164
);
164165

@@ -178,40 +179,138 @@ mod tests {
178179
}
179180

180181
#[test]
181-
fn check_side_horizontal() {
182-
let line = OriginLinearEquation::with_angle(0.0.deg());
183-
assert!(line.check_side(Point::new(0, 0), LineSide::Left));
184-
assert!(line.check_side(Point::new(1, 0), LineSide::Right));
185-
assert!(!line.check_side(Point::new(-2, 1), LineSide::Left));
186-
assert!(line.check_side(Point::new(3, 1), LineSide::Right));
187-
assert!(line.check_side(Point::new(-4, -1), LineSide::Left));
188-
assert!(!line.check_side(Point::new(5, -1), LineSide::Right));
189-
190-
let line = OriginLinearEquation::with_angle(180.0.deg());
191-
assert!(line.check_side(Point::new(0, 0), LineSide::Left));
192-
assert!(line.check_side(Point::new(1, 0), LineSide::Right));
193-
assert!(line.check_side(Point::new(-2, 1), LineSide::Left));
194-
assert!(!line.check_side(Point::new(3, 1), LineSide::Right));
195-
assert!(!line.check_side(Point::new(-4, -1), LineSide::Left));
196-
assert!(line.check_side(Point::new(5, -1), LineSide::Right));
182+
fn check_side_horizontal_0deg() {
183+
let eq1 = OriginLinearEquation::with_angle(0.0.deg());
184+
let eq2 = LinearEquation::from_line(&Line::with_delta(Point::zero(), Point::new(10, 0)));
185+
186+
use LineSide::*;
187+
for (point, side, expected) in [
188+
((0, 0), Left, true),
189+
((1, 0), Right, true),
190+
((-2, 1), Left, false),
191+
((3, 1), Right, true),
192+
((-4, -1), Left, true),
193+
((5, -1), Right, false),
194+
]
195+
.into_iter()
196+
{
197+
assert_eq!(
198+
eq1.check_side(point.into(), side),
199+
expected,
200+
"{:?}, {:?}",
201+
point,
202+
side
203+
);
204+
205+
assert_eq!(
206+
eq2.check_side(point.into(), side),
207+
expected,
208+
"{:?}, {:?}",
209+
point,
210+
side
211+
);
212+
}
197213
}
198214

199215
#[test]
200-
fn check_side_vertical() {
201-
let line = OriginLinearEquation::with_angle(90.0.deg());
202-
assert!(line.check_side(Point::new(0, 0), LineSide::Left));
203-
assert!(line.check_side(Point::new(0, -1), LineSide::Right));
204-
assert!(line.check_side(Point::new(-1, 2), LineSide::Left));
205-
assert!(!line.check_side(Point::new(-1, -3), LineSide::Right));
206-
assert!(!line.check_side(Point::new(1, 4), LineSide::Left));
207-
assert!(line.check_side(Point::new(1, -5), LineSide::Right));
208-
209-
let line = OriginLinearEquation::with_angle(270.0.deg());
210-
assert!(line.check_side(Point::new(0, 0), LineSide::Left));
211-
assert!(line.check_side(Point::new(0, 1), LineSide::Right));
212-
assert!(!line.check_side(Point::new(-1, -2), LineSide::Left));
213-
assert!(line.check_side(Point::new(-1, 3), LineSide::Right));
214-
assert!(line.check_side(Point::new(1, -4), LineSide::Left));
215-
assert!(!line.check_side(Point::new(1, 5), LineSide::Right));
216+
fn check_side_horizontal_180deg() {
217+
let eq1 = OriginLinearEquation::with_angle(180.0.deg());
218+
let eq2 = LinearEquation::from_line(&Line::with_delta(Point::zero(), Point::new(-10, 0)));
219+
220+
use LineSide::*;
221+
for (point, side, expected) in [
222+
((0, 0), Left, true),
223+
((1, 0), Right, true),
224+
((-2, 1), Left, true),
225+
((3, 1), Right, false),
226+
((-4, -1), Left, false),
227+
((5, -1), Right, true),
228+
]
229+
.into_iter()
230+
{
231+
assert_eq!(
232+
eq1.check_side(point.into(), side),
233+
expected,
234+
"{:?}, {:?}",
235+
point,
236+
side
237+
);
238+
239+
assert_eq!(
240+
eq2.check_side(point.into(), side),
241+
expected,
242+
"{:?}, {:?}",
243+
point,
244+
side
245+
);
246+
}
247+
}
248+
249+
#[test]
250+
fn check_side_vertical_90deg() {
251+
let eq1 = OriginLinearEquation::with_angle(90.0.deg());
252+
let eq2 = LinearEquation::from_line(&Line::with_delta(Point::zero(), Point::new(0, 10)));
253+
254+
use LineSide::*;
255+
for (point, side, expected) in [
256+
((0, 0), Left, true),
257+
((0, 1), Right, true),
258+
((-1, -2), Left, false),
259+
((-1, 3), Right, true),
260+
((1, -4), Left, true),
261+
((1, 5), Right, false),
262+
]
263+
.into_iter()
264+
{
265+
assert_eq!(
266+
eq1.check_side(point.into(), side),
267+
expected,
268+
"{:?}, {:?}",
269+
point,
270+
side
271+
);
272+
273+
assert_eq!(
274+
eq2.check_side(point.into(), side),
275+
expected,
276+
"{:?}, {:?}",
277+
point,
278+
side
279+
);
280+
}
281+
}
282+
283+
#[test]
284+
fn check_side_vertical_270deg() {
285+
let eq1 = OriginLinearEquation::with_angle(270.0.deg());
286+
let eq2 = LinearEquation::from_line(&Line::with_delta(Point::zero(), Point::new(0, -10)));
287+
288+
use LineSide::*;
289+
for (point, side, expected) in [
290+
((0, 0), Left, true),
291+
((0, -1), Right, true),
292+
((-1, 2), Left, true),
293+
((-1, -3), Right, false),
294+
((1, 4), Left, false),
295+
((1, -5), Right, true),
296+
]
297+
.into_iter()
298+
{
299+
assert_eq!(
300+
eq1.check_side(point.into(), side),
301+
expected,
302+
"{:?}, {:?}",
303+
point,
304+
side
305+
);
306+
307+
assert_eq!(
308+
eq2.check_side(point.into(), side),
309+
expected,
310+
"{:?}, {:?}",
311+
point,
312+
side
313+
);
314+
}
216315
}
217316
}

0 commit comments

Comments
 (0)