Repository navigation
Expand file tree
/
Copy pathextend_line_segment.rs
More file actions
128 lines (108 loc) · 2.8 KB
/
Copy pathextend_line_segment.rs
File metadata and controls
128 lines (108 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use hogg_spatial_grid_map::{Fxx, PI};
pub type X1Y1X2Y2 = (Fxx, Fxx, Fxx, Fxx);
pub fn extend_line_segment(
line_segment: X1Y1X2Y2,
bbox: X1Y1X2Y2,
extend_start: bool,
extend_end: bool,
) -> X1Y1X2Y2 {
let (mut x1, mut y1, mut x2, mut y2) = line_segment;
let (min_x, min_y, max_x, max_y) = bbox;
let dx = x2 - x1;
let dy = y2 - y1;
let is_horizontal = dy.abs() < Fxx::EPSILON;
let is_vertical = dx.abs() < Fxx::EPSILON;
// For cases where the line is horizontal or vertical,
// we can just use the min/max values of the bbox, and
// we can avoid any division by zero errors
if is_horizontal || is_vertical {
if is_horizontal {
if x1 < x2 {
if extend_start {
x1 = min_x;
}
if extend_end {
x2 = max_x
}
} else {
if extend_start {
x1 = max_x;
}
if extend_end {
x2 = min_x
}
}
}
if is_vertical {
if y1 < y2 {
if extend_start {
y1 = min_y;
}
if extend_end {
y2 = max_y
}
} else {
if extend_start {
y1 = max_y;
}
if extend_end {
y2 = min_y
}
}
}
return (x1, y1, x2, y2);
}
let m = dy / dx;
let b = y1 - m * x1;
let x = |y: Fxx| (y - b) / m;
let y = |x: Fxx| m * x + b;
let x_for_min_y = x(min_y);
let x_for_max_y = x(max_y);
let y_for_min_x = y(min_x);
let y_for_max_x = y(max_x);
let intercepts_min_y = x_for_min_y >= min_x && x_for_min_y <= max_x;
let intercepts_max_y = x_for_max_y >= min_x && x_for_max_y <= max_x;
let intercepts_min_x = y_for_min_x >= min_y && y_for_min_x <= max_y;
let intercepts_max_x = y_for_max_x >= min_y && y_for_max_x <= max_y;
let cx = (x1 + x2) * 0.5;
let cy = (y1 + y2) * 0.5;
let atan_p1 = (y1 - cy).atan2(x1 - cx);
let atan_p2 = (y2 - cy).atan2(x2 - cx);
if intercepts_min_y {
if extend_start && atan_p1 < 0.0 {
x1 = x_for_min_y;
y1 = min_y;
} else if extend_end && atan_p2 < 0.0 {
x2 = x_for_min_y;
y2 = min_y;
}
}
if intercepts_max_y {
if extend_start && atan_p1 > 0.0 {
x1 = x_for_max_y;
y1 = max_y;
} else if extend_end && atan_p2 > 0.0 {
x2 = x_for_max_y;
y2 = max_y;
}
}
if intercepts_min_x {
if extend_start && !(PI * -0.5..=PI * 0.5).contains(&atan_p1) {
x1 = min_x;
y1 = y_for_min_x;
} else if extend_end && !(PI * -0.5..=PI * 0.5).contains(&atan_p2) {
x2 = min_x;
y2 = y_for_min_x;
}
}
if intercepts_max_x {
if extend_start && (atan_p1 > PI * -0.5 && atan_p1 < PI * 0.5) {
x1 = max_x;
y1 = y_for_max_x;
} else if extend_end && (atan_p2 > PI * -0.5 && atan_p2 < PI * 0.5) {
x2 = max_x;
y2 = y_for_max_x;
}
}
(x1, y1, x2, y2)
}