diff --git a/appveyor.yml b/appveyor.yml index 02059dd39..c1f71ee3d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,6 +28,7 @@ init: install: - mamba env create -f environment.yml - conda activate cadquery + - conda list build: false diff --git a/cadquery/occ_impl/shapes.py b/cadquery/occ_impl/shapes.py index 216ea6349..b9330d68f 100644 --- a/cadquery/occ_impl/shapes.py +++ b/cadquery/occ_impl/shapes.py @@ -11,8 +11,9 @@ overload, TypeVar, cast as tcast, + Literal, + Protocol, ) -from typing_extensions import Literal, Protocol from io import BytesIO @@ -2505,13 +2506,18 @@ def fillet( edges = list(self) all_vertices = self.Vertices() + n_edges = len(edges) + n_vertices = len(all_vertices) + newEdges = [] currentEdge = edges[0] verticesSet = set(vertices) if vertices else set() - for i in range(len(edges) - 1): - nextEdge = edges[i + 1] + for i in range(n_edges): + if i == n_edges - 1 and not self.IsClosed(): + break + nextEdge = edges[(i + 1) % n_edges] # Create a plane that is spanned by currentEdge and nextEdge currentDir = currentEdge.tangentAt(1) @@ -2522,7 +2528,8 @@ def fillet( # 1. The edges are parallel # 2. The vertex is not in the vertices white list if normalDir.Length == 0 or ( - all_vertices[i + 1] not in verticesSet and bool(verticesSet) + all_vertices[(i + 1) % n_vertices] not in verticesSet + and bool(verticesSet) ): newEdges.append(currentEdge) currentEdge = nextEdge @@ -2551,8 +2558,11 @@ def fillet( currentEdge = nextEdge - # Add the last edge - newEdges.append(currentEdge) + # Add the last edge unless we are closed, since then + # currentEdge is the first edge, which was already added + # (and clipped) + if not self.IsClosed(): + newEdges.append(currentEdge) return Wire.assembleEdges(newEdges) diff --git a/cadquery/occ_impl/sketch_solver.py b/cadquery/occ_impl/sketch_solver.py index bf75b15a1..0dede03e2 100644 --- a/cadquery/occ_impl/sketch_solver.py +++ b/cadquery/occ_impl/sketch_solver.py @@ -1,5 +1,5 @@ from typing import Tuple, Union, Any, Callable, List, Optional, Iterable, Dict, Sequence -from typing_extensions import Literal +from typing import Literal from nptyping import NDArray as Array from nptyping import Float from itertools import accumulate, chain diff --git a/cadquery/sketch.py b/cadquery/sketch.py index fce851fcb..5ffddf4c0 100644 --- a/cadquery/sketch.py +++ b/cadquery/sketch.py @@ -11,8 +11,8 @@ Sequence, TypeVar, cast as tcast, + Literal, ) -from typing_extensions import Literal from math import tan, sin, cos, pi, radians, remainder from itertools import product, chain from multimethod import multimethod diff --git a/tests/test_cad_objects.py b/tests/test_cad_objects.py index f71252d14..498f30306 100644 --- a/tests/test_cad_objects.py +++ b/tests/test_cad_objects.py @@ -780,6 +780,17 @@ def testWireFillet(self): with self.assertRaises(ValueError): wfillet = wire.fillet(radius=1.0) + # Test a closed fillet + points = [[0, 0, 0], [5, 4, 0], [8, 3, 1], [10, 0, 0]] + + wire = Wire.makePolygon(points, close=True) + wfillet = wire.fillet(radius=0.5) + assert len(wfillet.Edges()) == 2 * len(points) + + # Fillet a single vertex + wfillet = wire.fillet(radius=0.5, vertices=wire.Vertices()[0:1]) + assert len(wfillet.Edges()) == len(points) + 1 + @pytest.mark.parametrize( "points, close, expected_edges",