Sketch Offset: the side of the copy depends on the drawing direction of the contour, not on the sign of the distance
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
Research direction
Start with Project::offset_entities in crates/qymcad-core/src/model/sketch.rs, then read entity_bulge_loops in crates/qymcad-core/src/model/tess.rs and the offset helpers in crates/qymcad-core/src/offset.rs. Review the offset tests in crates/qymcad-core/tests/modify.rs; their current checks do not verify which side the copy lands on. Done means positive distance produces a consistent side for clockwise and counter-clockwise contours, circles, and rectangles, with tests checking the resulting geometry.
Written by the indexing model from the issue text.
Description
Summary
Sketch Offset puts the copy on a side that depends on the direction the contour was drawn in, not on the sign of the distance. The same +3 gives an outside copy for a clockwise contour and an inside copy for a counter-clockwise one. Circles always grow with a positive distance, while a Rectangle-tool rectangle (and the starter cube sketch) shrinks. So a wall or allowance can silently come out on the wrong side.
The help page (docs/help/en/sketch/20-offset.md) says: "The sign of the distance chooses the side: with one sign the copy lies outside, with the other inside."
Steps to reproduce
- Start QymCAD (new document). Double-click Cube. Pick Sketch and choose the XY plane.
- With the Line tool, draw square A clockwise: top-left → top-right → bottom-right → bottom-left → back to top-left. Press Esc.
- With the Line tool, draw square B of the same size counter-clockwise: top-left → bottom-left → bottom-right → top-right → back to top-left. Press Esc.
- Pick Offset (Edit section) with Distance = 3 (the default). Click the 4 sides of A and press Enter. Press Esc twice.
- Pick Offset again with Distance = 3. Click the 4 sides of B and press Enter.
- Second case: in a sketch, draw a circle Ø8 and offset it by 3. Draw a rectangle with the Rectangle tool and offset it by 3. The cube's own base sketch (Sketch 1) behaves like the rectangle.
Expected
The same +3 puts the copy on the same side (inside or outside) for every closed contour, whatever the drawing direction or the tool used.
Actual
- Square A (clockwise): the copy is outside, with R3 rounded corners.
- Square B (counter-clockwise): the copy is inside, 3 mm in from each side.
- Circle Ø8 at +3 becomes Ø14 (outside). A Rectangle-tool rectangle (and the starter cube sketch) at +3 gets an inside copy.
Root cause analysis
Project::offset_entities in crates/qymcad-core/src/model/sketch.rs:
- Circles use
nr = r + dist, so a positive distance always grows them. - Line/arc loops are built by
entity_bulge_loops(model/tess.rs) in whatever order the entities chain, and passed as they are tooffset::offset_bulge(sketch.rs#L2885-L2886), which calls cavalier_contoursparallel_offset(dist). The orientation is never normalised (no signed-area or CCW check). cavalier's offset side follows the polyline's direction, so a positive distance shrinks CCW loops and grows CW loops.
The same module already has an orientation-independent helper for the CAM path: offset::offset_to_side picks the side by comparing areas. The arc-preserving offset_bulge used by the sketch has nothing equivalent. Normalising each loop to CCW (or flipping the sign of dist by the loop's signed area) before offset_bulge would make the side consistent with circles.
False-green tests
In crates/qymcad-core/tests/modify.rs:
offset_makes_inner_loop(-2, "Inwards") only checks that a contour is produced. It never checks which side it lands on.offset_loop_with_arc_keeps_arcsis described as "after an outward offset the arcs stay arcs" and uses +1, but it only checks that an arc is produced. The test rectangle comes fromadd_rect_entity, whose corners are laid counter-clockwise (sketch.rs#L3700-L3705). It's the same call that builds the starter cube sketch (model.rs#L3277). I ran the same steps as this test (10x10 rectangle from 0 to 10, one corner filleted R2, offset +1) and printed the new entities: their bounding box is x 1..9, y 1..9. So the "outward" offset in this test actually goes inward, and neither test can catch this bug.
Environment
- Commit:
8f66226(main, 2026-10-06), version 0.1.0, built from source - OS: Debian 13.7 (trixie) x86_64 (container)
- Toolchain: rustc 1.99.0 (stable), OpenCASCADE 7.8.1 (Debian
libocct-*-dev7.8.1+dfsg1-3) - Build:
OCCT_LIB_DIR=/usr/lib/x86_64-linux-gnu cargo build -p qymcad(debug profile) - Display: Xvfb 1600x1000x24, no window manager,
WGPU_BACKEND=vulkan(Mesa lavapipe 25.0.7) - UI language: English (default), fresh settings
Visual proof
Screenshots are attached in the comment below.
- Dominant language
- Rust
- Stars
- 543
- Forks
- 27
- Avg merge
- 4h 9m
- Merged PRs (30d)
- 42
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from QymIs-Tech/QymCAD
-
Saving the same edit twice gives two different project files: the deleted bodies are saved in HashSet orderPossibly taken @qmlxml claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
QymIs-Tech/QymCAD#147 · 1 comment ·
Maintainers usually reply within 1 day
-
Renaming a parameter whose name overlaps itself in a formula panics ("byte range starts at 3 but ends at 2")Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
QymIs-Tech/QymCAD#143 · 1 comment ·
Maintainers usually reply within 1 day
-
Changing the document title, author, comment or a part colour does not mark the project modified (the edit is lost on close)Possibly taken @qmlxml claimed this 2 days ago. Openbug ui
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
QymIs-Tech/QymCAD#101 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
"Auto-saved (HH:MM)" status shows UTC time instead of local timePossibly taken @styx claimed this 2 days ago. Openbug ui
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
QymIs-Tech/QymCAD#88 · 2 comments ·
Maintainers usually reply within 1 day
-
bug ui
Difficulty 1/5 Under an hour Newbie friendliness 88/100
QymIs-Tech/QymCAD#87 · 1 comment ·
Maintainers usually reply within 1 day
All issues in QymIs-Tech/QymCAD
Similar issues
-
area:docs documentation good first issue priority:low
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
triage:accepted
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
open-telemetry/otel-arrow#4343 ·
Maintainers usually reply within 2 days
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
mishraprafful/multihull#150 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
voidzero-dev/vite-plus#2970 ·
Maintainers usually reply within 1 day
-
ai_p2 comp-parquet-reader-v3
Difficulty 2/5 Half a day Newbie friendliness 66/100
ClickHouse/ClickHouse#124986 ·
Maintainers usually reply within 1 day