4
$\begingroup$

I want to draw script-calculated curves with the grease pencil. Using this line of python I'm able to redefine the points of an existing stroke, shown below.

So far I can't add a point like this:

newpt = points[200].copy()  # error
points.append(newpt)        # error

or this:

points.items().append('put various things here')   # NO error, but no new points either

where:

points = bpy.data.grease_pencil[0].layers[0].active_frame.strokes[0].points

So instead, I draw a big scribble, find out the length using the interactive python window (in this case it's 427) and then make a new set of coordinates of the same length.

How can I create or at least increase the number of points of a grease pencil stroke? I'm looking for something similar to the way I can make new mesh objects:

# example: make a new mesh object - I wish I could make grease pencil objects like this!!!
newmesh = bpy.data.meshes.new('Newmesh')
newobj  = bpy.data.objects.new('Newobj', newmesh)

bpy.context.scene.objects.link(newmesh)
newmesh.from_pydata(verts, [], faces)

krazy koil

import numpy as np
import bpy

pi, twopi = np.pi, 2*np.pi

theta = np.linspace(0, 20*twopi, 427)
theta -= theta.mean()

r = 4 - 2*np.cos(0.1*theta)

y = theta / twopi
x = r*np.cos(theta)
z = r*np.sin(theta)

krazy_koil_points = np.vstack((x, y, z)).T

points = bpy.data.grease_pencil[0].layers[0].active_frame.strokes[0].points
for i, point in enumerate(points):
    point.co = krazy_koil_points[i]

Same thing, but without numpy:

import bpy, math

pi, twopi = math.pi, 2*math.pi

theta = [20*twopi * i / 427. for i in range(427)]

mean  = sum(theta)/float(len(theta))

theta = [th - mean for th in theta]

r = [4 - 2*math.cos(0.1*th) for th in theta]

y = [th/twopi for th in theta]
x = [a*math.cos(b) for a, b in zip(r, theta)]
z = [a*math.sin(b) for a, b in zip(r, theta)]

krazy_koil_points = list(zip(x, y, z))

points = bpy.data.grease_pencil[0].layers[0].active_frame.strokes[0].points
for i, point in enumerate(points):
    point.co = krazy_koil_points[i]
$\endgroup$
7
$\begingroup$

What you're looking for is the add method within the points collection.

EDITED: Fixed script to work with fresh clean files that have no grease pencil data.

enter image description here

import bpy, math

S  = bpy.context.scene

# Create grease pencil data if none exists
if not S.grease_pencil:
    a = [ a for a in bpy.context.screen.areas if a.type == 'VIEW_3D' ][0]
    override = {
        'scene'         : S,
        'screen'        : bpy.context.screen,
        'object'        : bpy.context.object,
        'area'          : a,
        'region'        : a.regions[0],
        'window'        : bpy.context.window,
        'active_object' : bpy.context.object
    }

    bpy.ops.gpencil.data_add( override )

gp = S.grease_pencil

# Reference grease pencil layer or create one of none exists
if gp.layers:
    gpl = gp.layers[0]
else:
    gpl = gp.layers.new('gpl', set_active = True )

# Reference active GP frame or create one of none exists    
if gpl.frames:
    fr = gpl.active_frame
else:
    fr = gpl.frames.new(1) 

# Create a new stroke
str = fr.strokes.new()
str.draw_mode = '3DSPACE'

# Number of stroke points
strokeLength = 500 

# Add points
str.points.add(count = strokeLength )

pi, twopi = math.pi, 2*math.pi

theta = [20 * twopi * i / strokeLength for i in range(strokeLength)]

mean  = sum(theta)/float(len(theta))

theta = [th - mean for th in theta]

r = [4 - 2*math.cos(0.1*th) for th in theta]

y = [th/twopi for th in theta]
x = [a*math.cos(b) for a, b in zip(r, theta)]
z = [a*math.sin(b) for a, b in zip(r, theta)]

krazy_koil_points = list(zip(x, y, z))

points = str.points
for i, point in enumerate(points):
    points[i].co = krazy_koil_points[i]
$\endgroup$
  • $\begingroup$ Thanks :) Weird though, I use 2.74 here as well and it did work. Curious to see the errors you ran into. $\endgroup$ – TLousky Mar 17 '16 at 15:00
  • $\begingroup$ Found the issue, fixing the script in a min (no grease pencil data exists, you can fix it manually by creating adding a grease pencil layer, but I'll check for it in the script and add it there too). $\endgroup$ – TLousky Mar 17 '16 at 15:03
  • $\begingroup$ @uhoh, fixed it, please have another go. $\endgroup$ – TLousky Mar 17 '16 at 15:13
  • 1
    $\begingroup$ Hey super! This is exactly what I need! I like your answers - they are always concise and yet complete with running script. Thanks for your time and persistence :) $\endgroup$ – uhoh Mar 17 '16 at 15:36
  • 1
    $\begingroup$ oh, I was so happy to see this work that I forgot to accept the answer @@ thanks! $\endgroup$ – uhoh Mar 17 '16 at 16:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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