pdfgeom.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #Copyright ReportLab Europe Ltd. 2000-2017
  2. #see license.txt for license details
  3. #history https://hg.reportlab.com/hg-public/reportlab/log/tip/src/reportlab/pdfgen/pdfgeom.py
  4. __version__='3.3.0'
  5. __doc__="""
  6. This module includes any mathematical methods needed for PIDDLE.
  7. It should have no dependencies beyond the Python library.
  8. So far, just Robert Kern's bezierArc.
  9. """
  10. from math import sin, cos, pi, ceil
  11. def bezierArc(x1,y1, x2,y2, startAng=0, extent=90):
  12. """bezierArc(x1,y1, x2,y2, startAng=0, extent=90) --> List of Bezier
  13. curve control points.
  14. (x1, y1) and (x2, y2) are the corners of the enclosing rectangle. The
  15. coordinate system has coordinates that increase to the right and down.
  16. Angles, measured in degress, start with 0 to the right (the positive X
  17. axis) and increase counter-clockwise. The arc extends from startAng
  18. to startAng+extent. I.e. startAng=0 and extent=180 yields an openside-down
  19. semi-circle.
  20. The resulting coordinates are of the form (x1,y1, x2,y2, x3,y3, x4,y4)
  21. such that the curve goes from (x1, y1) to (x4, y4) with (x2, y2) and
  22. (x3, y3) as their respective Bezier control points."""
  23. x1,y1, x2,y2 = min(x1,x2), max(y1,y2), max(x1,x2), min(y1,y2)
  24. if abs(extent) <= 90:
  25. arcList = [startAng]
  26. fragAngle = float(extent)
  27. Nfrag = 1
  28. else:
  29. arcList = []
  30. Nfrag = int(ceil(abs(extent)/90.))
  31. fragAngle = float(extent) / Nfrag
  32. x_cen = (x1+x2)/2.
  33. y_cen = (y1+y2)/2.
  34. rx = (x2-x1)/2.
  35. ry = (y2-y1)/2.
  36. halfAng = fragAngle * pi / 360.
  37. kappa = abs(4. / 3. * (1. - cos(halfAng)) / sin(halfAng))
  38. if fragAngle < 0:
  39. sign = -1
  40. else:
  41. sign = 1
  42. pointList = []
  43. for i in range(Nfrag):
  44. theta0 = (startAng + i*fragAngle) * pi / 180.
  45. theta1 = (startAng + (i+1)*fragAngle) *pi / 180.
  46. if fragAngle > 0:
  47. pointList.append((x_cen + rx * cos(theta0),
  48. y_cen - ry * sin(theta0),
  49. x_cen + rx * (cos(theta0) - kappa * sin(theta0)),
  50. y_cen - ry * (sin(theta0) + kappa * cos(theta0)),
  51. x_cen + rx * (cos(theta1) + kappa * sin(theta1)),
  52. y_cen - ry * (sin(theta1) - kappa * cos(theta1)),
  53. x_cen + rx * cos(theta1),
  54. y_cen - ry * sin(theta1)))
  55. else:
  56. pointList.append((x_cen + rx * cos(theta0),
  57. y_cen - ry * sin(theta0),
  58. x_cen + rx * (cos(theta0) + kappa * sin(theta0)),
  59. y_cen - ry * (sin(theta0) - kappa * cos(theta0)),
  60. x_cen + rx * (cos(theta1) - kappa * sin(theta1)),
  61. y_cen - ry * (sin(theta1) + kappa * cos(theta1)),
  62. x_cen + rx * cos(theta1),
  63. y_cen - ry * sin(theta1)))
  64. return pointList