Skip to content

Commit a733521

Browse files
authored
Create drawSines.py
1 parent 5e94cab commit a733521

1 file changed

Lines changed: 148 additions & 0 deletions

File tree

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import fitz, math
2+
"""
3+
Created on 2017-08-17
4+
5+
@author: (c) 2017, Jorj X. McKie
6+
7+
License: GNU GPL V3
8+
9+
PyMuPDF Demo Program
10+
---------------------
11+
Create a PDF with drawings of the sine and cosine functions using PyMuPDF.
12+
Depending on how start and end points are located with respect to each
13+
other, horizontal or vertical drawings result.
14+
The vertical case can obviously be used for creating inverse function
15+
(arcus sine / cosine) graphs.
16+
17+
The function graphs are pieced together in 90 degree parts, for which Bezier
18+
curves are used.
19+
20+
Note that the 'alfa' and 'beta' constants represent values for use as
21+
Bezier control points like so:
22+
x-values (written in degrees): [0, 30, 60, 90]
23+
corresponding y-values: [0, alfa, beta, 1]
24+
25+
These values have been calculated by the scipy.interpolate.splrep() method.
26+
They provide an excellent spline approximation of the sine / cosine
27+
functions - please look at SciPy documentation for background.
28+
29+
"""
30+
def bsinPoints(pb, pe):
31+
"""Return Bezier control points, when pb and pe stand for a full period
32+
from (0,0) to (2*pi, 0), respectively, in the user's coordinate system.
33+
The returned points can be used to draw up to four Bezier curves for
34+
the complete sine function graph from 0 to 2*pi.
35+
"""
36+
f = abs(pe - pb) * 0.5 / math.pi # represents the unit
37+
alfa = 5.34295228e-01
38+
beta = 1.01474288e+00
39+
# adjust for either horizontal or vertical
40+
if pb.y == pe.y:
41+
y_ampl = (0, f)
42+
y_alfa = (0, f * alfa)
43+
y_beta = (0, f * beta)
44+
elif pb.x == pe.x:
45+
y_ampl = (-f, 0)
46+
y_alfa = (-f * alfa, 0)
47+
y_beta = (-f * beta, 0)
48+
else:
49+
raise ValueError("can only draw horizontal or vertical")
50+
51+
p0 = pb
52+
p4 = pe
53+
p1 = pb + (pe - pb)*0.25 - y_ampl
54+
p2 = pb + (pe - pb)*0.5
55+
p3 = pb + (pe - pb)*0.75 + y_ampl
56+
k1 = pb + (pe - pb)*(1./12.) - y_alfa
57+
k2 = pb + (pe - pb)*(2./12.) - y_beta
58+
k3 = pb + (pe - pb)*(4./12.) - y_beta
59+
k4 = pb + (pe - pb)*(5./12.) - y_alfa
60+
k5 = pb + (pe - pb)*(7./12.) + y_alfa
61+
k6 = pb + (pe - pb)*(8./12.) + y_beta
62+
k7 = pb + (pe - pb)*(10./12.) + y_beta
63+
k8 = pb + (pe - pb)*(11./12.) + y_alfa
64+
return p0, k1, k2, p1, k3, k4, p2, k5, k6, p3, k7, k8, p4
65+
66+
def bcosPoints(pb, pe):
67+
"""Return Bezier control points, when pb and pe stand for a full period
68+
from (0,0) to (2*pi, 0), respectively, in the user's coordinate system.
69+
The returned points can be used to draw up to four Bezier curves for
70+
the complete cosine function graph from 0 to 2*pi.
71+
"""
72+
f = abs(pe - pb) * 0.5 / math.pi # represents the unit
73+
alfa = 5.34295228e-01
74+
beta = 1.01474288e+00
75+
# adjust for either horizontal or vertical
76+
if pb.y == pe.y:
77+
y_ampl = (0, f)
78+
y_alfa = (0, f * alfa)
79+
y_beta = (0, f * beta)
80+
elif pb.x == pe.x:
81+
y_ampl = (-f, 0)
82+
y_alfa = (-f * alfa, 0)
83+
y_beta = (-f * beta, 0)
84+
else:
85+
raise ValueError("can only draw horizontal or vertical")
86+
87+
p0 = pb - y_ampl
88+
p4 = pe - y_ampl
89+
p1 = pb + (pe - pb)*0.25
90+
p2 = pb + (pe - pb)*0.5 + y_ampl
91+
p3 = pb + (pe - pb)*0.75
92+
k1 = pb + (pe - pb)*(1./12.) - y_beta
93+
k2 = pb + (pe - pb)*(2./12.) - y_alfa
94+
k3 = pb + (pe - pb)*(4./12.) + y_alfa
95+
k4 = pb + (pe - pb)*(5./12.) + y_beta
96+
k5 = pb + (pe - pb)*(7./12.) + y_beta
97+
k6 = pb + (pe - pb)*(8./12.) + y_alfa
98+
k7 = pb + (pe - pb)*(10./12.) - y_alfa
99+
k8 = pb + (pe - pb)*(11./12.) - y_beta
100+
return p0, k1, k2, p1, k3, k4, p2, k5, k6, p3, k7, k8, p4
101+
102+
if __name__ == "__main__":
103+
from fitz.utils import getColor
104+
doc = fitz.open()
105+
page = doc.newPage()
106+
red = getColor("red") # line color for sine
107+
blue = getColor("blue") # line color for cosine
108+
yellow = getColor("py_color") # background color
109+
w = 0.3 # line width
110+
#--------------------------------------------------------------------------
111+
# define end points of x axis we want to use as 0 and 2*pi
112+
# these may be oriented horizontally or vertically
113+
#--------------------------------------------------------------------------
114+
pb = fitz.Point(50, 200) # example values for
115+
pe = fitz.Point(550, 200) # horizontal drawing
116+
#pb = fitz.Point(300, 100) # example values for
117+
#pe = fitz.Point(300, 600) # vertical drawing
118+
page.drawLine(pb, pe, width = w) # draw x-axis (default color)
119+
120+
# get all points for the sine function
121+
pnt = bsinPoints(pb, pe)
122+
# draw some points for better orientation
123+
for i in (0, 3, 6, 9, 12):
124+
page.drawCircle(pnt[i], 1, color = red)
125+
# now draw a complete sine graph period in "red"
126+
for i in (0, 3, 6, 9): # draw all 4 function segments
127+
page.drawBezier(pnt[i], pnt[i+1], pnt[i+2], pnt[i+3],
128+
color = red, width = w)
129+
130+
# same thing for cosine with "blue"
131+
pnt = bcosPoints(pb, pe)
132+
for i in (0, 3, 6, 9, 12):
133+
page.drawCircle(pnt[i], 1, color = blue)
134+
for i in (0, 3, 6, 9): # draw all 4 function segments
135+
page.drawBezier(pnt[i], pnt[i+1], pnt[i+2], pnt[i+3],
136+
color = blue, width = w)
137+
138+
# finally draw a rectangle around everything (in background):
139+
rect = fitz.Rect(pb, pb) # create smallest rectangle
140+
for p in pnt: # containing all the points
141+
rect = rect | p
142+
# leave 5 px space around the picture
143+
rect.x0 -= 5
144+
rect.y0 -= 5
145+
rect.x1 += 5
146+
rect.y1 += 5
147+
page.drawRect(rect, width = w, fill = yellow, overlay = False)
148+
doc.save("drawSines.pdf")

0 commit comments

Comments
 (0)