CadQuery / CadQuery/cadquery

Sketch close returns start point of for construction edge when closing non construction edge

Open
#1,443 1 comment 0 reactions 0 assignees View on GitHub
bug sketching
Dominant language
Python
Stars
5.8k
Forks
541
Avg merge
3d 2h
Merged PRs (30d)
5

Description

`Sketch` `close()` closes an edge that is not for construction with an edge created with `forConstruction=True`.

I attempted to close the triangle with itself, however, it was closed with the starting point of the for construction arc.

```py
import cadquery as cq

s0 = (
cq.Sketch()
.arc((0, 0), 30, 0, 120, tag="e0", forConstruction=True)
.edges(tag="e0")
.distribute(1, rotate=False)
.segment((0, 0), (10, 2))
.segment((10, -2))
.close()
# .assemble()
)

show_object(s0, name="s0")
```

![issue1](https://github.com/CadQuery/cadquery/assets/16394272/fe0dd65b-b31f-4e7b-9633-fc6d9e05c9b5)

Uncommenting `assemble()`:

![issue1_assemble](https://github.com/CadQuery/cadquery/assets/16394272/b588e576-c5be-43f2-b88f-705e527a2ec6)

A solution is to omit close by explicitly specifying the edge end/start point:

```py
s0 = (
cq.Sketch()
.arc((0, 0), 30, 0, 120, tag="e0", forConstruction=True)
.edges(tag="e0")
.distribute(1, rotate=False)
.segment((0, 0), (10, 2))
.segment((10, -2))
.segment((0, 0))
.assemble()
)
```

![without_close](https://github.com/CadQuery/cadquery/assets/16394272/9915b281-9c1b-49d8-be01-c30132d1928f)

Solution using callback:

```py
def triangle(loc):
s = cq.Sketch().segment((0, 0), (10, 2)).segment((10, -2)).close().assemble()
return s.moved(loc)

s0 = (
cq.Sketch()
.arc((0, 0), 30, 0, 120, tag="e0", forConstruction=True)
.edges(tag="e0")
.distribute(1, rotate=False)
.each(triangle)
)
```

Is there a scenario where it is desired to close an edge in non construction mode with an edge in construction mode?
If not, perhaps Sketch `_startPoint` can be changed to something like this:

```py
def _startPoint(self) -> Vector:

if not self._edges:
raise ValueError("No free edges available")

# find the first edge matching current edge mode
mode = self._edges[-1].forConstruction
for edge in reversed(self._edges):
if edge.forConstruction != mode:
break
prevedge = edge

e = prevedge

# current implementation selects first edge:
# e = self._edges[0]

return e.startPoint()
```

I didn't find any failing tests with this change.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.