diff --git a/cadquery/occ_impl/shapes.py b/cadquery/occ_impl/shapes.py index a3d4a8e9d..c7de1a02c 100644 --- a/cadquery/occ_impl/shapes.py +++ b/cadquery/occ_impl/shapes.py @@ -244,7 +244,7 @@ from OCP.BRepAlgo import BRepAlgo -from math import pi, sqrt, inf +from math import pi, sqrt, inf, radians, cos import warnings @@ -253,7 +253,6 @@ Real = Union[float, int] TOLERANCE = 1e-6 -DEG2RAD = 2 * pi / 360.0 HASH_CODE_MAX = 2147483647 # max 32bit signed int, required by OCC.Core.HashCode shape_LUT = { @@ -900,7 +899,7 @@ def rotate( Vector(startVector).toPnt(), (Vector(endVector) - Vector(startVector)).toDir(), ), - angleDegrees * DEG2RAD, + radians(angleDegrees), ) return self._apply_transform(Tr) @@ -1757,7 +1756,7 @@ def makeCircle( return cls(BRepBuilderAPI_MakeEdge(circle_gp).Edge()) else: # arc case circle_geom = GC_MakeArcOfCircle( - circle_gp, angle1 * DEG2RAD, angle2 * DEG2RAD, orientation + circle_gp, radians(angle1), radians(angle2), orientation ).Value() return cls(BRepBuilderAPI_MakeEdge(circle_geom).Edge()) @@ -1796,7 +1795,7 @@ def makeEllipse( if y_radius > x_radius: # swap x and y radius and rotate by 90° afterwards to create an ellipse with x_radius < y_radius - correction_angle = 90.0 * DEG2RAD + correction_angle = radians(90.0) ellipse_gp = gp_Elips(ax2, y_radius, x_radius).Rotated( ax1, correction_angle ) @@ -1810,8 +1809,8 @@ def makeEllipse( # take correction_angle into account ellipse_geom = GC_MakeArcOfEllipse( ellipse_gp, - angle1 * DEG2RAD - correction_angle, - angle2 * DEG2RAD - correction_angle, + radians(angle1) - correction_angle, + radians(angle2) - correction_angle, sense == 1, ).Value() ellipse = cls(BRepBuilderAPI_MakeEdge(ellipse_geom).Edge()) @@ -2175,7 +2174,7 @@ def makeHelix( else: geom_surf = Geom_ConicalSurface( gp_Ax3(Vector(center).toPnt(), Vector(dir).toDir()), - angle * DEG2RAD, + radians(angle), radius, ) @@ -2816,7 +2815,7 @@ def dprism( shape, face.wrapped, basis.wrapped if basis else TopoDS_Face(), - taper * DEG2RAD, + radians(taper), additive, False, ) @@ -2983,7 +2982,7 @@ def makeCone( radius1, radius2, height, - angleDegrees * DEG2RAD, + radians(angleDegrees), ).Shape() ) @@ -3006,7 +3005,7 @@ def makeCylinder( gp_Ax2(Vector(pnt).toPnt(), Vector(dir).toDir()), radius, height, - angleDegrees * DEG2RAD, + radians(angleDegrees), ).Shape() ) @@ -3031,8 +3030,8 @@ def makeTorus( gp_Ax2(Vector(pnt).toPnt(), Vector(dir).toDir()), radius1, radius2, - angleDegrees1 * DEG2RAD, - angleDegrees2 * DEG2RAD, + radians(angleDegrees1), + radians(angleDegrees2), ).Shape() ) @@ -3104,9 +3103,9 @@ def makeSphere( BRepPrimAPI_MakeSphere( gp_Ax2(Vector(pnt).toPnt(), Vector(dir).toDir()), radius, - angleDegrees1 * DEG2RAD, - angleDegrees2 * DEG2RAD, - angleDegrees3 * DEG2RAD, + radians(angleDegrees1), + radians(angleDegrees2), + radians(angleDegrees3), ).Shape() ) @@ -3246,9 +3245,11 @@ def extrudeLinear( ) else: faceNormal = face.normalAt() - d = 1 if vecNormal.getAngle(faceNormal) < 90 * DEG2RAD else -1 + d = 1 if vecNormal.getAngle(faceNormal) < radians(90.0) else -1 + + # Divided by cos of taper angle to ensure the height chosen by the user is respected prism_builder = LocOpe_DPrism( - face.wrapped, d * vecNormal.Length, d * taper * DEG2RAD + face.wrapped, (d * vecNormal.Length) / cos(radians(taper)), d * radians(taper) ) return cls(prism_builder.Shape()) @@ -3298,7 +3299,7 @@ def revolve( v2 = Vector(axisEnd) v2 = v2 - v1 revol_builder = BRepPrimAPI_MakeRevol( - face.wrapped, gp_Ax1(v1.toPnt(), v2.toDir()), angleDegrees * DEG2RAD, True + face.wrapped, gp_Ax1(v1.toPnt(), v2.toDir()), radians(angleDegrees), True ) return cls(revol_builder.Shape()) diff --git a/tests/test_cadquery.py b/tests/test_cadquery.py index 55424f9ec..154ad362c 100644 --- a/tests/test_cadquery.py +++ b/tests/test_cadquery.py @@ -3686,6 +3686,33 @@ def testTaperedExtrudeCutBlind(self): .cutBlind(-h, True, float(t)) ) + def testTaperedExtrudeHeight(self): + """ + Ensures that the tapered prism has the correct height. + """ + + # Tapered extrusion to check the height of, with positive taper + s = ( + Workplane('XY') + .rect(100.0,100.0) + .extrude(100.0, taper=20.0) + ) + + # Get the bounding box and make sure the height matches the requested height + bb = s.val().BoundingBox() + self.assertAlmostEqual(bb.zlen, 100.0) + + # Tapered extrusion to check the height of, with negative taper + s2 = ( + Workplane('XY') + .rect(100.0,100.0) + .extrude(100.0, taper=-20.0) + ) + + # Get the bounding box and make sure the height matches the requested height + bb2 = s2.val().BoundingBox() + self.assertAlmostEqual(bb2.zlen, 100.0) + def testClose(self): # Close without endPoint and startPoint coincide. # Create a half-circle