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

Function sutherland_hodgman

nodedb-spatial/src/predicates/intersection.rs:116–162  ·  view source on GitHub ↗

Sutherland-Hodgman polygon clipping. Clips `subject` polygon against `clip` polygon. Both are coordinate rings (closed or unclosed). Returns the clipped polygon vertices (unclosed). The clip polygon's edges define half-planes. For each edge, vertices of the subject that are "inside" (left of the edge) are kept. Vertices that cross from inside to outside (or vice versa) generate intersection poin

(subject: &[[f64; 2]], clip: &[[f64; 2]])

Source from the content-addressed store, hash-verified

114/// that cross from inside to outside (or vice versa) generate intersection
115/// points on the clip edge.
116fn sutherland_hodgman(subject: &[[f64; 2]], clip: &[[f64; 2]]) -> Vec<[f64; 2]> {
117 if subject.is_empty() || clip.is_empty() {
118 return Vec::new();
119 }
120
121 let mut output = strip_closing(subject);
122 let clip_edges = strip_closing(clip);
123
124 let n = clip_edges.len();
125 for i in 0..n {
126 if output.is_empty() {
127 return Vec::new();
128 }
129
130 let edge_start = clip_edges[i];
131 let edge_end = clip_edges[(i + 1) % n];
132
133 let input = output;
134 output = Vec::with_capacity(input.len());
135
136 let m = input.len();
137 for j in 0..m {
138 let current = input[j];
139 let previous = input[(j + m - 1) % m];
140
141 let curr_inside = is_inside(current, edge_start, edge_end);
142 let prev_inside = is_inside(previous, edge_start, edge_end);
143
144 if curr_inside {
145 if !prev_inside {
146 // Entering: add intersection point.
147 if let Some(pt) = line_intersection(previous, current, edge_start, edge_end) {
148 output.push(pt);
149 }
150 }
151 output.push(current);
152 } else if prev_inside {
153 // Leaving: add intersection point.
154 if let Some(pt) = line_intersection(previous, current, edge_start, edge_end) {
155 output.push(pt);
156 }
157 }
158 }
159 }
160
161 output
162}
163
164/// Check if a point is on the "inside" (left side) of a directed edge.
165fn is_inside(point: [f64; 2], edge_start: [f64; 2], edge_end: [f64; 2]) -> bool {

Callers 1

st_intersectionFunction · 0.85

Calls 6

strip_closingFunction · 0.85
is_insideFunction · 0.85
line_intersectionFunction · 0.85
is_emptyMethod · 0.45
lenMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected