0
\$\begingroup\$

Is there a function or some easier way to draw this, each of this little circles should have 8 other smaller circles around them like the big circle... So far i made big circle in center with 8 smaller circles using canvas

from Tkinter import *

canvas = Canvas(width=700, height=700, bg='black')  
canvas.pack(expand=YES, fill=BOTH)                

canvas.create_oval(240, 240, 410, 410, width=2, fill='yellow') #big circle
canvas.create_oval(140, 140, 210, 210, width=2, fill='yellow') #10h
canvas.create_oval(440, 440, 510, 510, width=2, fill='yellow') #16h
canvas.create_oval(285, 100, 355, 170, width=2, fill='yellow') #12h
canvas.create_oval(285, 480, 355, 550, width=2, fill='yellow') #18h
canvas.create_oval(440, 140, 510, 210, width=2, fill='yellow') #13h
canvas.create_oval(140, 440, 210, 510, width=2, fill='yellow') #19h
canvas.create_oval(100, 285, 170, 355, width=2, fill='yellow') #21h
canvas.create_oval(480, 285, 550, 355, width=2, fill='yellow') #15h

#lines

#1
canvas.create_line(320, 170, 320, 250, fill="yellow")
canvas.create_line(320, 400, 320, 480, fill="yellow")

#2
canvas.create_line(170, 320, 250, 320, fill="yellow")
canvas.create_line(400, 320, 480, 320, fill="yellow")

#3
canvas.create_line(200, 200, 275, 275, fill="yellow")
canvas.create_line(450, 200, 375, 275, fill="yellow")

#4
canvas.create_line(185, 465, 270, 380, fill="yellow")
canvas.create_line(480, 480, 380, 380, fill="yellow")

mainloop()
\$\endgroup\$
4
  • \$\begingroup\$ Well you have a lot of duplication you could easily factor out! \$\endgroup\$
    – jonrsharpe
    Commented May 13, 2015 at 14:07
  • \$\begingroup\$ And how do I do that? Sorry I'm new at this \$\endgroup\$ Commented May 13, 2015 at 14:25
  • \$\begingroup\$ Look at the code - every time you see two (or nine!) lines with mostly the same structure and some different values, pull out all the bits that are the same into a function and make the differences parameters of that function. See e.g. docs.python.org/2/tutorial/controlflow.html#defining-functions \$\endgroup\$
    – jonrsharpe
    Commented May 13, 2015 at 14:27
  • \$\begingroup\$ Can you write an example? \$\endgroup\$ Commented May 13, 2015 at 14:30

1 Answer 1

4
\$\begingroup\$

Here's one approach (some additional explanation after code):

from Tkinter import *
import numpy as np


def circle_burst(center_x, center_y, radius, ncircles, depth):
    """Make a circle burst pattern.

       ncircles gives the number of circles surrounding the center
       depth gives the number of levels of burst"""

    # center circle
    canvas.create_oval(center_x-radius, center_y-radius,
                   center_x+radius, center_y+radius,
                   width=2, fill='yellow')

    # values for the smaller circles
    small_radius = radius/3.0
    circle_spread = 2*radius

    # loop to make the smaller circles
    for i in xrange(ncircles):
        angle = i*2*np.pi/ncircles
        epicenter_x = center_x + circle_spread*np.sin(angle)
        epicenter_y = center_y + circle_spread*np.cos(angle)
        if depth > 1:
            circle_burst(epicenter_x, epicenter_y, small_radius, ncircles,
                         depth-1)
            canvas.create_line(center_x, center_y, epicenter_x, epicenter_y,
                               fill='yellow')
        else:
            canvas.create_oval(epicenter_x-small_radius,
                               epicenter_y-small_radius,
                               epicenter_x+small_radius,
                               epicenter_y+small_radius,
                               width=2, fill='yellow')
            canvas.create_line(center_x, center_y, epicenter_x, epicenter_y,
                               fill='yellow')


# make the canvas
width = 700
height = 700
canvas = Canvas(width=width, height=height, bg='black')  
canvas.pack(expand=YES, fill=BOTH)                

center_x = width/2
center_y = height/2
big_radius = width/8

# generate the pattern
circle_burst(center_x, center_y, big_radius, 8, 2)


mainloop()

Notes:

  1. Parameterize everything you can/avoid magic numbers. Since you want your circles to have the same radius and the same offset from the center, it makes sense to calculate the x, y values that go into the create_oval calls from radius and offset rather than hardcode them in as numbers. This is true of the canvas size and center of the canvas, as well.

  2. You're essentially describing a recursive procedure, so it makes sense to use recursion to tackle it (each circle is surrounded by a collection of smaller circles). The depth parameter indicates how many levels of recursion to use.

  3. Math is your friend! Equally spacing objects in a circular pattern is pretty easy when you use a little trig.

  4. You could easily have the scalings for small_radius and circle_spread be parameters rather than hardcoded; I chose some values that looked decent to me for a ncircles=8 and depth=2.

\$\endgroup\$
4
  • \$\begingroup\$ thanks for help but i was hoping i could do that without numpy because we didn't work that yet. Is there any other way? \$\endgroup\$ Commented May 13, 2015 at 15:06
  • \$\begingroup\$ I run your code at depth 5: it is fractal! So nice \$\endgroup\$
    – Caridorc
    Commented May 13, 2015 at 15:23
  • \$\begingroup\$ Regarding the use of numpy: sin, cos, and pi are also in the math module. I use numpy a lot, so it's sort of reflexive for me to use it, but you could just use the math module instead. \$\endgroup\$
    – tachycline
    Commented May 13, 2015 at 15:28
  • \$\begingroup\$ Oh thanks a lot! Just one more little thing. What do I add to that code to make even smaller circler around small circles but without that line or shorter line? \$\endgroup\$ Commented May 13, 2015 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.