1

In Blender 3.2.1, I need a unit mesh circle at origin and path on the x-axis with a length of $2\pi$. Object constraint on circle to follow path. Keyframe on unit circle at 0 & 250 with $360^{\circ}$ z-rotation. How do I get a single vertex on the unit circle to trace the sine or cosine wave?

Harry McKenzie
  • 10,995
  • 8
  • 23
  • 51
  • could you pls tell us what your end goal is? – Chris Aug 01 '22 at 11:15
  • i want to trace the sine/cosine wave from the rotating unit circle. i just dont know how to get the vertex to trace the path. it is a step in a larger gear driven idea. – axiomatibus Aug 01 '22 at 11:19
  • i still don't get it. you only get a sin or cos wave, if you would move the circle while following path. If the circle is fixed, you only get a right left or up down movement. So what do you want? – Chris Aug 01 '22 at 11:23
  • do you want that? [1]: https://i.stack.imgur.com/o8cI9.gif – Chris Aug 01 '22 at 11:25
  • https://blender.stackexchange.com/questions/48866/draw-line-from-armature-animation/ https://blender.stackexchange.com/questions/104732/is-it-possible-to-achieve-a-spirograph-efect https://blender.stackexchange.com/questions/261399/how-can-i-trace-an-object-that-move-along-equation – Duarte Farrajota Ramos Aug 01 '22 at 11:35
  • If the circle is moving along the line while rotating, the path scribed by a point on its circumference is a cycloid, not a sine wave ? – Robin Betts Aug 01 '22 at 15:57
  • yes, the way i was describing it wouldn't give a sine wave. – axiomatibus Aug 02 '22 at 01:45

1 Answers1

2

Just copy the script and execute then press spacebar in the Timeline to play the animation or you can scrub through the timeline from frame 0 to 250.

enter image description here

import bpy
import math

REVOLUTION = 360 TOTAL_FRAMES = 250 SINEWAVE_RESOLUTION = 64 RADIUS = 1

bpy.context.scene.frame_start = 1 bpy.context.scene.frame_end = TOTAL_FRAMES bpy.context.scene.frame_current = 1

def get_object(name): objects = bpy.context.scene.objects if name in objects: return objects[name] m = bpy.data.meshes.new(name + "-mesh") o = bpy.data.objects.new(name, m) #o.modifiers.new(name, 'SKIN') bpy.context.collection.objects.link(o) return o

def get_empty(name): objects = bpy.context.scene.objects if name in objects: return objects[name] bpy.ops.object.empty_add(type='SPHERE', align='WORLD', location=(0, 0, 0)) empty = bpy.context.object empty.name = name empty.scale = 0.1, 0.1, 0.1 return empty

==================================================================================================

Descritpion: plot the sinwave with some points

==================================================================================================

def get_range(start, end, step = 2): return [x * 0.1 for x in range(start * 10, end * 10, step)]

def get_sinewave_x(angle): return RADIUS * math.cos(REVOLUTION - math.radians(angle))

def get_sinewave_y(angle): return RADIUS * math.sin(math.radians(angle))

def get_sinewave_length(): return RADIUS * 4

def draw_sinwave(angle, id): verts = [] xunits = get_sinewave_length() for u in range(0, SINEWAVE_RESOLUTION + 1): a = u / SINEWAVE_RESOLUTION * REVOLUTION px = xunits / SINEWAVE_RESOLUTION * u py = get_sinewave_y(a) if (a <= angle): verts.append([px, py, 0.0])

#verts.append([xunits, 0, 0.0])
edges = []
for i in range(len(verts)-1):
    edges.append((i, i+1))

o = get_object(&quot;sinewave-&quot; + id)
m = o.data
m.clear_geometry()
m.from_pydata(verts, edges, ())

==================================================================================================

Create Circle

==================================================================================================

def create_circle(n): o = get_object("circle") exists = len(o.data.vertices) > 0 if exists: return o

verts = []
for i in range(n):
    verts.append((0.0, 0.0, 0.0))
edges = []
for i in range(len(verts)-1):
    edges.append((i, i+1))
edges.append((i+1, 0))

m = o.data
m.clear_geometry()
m.from_pydata(verts, edges, ())
return o

def draw_circle(r, segments = 32): o = create_circle(segments) o.location = 0.0, 0.0, 0.0

for i in range(segments):
    a = 2 * math.pi / segments * i
    o.data.vertices[i].co = math.cos(a) * r, math.sin(a) * r, 0.0

==================================================================================================

draw lines connecting circle and x-axis

==================================================================================================

def draw_line(x, y, px, py, id): o = get_object("line-" + id) m = o.data verts = m.vertices exists = len(verts) > 0

if exists:
    verts[0].co = x, y, 0.0
    verts[1].co = px, py, 0.0
    return

verts = []
verts.append((x, y, 0.0))
verts.append((px, py, 0.0))

m.clear_geometry()
m.from_pydata(verts, [(0,1)], ())

==================================================================================================

draw geometry

==================================================================================================

def draw_empties(x, y, px, py): get_empty("empty-1").location = x, y, 0.0 get_empty("empty-2").location = px, py, 0.0

def draw_circle_angle(angle): rad = math.radians(angle) draw_circle(RADIUS) l1x = RADIUS * math.cos(math.pi * 2 - rad) l1y = RADIUS * math.sin(rad) l2x = angle / REVOLUTION * get_sinewave_length() l2y = get_sinewave_y(angle) draw_line(0, 0, l1x, l1y, "1") draw_line(l2x, 0, l2x, l2y, "2") draw_empties(l2x, l2y, l1x, l1y)

==================================================================================================

animation functions

==================================================================================================

def animate(): f = bpy.context.scene.frame_current angle = REVOLUTION / TOTAL_FRAMES * f draw_sinwave(angle, '1') draw_circle_angle(angle)

==================================================================================================

execute code

==================================================================================================

def on_enter_frame(a,b): animate()

bpy.app.handlers.frame_change_post.clear() bpy.app.handlers.frame_change_post.append(on_enter_frame)

draw_sinwave(REVOLUTION, '2') on_enter_frame(None, None)

for o in bpy.context.scene.objects: o.select_set(True) bpy.context.view_layer.objects.active = get_object("sinewave-1")

bpy.context.scene.objects['sinewave-2'].select_set(False)

Harry McKenzie
  • 10,995
  • 8
  • 23
  • 51