Skip to main content

dear_imgui_rs/utils/
geometry.rs

1use crate::sys;
2
3impl crate::ui::Ui {
4    /// Get cursor position in screen coordinates.
5    #[doc(alias = "GetCursorScreenPos")]
6    pub fn get_cursor_screen_pos(&self) -> [f32; 2] {
7        let pos = self.run_with_bound_context(|| unsafe { sys::igGetCursorScreenPos() });
8        [pos.x, pos.y]
9    }
10
11    /// Get available content region size.
12    #[doc(alias = "GetContentRegionAvail")]
13    pub fn get_content_region_avail(&self) -> [f32; 2] {
14        let size = self.run_with_bound_context(|| unsafe { sys::igGetContentRegionAvail() });
15        [size.x, size.y]
16    }
17
18    /// Check if a point is inside a rectangle.
19    pub fn is_point_in_rect(
20        &self,
21        point: [f32; 2],
22        rect_min: [f32; 2],
23        rect_max: [f32; 2],
24    ) -> bool {
25        point[0] >= rect_min[0]
26            && point[0] <= rect_max[0]
27            && point[1] >= rect_min[1]
28            && point[1] <= rect_max[1]
29    }
30
31    /// Calculate distance between two points.
32    pub fn distance(&self, p1: [f32; 2], p2: [f32; 2]) -> f32 {
33        let dx = p2[0] - p1[0];
34        let dy = p2[1] - p1[1];
35        (dx * dx + dy * dy).sqrt()
36    }
37
38    /// Calculate squared distance between two points (faster than distance).
39    pub fn distance_squared(&self, p1: [f32; 2], p2: [f32; 2]) -> f32 {
40        let dx = p2[0] - p1[0];
41        let dy = p2[1] - p1[1];
42        dx * dx + dy * dy
43    }
44
45    /// Check if two line segments intersect.
46    pub fn line_segments_intersect(
47        &self,
48        p1: [f32; 2],
49        p2: [f32; 2],
50        p3: [f32; 2],
51        p4: [f32; 2],
52    ) -> bool {
53        let d1 = self.cross_product(
54            [p4[0] - p3[0], p4[1] - p3[1]],
55            [p1[0] - p3[0], p1[1] - p3[1]],
56        );
57        let d2 = self.cross_product(
58            [p4[0] - p3[0], p4[1] - p3[1]],
59            [p2[0] - p3[0], p2[1] - p3[1]],
60        );
61        let d3 = self.cross_product(
62            [p2[0] - p1[0], p2[1] - p1[1]],
63            [p3[0] - p1[0], p3[1] - p1[1]],
64        );
65        let d4 = self.cross_product(
66            [p2[0] - p1[0], p2[1] - p1[1]],
67            [p4[0] - p1[0], p4[1] - p1[1]],
68        );
69
70        (d1 > 0.0) != (d2 > 0.0) && (d3 > 0.0) != (d4 > 0.0)
71    }
72
73    /// Calculate cross product of two 2D vectors.
74    fn cross_product(&self, v1: [f32; 2], v2: [f32; 2]) -> f32 {
75        v1[0] * v2[1] - v1[1] * v2[0]
76    }
77
78    /// Normalize a 2D vector.
79    pub fn normalize(&self, v: [f32; 2]) -> [f32; 2] {
80        let len = (v[0] * v[0] + v[1] * v[1]).sqrt();
81        if len > f32::EPSILON {
82            [v[0] / len, v[1] / len]
83        } else {
84            [0.0, 0.0]
85        }
86    }
87
88    /// Calculate dot product of two 2D vectors.
89    pub fn dot_product(&self, v1: [f32; 2], v2: [f32; 2]) -> f32 {
90        v1[0] * v2[0] + v1[1] * v2[1]
91    }
92
93    /// Calculate the angle between two vectors in radians.
94    pub fn angle_between_vectors(&self, v1: [f32; 2], v2: [f32; 2]) -> f32 {
95        let dot = self.dot_product(v1, v2);
96        let len1 = (v1[0] * v1[0] + v1[1] * v1[1]).sqrt();
97        let len2 = (v2[0] * v2[0] + v2[1] * v2[1]).sqrt();
98
99        if len1 > f32::EPSILON && len2 > f32::EPSILON {
100            (dot / (len1 * len2)).acos()
101        } else {
102            0.0
103        }
104    }
105
106    /// Check if a point is inside a circle.
107    pub fn is_point_in_circle(&self, point: [f32; 2], center: [f32; 2], radius: f32) -> bool {
108        self.distance_squared(point, center) <= radius * radius
109    }
110
111    /// Calculate the area of a triangle given three points.
112    pub fn triangle_area(&self, p1: [f32; 2], p2: [f32; 2], p3: [f32; 2]) -> f32 {
113        let cross = self.cross_product(
114            [p2[0] - p1[0], p2[1] - p1[1]],
115            [p3[0] - p1[0], p3[1] - p1[1]],
116        );
117        cross.abs() * 0.5
118    }
119}