Wednesday, June 4, 2014

14. Line

Line is a vertex canvas instruction. It allows drawing of lines through points.




The Python program first imports BoxLayout so the root class is based on this layout. The App import always has to be done. Then the math standard library is used. Three of the math functions will be used here: cos, sin, and radians. The function radians is imported as the alias rad. The function radians() converts the degrees to radians so cos and sin can be used.




Inside the build function, there is a nested function. The function, ellie(), is based on transversing the points, around an ellipse, centered at origin variable, orig. The ellipse height, is 2b, and ellipse width, is 2a. An ellipse goes from 0 to 360 degrees, however, here, start angle and stop angle can be specified, to create an arc. The number of segments determine the step angle. The List pts is returned, which has the length of 2 times segments plus 2.




The ellie() function is used to create four ellipses and two arcs. Note, orig, can either be a list or tuple. In Python, usually, the two, often, are interchangable. You can change the parameters to find a suitable set.


# ex14.py

from kivy.uix.boxlayout import BoxLayout
from kivy.app import App

from math import cos,sin,radians as rad

class Ex14(BoxLayout):
    pass
   
class Ex14App(App):
    def build(self):
        def ellie(a,b,orig,start_ang,stop_ang,seg):
            pts=[]
            step_ang=(stop_ang-start_ang)//seg
            for ang in range(start_ang,stop_ang+step_ang,step_ang):
                pts.extend([a*cos(rad(ang))+orig[0],
                            b*sin(rad(ang))+orig[1]])
            return pts
        
        self.Head=ellie(400,300,[400,300],-45,225,6)
        self.Chin=ellie(400,300,(400,300),225,315,3)
        self.Leye=ellie(60,40,[250,450],0,360,15)
        self.Reye=ellie(60,40,(550,450),0,360,15)
        self.Mouth=ellie(160,30,[400,200],0,360,25)
        self.Nose=ellie(5,50,(400,350),0,360,25)
        print(self.Chin)
        print(len(self.Chin))
        return Ex14()

if __name__=='__main__':
    Ex14App().run()



In the kv file, the import directive is used to import the random module from the standard library. It is not imported with any alias. It is used to create a gray color with the red, green, and blue components, between .245 and .295. This gray color will be the background.




Now the lines corresponding to Head and Chin are drawn with the specified color. Here, two lists are joined to create a bigger list.




The rest of the Lines are drawn. We can not use the plus operator to join them, since that will draw an additional line connecting the different components, resulting in all joined shapes. Thus, the lines have to be seperate since you do not want these parts physically joined.


# ex14.kv
#:import random random

<Ex14>:
    canvas:
        Color:
            rgb: [.245+.05*random.random()]*3
        Rectangle:
            pos: self.pos
            size: self.size
        Color:
            rgb: 1,.1,.5
        Line:
            points: app.Head+app.Chin
            width: 3
        Color:
            rgb: 1,.5,.1
        Line:
            points: app.Leye
            width: 2
        Line:
            points: app.Reye
            width: 2
        Line:
            points: app.Mouth
            width: 2
        Line:
            points: app.Nose
            width: 2
    



This is the result. Lines, for the Head and Chin, are collectively 360 degrees, and form the outer, nine-sided polygon. The interior contains four ellipses as they all went from 0 to 360 degrees. They have enough segments to look curved. It will be a very simple modification, to add a rotate parameter, to the ellie() function, to give the ellipses a slant. We can also use the context rotate canvas instructions.




Tuesday, June 3, 2014

13. Ellipse

Ellipse is a vertex canvas instruction. It allows drawing of a regular polygon, or an arc based on them.




This article shows regular polygons with different number of sides. They have many vertices on a circle.




However, in Kivy we can make polygons based on an ellipse. The area of an ellipse is smaller than a similarly sized rectangle.




This shows an ellipse, as well as what an ellipse, approximated by N = 8 segments looks like. We can see that as N increases, the shape approximates a true ellipse. The default in Kivy is 180.




These are the formulas for x and y. These math formulas assume the center is 0,0. Thus, after calculations are done, there has to be translation by x of a and y of b. The width is 2a, and height is 2b. Note, the angles in Kivy, are different than those in math. In Kivy, the 0 degree point, corresponds to the 90 degree-point, in math.




This shows an example when the number of segments is 6. We have 6 angles, and we have to find six x, and y coordinates. The first two are calculated here. After calculation, we have to translate. The first point becomes x of 800, and y of 300, after the translation.




This Python program shows the root widget is a GridLayout.


# ex13.py

from kivy.uix.gridlayout import GridLayout
from kivy.app import App

class Ex13(GridLayout):
    pass
   
class Ex13App(App):
    def build(self):
        return Ex13()

if __name__=='__main__':
    Ex13App().run()



For the GridLayout, we have 4 columns. In this program, we use the set directive. Note directives, look like comments, but they are really commands. It sets a variable to an expression. Here, we just set them equal to different constants. These constants refer to what arc to cut for the figures in row2 and row3 of the Grid. The window is cleared, by painting with white color.




These instructions define the first two ellipses. We set a color for the row. The first ellipse has N = 180 (which is the default number of segments). The next one has 5 segments, which will be a pentagon.




The next 2 ellipses in the first row have segments of 4, and 3. This gives shapes of a square, and an equilateral triangle.




First, the color is set for the second row. These two arcs are created. For the arcs, we have to give the start, and the end angle. We use default number of segments, 180, and 5, for the two ellipse arcs. The rest of the kv file, corresponds, to the other, 6 ellipse arcs, following the same pattern.


# ex13.kv

#:set angle_start_row2 240 
#:set angle_end_row2 480
#:set angle_start_row3 120
#:set angle_end_row3 240

<Ex13>:
    cols:4
    canvas:
        Color:
            rgb: 1,1,1
        Rectangle:
            pos: self.pos
            size: self.size
    RelativeLayout:
        canvas:
            Color:
                rgb: 1,.1,.5
            Ellipse:
                pos: 0,0
                size: self.size
    RelativeLayout:
        canvas:
            Ellipse:
                segments: 5
                pos: 0,0
                size: self.size
    RelativeLayout:
        canvas:
            Ellipse:
                segments: 4
                pos: 0, 0
                size: self.size
    RelativeLayout:
        canvas:
            Ellipse:
                segments: 3
                pos: 0, 0
                size: self.size

    RelativeLayout:
        canvas:
            Color:
                rgb: 1,.5,1
            Ellipse:
                angle_start: angle_start_row2
                angle_end: angle_end_row2
                pos: 0,0
                size: self.size
    RelativeLayout:
        canvas:
            Ellipse:
                angle_start: angle_start_row2
                angle_end: angle_end_row2
                segments: 5
                pos: 0,0
                size: self.size
    RelativeLayout:
        canvas:
            Ellipse:
                angle_start: angle_start_row2
                angle_end: angle_end_row2
                segments: 4
                pos: 0, 0
                size: self.size
    RelativeLayout:
        canvas:
            Ellipse:
                angle_start: angle_start_row2
                angle_end: angle_end_row2
                segments: 3
                pos: 0, 0
                size: self.size

    RelativeLayout:
        canvas:
            Color:
                rgb: 1,.5,0
            Ellipse:
                angle_start: angle_start_row3
                angle_end: angle_end_row3
                pos: 0,0
                size: self.size
    RelativeLayout:
        canvas:
            Ellipse:
                angle_start: angle_start_row3
                angle_end: angle_end_row3
                segments: 5
                pos: 0,0
                size: self.size
    RelativeLayout:
        canvas:
            Ellipse:
                angle_start: angle_start_row3
                angle_end: angle_end_row3
                segments: 4
                pos: 0, 0
                size: self.size
    RelativeLayout:
        canvas:
            Ellipse:
                angle_start: angle_start_row3
                angle_end: angle_end_row3
                segments: 3
                pos: 0, 0
                size: self.size



This is the result. We have 3 rows and 4 columns. Rows 2 and 3 are arc shapes, while Row1 has the default angles, 0 and 360 to form a complete circle. By changing the size of the window manually, we can get ovals, and shapes based on them. For the arc, the number of segments, corresponds to the number of lines that approximate the circular portion.