Skip to content

Commit 242799d

Browse files
committed
Merge remote-tracking branch 'origin/dev' into refactor/kpm-query-keyframe-147
# Conflicts: # crates/core/src/kpm/freak/visual_database.rs
2 parents 3cb1f06 + 03fd9d7 commit 242799d

2 files changed

Lines changed: 128 additions & 0 deletions

File tree

crates/core/src/kpm/freak/matcher.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,22 @@ impl FeatureStore {
133133
pub fn bytes_per_feature(&self) -> usize {
134134
self.bytes_per_feature
135135
}
136+
137+
/// Returns all feature points as a slice.
138+
///
139+
/// Slice counterpart to [`point`](Self::point) — avoids forcing callers to
140+
/// loop `0..num_features()` element-by-element (facade parity, #148).
141+
pub fn points(&self) -> &[FeaturePoint] {
142+
&self.points
143+
}
144+
145+
/// Returns the flat descriptor buffer (`num_features() * bytes_per_feature()`
146+
/// bytes, descriptor `i` at `[i * bpf .. (i+1) * bpf]`).
147+
///
148+
/// Slice counterpart to [`descriptor`](Self::descriptor) (#148).
149+
pub fn descriptors(&self) -> &[u8] {
150+
&self.descriptors
151+
}
136152
}
137153

138154
// ============================================================================
@@ -583,6 +599,27 @@ mod tests {
583599
assert!(!s.point(2).maxima);
584600
}
585601

602+
#[test]
603+
fn test_feature_store_slice_accessors() {
604+
let mut s = FeatureStore::new(96).unwrap();
605+
let d0 = make_descriptor(0);
606+
let d1 = make_descriptor(1);
607+
s.add(fp(0.0, 0.0, true), &d0).unwrap();
608+
s.add(fp(1.0, 1.0, false), &d1).unwrap();
609+
610+
// points() slice agrees with per-element point(i).
611+
let pts = s.points();
612+
assert_eq!(pts.len(), 2);
613+
assert_eq!(pts[0].x, s.point(0).x);
614+
assert!(!pts[1].maxima);
615+
616+
// descriptors() flat buffer agrees with per-element descriptor(i).
617+
let descs = s.descriptors();
618+
assert_eq!(descs.len(), 2 * 96);
619+
assert_eq!(&descs[0..96], s.descriptor(0));
620+
assert_eq!(&descs[96..192], s.descriptor(1));
621+
}
622+
586623
#[test]
587624
fn test_feature_store_add_wrong_size() {
588625
let mut s = FeatureStore::new(96).unwrap();

crates/core/src/kpm/freak/visual_database.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,54 @@ impl VisualDatabase {
695695
pub fn keyframe(&self, id: usize) -> Option<&Keyframe> {
696696
self.keyframes.get(&id)
697697
}
698+
699+
// ── Facade-parity convenience accessors (#148, Group A) ──────────────
700+
// Thin getters mirroring `VisualDatabaseFacade`, so callers don't have to
701+
// reach through `keyframe(id).store` and loop element-by-element.
702+
703+
/// Feature points of the reference keyframe stored under `id`.
704+
///
705+
/// C equivalent: `getFeaturePoints(id)`.
706+
pub fn get_feature_points(&self, id: usize) -> Option<&[FeaturePoint]> {
707+
self.keyframes.get(&id).map(|kf| kf.store.points())
708+
}
709+
710+
/// Flat descriptor buffer of the reference keyframe stored under `id`.
711+
///
712+
/// C equivalent: `getDescriptors(id)`.
713+
pub fn get_descriptors(&self, id: usize) -> Option<&[u8]> {
714+
self.keyframes.get(&id).map(|kf| kf.store.descriptors())
715+
}
716+
717+
/// Feature points of the most recent query frame (see [`query`](Self::query)).
718+
///
719+
/// C equivalent: `getQueryFeaturePoints()`.
720+
pub fn get_query_feature_points(&self) -> Option<&[FeaturePoint]> {
721+
self.query_keyframe.as_ref().map(|kf| kf.store.points())
722+
}
723+
724+
/// Flat descriptor buffer of the most recent query frame.
725+
///
726+
/// C equivalent: `getQueryDescriptors()`.
727+
pub fn get_query_descriptors(&self) -> Option<&[u8]> {
728+
self.query_keyframe
729+
.as_ref()
730+
.map(|kf| kf.store.descriptors())
731+
}
732+
733+
/// Width of the reference image stored under `id`.
734+
///
735+
/// C equivalent: `getWidth(id)`.
736+
pub fn get_width(&self, id: usize) -> Option<i32> {
737+
self.keyframes.get(&id).map(|kf| kf.width)
738+
}
739+
740+
/// Height of the reference image stored under `id`.
741+
///
742+
/// C equivalent: `getHeight(id)`.
743+
pub fn get_height(&self, id: usize) -> Option<i32> {
744+
self.keyframes.get(&id).map(|kf| kf.height)
745+
}
698746
}
699747

700748
impl Default for VisualDatabase {
@@ -1081,6 +1129,49 @@ mod tests {
10811129
);
10821130
}
10831131

1132+
#[test]
1133+
fn test_facade_parity_accessors() {
1134+
// Build a tiny keyframe directly (no image pipeline) so the getters are
1135+
// exercised deterministically and fast (#148, Group A).
1136+
let mut kf = Keyframe::new(640, 480).unwrap();
1137+
let p0 = FeaturePoint {
1138+
x: 1.0,
1139+
y: 2.0,
1140+
angle: 0.0,
1141+
scale: 1.0,
1142+
maxima: true,
1143+
};
1144+
let p1 = FeaturePoint {
1145+
x: 3.0,
1146+
y: 4.0,
1147+
angle: 0.0,
1148+
scale: 1.0,
1149+
maxima: false,
1150+
};
1151+
kf.store.add(p0, &[7u8; 96]).unwrap();
1152+
kf.store.add(p1, &[9u8; 96]).unwrap();
1153+
1154+
let mut db = VisualDatabase::new().expect("new");
1155+
db.add_keyframe(kf, 0).expect("add_keyframe");
1156+
1157+
// Reference accessors for the stored id.
1158+
assert_eq!(db.get_width(0), Some(640));
1159+
assert_eq!(db.get_height(0), Some(480));
1160+
assert_eq!(db.get_feature_points(0).unwrap().len(), 2);
1161+
assert_eq!(db.get_feature_points(0).unwrap()[0].x, 1.0);
1162+
let descs = db.get_descriptors(0).unwrap();
1163+
assert_eq!(descs.len(), 2 * 96);
1164+
assert_eq!(&descs[0..96], &[7u8; 96]);
1165+
1166+
// Missing id → None.
1167+
assert!(db.get_feature_points(99).is_none());
1168+
assert!(db.get_width(99).is_none());
1169+
1170+
// No query run yet → query accessors are None.
1171+
assert!(db.get_query_feature_points().is_none());
1172+
assert!(db.get_query_descriptors().is_none());
1173+
}
1174+
10841175
// -----------------------------------------------------------------
10851176
// Dual-mode parity test (M9-1 gate per #140, closed by M9 #146)
10861177
// -----------------------------------------------------------------

0 commit comments

Comments
 (0)