• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 18554766227

16 Oct 2025 08:12AM UTC coverage: 88.843% (+0.3%) from 88.543%
18554766227

push

github

web-flow
build: update dependencies (#1081)

* update sqlfluff

* clippy autofix

* manual clippy fixes

* removal of unused code

* update deps

* upgrade packages

* enable cargo lints

* make sqlfluff happy

* fix chrono parsin error

* clippy

* byte_size

* fix image cmp with tiffs

* remove debug

177 of 205 new or added lines in 38 files covered. (86.34%)

41 existing lines in 20 files now uncovered.

106415 of 119779 relevant lines covered (88.84%)

84190.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.48
/operators/src/processing/circle_merging_quadtree/node.rs
1
use geo::Intersects;
2
use geoengine_datatypes::{operations::Contains, primitives::BoundingBox2D};
3

4
use super::circle_of_points::CircleOfPoints;
5

6
pub type QuadReference = [Node; 4];
7

8
///  * `top_left`
9
///  * `top_right`
10
///  * `bottom_left`
11
///  * `bottom_right`
12
pub type Link = Option<Box<QuadReference>>;
13

14
#[derive(Debug)]
15
pub struct Node {
16
    pub rectangle: BoundingBox2D,
17
    pub circles: Vec<CircleOfPoints>,
18
    pub link: Link,
19
}
20

21
pub type TryResult = Result<(), (CircleOfPoints, CircleOfPoints)>;
22
type PartialTryResult = Option<CircleOfPoints>;
23

24
impl Node {
25
    pub fn new(rectangle: BoundingBox2D) -> Self {
60✔
26
        Node {
60✔
27
            rectangle,
60✔
28
            circles: Vec::new(),
60✔
29
            link: None,
60✔
30
        }
60✔
31
    }
60✔
32

33
    pub fn add(
44✔
34
        &mut self,
44✔
35
        circle: CircleOfPoints,
44✔
36
        epsilon_distance: f64,
44✔
37
        max_items_per_node: usize,
44✔
38
    ) {
44✔
39
        if let Some(ref mut link) = self.link {
44✔
40
            // node is splitted
41

42
            for section in link.iter_mut() {
×
43
                if section
×
44
                    .rectangle
×
45
                    .contains(&circle.circle.buffer(epsilon_distance))
×
46
                {
47
                    // should not be reached, but just in case
48
                    section.add(circle, epsilon_distance, max_items_per_node);
×
49
                    return;
×
50
                }
×
51
            }
52

53
            self.circles.push(circle);
×
54
        } else {
55
            // node is unsplitted
56

57
            self.circles.push(circle);
44✔
58

59
            // handle overflow
60
            if self.circles.len() > max_items_per_node {
44✔
61
                let (top_left_rect, top_right_rect, bottom_left_rect, bottom_right_rect) =
12✔
62
                    self.rectangle.split_into_quarters();
12✔
63

64
                let mut link = Box::new([
12✔
65
                    Node::new(top_left_rect),
12✔
66
                    Node::new(top_right_rect),
12✔
67
                    Node::new(bottom_left_rect),
12✔
68
                    Node::new(bottom_right_rect),
12✔
69
                ]);
12✔
70

71
                'circle: for circle in std::mem::take(&mut self.circles) {
24✔
72
                    for section in &mut *link {
73✔
73
                        if section
67✔
74
                            .rectangle
67✔
75
                            .contains(&circle.circle.buffer(epsilon_distance))
67✔
76
                        {
77
                            section.add(circle, epsilon_distance, max_items_per_node);
18✔
78
                            continue 'circle;
18✔
79
                        }
49✔
80
                    }
81

82
                    self.circles.push(circle);
6✔
83
                }
84

85
                self.link = Some(link);
12✔
86
            }
32✔
87
        }
88
    }
44✔
89

90
    pub fn try_insert(
34✔
91
        &mut self,
34✔
92
        mut new_circle: CircleOfPoints,
34✔
93
        epsilon_distance: f64,
34✔
94
        max_items_per_node: usize,
34✔
95
    ) -> TryResult {
34✔
96
        // overlap with a contained circle
97
        if let Some(circle) = self.remove_intersecting_circle(&new_circle, epsilon_distance) {
34✔
98
            return Err((new_circle, circle));
6✔
99
        }
28✔
100

101
        // try to insert in children
102
        if let Some(ref mut quad) = self.link {
28✔
103
            let result =
2✔
104
                Node::try_insert_children(quad, new_circle, epsilon_distance, max_items_per_node);
2✔
105

106
            match result {
2✔
107
                Ok(try_result) => {
2✔
108
                    return try_result;
2✔
109
                }
110
                Err(returned_new_circle) => {
×
111
                    new_circle = returned_new_circle;
×
112

113
                    // try to find overlap in intersecting child nodes
114
                    for section in quad.iter_mut() {
×
115
                        if section
×
116
                            .rectangle
×
117
                            .intersects(&new_circle.circle.buffer(epsilon_distance))
×
NEW
118
                            && let Some(circle) = section.try_partial(&new_circle, epsilon_distance)
×
119
                        {
NEW
120
                            return Err((new_circle, circle));
×
UNCOV
121
                        }
×
122
                    }
123
                }
124
            }
125
        }
26✔
126

127
        self.add(new_circle, epsilon_distance, max_items_per_node);
26✔
128
        Ok(())
26✔
129
    }
34✔
130

131
    #[inline]
132
    fn try_insert_children(
2✔
133
        quad: &mut QuadReference,
2✔
134
        new_circle: CircleOfPoints,
2✔
135
        epsilon_distance: f64,
2✔
136
        max_items_per_node: usize,
2✔
137
    ) -> Result<TryResult, CircleOfPoints> {
2✔
138
        for section in quad {
4✔
139
            if section
4✔
140
                .rectangle
4✔
141
                .contains(&new_circle.circle.buffer(epsilon_distance))
4✔
142
            {
143
                return Ok(section.try_insert(new_circle, epsilon_distance, max_items_per_node));
2✔
144
            }
2✔
145
        }
146
        Err(new_circle)
×
147
    }
2✔
148

149
    fn try_partial(
×
150
        &mut self,
×
151
        new_circle: &CircleOfPoints,
×
152
        epsilon_distance: f64,
×
153
    ) -> PartialTryResult {
×
154
        if let Some(circle) = self.remove_intersecting_circle(new_circle, epsilon_distance) {
×
155
            return Some(circle);
×
156
        }
×
157

158
        if let Some(quad) = self.link.as_mut() {
×
159
            for section in quad.iter_mut() {
×
160
                if section
×
161
                    .rectangle
×
162
                    .intersects(&new_circle.circle.buffer(epsilon_distance))
×
NEW
163
                    && let Some(circle) = section.try_partial(new_circle, epsilon_distance)
×
164
                {
NEW
165
                    return Some(circle);
×
166
                }
×
167
            }
168
        }
×
169

170
        None
×
171
    }
×
172

173
    fn remove_intersecting_circle(
34✔
174
        &mut self,
34✔
175
        test_circle: &CircleOfPoints,
34✔
176
        epsilon_distance: f64,
34✔
177
    ) -> Option<CircleOfPoints> {
34✔
178
        let mut remove_index = None;
34✔
179
        for (i, circle) in self.circles.iter().enumerate() {
34✔
180
            if circle
17✔
181
                .circle
17✔
182
                .intersects_with_epsilon(&test_circle.circle, epsilon_distance)
17✔
183
            {
184
                remove_index = Some(i);
6✔
185
                break;
6✔
186
            }
11✔
187
        }
188

189
        remove_index.map(|i| self.circles.remove(i))
34✔
190
    }
34✔
191
}
192

193
impl PartialEq for Node {
194
    fn eq(&self, other: &Self) -> bool {
×
195
        self.rectangle == other.rectangle
×
196
    }
×
197
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc