Skip to content

Commit

Permalink
Use Option<Feature> instead of Feature::None
Browse files Browse the repository at this point in the history
  • Loading branch information
julianschuler committed Feb 18, 2025
1 parent 0e6a624 commit ef9e3e0
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 33 deletions.
41 changes: 16 additions & 25 deletions crates/ransac/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ use ordered_float::NotNan;
use rand::{seq::SliceRandom, Rng};
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub enum RansacFeature<Frame> {
#[default]
None,
Line(Line2<Frame>),
TwoLines(TwoLines<Frame>),
}
Expand Down Expand Up @@ -51,7 +49,6 @@ impl<Frame> RansacFeature<Frame> {
impl<Frame> Distance<Point2<Frame>> for RansacFeature<Frame> {
fn squared_distance_to(&self, point: Point2<Frame>) -> f32 {
match self {
RansacFeature::None => f32::INFINITY,
RansacFeature::Line(line) => line.squared_distance_to(point),
RansacFeature::TwoLines(two_lines) => two_lines.squared_distance_to(point),
}
Expand All @@ -65,7 +62,6 @@ impl<Frame> IntoIterator for RansacResult<Frame> {

fn into_iter(self) -> Self::IntoIter {
match self.feature {
RansacFeature::None => Vec::new(),
RansacFeature::Line(line) => {
RansacLineSegment::try_from_used_points(line, self.used_points)
.map(|line_segment| vec![line_segment])
Expand Down Expand Up @@ -140,7 +136,7 @@ impl<Frame> RansacLineSegment<Frame> {
}
}

#[derive(Default, Debug, PartialEq)]
#[derive(Debug, PartialEq)]
pub struct RansacResult<Frame> {
pub feature: RansacFeature<Frame>,
pub used_points: Vec<Point2<Frame>>,
Expand All @@ -164,21 +160,18 @@ impl<Frame> Ransac<Frame> {
fit_two_lines: bool,
maximum_score_distance: f32,
maximum_inclusion_distance: f32,
) -> RansacResult<Frame> {
) -> Option<RansacResult<Frame>> {
if self.unused_points.len() < 2 {
return RansacResult {
feature: RansacFeature::None,
used_points: vec![],
};
return None;
}
if self.unused_points.len() == 2 {
return RansacResult {
return Some(RansacResult {
feature: RansacFeature::Line(Line::from_points(
self.unused_points[0],
self.unused_points[1],
)),
used_points: self.unused_points.clone(),
};
});
}

let maximum_score_distance_squared = maximum_score_distance * maximum_score_distance;
Expand Down Expand Up @@ -224,10 +217,10 @@ impl<Frame> Ransac<Frame> {
});
self.unused_points = unused_points;

RansacResult {
Some(RansacResult {
feature: best_feature,
used_points,
}
})
}
}

Expand All @@ -247,20 +240,14 @@ mod test {
fn ransac_empty_input() {
let mut ransac = Ransac::<SomeFrame>::new(vec![]);
let mut rng = ChaChaRng::from_entropy();
assert_eq!(
ransac.next_feature(&mut rng, 10, false, 5.0, 5.0),
RansacResult::default()
);
assert_eq!(ransac.next_feature(&mut rng, 10, false, 5.0, 5.0), None);
}

#[test]
fn ransac_single_point() {
let mut ransac = Ransac::<SomeFrame>::new(vec![]);
let mut rng = ChaChaRng::from_entropy();
assert_eq!(
ransac.next_feature(&mut rng, 10, false, 5.0, 5.0),
RansacResult::default()
);
assert_eq!(ransac.next_feature(&mut rng, 10, false, 5.0, 5.0), None);
}

#[test]
Expand All @@ -272,7 +259,9 @@ mod test {
let RansacResult {
feature,
used_points,
} = ransac.next_feature(&mut rng, 10, false, 5.0, 5.0);
} = ransac
.next_feature(&mut rng, 10, false, 5.0, 5.0)
.expect("expected a feature");
println!("{feature:#?}");
println!("{used_points:#?}");

Expand All @@ -298,7 +287,9 @@ mod test {

let mut ransac = Ransac::<SomeFrame>::new(points.clone());
let mut rng = ChaChaRng::from_entropy();
let result = ransac.next_feature(&mut rng, 15, false, 1.0, 1.0);
let result = ransac
.next_feature(&mut rng, 15, false, 1.0, 1.0)
.expect("expected feature");

if let RansacFeature::Line(line) = result.feature {
assert_relative_eq!(line.slope(), slope, epsilon = 0.0001);
Expand Down
12 changes: 8 additions & 4 deletions crates/vision/src/field_border_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,27 +110,31 @@ fn find_border_lines(
second_line_association_distance: f32,
) -> Vec<LineSegment<Pixel>> {
// first line
let result = ransac.next_feature(
let Some(result) = ransac.next_feature(
random_state,
20,
false,
first_line_association_distance,
first_line_association_distance,
);
) else {
return Vec::new();
};
if !matches!(result.feature, RansacFeature::Line(_))
|| result.used_points.len() < min_points_per_line
{
return Vec::new();
}
let first_line = best_fit_line(&result.used_points);
// second line
let result = ransac.next_feature(
let Some(result) = ransac.next_feature(
random_state,
20,
false,
second_line_association_distance,
second_line_association_distance,
);
) else {
return Vec::new();
};
if !matches!(result.feature, RansacFeature::Line(_))
|| result.used_points.len() < min_points_per_line
{
Expand Down
7 changes: 4 additions & 3 deletions crates/vision/src/line_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,15 @@ impl LineDetection {
if ransac.unused_points.len() < *context.minimum_number_of_points_on_line {
break;
}
let ransac_result = ransac.next_feature(
let Some(ransac_result) = ransac.next_feature(
&mut self.random_state,
*context.ransac_iterations,
*context.ransac_fit_two_lines,
*context.maximum_fit_distance_in_ground,
*context.maximum_fit_distance_in_ground + *context.margin_for_point_inclusion,
);
) else {
break;
};
detected_features.push(ransac_result.feature.clone());

for line_segment in ransac_result {
Expand Down Expand Up @@ -241,7 +243,6 @@ impl LineDetection {
detected_features
.into_iter()
.map(|feature| match feature {
RansacFeature::None => RansacFeature::None,
RansacFeature::Line(line) => RansacFeature::Line(Line::from_points(
context.camera_matrix.ground_to_pixel(line.point).unwrap(),
context
Expand Down
1 change: 0 additions & 1 deletion tools/twix/src/panels/image/overlays/line_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ impl Overlay for LineDetection {
};
for feature in detected_features {
match feature {
RansacFeature::None => {}
RansacFeature::Line(line) => {
painter.line(line.point, line.direction, Stroke::new(2.0, Color32::RED))
}
Expand Down

0 comments on commit ef9e3e0

Please sign in to comment.