Quest For A Python Circle

Ok,
This thread is dedicated to creating a python script that will make a valid circle in Blender.
You should be able for pass it a radius and it will generate a bezier curve circle.
That said, here is what I know about point on a circle code: (I am learning python and don’t have the syntax, so I am posting VB for now.)


radius = 10
for n = 0 to 360
x = cos(n) * radius
y = sin (n) * radius
next

Ok, yeah, we have point on a circle. let’s turn it into a function.


function (passedRadius, passedPointCount) as array
for n = 0 to 360 step (360/passedPointCount)
x = cos(n) * passedRadius
y = sin(n) * passed Radius
tempArray (n) = trim$(x) & "," & trim$(y)
next
return tempArray

Ok, I know that is a hack, but the intention is to have a funtion that will return an array of points when you give it a radius and point count.
So now we have an array of x,y coordinates that are points on a circle at a given radius.
Time for python now…

Here is code directly from the Blender API site.


from Blender import Curve, Object, Scene
c = Curve.New() # create new curve data
cur = Scene.getCurrent() # get current scene
ob = Object.New('Curve') # make curve object
ob.link(c) # link curve data with this object
cur.link(ob) # link object into scene

This code, of course, does not work and crashes on line 1.
But the basic premise is here.

The question is, how do I link my array of coordinates into these objects?

A bezier circle can be defined by four points (knots) equally spaced around the circle. Actually you could probably do it with any number >= 2 if you were tricky. With four though you only need to create auto handles and the circle shall appear…

There is unfortunatly a bug in Blender 2.42a that prevents curve handles from being recalculated when they are made by a script. I think it is fixed in cvs though. If you want I could post some code to draw a bezier circle.

Drawing a circle with a mesh on the other hand is a much more difficult problem. With curves you should define as few control points as possible because the curve will interpolate between points - that is the point of using curves! On a mesh though you can only make straight segments, so you have to decide how many verts to put around a circle, and of course bigger circles will need more verts to stay smooth…

Yes,
I would love to see code posted, could you?

Gimme a little bit, the code I have is part of a larger script…

Okay, that was easy:

import Blender

from Blender import BezTriple, Curve, Mathutils, Object, Scene
c = Curve.New()             # create new  curve data
cur = Scene.getCurrent()    # get current scene
ob = Object.New('Curve')    # make curve object
ob.link(c)                  # link curve data with this object
cur.link(ob)                # link object into scene

center = (5,5,0)
radius = 5

AUTO = BezTriple.HandleTypes.AUTO
# Build four points at radius distance in the four cardnal directions
p1 = (0, -radius, 0)
p2 = (radius, 0, 0)
p3 = (0, radius, 0)
p4 = (-radius, 0, 0)

p1 = BezTriple.New(p1)
p2 = BezTriple.New(p2)
p3 = BezTriple.New(p3)
p4 = BezTriple.New(p4)

# Can't have a curve without points...
curve = c.appendNurb(p1)
curve.append(p2)
curve.append(p3)
curve.append(p4)

# Set both handles to auto for each point
for point in curve:
    point.handleTypes = [AUTO, AUTO]
curve.flagU = 1 # Set curve cyclic
c.update()
ob.loc = center # Put it where it goes
Blender.Redraw()

This is actually the test code I wrote while trying to figure out how to do this myself. I think I have a nice version wrapped in a function in the code I mentioned above, but I found this first :wink:
I tested it and it works under the current cvs! On 2.42a it draws a square instead of a circle though :rolleyes:

Thanks for the post,
Here is what I came up with…


#Create a circular path for Blender 2.42a
import Blender
from Blender import *
import math
from math import *
   
def makeCircle(passedNumberOfPoints, passedRadius):
  c = Curve.New()
 c.setPathLen(300)
 c.setFlag(8)
 
 z = 0         # 2D Drawing for now.
 w = 1         #Weight is 1.
 final_x = 0
 final_y = 0
 angleStep = 360/ passedNumberOfPoints
 for ang in range(0, 359,angleStep):
  x = passedRadius * math.cos(math.radians(ang))
  y = passedRadius * math.sin(math.radians(ang))
  if (ang ==0):
   final_x = x
   final_y = y
   c.appendNurb([x,y,z,w])
   c[0].type = 0      # Poly line
  else:
   c.appendPoint(0,[x,y,z,w,0])  # Can add tilt here with w.
 c.appendPoint(0,[final_x,final_y,z,w,0]) # Can add tilt here.
 c.update()
 scn = Scene.GetCurrent()     # New Curve and add to Scene.
 ob = Object.New('Curve')
 ob.setName ("PolyBezier")
 ob.link(c)
 scn.link(ob)
 ob.sel = 1         # Make active and selected
makeCircle(16,5)

I’m going to try your code out.