-
Notifications
You must be signed in to change notification settings - Fork 98
[SOLVE]: constraint freedom visualisation #9573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
126338a
e8b9891
6c99112
4349586
8d995af
1c5af13
e22fd11
d96de89
915e74f
08c2a98
686a1f0
5d0d4c3
30b6dbc
8515d52
39b6b00
23f0289
b856930
ff0b897
81f014a
ff6e942
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| #[cfg(test)] | ||
| #[cfg(feature = "artifact-graph")] | ||
| mod test { | ||
| use std::sync::Arc; | ||
|
|
||
| use crate::{ | ||
| ExecutorContext, ExecutorSettings, | ||
| engine::conn_mock::EngineConnection, | ||
| execution::{ContextType, MockConfig}, | ||
| front::{Freedom, ObjectKind}, | ||
| frontend::api::ObjectId, | ||
| }; | ||
|
|
||
| async fn run_with_freedom_analysis(kcl: &str) -> Vec<(ObjectId, Freedom)> { | ||
| let program = crate::Program::parse_no_errs(kcl).unwrap(); | ||
|
|
||
| let exec_ctxt = ExecutorContext { | ||
| engine: Arc::new(Box::new(EngineConnection::new().unwrap())), | ||
| fs: Arc::new(crate::fs::FileManager::new()), | ||
| settings: ExecutorSettings::default(), | ||
| context_type: ContextType::Mock, | ||
| }; | ||
|
|
||
| let mock_config = MockConfig { | ||
| freedom_analysis: true, | ||
| ..Default::default() | ||
| }; | ||
|
|
||
| let outcome = exec_ctxt.run_mock(&program, &mock_config).await.unwrap(); | ||
|
|
||
| let mut point_freedoms = Vec::new(); | ||
| for obj in &outcome.scene_objects { | ||
| if let ObjectKind::Segment { | ||
| segment: crate::front::Segment::Point(point), | ||
| } = &obj.kind | ||
| { | ||
| point_freedoms.push((obj.id, point.freedom)); | ||
| } | ||
| } | ||
| // Sort by object ID for consistent ordering | ||
| point_freedoms.sort_by_key(|(id, _)| id.0); | ||
| point_freedoms | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add this? It's a no-op for mock contexts, but I want us to get in the habit of closing because it's a bug for an engine context. |
||
|
|
||
| #[tokio::test(flavor = "multi_thread")] | ||
| async fn test_freedom_analysis_with_conflicts() { | ||
| let kcl = r#" | ||
| @settings(experimentalFeatures = allow) | ||
| sketch(on = YZ) { | ||
| line1 = sketch2::line(start = [var 2mm, var 8mm], end = [var 5mm, var 7mm]) | ||
| line1.start.at[0] == 2 | ||
| line1.start.at[1] == 8 | ||
| line1.end.at[0] == 5 | ||
| line1.end.at[1] == 7 | ||
| line2 = sketch2::line(start = [var 2mm, var 1mm], end = [var -4.75mm, var -0.88mm]) | ||
| line2.start.at[0] == 2 | ||
| line2.start.at[1] == 1 | ||
| line3 = sketch2::line(start = [var -2.591mm, var -7.081mm], end = [var 1.331mm, var -3.979mm]) | ||
| sketch2::distance([line3.start, line3.end]) == 4mm | ||
| sketch2::distance([line3.start, line3.end]) == 6mm | ||
| } | ||
| "#; | ||
|
|
||
| let point_freedoms = run_with_freedom_analysis(kcl).await; | ||
|
|
||
| // Expected: line1 has both ends constrained -> Fixed, Fixed | ||
| // line2 has one end constrained -> Fixed, Free (but currently shows Fixed, Conflict - bug) | ||
| // line3 has conflicting distance constraints -> Conflict, Conflict (but currently shows Free, Free - bug) | ||
| // Note: IDs skip every third because segments don't get freedom values | ||
| // Format: (ObjectId, Freedom) | ||
|
|
||
| println!("Point freedoms: {:?}", point_freedoms); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| let expected = vec![ | ||
| (ObjectId(1), Freedom::Fixed), | ||
| (ObjectId(2), Freedom::Fixed), | ||
| (ObjectId(4), Freedom::Fixed), | ||
| (ObjectId(5), Freedom::Free), | ||
| (ObjectId(7), Freedom::Conflict), | ||
| (ObjectId(8), Freedom::Conflict), | ||
| ]; | ||
|
|
||
| // This assertion will fail until the bug is fixed | ||
| assert_eq!( | ||
| point_freedoms, expected, | ||
| "Point freedoms should match expected values. Current behavior shows bugs with conflicts and reordered lines." | ||
| ); | ||
| } | ||
|
|
||
| #[tokio::test(flavor = "multi_thread")] | ||
| async fn test_freedom_analysis_without_conflicts() { | ||
| let kcl = r#" | ||
| @settings(experimentalFeatures = allow) | ||
| sketch(on = YZ) { | ||
| line1 = sketch2::line(start = [var 2mm, var 8mm], end = [var 5mm, var 7mm]) | ||
| line1.start.at[0] == 2 | ||
| line1.start.at[1] == 8 | ||
| line1.end.at[0] == 5 | ||
| line1.end.at[1] == 7 | ||
| line2 = sketch2::line(start = [var 2mm, var 1mm], end = [var -4.75mm, var -0.88mm]) | ||
| line2.start.at[0] == 2 | ||
| line2.start.at[1] == 1 | ||
| line3 = sketch2::line(start = [var -2.591mm, var -7.081mm], end = [var 1.331mm, var -3.979mm]) | ||
| sketch2::distance([line3.start, line3.end]) == 4mm | ||
| } | ||
| "#; | ||
|
|
||
| let point_freedoms = run_with_freedom_analysis(kcl).await; | ||
|
|
||
| // Expected: line1 has both ends constrained -> Fixed, Fixed | ||
| // line2 has one end constrained -> Fixed, Free | ||
| // line3 has one distance constraint -> Free, Free (both points can move) | ||
|
|
||
| println!("Point freedoms: {:?}", point_freedoms); | ||
|
|
||
| // Expected: Fixed, Fixed, Fixed, Free, Free, Free | ||
| let expected = vec![ | ||
| (ObjectId(1), Freedom::Fixed), | ||
| (ObjectId(2), Freedom::Fixed), | ||
| (ObjectId(4), Freedom::Fixed), | ||
| (ObjectId(5), Freedom::Free), | ||
| (ObjectId(7), Freedom::Free), | ||
| (ObjectId(8), Freedom::Free), | ||
| ]; | ||
|
|
||
| assert_eq!(point_freedoms, expected, "Point freedoms should match expected values"); | ||
| } | ||
|
|
||
| #[tokio::test(flavor = "multi_thread")] | ||
| async fn test_freedom_analysis_reordered_lines() { | ||
| let kcl = r#" | ||
| @settings(experimentalFeatures = allow) | ||
| sketch(on = YZ) { | ||
| line1 = sketch2::line(start = [var 2mm, var 8mm], end = [var 5mm, var 7mm]) | ||
| line1.start.at[0] == 2 | ||
| line1.start.at[1] == 8 | ||
| line1.end.at[0] == 5 | ||
| line1.end.at[1] == 7 | ||
| line3 = sketch2::line(start = [var -2.591mm, var -7.081mm], end = [var 1.331mm, var -3.979mm]) | ||
| sketch2::distance([line3.start, line3.end]) == 4mm | ||
| sketch2::distance([line3.start, line3.end]) == 6mm | ||
| line2 = sketch2::line(start = [var 2mm, var 1mm], end = [var -4.75mm, var -0.88mm]) | ||
| line2.start.at[0] == 2 | ||
| line2.start.at[1] == 1 | ||
| } | ||
| "#; | ||
|
|
||
| let point_freedoms = run_with_freedom_analysis(kcl).await; | ||
|
|
||
| // Expected: line1 has both ends constrained -> Fixed, Fixed | ||
| // line3 has conflicting distance constraints -> Conflict, Conflict (but bug shows one Conflict, one Free) | ||
| // line2 has one end constrained -> Fixed, Free | ||
|
|
||
| println!("Point freedoms: {:?}", point_freedoms); | ||
|
|
||
| let expected = vec![ | ||
| (ObjectId(1), Freedom::Fixed), | ||
| (ObjectId(2), Freedom::Fixed), | ||
| (ObjectId(4), Freedom::Conflict), | ||
| (ObjectId(5), Freedom::Conflict), | ||
| (ObjectId(9), Freedom::Fixed), | ||
| (ObjectId(10), Freedom::Free), | ||
| ]; | ||
|
|
||
| // This assertion will fail until the bug is fixed | ||
| assert_eq!( | ||
| point_freedoms, expected, | ||
| "Point freedoms should match expected values. Current behavior shows bug where line3.end is Free instead of Conflict." | ||
| ); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added these tests failing before I started working on a fix, now they pass.