Def using "While"

As usuall it seams to be the simplest ones that are the hardest.

End End Goal is to have more use of loop / while functions to allow itterating through list of items.

End Goal today is simply to creat a def where once can take a close poly curve, and nest a copy of itself with in it rotated by a an amount.

In a one time process this works fine. - code block text below.

PC_1 = PolyCurve.Curves(results);
pts1 = Curve.PointAtParameter(PC_1,0.2);
pts2 =List.ShiftIndices(pts1,1);
ln = Line.ByStartPointEndPoint(pts2,pts1);
PC = PolyCurve.ByJoinedCurves(ln);

and i can string these together in series to nest ever smaller shapes and given amount.

image

this seams like a waste of steps. So I attempted a simple def when I could loop the process to a given amount of itterations.

I receive no errors, and it appears to finish (dynamo doesnt go into a endless loop) but after much editiing and trial all that appears to return is “null”

I have completed an approximation of this same defintion swaping all geometry oppertations for math and it will work. Is there a limitation to looping geomotric functions, or am i missing something else.

def test(Geom,Itt)
{
return = [Imperative]
{
//
sequence = {Geom};
i = List.Count(sequence);
while (i != Itt)
{
results = sequence[0];
PC_1 = PolyCurve.Curves(results);
pts1 = Curve.PointAtParameter(PC_1,0.2);
pts2 =List.ShiftIndices(pts1,1);
ln = Line.ByStartPointEndPoint(pts2,pts1);
PC = PolyCurve.ByJoinedCurves(ln);
sequence = List.AddItemToEnd(PC,sequence);
i=i+1;
}
return = {i,results};
}
};

What version of Dynamo is this?

Dynamo Studio 1.3
Dynamo Core 1.3.1
Attempted in both studio and sandbox

You have to remember that you can’t use associative calls such as “Curve.PointAtParameter” on a list of objects in imperative blocks. Try the below version instead:

def recursive(Geom, Itt){
return = [Imperative]{
sequence = {Geom};
i = 0;
while (i < Itt)
{
	curves = Geom.Curves();
	pts1 = {};
	for (j in GetKeys(curves) )
	{
		pts1[j] = curves[j].PointAtParameter(0.2);
	}
	Geom = PolyCurve.ByPoints(pts1, 1);
	sequence = List.AddItemToEnd(Geom, sequence);
	i = i + 1;
}
return = sequence;
}};

Imperative DS functions are more trouble than they’re worth, now more than ever. If anybody is considering using them, arm yourself with a ton of patience. These few lines of code took 5+ attempts. You’ve never gotten any feedback and debugging information but now it’s worse than ever…

  • Using class methods (like PolyCurve.Curves(x) ) failed silently
  • If you have any ZT packages that use the same names as the core namespaces and classes (List, Solid, Point, Vector), they become unusable in in DS
  • I had to copy/paste the function multiple times because it didn’t properly detect code changes
  • For some weird reason, all of a sudden the interpreter assumed that the function doesn’t work with “Rectangle” types any more and I got an error even tho I’ve never defined the argument type. I had to copy/paste the function into a new CBN yet again.
  • You have to be careful with the definition of your variables. They now have a scope and if you don’t define a variable at the right place, it may be inaccessible in a different part of the code.
    - The performance of DS function calls has tanked compared to previous versions.

It feels to me like this functionality has really deteriorated over time.

4 Likes

@Dimitar_Venkov thanks for finding the issue here with anticipating replication.

we should follow up to figure out how to improve the experience of using imperative blocks - are you finding performance decreases in 2.0 vs 1.3 in imperative blocks?

@Aparajit_Pratap @Zach_Kron FYI.

1 Like

@Michael_Kirschner2

I take that part back - I ran this by the numbers and the performance of calling custom DS functions in 1.32 and 2.0 has actually increased relative to older versions.

I imagine it has more to do with the fact that all the added tiny issues popping up over time have impacted my overall perceived experience with DS functions negatively - it definitely feels like it takes longer to get them running properly but the actual performance is indeed faster.

This goes to show that you should always measure things first, or else you’ll end up eating your words :slight_smile:

Multiple function calls are still expensive tho and you should avoid them if possible:
image

DS_Func_Perf_1.3.dyn (14.2 KB)

Thank you all, information is invaluable.

“arm yourself with a ton of patience.” - this is absolutely true.

Any thoughts on doing this in Python vs Codeblock?

1 Like

This discussion could help:

@Mike_Engel1 @Dimitar_Venkov thanks for your findings. We are making changes/improvements to imperative blocks in 2.0 where we are addressing some of these issues. You can find a brief description on language changes here: http://dynamobim.org/resuming-pre-release-builds/. Regarding specific imperative language changes, there are new scoping rules, such that variables defined in an outer scope are readonly within an imperative scope and if modified within the imperative scope, will not affect values in the parent associative scope. Secondly statements like “PolyCurve.Curves(pc);” and “Curve.PointAtParameter(list_of_curves, 0.2);” will also work but not “list_of_curves.PointAtParameter(0.2);” as @Dimitar_Venkov rightly pointed out. The latter will only work within an “Associative” scope since it involves replication.

2 Likes

Wonderful - my next thought was to test on 2.0 builds, but looks like you covered it.

1 Like

Here is a Python version of “recursive”, for anyone interested in a quick comparison with DesignScript :slight_smile: :

import clr

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

Geom = IN[0]
itt = IN[1]
sequence = [Geom]
curvs = []
i = 0

while i < itt:
	curvs = Geom.Curves()
	pts = []
	for crv in curvs:
		pts.append(Curve.PointAtParameter(crv, 0.2))
	Geom = PolyCurve.ByPoints(pts, 1)
	sequence.append(Geom)
	i = i + 1

OUT = (pts, sequence)

2 Likes