Commit 487757ad authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

1. drawing wedges within clip paths - fixed for escher->0 or escher->inf

2. fixed artifact border line from the central square used for initial filling
3. auto filename
parent 5a37ebb3
...@@ -30,6 +30,7 @@ from matplotlib.patches import Circle ...@@ -30,6 +30,7 @@ from matplotlib.patches import Circle
from matplotlib.patches import Rectangle from matplotlib.patches import Rectangle
from matplotlib.patches import Polygon from matplotlib.patches import Polygon
from matplotlib.patches import Wedge from matplotlib.patches import Wedge
from matplotlib.patches import PathPatch
import matplotlib as mpl import matplotlib as mpl
...@@ -39,6 +40,8 @@ from matplotlib.path import Path ...@@ -39,6 +40,8 @@ from matplotlib.path import Path
import copy import copy
import math import math
import sys
''' '''
requirements: requirements:
...@@ -56,10 +59,13 @@ class Escher_Pattern: ...@@ -56,10 +59,13 @@ class Escher_Pattern:
# units are mms but coordinates are in pt to compare with php script # units are mms but coordinates are in pt to compare with php script
MM2PT = 72.0/25.4 MM2PT = 72.0/25.4
opts_k = {'facecolor':'black','edgecolor':'r','linewidth':0}
opts_w = {'facecolor':'white','edgecolor':'r','linewidth':0}
opts_b = {'facecolor':'blue', 'edgecolor':'r','linewidth':0}
opts_r = {'facecolor':'red', 'edgecolor':'r','linewidth':0}
# init # init
def __init__(self, def __init__(self,
filename = "pattern.pdf",
width = 270, # width in units width = 270, # width in units
height = 210, # height in units height = 210, # height in units
lpm = 50, # lines per meter lpm = 50, # lines per meter
...@@ -67,7 +73,7 @@ class Escher_Pattern: ...@@ -67,7 +73,7 @@ class Escher_Pattern:
rotate = 5, # degrees rotate = 5, # degrees
units = 'mm', units = 'mm',
): ):
self.filename = filename
self.width = int(width*self.MM2PT) self.width = int(width*self.MM2PT)
self.height = int(height*self.MM2PT) self.height = int(height*self.MM2PT)
self.lpm = lpm self.lpm = lpm
...@@ -75,6 +81,15 @@ class Escher_Pattern: ...@@ -75,6 +81,15 @@ class Escher_Pattern:
self.angle = rotate self.angle = rotate
self.units = units self.units = units
self.basename = 'escher-pattern'
self.basename += '-ESCHER'+str(self.escher)
self.basename += '-LPM'+str(self.lpm)
self.basename += '-ROT'+str(self.angle)
self.basename += '-PAGE_WIDTH'+str(width)
self.basename += '-PAGE_HEIGHT'+str(height)
self.pdf_name = self.basename+".pdf"
plt.autoscale(tight=True) plt.autoscale(tight=True)
plt.axis('off') plt.axis('off')
plt.margins(0.0) plt.margins(0.0)
...@@ -95,23 +110,88 @@ class Escher_Pattern: ...@@ -95,23 +110,88 @@ class Escher_Pattern:
self.ax.set_ylim([0,self.height]) self.ax.set_ylim([0,self.height])
self.ax.set_xlim([0,self.width]) self.ax.set_xlim([0,self.width])
print("init done") self.rotation = mpl.transforms.Affine2D().rotate_deg(-self.angle) + self.ax.transData
print("init done")
# rotate clock-wise
def rotate(self,deg):
t_start = self.ax.transData
t = mpl.transforms.Affine2D().rotate_deg(-deg)
t_end = t_start + t
for x in self.ax.patches + self.ax.collections:
x.set_transform(t_end)
# generate and place a patch
def generate_cell(self,x,y,tpts,template,halfAngle,r,ba):
for k,v in enumerate(template):
# even-even black cell
vcp = copy.copy(v)
if (type(v)==Wedge):
vcp.set_center((tpts[k][0]+x,tpts[k][1]+y))
elif (type(v)==Rectangle):
vcp.set_xy((tpts[k][0]+x,tpts[k][1]+y))
self.ax.add_patch(vcp)
vcp.set_transform(self.rotation)
# do clipping
if (type(v)==Wedge):
sin0 = math.sin(math.radians(halfAngle))
cos0 = math.cos(math.radians(halfAngle))
if ba[k]==0:
w0 = r - r*cos0
h0 = 2*r*sin0
x0 = tpts[k][0] + r - w0
y0 = tpts[k][1] - h0/2
if ba[k]==180:
w0 = r - r*cos0
h0 = 2*r*sin0
x0 = tpts[k][0] - r
y0 = tpts[k][1] - h0/2
if ba[k]==270:
w0 = 2*r*sin0
h0 = r - r*cos0
x0 = tpts[k][0] - w0/2
y0 = tpts[k][1] - r
if ba[k]==90:
w0 = 2*r*sin0
h0 = r - r*cos0
x0 = tpts[k][0] - w0/2
y0 = tpts[k][1] + r - h0
# correction, so the shadow line from Rectange is not seen
if ba[k]==0:
x0 -= w0
w0 *= 2
if ba[k]==180:
w0 *= 2
if ba[k]==270:
h0 *= 2
if ba[k]==90:
y0 -= h0
h0 *= 2
cp = Rectangle((x0,y0),w0,h0,**self.opts_w, lw=0)
vcp2 = copy.copy(cp)
xy = vcp2.get_xy()
vcp2.set_xy((xy[0]+x,xy[1]+y))
path = vcp2.get_path()
transform = vcp2.get_transform()
path = transform.transform_path(path)
vcp2 = PathPatch(path, fc='none', ec='none', lw=0)
self.ax.add_patch(vcp2)
# rotate here
vcp2.set_transform(self.rotation)
vcp.set_clip_path(vcp2)
# generate the whole pattern
def generate(self): def generate(self):
side = 500/self.lpm*self.MM2PT side = 500/self.lpm*self.MM2PT
# escher pattern
if (self.escher>0): if (self.escher>0):
# no rounding # no rounding
...@@ -126,6 +206,18 @@ class Escher_Pattern: ...@@ -126,6 +206,18 @@ class Escher_Pattern:
halfAngle = math.degrees(math.atan(qSize/h)) halfAngle = math.degrees(math.atan(qSize/h))
center = dc+r center = dc+r
ba = [
None,
0,
180,
270,
90,
180,
0,
90,
270
]
tpts = [ tpts = [
[center-hSize, center-hSize], [center-hSize, center-hSize],
[center-Size+dc, center-qSize], [center-Size+dc, center-qSize],
...@@ -139,57 +231,49 @@ class Escher_Pattern: ...@@ -139,57 +231,49 @@ class Escher_Pattern:
] ]
template = [ template = [
Rectangle( tpts[0], Size, Size, facecolor="k",linewidth=0,edgecolor="r"), Rectangle( tpts[0], Size, Size, **self.opts_k),
Wedge( tpts[1], r, 0-halfAngle, 0+halfAngle,facecolor="w",linewidth=0,edgecolor="r"), Wedge( tpts[1], r, ba[1]-halfAngle, ba[1]+halfAngle, **self.opts_w),
Wedge( tpts[2], r, 180-halfAngle,180+halfAngle,facecolor="k",linewidth=0,edgecolor="r"), Wedge( tpts[2], r, ba[2]-halfAngle, ba[2]+halfAngle, **self.opts_k),
Wedge( tpts[3], r, 270-halfAngle,270+halfAngle,facecolor="w",linewidth=0,edgecolor="r"), Wedge( tpts[3], r, ba[3]-halfAngle, ba[3]+halfAngle, **self.opts_w),
Wedge( tpts[4], r, 90-halfAngle, 90+halfAngle,facecolor="k",linewidth=0,edgecolor="r"), Wedge( tpts[4], r, ba[4]-halfAngle, ba[4]+halfAngle, **self.opts_k),
Wedge( tpts[5], r, 180-halfAngle,180+halfAngle,facecolor="w",linewidth=0,edgecolor="r"), Wedge( tpts[5], r, ba[5]-halfAngle, ba[5]+halfAngle, **self.opts_w),
Wedge( tpts[6], r, 0-halfAngle, 0+halfAngle,facecolor="k",linewidth=0,edgecolor="r"), Wedge( tpts[6], r, ba[6]-halfAngle, ba[6]+halfAngle, **self.opts_k),
Wedge( tpts[7], r, 90-halfAngle, 90+halfAngle,facecolor="w",linewidth=0,edgecolor="r"), Wedge( tpts[7], r, ba[7]-halfAngle, ba[7]+halfAngle, **self.opts_w),
Wedge( tpts[8], r, 270-halfAngle,270+halfAngle,facecolor="k",linewidth=0,edgecolor="r") Wedge( tpts[8], r, ba[8]-halfAngle, ba[8]+halfAngle, **self.opts_k)
] ]
# checker board
else: else:
halfAngle = 0
r = 0
ba = [
None
]
tpts = [ tpts = [
[0,0] [0,0]
] ]
template = [ template = [
Rectangle(tpts[0],side,side,facecolor="k",linewidth=0,edgecolor="r") Rectangle(tpts[0],side,side, **self.opts_k)
] ]
# calc how much more is needed for the rotation # calc how much more is needed for the rotation
abs_angle_rad = math.radians(abs(self.angle)) abs_angle_rad = math.radians(abs(self.angle))
extra_w = self.height*math.tan(abs_angle_rad) + side extra_w = self.height*math.tan(abs_angle_rad) # + side
extra_h = self.width *math.tan(abs_angle_rad) + side extra_h = self.width *math.tan(abs_angle_rad) # + side
# would like to pass (0,0)
extra_w = int(extra_w/(2*side)+1)*2*side
extra_h = int(extra_h/(2*side)+1)*2*side
a = np.arange(-extra_w, self.width +extra_w, 2*side) a = np.arange(-extra_w, self.width +extra_w, 2*side)
b = np.arange(-extra_h, self.height+extra_h, 2*side) b = np.arange(-extra_h, self.height+extra_h, 2*side)
for x, y in [(x,y) for x in a for y in b]: for x, y in [(x,y) for x in a for y in b]:
self.generate_cell(x ,y ,tpts,template,halfAngle,r,ba)
for k,v in enumerate(template): self.generate_cell(x+side,y+side,tpts,template,halfAngle,r,ba)
# even-even black cell
vcp = copy.copy(v)
if (type(v)==Wedge):
vcp.set_center((tpts[k][0]+x,tpts[k][1]+y))
elif (type(v)==Rectangle):
vcp.set_xy((tpts[k][0]+x,tpts[k][1]+y))
self.ax.add_patch(vcp)
# odd-odd black cell
vcp = copy.copy(v)
if (type(v)==Wedge):
vcp.set_center((tpts[k][0]+x+side,tpts[k][1]+y+side))
elif (type(v)==Rectangle):
vcp.set_xy((tpts[k][0]+x+side,tpts[k][1]+y+side))
self.ax.add_patch(vcp)
# now rotate
self.rotate(self.angle)
# test # test
...@@ -215,7 +299,7 @@ class Escher_Pattern: ...@@ -215,7 +299,7 @@ class Escher_Pattern:
# save function # save function
def save(self): def save(self):
pp = PdfPages(self.filename) pp = PdfPages(self.pdf_name)
self.fig.tight_layout(pad=0) self.fig.tight_layout(pad=0)
#plt.show() #plt.show()
...@@ -230,7 +314,9 @@ if __name__ == "__main__": ...@@ -230,7 +314,9 @@ if __name__ == "__main__":
#ep = Escher_Pattern("test.pdf", escher=2.0, lpm=50, rotate=10) #ep = Escher_Pattern("test.pdf", escher=2.0, lpm=50, rotate=10)
#http://192.168.0.137/escher/escher_pattern.php?PAGE_WIDTH=1524&PAGE_HEIGHT=3048&LPM=2.705449885575893&ROTATE=14.036243467 #http://192.168.0.137/escher/escher_pattern.php?PAGE_WIDTH=1524&PAGE_HEIGHT=3048&LPM=2.705449885575893&ROTATE=14.036243467
ep = Escher_Pattern("test.pdf", width= 1524, height= 3048, escher=2.0, lpm=2.705449885575893, rotate=14.036243467) #ep = Escher_Pattern(width= 1524, height= 3048, escher=0, lpm=2.705449885575893, rotate=10)
ep = Escher_Pattern(width= 1524, height= 3048, escher=2, lpm=2.705449885575893, rotate=14.036243467)
#ep = Escher_Pattern(width= 160, height= 320, escher=2, lpm=50, rotate=13)
ep.generate() ep.generate()
ep.save() ep.save()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment