MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / buffer_linestring

Function buffer_linestring

nodedb-spatial/src/operations.rs:128–192  ·  view source on GitHub ↗

Buffer a linestring by creating a corridor (parallel offset on both sides + end caps).

(line: &[[f64; 2]], meters: f64, segments: usize)

Source from the content-addressed store, hash-verified

126
127/// Buffer a linestring by creating a corridor (parallel offset on both sides + end caps).
128fn buffer_linestring(line: &[[f64; 2]], meters: f64, segments: usize) -> Geometry {
129 if line.is_empty() {
130 return Geometry::Polygon {
131 coordinates: vec![vec![]],
132 };
133 }
134 if line.len() == 1 {
135 return buffer_point(line[0][0], line[0][1], meters, segments);
136 }
137
138 // Build the offset polygon: left side forward, right side backward, with
139 // semicircular end caps.
140 let mut left_side = Vec::new();
141 let mut right_side = Vec::new();
142
143 for i in 0..line.len() - 1 {
144 let (nl, nr) = offset_segment(line[i], line[i + 1], meters);
145 left_side.push(nl.0);
146 left_side.push(nl.1);
147 right_side.push(nr.0);
148 right_side.push(nr.1);
149 }
150
151 // Build polygon: left side forward → end cap → right side backward → start cap.
152 let mut ring = Vec::new();
153 ring.extend_from_slice(&left_side);
154
155 // End cap (semicircle around last point).
156 let last = line[line.len() - 1];
157 let cap_segments = segments / 2;
158 let end_dir = direction(line[line.len() - 2], last);
159 for i in 0..=cap_segments {
160 let angle = end_dir - std::f64::consts::FRAC_PI_2
161 + std::f64::consts::PI * (i as f64) / (cap_segments as f64);
162 let dlat = meters / 110_540.0;
163 let dlng = meters / (111_320.0 * last[1].to_radians().cos().max(0.001));
164 ring.push([last[0] + dlng * angle.cos(), last[1] + dlat * angle.sin()]);
165 }
166
167 // Right side backward.
168 for pt in right_side.iter().rev() {
169 ring.push(*pt);
170 }
171
172 // Start cap (semicircle around first point).
173 let first = line[0];
174 let start_dir = direction(first, line[1]);
175 for i in 0..=cap_segments {
176 let angle = start_dir
177 + std::f64::consts::FRAC_PI_2
178 + std::f64::consts::PI * (i as f64) / (cap_segments as f64);
179 let dlat = meters / 110_540.0;
180 let dlng = meters / (111_320.0 * first[1].to_radians().cos().max(0.001));
181 ring.push([first[0] + dlng * angle.cos(), first[1] + dlat * angle.sin()]);
182 }
183
184 // Close.
185 if let Some(&first_pt) = ring.first() {

Callers 1

st_bufferFunction · 0.85

Calls 8

buffer_pointFunction · 0.85
offset_segmentFunction · 0.85
directionFunction · 0.85
firstMethod · 0.80
is_emptyMethod · 0.45
lenMethod · 0.45
pushMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected