-
Notifications
You must be signed in to change notification settings - Fork 17
compat: add XMILE straight-line link compatibility #203
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
Conversation
Other SD software like Stella doesn't support the is_straight attribute for connectors, so we need to always include the angle attribute. On export: When a link has LinkShape::Straight, calculate the actual straight-line angle from the from/to element positions and set it as the angle attribute. This allows other software to render the connector. On import: When a link has an angle that exactly matches the calculated straight-line angle (within a tight epsilon of 0.01 degrees), convert it to LinkShape::Straight to use the simplified internal representation. Using a tight epsilon ensures roundtrip fidelity - angles that are "visually straight" but not exactly the straight-line angle are preserved as Arc values. This maintains byte-for-byte identical XMILE output after roundtrip while providing compatibility with other SD software.
Review of PR #203: XMILE Straight-Line Link CompatibilityThank you for this PR! The implementation addresses an important compatibility issue with other SD software. Overall, the code is well-structured and thoroughly tested. Strengths
Code Quality ObservationsPotential Issue: Angle Wraparound Edge Case In Code Duplication Two functions get element positions:
Consider whether this duplication is necessary or if one could be refactored. Minor Nit Line 1250: Testing Suggestions
SummarySolid implementation that solves a real compatibility problem. Main suggestion is additional test coverage for edge cases. Code follows project conventions and best practices. Recommendation: Approve with minor suggestions for additional test coverage. |
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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 662a73da4f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
src/simlin-compat/src/xmile.rs
Outdated
| // Check if this angle represents a straight line | ||
| if let (Some(&(from_x, from_y)), Some(&(to_x, to_y))) = | ||
| (positions.get(&from_uid), positions.get(&to_uid)) | ||
| { | ||
| if is_straight_line_angle(angle, from_x, from_y, to_x, to_y) { |
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.
Convert XMILE angle before straight-line comparison
Here the straight-line detection compares the raw angle attribute from the XMILE file against a canvas-coordinate angle from calculate_straight_line_angle. XMILE connector angles are in the XMILE coordinate system (see the existing conversion helpers used elsewhere in this module), so values like 270 for a vertical-down link won’t match the computed canvas 90 and will be incorrectly imported as Arc instead of Straight. This breaks the new compatibility behavior for XMILE files that use standard 0–360° angles, because straight connectors will remain curved on import unless is_straight is explicitly set.
Useful? React with 👍 / 👎.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #203 +/- ##
==========================================
+ Coverage 75.98% 75.99% +0.01%
==========================================
Files 48 48
Lines 15320 15402 +82
==========================================
+ Hits 11641 11705 +64
- Misses 3679 3697 +18 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@codex review |
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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a4f8f57603
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
src/simlin-compat/src/xmile.rs
Outdated
| LinkShape::Arc(angle) => { | ||
| (None, Some(convert_angle_from_xmile_to_canvas(angle)), None) | ||
| // Internal angles are already normalized to [0, 360), output directly | ||
| (None, Some(angle), None) |
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.
Convert link angles to XMILE CCW coordinates
XMILE specifies connector angles as “0 is 3 o’clock and angles increase counter‑clockwise” (doc/xmile-v1.0.html lines 7928–7930). Internal view coordinates use a canvas system with +Y downward, so calculate_straight_line_angle/normalize_angle produce clockwise angles. Writing LinkShape::Arc angles directly (angle passthrough here) means exported XMILE arcs are mirrored vertically and any non‑horizontal connectors will render with the wrong curvature in external tools; similarly, re‑imported arcs/straight detection will be compared in the wrong coordinate system. This regression shows up as soon as an arc or straight line is not exactly horizontal.
Useful? React with 👍 / 👎.
Code Review: XMILE Straight-Line Link CompatibilitySummaryThis PR adds bidirectional conversion between Simlin's internal LinkShape::Straight representation and XMILE angle attributes for compatibility with other SD software like Stella. The implementation is generally solid with good test coverage, but there are a few important issues to address. Critical Issues1. Zero-Length Vector Handling (High Priority)Location: src/simlin-compat/src/xmile.rs:1252-1256 Issue: When from and to positions are identical (dx=0, dy=0), atan2(0.0, 0.0) returns 0.0, which is mathematically undefined behavior. While Rust's f64::atan2 handles this case without panicking, it's semantically incorrect to calculate an angle for a zero-length link. Impact: Links with coincident endpoints will silently export with angle=0, which could cause roundtrip issues or unexpected behavior in other software. Recommendation: Add an early return or assertion to handle this edge case by making the function return Option and returning None when dx and dy are both near zero. 2. Missing Test for Negative Angles and WraparoundIssue: While test_normalize_angle() tests angle normalization, there's no test verifying that the wraparound logic in is_straight_line_angle() (lines 1275-1276) actually works correctly for angles near 0°/360°. Recommendation: Add a test case that verifies -0.005 degrees normalizes and matches a calculated angle near 0. Code Quality Issues3. Inconsistent Error Handling PhilosophyLocation: src/simlin-compat/src/xmile.rs:2053-2055 Issue: Per CLAUDE.md guidelines: Strongly prefer .unwrap() over .unwrap_or_default() and it is valuable to understand when our assumptions are wrong. The fallback to is_straight=true silently hides a data integrity issue. Impact: If element positions are missing (possibly due to data corruption or parsing errors), the export will succeed but produce incorrect XMILE that might not match the visual representation. Recommendation: Consider using .unwrap() with a descriptive panic message instead of the silent fallback. 4. Performance: Redundant HashMap Allocation in TestsLocation: src/simlin-compat/src/xmile.rs:2029-2037 Issue: The link_from_xmile_with_view helper rebuilds the position HashMap on every call. While this is test-only code, it's creating technical debt. Impact: Negligible for current tests, but could slow down if more link conversion tests are added. Positive Aspects
Minor Suggestions5. Documentation: Clarify Coordinate SystemThe comments mention canvas coordinates but it might be clearer to explicitly state that:
This would help future maintainers understand why atan2(dy, dx) is correct. 6. Consider Adding Integration TestWhile unit tests are comprehensive, consider adding an integration test that:
This would validate the full roundtrip behavior mentioned in the PR description. Performance ConsiderationsThe changes add computational overhead during XMILE import/export:
The position HashMap is built once during view conversion, which is optimal. Security ConcernsNone identified. The code:
RecommendationApprove with changes requested:
The core implementation is sound and the test coverage is good. The issues identified are edge cases that should be addressed before merge. |
Add normalize_angle() to sanitize angles read from XMILE files to [0, 360) before conversion. This handles files that may have angles outside the standard range (e.g., -45 or 400). The internal format throughout simlin remains canvas coordinates ([-180, 180], Y-down), with conversions at the XMILE boundary: - On import: normalize_angle() then convert_angle_from_xmile_to_canvas() - On export: convert_angle_from_canvas_to_xmile() then normalize_angle() This ensures XMILE files always have angles in the standard [0, 360) range regardless of what was in the original file, improving compatibility with other SD software.
a4f8f57 to
5f96933
Compare
Code ReviewSummaryThis PR adds XMILE compatibility for straight-line links by calculating angles on export and detecting straight lines on import. The implementation is well-designed with good test coverage. Positive AspectsStrong Design Decisions:
Code Quality:
Issues Found1. Critical Logic Error in
|
|
@codex review |
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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5f969332a5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if let (Some(&(from_x, from_y)), Some(&(to_x, to_y))) = | ||
| (positions.get(&from_uid), positions.get(&to_uid)) | ||
| { |
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.
Fall back to names when UIDs are missing
Straight-line detection only consults from_uid/to_uid to look up positions, so any XMILE file that omits those attributes (common in the repo, e.g. test/test-models/samples/teacup/teacup_w_diagram.xmile uses only <from>/<to> names) will never satisfy this lookup and will still be imported as Arc. That means the new “angle-matches-straight” path won’t run for typical XMILE inputs, and straight connectors will continue to render curved. Consider falling back to resolving positions by LinkEnd::Named (or alias) when UIDs are absent so the feature works with name-only XMILE files.
Useful? React with 👍 / 👎.
Summary
LinkShape::Straightlink, calculate the straight-line angle from element positions and set it as the angle attribute (for compatibility with Stella and other SD software)LinkShape::Straight(using a tight 0.01 degree epsilon for roundtrip fidelity)Test plan