diff --git a/cadquery/occ_impl/nurbs.py b/cadquery/occ_impl/nurbs.py index 4a958d35f..9f77b1949 100644 --- a/cadquery/occ_impl/nurbs.py +++ b/cadquery/occ_impl/nurbs.py @@ -357,7 +357,7 @@ def isoline(self, param: float, dir: Literal["u", "v"] = "u") -> Curve: @njiti def _preprocess( u: Array, order: int, knots: Array, periodic: bool -) -> Tuple[Array, Array, Optional[int], Optional[int], int]: +) -> Tuple[Array, Array, int, int, int]: """ Helper for handling periodicity. This function extends the knot vector, wraps the parameters and calculates the delta span. diff --git a/cadquery/occ_impl/shapes.py b/cadquery/occ_impl/shapes.py index 7d3c665a9..753663107 100644 --- a/cadquery/occ_impl/shapes.py +++ b/cadquery/occ_impl/shapes.py @@ -2357,7 +2357,10 @@ def normal(self: Mixin1DProtocol) -> Vector: if isinstance(surf, Geom_Plane): pln = surf.Pln() - rv = Vector(pln.Axis().Direction()) + direction = ( + pln.Axis().Direction().Transformed(fs.Location().Transformation()) + ) + rv = Vector(direction) else: raise ValueError("Normal not defined") diff --git a/tests/test_cadquery.py b/tests/test_cadquery.py index 0ccec4403..a65ae3e54 100644 --- a/tests/test_cadquery.py +++ b/tests/test_cadquery.py @@ -4934,6 +4934,20 @@ def testNormal(self): self.assertTupleAlmostEquals(n.toTuple(), (0, 0, 1), 6) + located_circle = face(circle(1)).wire().move(y=3, ry=90) + + assert located_circle.normal().toTuple() == approx((1, 0, 0)) + assert located_circle.edge().normal().toTuple() == approx((1, 0, 0)) + + located_ellipse = face(ellipse(2, 1)).wire().move(y=3, ry=90) + + assert located_ellipse.normal().toTuple() == approx((1, 0, 0)) + assert located_ellipse.edge().normal().toTuple() == approx((1, 0, 0)) + + located_rectangle = plane(2, 2).wire().move(y=3, ry=90) + + assert located_rectangle.normal().toTuple() == approx((1, 0, 0)) + with self.assertRaises(ValueError): edge = Workplane().rect(1, 2).edges().val() n = edge.normal()