Skip to content
This repository has been archived by the owner on Feb 9, 2021. It is now read-only.

Commit

Permalink
Merge pull request #254 from gntech/add-radiusArc
Browse files Browse the repository at this point in the history
@gntech thanks for this contribution! You rock!
  • Loading branch information
dcowden authored Apr 25, 2018
2 parents 86f3b7c + d75ed82 commit c4df65c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 22 deletions.
47 changes: 37 additions & 10 deletions cadquery/cq.py
Original file line number Diff line number Diff line change
Expand Up @@ -1320,11 +1320,13 @@ def threePointArc(self, point1, point2, forConstruction=False):
provide tangent arcs
"""

gstartPoint = self._findFromPoint(False)
gpoint1 = self.plane.toWorldCoords(point1)
gpoint2 = self.plane.toWorldCoords(point2)
startPoint = self._findFromPoint(False)
if not isinstance(point1, Vector):
point1 = self.plane.toWorldCoords(point1)
if not isinstance(point2, Vector):
point2 = self.plane.toWorldCoords(point2)

arc = Edge.makeThreePointArc(gstartPoint, gpoint1, gpoint2)
arc = Edge.makeThreePointArc(startPoint, point1, point2)

if not forConstruction:
self._addPendingEdge(arc)
Expand All @@ -1347,8 +1349,8 @@ def sagittaArc(self, endPoint, sag, forConstruction=False):
See "https://en.wikipedia.org/wiki/Sagitta_(geometry)" for more information.
"""

startPoint = self._findFromPoint(False)
endPoint = self.plane.toWorldCoords(endPoint)
startPoint = self._findFromPoint(useLocalCoords=True)
endPoint = Vector(endPoint)
midPoint = endPoint.add(startPoint).multiply(0.5)

sagVector = endPoint.sub(startPoint).normalized().multiply(abs(sag))
Expand All @@ -1359,12 +1361,37 @@ def sagittaArc(self, endPoint, sag, forConstruction=False):

sagPoint = midPoint.add(sagVector)

arc = Edge.makeThreePointArc(startPoint, sagPoint, endPoint)
return self.threePointArc(sagPoint, endPoint, forConstruction)

if not forConstruction:
self._addPendingEdge(arc)
def radiusArc(self, endPoint, radius, forConstruction=False):
"""
Draw an arc from the current point to endPoint with an arc defined by the sag (sagitta).
return self.newObject([arc])
:param endPoint: end point for the arc
:type endPoint: 2-tuple, in workplane coordinates
:param radius: the radius of the arc
:type radius: float, the radius of the arc between start point and end point.
:return: a workplane with the current point at the end of the arc
Given that a closed contour is drawn clockwise;
A positive radius means convex arc and negative radius means concave arc.
"""

startPoint = self._findFromPoint(useLocalCoords=True)
endPoint = Vector(endPoint)

# Calculate the sagitta from the radius
length = endPoint.sub(startPoint).Length / 2.0
try:
sag = abs(radius) - math.sqrt(radius**2 - length**2)
except ValueError:
raise ValueError("Arc radius is not large enough to reach the end point.")

# Return a sagittaArc
if radius > 0:
return self.sagittaArc(endPoint, sag, forConstruction)
else:
return self.sagittaArc(endPoint, -sag, forConstruction)

def rotateAndCopy(self, matrix):
"""
Expand Down
23 changes: 14 additions & 9 deletions examples/FreeCAD/Ex005_Extruded_Lines_and_Arcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,28 @@
# half-way back to the origin in the X direction and 0.5 mm above where
# the last line ended at. The arc then ends at (0.0, 1.0), which is 1.0 mm
# above (in the Y direction) where our first line started from.
# 5. An arc is drawn from the last point that ends on (0.3, 0.2), the sag of
# the curve 0.1 determines that the curve is concave with the midpoint 0.1 mm
# from the arc baseline. If the sag was -0.1 the arc would be convex.
# 5. An arc is drawn from the last point that ends on (-0.5, 1.0), the sag of
# the curve 0.2 determines that the curve is concave with the midpoint 0.1 mm
# from the arc baseline. If the sag was -0.2 the arc would be convex.
# This convention is valid when the profile is drawn counterclockwise.
# The reverse is true if the profile is drawn clockwise.
# Clockwise: +sag => convex, -sag => concave
# Counterclockwise: +sag => concave, -sag => convex
# 6. close() is called to automatically draw the last line for us and close
# 6. An arc is drawn from the last point that ends on (-0.7, -0.2), the arc is
# determined by the radius of -1.5 mm.
# Clockwise: +radius => convex, -radius => concave
# Counterclockwise: +radius => concave, -radius => convex
# 7. close() is called to automatically draw the last line for us and close
# the sketch so that it can be extruded.
# 6a. Without the close(), the 2D sketch will be left open and the extrude
# 7a. Without the close(), the 2D sketch will be left open and the extrude
# operation will provide unpredictable results.
# 7. The 2D sketch is extruded into a solid object of the specified thickness.
# 8. The 2D sketch is extruded into a solid object of the specified thickness.
result = cq.Workplane("front").lineTo(width, 0) \
.lineTo(width, 1.0) \
.threePointArc((1.0, 2.5), (0.2, 2.6)) \
.sagittaArc((0.3, 0.2), 0.1) \
.threePointArc((1.0, 1.5), (0.0, 1.0)) \
.sagittaArc((-0.5, 1.0), 0.2) \
.radiusArc((-0.7, -0.2), -1.5) \
.close().extrude(thickness)

# Displays the result of this script
show_object(result)
16 changes: 13 additions & 3 deletions tests/TestCadQuery.py
Original file line number Diff line number Diff line change
Expand Up @@ -867,9 +867,19 @@ def test2DDrawing(self):
r.vertices(selectors.NearestToPointSelector((0.0, 0.0, 0.0)))\
.first().val().Y))

# Test the sagittaArc functions
s = Workplane(Plane.YZ())
r = s.sagittaArc((10, 8), 1).close()
# Test the sagittaArc and radiusArc functions
a1 = Workplane(Plane.YZ()).threePointArc((5, 1), (10, 0))
a2 = Workplane(Plane.YZ()).sagittaArc((10, 0), -1)
a3 = Workplane(Plane.YZ()).threePointArc((6, 2), (12, 0))
a4 = Workplane(Plane.YZ()).radiusArc((12, 0), -10)

assert(a1.edges().first().val().geomType() == "CIRCLE")
assert(a2.edges().first().val().geomType() == "CIRCLE")
assert(a3.edges().first().val().geomType() == "CIRCLE")
assert(a4.edges().first().val().geomType() == "CIRCLE")

assert(a1.edges().first().val().Length() == a2.edges().first().val().Length())
assert(a3.edges().first().val().Length() == a4.edges().first().val().Length())

def testLargestDimension(self):
"""
Expand Down

0 comments on commit c4df65c

Please sign in to comment.