User defined Ellipse Function in Python Canvas(2)
使用者自定橢圓函數(2)
By daych169
The self-defined ellipse function is very widely used, except for the one mentioned in the previous article, such as icon draw, digital plot, grids diagram.
To the small icon, bitmap, small icon, xbm bitmap mapping back to the grid map is very useful. The canvas.create_oval() supported by the Python canvas
can only draw orthogonal ellipses. The graphics coordinates only provide box coordinates, so there are too many restrictions on usage.
Using the custom ellipse function, we can simplify the drawing of oval or ellipse by Python canvas and PIL (Python Imaging Library) into canvas.create_line(),
canvan.create_polygon() and PIL draw.line() and draw.polygon echo each other.
自訂橢圓函數(self_defined ellipse function)使用範圍非常廣泛,除了在上一片篇所提及外,其他如小示圖(icon draw),數位繪圖設計(digital plot),
方格圖(grids diagram)映射至小圖示,bitmap,小圖示、xbm bitmap映射回方格圖大有妙用。Python canvas支援之 canvas.create_oval()
只能繪製正交橢圓,圖形座標只提供箱形座談(box coordinates),因此在使用上限制太多?利用自訂橢圓函數,我們可以將Python canvas及PIL(Python Imaging Library)繪製oval或ellipse簡化成canvas.create_line(),canvan.create_polygon()及PIL之draw.line()及draw.polygon互相呼應。
def canvas_imagePlot(self,canvas,commandIn,ngridx,ngridy,pts,fillrgb):
#print('fillrgb',fillrgb)
#print('pts',pts)
imageTpt =Image.new('RGB', (ngridx,ngridy),(255,255,255))
draw =ImageDraw.Draw(imageTpt)
if commandIn=='line':
draw.line(pts, fill=fillrgb)
self.canvas.create_line(pts,fill=rgbtocolorhex(fillrgb))
if commandIn=='polygon':
draw.polygon(pts, fill=fillrgb)
self.canvas.create_poygon(pts,fill=rgbtocolorhex(fillrgb))
maps_01_colr=[]
for i in range(imageTpt.size[0]): # For every pixel:
for j in range(imageTpt.size[1]):
r, g, b = imageTpt.getpixel((i, j))
maps_01_colr.append((r,g,b))
filename = "temp.jpg"
imageTpt.save(filename)
self.image=imageTpt
#imageTpt.show()
return maps_01_colr
為配合PIL繪圖座標格式,E llipse及圓之函數,我將其修正如下:
def Cir3pt_Draw(x0,y0,x1,y1,x2,y2,angBeg=0,angEnd=360,npt=18):
#print('into Cir3pt_Prop' )
v31X = x2 - x0
v31Y = y2 - y0
v21X = x1 - x0
v21Y = y1 - y0
d_ca = v31X * v21X + v31Y * v21Y
v32X = x2 - x1
v32Y = y2 - y1
v12X = x0 - x1
v12Y = y0 - y1
d_ba = v32X * v12X + v32Y * v12Y
v13X = x0 - x2
v13Y = y0 - y2
v23X = x1 - x2
v23Y = y1 - y2
d_cb = v13X * v23X + v13Y * v23Y
n1 = d_ba * d_cb
n2 = d_cb * d_ca
n3 = d_ca * d_ba
radius_ = math.sqrt((d_ca + d_ba) * (d_ba + d_cb) * (d_cb + d_ca)/(n1 + n2 + n3)) / 2.0
ptCenX = ((n2 + n3) * x0 + (n3 + n1) * x1 + (n1 + n2) * x2) / 2.0/(n1 + n2 + n3)
ptCenY = ((n2 + n3) * y0 + (n3 + n1) * y1 + (n1 + n2) * y2) / 2.0 /(n1 + n2 + n3)
#print('xcn,ycn,rad',ptCenX,ptCenY,radius_)
xa=[]
ya=[]
pts=[]
ndo=npt
angdel=math.radians((angEnd-angBeg)/npt)
#print('ndo,angdel',ndo,angdel)
for i in range(npt+1):
angdelT=angdel*i
xtpt=ptCenX+radius_*math.cos(angdelT)
ytpt=ptCenY+radius_*math.sin(angdelT)
#print('i,ang,x,y=',i,math.degrees(angdelT),xtpt,ytpt)
pts.append(xtpt)
pts.append(ytpt)
return pts
def ellipsemaker_XY(x0,y0,x1,y1,x2,y2,angbeg=0,angend=360,npt=18):
#print('ellipsemaker_XYx0,y0,x1,y1,x2,y2',x0,y0,x1,y1,x2,y2)
ptcenx=(x0+x1) / 2.
ptceny=(y0+y1) / 2.
#print("ptcen.x,ptcen.y",ptcen.x,ptcen.y)
angslop = math.degrees(math.atan2((y1-y0), (x1-x0)))
#print( 'angslop=',angslop)
aa = math.sqrt((x0 - ptcenx)**2 + (y0 - ptceny) **2)
#print('aa',aa)
ptanyx = x2
ptanyy = y2
#print('ptany=',ptany.x,ptany.y)
ta1 = ptanyx - ptcenx
ta2 = aa * math.cos(math.radians(angslop))
ta3 = -math.sin(math.radians(angslop))
#print('ta1,ta2,ta3',ta1,ta2,ta3)
tb1 = ptanyy - ptceny
tb2 = aa * math.sin(math.radians(angslop))
tb3 = math.cos(math.radians(angslop))
#print('tb1,tb2,tb3',tb1,tb2,tb3)
t1 = (ta1 * tb3 - tb1 * ta3) / (ta2 * tb3 - ta3 * tb2)
t2 = (ta2 * tb1 - tb2 * ta1) / (ta2 * tb3 - ta3 * tb2)
#print("t1,t2",t1,t2)
#print(1-t1**2)
bb=aa
try:
if (1.0-t1**2) >= 0.0000001 :
bb = math.sqrt(t2**2 / (1.0 - t1 ** 2))
#print("bb",bb)
else:
#print("error in function ellprop")
pass
except:
pass
#print('aa,bb',aa,bb)
#sttpt=str(aa)+str(bb)
ndo=npt
delang = (angend-angbeg) / npt
#print("delang=",delang)
xout=[]
yout=[]
pts=[]
for i in range(0,npt+1):
angi = angbeg + delang * i
tpt1=aa* math.cos(math.radians(angi))* math.cos(math.radians(angslop))
tpt2=- bb * math.sin(math.radians(angi)) * math.sin(math.radians(angslop)) # 'x座標
ptsix=tpt1+tpt2
tpt3=aa* math.cos(math.radians(angi))* math.sin(math.radians(angslop))
tpt4= bb * math.sin(math.radians(angi)) * math.cos(math.radians(angslop)) # 'y座標
ptsiy=tpt3 +tpt4
ptsix=ptcenx+ptsix
ptsiy=ptceny+ptsiy
#print('i,angi,ptsix,ptsiy',i,angi,ptsix,ptsiy)
#ptstpt=pt2d(ptsix,ptsiy)
#print('i,ptstpt.x& .y',i,ptstpt.x,ptstpt.y)
pts.append(ptsix)
pts.append(ptsiy)
#print("in maker ptellp",i,ptsix,ptsiy)
return pts