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 canvasPIL(Python Imaging  Library)繪製ovalellipse簡化成canvas.create_line(),canvan.create_polygon()PILdraw.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