'Vector3d' object has no attribute '__float__'

Hello everyone!

I’m trying to simulate a script from the RhinoPythonPrimer101.pdf that can be found here. On page 43 there is an example to iteratively shorten a curve, under the heading Nested Lists.

Here is my code and I’m getting this error:

Message: ‘Vector3d’ object has no attribute ‘float

(Before that I was getting a “Expected float, got point3D” message, so I tried to change vm to float(vm) on line 15…)

What do you think is wrong?

''' python
import rhinoscriptsyntax as rs

def smoothingvector(point, prev_point, next_point, s):
    pm = (prev_point+next_point)/2 #middle point between the previous and next point
    va = rs.VectorCreate(pm, point)
    vm = rs.VectorScale(va, s)
    return vm

def smoothcurve(curve_id, s):
    curve_points = rs.CurvePoints(curve_id, s)
    new_curve_points.append(rs.AddPoint(curve_points[i], float(vm)))
    
    for i in range(1, len(curve_points)-1):
        vm = smoothingvector(curve_points[i], curve_points[i-1], curve_points[i+1], s)
        new_curve_points.append(rs.AddPoint(curve_points[i], float(vm)))
    
    knots = rs.CurveKnots(curve_id)
    degree = rs.CurveDegree(curve_id)
    weights = rs.CurveWeights(curve_id,0)
    newcurve_id = rs.AddNurbsCurve(new_curve_points, knots, degree, weights)
    if newcurve_id: rs.DeleteObject(curve_id)
    return newcurve_id

def iterativeshortencurve():
    curve_id = rs.GetObject("Open curve to smooth", 4, True)
    if curve_id is None or rs.IsCurveClosed(curve_id): return
    
    min = rs.Distance(rs.CurveStartPoint(curve_id), rs.CurveEndPoint(curve_id))
    max = rs.CurveLength(curve_id)
    goal = rs.GetReal("Goal length", 0.5*(min+max), min, max)
    if goal is None: return
    
    while rs.CurveLength(curve_id)>goal:
        rs.EnableRedraw(False)
        curve_id = smoothcurve(curve_id, 0.1)
        rs.EnableRedraw(True)
        if curve_id is None: break

if( __name__ == "__main__" ):
    iterativeshortencurve()
'''

Hi,

what python is trying to tell you is that it is expecting a float as an argument to the function, and that the vector 3d object can’t be cast to a float.

Addpoint takes either a point 3d object, or a list of coordinates like so: rs.AddPoint( (1,2,3) ). You’re passing 2 points, which doesn’t work. Just split it up in two calls, add one point after the other, while appending their guids to your list.

edit:

the docs are always useful in these cases, when you’re unsure of how a function works…

https://developer.rhino3d.com/api/RhinoScriptSyntax/#collapse-AddPoint

1 Like

Hi Lukas,

While reading your comment, I had the opportunity to check my code and I realized that I put rs.AddPoint instead of rs.PointAdd. So correcting it solved the issue. Thank you.

I’m thinking the possibility that this code in this document and the current version of Python in Rhino 6 maybe is not compatible. I realized this when I tried to manually insert curve start and end points into the new_curve_points list (I did this because the knots option produced an error saying that there is less points than the number of knots stored from the original curve). The code on the PDF reads:

“list.insert(i,x) Inserts item i at location x.”

So, when I tried this it produced a type mismatch, it was looking for an integer but found tuple. So I looked it up as the way Lukas said and saw that when we do “list.insert(i,x)” it actually places item “x” in location “i”. So the first one is the location and the second one is the item itself.

I rearranged the code. Now it works just as intended. Here it is if anyone needs it…

import rhinoscriptsyntax as rs

def iterativeshortencurve():
    curve_id = rs.GetObject("Open curve to smooth", 4, True)
    if curve_id is None or rs.IsCurveClosed(curve_id): return
    
    min = rs.Distance(rs.CurveStartPoint(curve_id), rs.CurveEndPoint(curve_id))
    max = rs.CurveLength(curve_id)
    goal = rs.GetReal("Goal length", 0.5*(min+max), min, max)
    if goal is None: return
    
    while rs.CurveLength(curve_id)>goal:
        rs.EnableRedraw(False)
        curve_id = smoothcurve(curve_id, 0.1)
        rs.EnableRedraw(True)
        if curve_id is None: break

def smoothingvector(point, prev_point, next_point, s):
    pm = (prev_point+next_point)/2 #middle point between the previous and next point
    va = rs.VectorCreate(pm, point)
    vm = rs.VectorScale(va, s)
    return vm

def smoothcurve(curve_id, s):
    curve_points = rs.CurvePoints(curve_id, s)
    new_curve_points = []
    
    for i in range(1, len(curve_points)-1):
        vm = smoothingvector(curve_points[i], curve_points[i-1], curve_points[i+1], s)
        new_curve_points.append(rs.PointAdd(curve_points[i], vm))
    
    crv_start = rs.CurveStartPoint(curve_id)
    crv_end = rs.CurveEndPoint(curve_id)
    new_curve_points.insert(0, crv_start)
    new_curve_points.insert(-1,crv_end)
    print(new_curve_points)
    knots = rs.CurveKnots(curve_id)
    degree = rs.CurveDegree(curve_id)
    weights = rs.CurveWeights(curve_id,0)
    newcurve_id = rs.AddNurbsCurve(new_curve_points, knots, degree, weights)
    if newcurve_id: rs.DeleteObject(curve_id)
    return newcurve_id

if( __name__ == "__main__" ):
    iterativeshortencurve()
1 Like

Hello Erdem

You can move the rs.EnableRedraw(False) Before the loop if you want to hide the script calculating.
I hope it help.

Sylvain

import rhinoscriptsyntax as rs

def iterativeshortencurve():
curve_id = rs.GetObject(“Open curve to smooth”, 4, True)
if curve_id is None or rs.IsCurveClosed(curve_id): return

min = rs.Distance(rs.CurveStartPoint(curve_id), rs.CurveEndPoint(curve_id))
max = rs.CurveLength(curve_id)
goal = rs.GetReal("Goal length", 0.5*(min+max), min, max)
if goal is None: return
rs.EnableRedraw(False)
while rs.CurveLength(curve_id)>goal:
    #rs.EnableRedraw(False)
    curve_id = smoothcurve(curve_id, 0.1)
    #rs.EnableRedraw(True)
    if curve_id is None: 
        rs.EnableRedraw(True)
        break

def smoothingvector(point, prev_point, next_point, s):
pm = (prev_point+next_point)/2 #middle point between the previous and next point
va = rs.VectorCreate(pm, point)
vm = rs.VectorScale(va, s)
return vm

def smoothcurve(curve_id, s):
curve_points = rs.CurvePoints(curve_id, s)
new_curve_points =

for i in range(1, len(curve_points)-1):
    vm = smoothingvector(curve_points[i], curve_points[i-1], curve_points[i+1], s)
    new_curve_points.append(rs.PointAdd(curve_points[i], vm))

crv_start = rs.CurveStartPoint(curve_id)
crv_end = rs.CurveEndPoint(curve_id)
new_curve_points.insert(0, crv_start)
new_curve_points.insert(-1,crv_end)

knots = rs.CurveKnots(curve_id)
degree = rs.CurveDegree(curve_id)
weights = rs.CurveWeights(curve_id,0)
newcurve_id = rs.AddNurbsCurve(new_curve_points, knots, degree, weights)
if newcurve_id: rs.DeleteObject(curve_id)
return newcurve_id

if( name == “main” ):
iterativeshortencurve()

And the rs.EnableRedraw(True) after (outside) the while loop

1 Like

Thank you both for the tip. Good idea!! :slight_smile: