1

How can I use Python to select one (spline control) point of a NURBS curve? I want to select and then move each point to a desired location. If this is not possible, I am happy to start with the locations and create a NURBS curve that ‘joins the dots’.

2 Answers2

2
import bpy

for p in bpy.context.object.data.splines.active.points:
    p.co.z = p.co.z + 1
bpy.ops.object.mode_set(mode='EDIT')

This works.

UPDATE: (only change selected points)

bpy.ops.object.mode_set(mode='OBJECT')

counter = 0 for p in bpy.context.object.data.splines.active.points: print("counter = ",counter) if p.select == True: p.co.z = p.co.z - 1 print("selected") counter = counter + 1 bpy.ops.object.mode_set(mode='EDIT')

Chris
  • 59,454
  • 6
  • 30
  • 84
  • Thanks! I must be doing something wrong.

    I assume I start in Object Mode, with the curve selected. I am then trying your code by pasting into Python Console.

    From: the_curve_data = bpy.context.scene.objects.active.data

    I get: AttributeError: 'bpy_prop_collection' object has no attribute 'active'

    – Paul St George May 01 '21 at 08:20
  • i am sorry - my mistake. i update the answer. this time i tested it ;) – Chris May 01 '21 at 09:03
  • Almost there. I think. I have tried your code with the last line indented (is that right?). No errors, but it does not select just one point. The curve is selected, not just a point. What do I add to say which point should be selected? – Paul St George May 01 '21 at 10:08
  • Yes, it moves all points, but hopefully you can add an if Statement in the for loop yourself. Can you? – Chris May 01 '21 at 10:34
  • I can't! Could you please show the point selection and the translation?? – Paul St George May 01 '21 at 10:47
  • i updated my answer - now it only changes selected points – Chris May 01 '21 at 11:13
  • Genius! Do I add bpy.ops.transform.translate(value=(2,0,0)) # insert after print("selected") and cycle through selecting and moving the points like that? – Paul St George May 01 '21 at 13:11
  • You don‘t need the translate. Just add/change x/y/z values directly like I did. – Chris May 01 '21 at 13:19
2

IMO would join the dots.

I want to select and then move each point to a desired location.

If the idea is to take a set of points and "join the dots" it is quite possibly a lot simpler to to create the spline.

Here is an example using NURBS answser from Create curve from Numpy Array using Python

enter image description here Result displayed in EDIT mode, after running script in OBJECT mode

Set the coordinates as desired, run the script in object mode, creates a curve object with control points at the input coordinates. Removes need to select points, mode toggle, and use operators.

Using numpy and in particular foreach_get(set) is going to be way quicker for a lot of points.

In this example have given each 4D NURB coordinate a weight w of 1.

import bpy
import numpy as np

def flatten(*args): c = np.empty(sum(arg.size for arg in args)) l = len(args) for i, arg in enumerate(args): c[i::l] = arg return c

context = bpy.context

x, y, z = np.array( ( (0, 0, 0), (1, 1, 1), (0, 1, 1), (0, 0, 1), ) ).T

w = np.ones(len(x)) cu = bpy.data.curves.new(name="poly", type='CURVE') cu.dimensions = '3D'

spline = cu.splines.new('NURBS') # poly type

spline is created with one point add more to match data

spline.points.add(x.size - 1) spline.points.foreach_set("co", flatten(x, y, z, w))

spline.use_endpoint_v = True spline.use_endpoint_u = True ob = bpy.data.objects.new("NURBS", cu)
context.collection.objects.link(ob) context.view_layer.objects.active = ob ob.select_set(True)

And for example sake,

enter image description here

running a loop and changing the weight assigned to the 4th coordinate

for j in range(1, 100, 10):
    w = np.ones(len(x))
    w[3] = j

Note.

If the desired result is to have the curve pass through the control points, it may be an idea to choose a curve type other than NURBS.

batFINGER
  • 84,216
  • 10
  • 108
  • 233
  • I agree. Joining the dots is much more sensible.I asked the wrong question (cf The XY Problem). I came up with something that has a similar structure as your code but is far less sophisticated. I used from mathutils import Vector. I would share it but don't seem to be able to use the mini-Markdown formatting in a comment. – Paul St George May 01 '21 at 17:56