Yna_Db
October 24, 2017, 2:41pm
1
I noticed it might be useful to gather some Python related posts in one thread to make it easy to get started with some basic understanding (and also for a consultation ease purpose). This is still a work in progress and there might be some slight inconsistencies. Feel free to add your own links or Python related comments, or to PM me on anything that should be revised. This first post relates naturally to tips for LEARNING PYTHON :
http://dynamoprimer.com/en/09_Custom-Nodes/9-4_Python.html
http://dynamoprimer.com/en/09_Custom-Nodes/9-5_Python-Revit.html
http://dynamoprimer.com/en/12_Best-Practice/12-1_Scripting-Strategies.html
http://dynamoprimer.com/en/12_Best-Practice/12-3_Scripting-Reference.html
http://dynamoprimer.com/en/Appendix/A-1_resources.html
I wrote a 30 page handout for my AU class on Python for Dynamo, thought I would leave this here
This site, that popped up recently, has a lot of thoroughly explained dynamo/python examples:
Preetesh-
I was in your situation a few months ago (February) , so I know how you feel right now. All I can do is tell you how I went about learning.
Get a good book on Python basics or go to http://learnpythonthehardway.org/
Assuming you are looking to integrate with Revit - download the Revit SDK and get comfortable using the Revit API chm help file.
Download some of the better packages available (Clockwork, Grimshaw, etc), open up their nodes, look at the python scripts, and force ā¦
Honestly, not a lot for basic stuff, and if your using packages that are written in IronPython, most of it can be ported with practically no effort. However itās a strong-typed language and requires more configuration and know-how compared to Python (installing Visual Studio, creating the correct project, loading the API dllās etc) which makes it un-forgiving if youāve never coded before.
My advice would be to use Python. Its very easy to learn, you can readily examine the code written by otherā¦
The PyRevit youtube channel is another great resource for Revit focused python learning:
However you should keep in mind that those videos are targeting the Revit python shell, which is implemented slightly differently from the Dynamo equivalent. (different ways to call the active document; no need to worry about element wrapping, because youāre not returning anything to the graph; etc.)
It seems consistent to add this other nice tutorial here:
30 Likes
Yna_Db
October 24, 2017, 2:43pm
2
This second post relates to IMPORTS :
Pawel,
These are the most used imports:
Thank you,
Now for the python script:
##CLR
Dynamo uses a version of python called IronPython which is capable of dealing with .NET libraries.
To interact with the Revit API we have to load an .NET assembly, a dll file named RevitAPI.dll, and for this we need the clr module from Iron Python. (http://ironpython.net/documentation/dotnet/ )
Thus the first lines of the code looks like this:
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
##Generic collections
If we look at the arā¦
Hi Hannes,
You need to import DSCore for DesignScript nodes to work and then use it like this, where the second argument is the amount of levels to flatten:
[image]
I have been doing this:
import os
appDataPath = os.getenv('APPDATA')
dynPath = appDataPath + r"\Dynamo\0.9"
if dynPath not in sys.path:
sys.path.Add(dynPath)
bbPath = appDataPath + r"\Dynamo\0.9\packages\Bumblebee\extra"
if bbPath not in sys.path:
try:
sys.path.Add(bbPath)
import bumblebee as bb
except:
import xml.etree.ElementTree as et
root = et.parse(dynPath + "\DynamoSettings.xml").getroot()
for child in root:
if child.tag == "CustomPackageFolders":
for path in child:ā¦
Hello Nikolay!
Try this:
import sys
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\DLLs')
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib')
import sqlite3
import xml
You would first have to define a path to IronPythonās librar, append it to the system path and then finally import the module.
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import random
#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
#Assign your output to the OUT variable.
OUT = random.random()
Works as expected:
[image]
https://forum.dynamobim.com/t/how-to-convert-dynamo-nodes-to-python-script/13050/2
import re
dataEnteringNode = IN
html = IN[0]
exp = rā(?<=id\s)([0-9]*)'
match = re.findall(exp, html)
if match:
OUT = set(match)
else:
OUT = āNot Foundā
Hi sajo
We know itās overwhelming, but you are more likely to get quick responses if you break these questions down into separate posts/subjects.
In any case, I will try to touch on some of the points:
What does the first four similar lines of every script doā¦?
See comments below
import clr
# imports Common Language Runtime library .This will serve as a bridge between python and the .NET wold
# See this: http://ironpython.net/documentation/dotnet/dotnet.html
clr.AddReference('Protoā¦
https://forum.dynamobim.com/t/rounding-numbers-in-python/14671/11
This should do it:
stringlist = IN[0]
import itertools
def generate_groups(lst, n):
if not lst:
yield []
else:
for group in (((lst[0],) + xs) for xs in itertools.combinations(lst[1:], n-1)):
for groups in generate_groups([x for x in lst if x not in group], n):
yield [group] + groups
OUT = generate_groups(stringlist, 2)
8 Likes
Yna_Db
October 24, 2017, 3:04pm
3
This third post is about REVIT API and C# TO PYTHON :
Online Documentation for Autodesk's Revit API: 2015, 2016, 2017, 2017.1, 2018
Online Documentation for Autodesk's Revit API: 2015, 2016, 2017, 2017.1, 2018
Online Documentation for Autodesk's Revit API: 2015, 2016, 2017, 2017.1, 2018
http://thebar.cc/converting-revit-api-c-code-to-python/
Autodesk is a global leader in design and make technology, with expertise across architecture, engineering, construction, design, manufacturing, and entertainment.
http://thebuildingcoder.typepad.com/blog/about-the-author.html
Hello Rajkumar!
This article explains a lot when it comes to how dynamo works with the revit api: https://github.com/DynamoDS/Dynamo/wiki/Python-0.6.3-to-0.7.x-Migration#revitapi
The Revit API uses .NET assemblies to give access to functionalities in the program, these assemblies are .dll files. RevitAPI.dll and RevitAPIUI.dll are files that can be found in the Revit program folder.
To use .NET with python Dynamo uses a variant called IronPython. How clr and clr.AddReference work is explainedā¦
Maybe you can try @Dimitar_Venkov s C# interpreter: (found in the package manager). I just slightly edited the code to include some references and swapped to Dynamos document manager.
[image]
//Add references
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.ApplicationServices;
using Autoā¦
That return statement looks good and it seems to be doing what itās supposed to inside Dynamo. Tho Iām not sure why youāre generating new lists instead of using the existing lists?
I guess your question is how to return a Dynamo element instead? Youāll need to wrap the Revit element like so:
types.Add(doc.GetElement(id).ToDSType(true) )
You could also give the new C# interpreter a try. Itās up on the package manager:
[image]
If youāre testing something specific, you could always give my Dynamic CSharp Interpreter a go:
[image]
You can find it on the package manager
Because C# is a strongly typed language you have to specify the type for every variable. Thatās why it needs casting to a LocationCurve. Python on the other hand does the casting for you, so in this case you should be able to do something like this:
curve = l.Curve
Because you ask for .Curve property on a Location object Python will figure out that it needs to cast to LocationCurve and then return the Curve.
Hi sajo
We know itās overwhelming, but you are more likely to get quick responses if you break these questions down into separate posts/subjects.
In any case, I will try to touch on some of the points:
What does the first four similar lines of every script doā¦?
See comments below
import clr
# imports Common Language Runtime library .This will serve as a bridge between python and the .NET wold
# See this: http://ironpython.net/documentation/dotnet/dotnet.html
clr.AddReference('Protoā¦
9 Likes
@Yna_Db
Give a man a fish and he can eat for a day.
Give a man a fishingrod and he can eat for a lifetime.
Thnx
Marcel
4 Likes
Yna_Db
October 24, 2017, 7:47pm
5
Totally agree
This post relates to IRONPYTHON and its LIBRARIES :
http://ironpython.net/
http://www.ironpython.info/index.php?title=Useful_Links
http://opensimulator.org/git/opensim-libs-save/IronPython/IronPython-1.1.1/Tutorial/Tutorial.htm
https://ironpython-test.readthedocs.io/en/latest/
python, ironpython
https://ironpython-test.readthedocs.io/en/latest/library/index.html
https://docs.python.org/2/library/intro.html
http://ironpython.net/documentation/dotnet/
Thatās because some modules are implemented using native c# libs and reside in the IronPythonModules.dll, which is loaded automatically at startup. The rest of the ipy modules are implemented as python code (and reside in the Lib folder) and are translated to the CLRās intermediate language every time you run the script:
[DynamoSandbox_2017-10-31_09-43-12]
Hi @Adrian_Crisan
You have to add the default ironpython library to the interpreterās path.
Not sure why itās not added by default (maybe @Dimitar_Venkov can shed some light?), but this should work:
[image]
3 Likes
Yna_Db
October 24, 2017, 8:04pm
6
This post is a selection of COMMENTED SCRIPTS :
Online Documentation for Autodesk's Revit API: 2015, 2016, 2017, 2017.1, 2018
Yna_Db is correct, itās read only and you need to use the SetProjection Method in a python node.
Here is an example of how to use the method:
element.SetProjection(AnalyticalElementSelector.EndOrTop, StickElementProjectionY.LocationLine, StickElementProjectionZ.Bottom)
Here is a complete working code:
[image]
import clr
# Import Revit API
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *
# Import DocumentManager and TransactionManager
cā¦
I found another script I had written once, but forgotten about. Think it does what you want:
[image]
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDoā¦
It was just random for debugging purposes. I believe the CreateParts method returns null. If you need to return the parts, I think you have to use PartUtils.GetAssociatedParts()
Yes, the script would be even easier if you can get the elements from an IN-port. Just replace the filtered element collector with IN[1] or something similar. Here is a modified version of the script:
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('System')
from System.Collā¦
try this: http://dp-stuff.org/room-plans-non-rectangular-viewports-revit-2014/
[image]
#dp Stuff | http://dp-stuff.org | createRoomPlanViews
#this Revit Python Script batch generates Room Plan Views
#before running the script select the rooms to generate Plan Views for
import clr
import math
clr.AddReference('RevitAPI')
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManageā¦
Hereās an easier to copy paste version of the code
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import*
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
views = UnwrapElement(IN[0])
ltop = UnwrapElement(IN[1])
toffset = IN[2]
lbottom = UnwrapElement(IN[3])
boffset = IN[4]
count = 0
TransactionManager.Instance.Ensurā¦
Probably easiest to say that just about everything directly related to how your trying to paint the walls is not correct. Hereās a script that I wrote a while back for the same kind of thing that you can look at and try to evaluate how it differs from yours. This isnāt the most robust script as it will fail if you donāt have a list (single object), or you have a multi-dimensional list, or if you have a face based wall, but it should be enough to get the point across.
[PaintWalls_python]
-Tim
1 Like
Totally agree, but the main problem in the forum is that some users are still doing the work of some lazy people.
Regards,
2 Likes
Yna_Db
October 24, 2017, 8:13pm
8
@Organon
I canāt resist to cite your very first lesson to coding in this thread 'cause I simply love it
for users in users:
if screenshot is None:
print ("This is not a 'do my work' forum.")
elif codeSample is None:
print ("This is not a 'do my work' forum.")
elif DYNfile is None or RVTfile is None:
print ("This is not a 'do my work' forum.")
else:
print ("Ok, let's see your question.")
4 Likes
@Yna_Db ,
Hahaha, itās the hard truth.
Regards,
1 Like
Yna_Db
October 24, 2017, 8:18pm
10
Organon:
the hard truth
ā¦ so much easier to say with a touch of humor
3 Likes
Yna_Db
October 26, 2017, 7:16pm
11
To complement this IF-ELSE STATEMENT proposal, here are a few additional examples:
https://forum.dynamobim.com/t/if-list-is-empty-switch-to-another-list/14720/6
layer = IN[0]
styles=[]
for i in layer:
if i == "red" :
styles.append("0.13mm")
elif i == "yellow":
styles.append ("0.18mm")
else :
styles.append ("0.13mm")
OUT = styles
https://forum.dynamobim.com/t/wall-property-function/11685/9
https://forum.dynamobim.com/t/msgbox-and-if-statement/12993/13
you are indeed. Your code only works on a singleton (i.e. one object, or in your case, a number). As you want to provide a list you need to store your result in a list and iterate over the input list. One method is a simple loop to iterate through the list (and python has some pretty powerful built-in itertools which you should check out on python.org which are more efficient than loops):
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
#The inputs to thā¦
Can some one tell me what Iām doing wrong here?.
[image]
Just luckily solved it myself if anyone has the same issue hereās my solution
[Capture]
Python
# Assign curves to groups according to whether they are connected via shared start points and end points. Group numbers are not important.
# Colin McCrone, 2015-09-28
import clr
import math
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Determine whether two points are equal
def PointsEqual(pt1, pt2):
tolerance = 0.00001
if (math.fabs(pt1.X ā¦
Yna_Db
November 1, 2017, 10:09pm
12
The following posts are related to PYTHON LISTS :
@staylor You have to iterate over your list of documents using a for loop. Right now you are defining doc as a list, so essentially in line 18 you are saying param_list = ListObject.FamilyManager.GetParameters() See below example, when I query the object type of the input without a for loop, it shows me the object is a list. If I query the object type of the input elements with the for loop, it returns the object type of the items in the list
[iterateoverdocs]
So, you need to put your code wā¦
Hi @Jordan_Billingsley - I already have a very simple Python script that accomplishes supplying a boolean output for whether or not elements are pinned are not, which I will provide below. You can use this inputting your wall elements, then using Filter.ByBoolMask with its output.
To encourage you to understand how the script works & to further learn using Python with the Revit API I will provide an explanation on how it works. if you look at the API Docs that @Nick_Boyts referenced above you wā¦
Thereās probably a cleaner way of doing this but a simple use of append will work.
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('DSCoreNodes')
from DSCore import *
#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
items = IN[0]
inlist = IN[1]
newlist = []
for indices in inlist:
sublist = []
for i in indices:
sublist.append(items[i])
newlist.append(sublist)
#Assign your output to the Oā¦
Strange. Works fine on my end. Have you tried closing the file and re-running it?
[image]
As an FYI, you should paste your Python code using the Preformatted Text option. Just highlight your pasted text and click </> in the toolbar above.
Yes, but I donāt think thatās what you need here. As @awilliams said, you can wrap your if statement within your for loop.
However, if you wanted to iterate through both lists simultaneously you would use:
for i, j in zip(list1, list2):
This would essentially get you paired values list1[0]/list2[0], list1[1]/list2[1], etc.
https://forum.dynamobim.com/t/lacing-on-replacing-item-on-index/16462/11
https://forum.dynamobim.com/t/help-with-group-by-key/11379/8
I have noticed that this before too, and it looks like UnwrapElement() is converting the Pyton List into a Collections.Generic.List. Thatās why isintance() returns false.
[image]
@Cesar_Escalante
Using Python, option 1:
[image]
def MergeSort(lst1,lst2):
MergedList=[]
for index,i in enumerate(lst1):
MergedList.append(i+lst2[index])
MergedList[index].sort()
return MergedList
OUT=MergeSort(IN[0],IN[1])
Option 2:
[image]
MergedList=[i+IN[1][index] for index,i in enumerate(IN[0])]
for i in MergedList:
i.sort()
OUT=MergedList
Hi JN,
Have you tried setting the lacing of the custom node that you created to Longest?
Otherwise you could use a for loop in Python:
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionMā¦
the function works with nulls as well :
[image]
we take each element among sublists and then find largest
iām not sure I got this part
@ Hannes - use List Comprehensions - they are much faster than loops:
import clr
clr.AddReference(āProtoGeometryā)
from Autodesk.DesignScript.Geometry import *
dataEnteringNode = IN[0]
OUT = [i for sublist in IN[0] for i in sublist]
https://docs.python.org/2/tutorial/datastructures.html
Nice that you got it to work!
If you wanted to combine the lists in python you could have used zip()
for view,curves in zip(views,curvelist):
#Create curveloop
loop = CurveLoop()
for c in curves:
loop.Append(c.ToRevitType())
#Set cropregion in Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
view.CropBoxActive = True
view.GetCropRegionShapeManager().SetCropShape(loop)
outputlist.append(view)
TransactionManager.Instance.TransactionTaskDone()
OUT = outputlist
I am guessing you have 2 sublists and really what youāre asking is how can you perform cross product lacing with sublist 1 against sublist 2?
Try this (this only works on a list with two sublists; if you are trying to match each item from sublist 1 with all items with sublist 2, then match each item from sublist 2 with all items from sublist 3ā¦etc then this wont work and you should think about how to manage your data better)
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScriā¦
The Konradās function using lists comprehension:
elements = IN[0]
ProcessLists = lambda function, lists: [ProcessLists(function, item) if isinstance(item, list) else function(item) for item in lists]
sum = lambda x: x + 1
if isinstance(elements, list):
out = ProcessLists(sum, elements)
else:
out = sum(elements)
OUT = out
[image]
Try using a definition like so above your inputsā¦
def tolist(obj1):
if hasattr(obj1,āiterā): return obj1
else: return [obj1]
And for the input beams write the followingā¦
beams = tolist(UnwrapElement(IN[0]))
This is what I use for inputs to ensure they are an iterable object. Very common point of failure in writing python nodes.
(I canāt seem to format the code on my mobile, but indented code after the first line naturally)
Hi @salvatoredragotta
Both versions get the ElementId using the same method, which is the .Id Property (any object that inherits from Element has it).
Whatās different, is what they do with the resulting ElementId objects retrieved. The method you use, will depend what you will do with the collection of ElementIds. More details below.
The 2nd in your example, creates a list (built-in Python list ) which is a generic, container native to Python, the other creates a List, a .NET data-type.
Pytā¦
2 Likes
Yna_Db
November 3, 2017, 10:33pm
13
These posts relate to STRINGS in Python:
you could do all that or use half a line of python code:
[Revit_2017-10-07_13-21-40]
On a side note: I assume youāre getting the trailing zeroes because youāve converted a double value to a string. In that case you could also use this python code to get what you want straight away:
[image]
https://forum.dynamobim.com/t/combine-nested-list-items-into-one-multiline-string/13158/2
https://forum.dynamobim.com/t/list-replace-multi-elements/13010/7
@3Pinter
You can also use a line of code in python:
OUT=[i.split('- ')[1] if '- ' in i else i for i in IN[0]]
or without list comprehension:
OUT=[]
for i in IN[0]:
if '- ' in i:
OUT.append(i.split('- ')[1])
else:
OUT.append(i)
[image]
@yyi is right. The problem here is that the code doesnāt accept different types of inputs (single integer or list of integers, single list of strings or nested lists, etc.)
What I would do is adapt the code to the worst case scenario for each case, being this when you have nested list of strings for the first one and a list of integers for the second. Pay attention to the if statement using isinstance().
Remove Characters
import re
inputList = IN[0]
outputList = []
def RemoveCharacters(listā¦
python, regex, string
Yna_Db
November 14, 2017, 10:31pm
14
This post is about FUNCTIONS :
A couple of things:
In python def means that a function is defined. Nothing will happen before you call the function.
I think you need to convert the reference plane to a sketch plane before it can be used to set the workplane.
insert is a function and should use (), not [].
https://forum.dynamobim.com/t/passing-nodes-as-functions-in-python-script/16324/4
Tomasz,
The ProcessList() method takes care of zipping the two arguments from lists. You donāt have to perform that inside your Intersection() method. Basically change it to:
def Intersection(elA, elB):
return elA.DoesIntersect(elB)
Then call it like so:
OUT = ProcessList(Intersection, ducts, walls)
Make sure that the two lists ducts and walls are exactly of the same structure. It works like this:
ducts = [duct1, duct2, duct3]
walls = [wall1, wall2, wall3]
Calling ProcessList(Interseā¦
@yyi is right. The problem here is that the code doesnāt accept different types of inputs (single integer or list of integers, single list of strings or nested lists, etc.)
What I would do is adapt the code to the worst case scenario for each case, being this when you have nested list of strings for the first one and a list of integers for the second. Pay attention to the if statement using isinstance().
Remove Characters
import re
inputList = IN[0]
outputList = []
def RemoveCharacters(listā¦
In python it may actually work faster than to convert to some text showing the type name and then testing on that. You could do the same thing there, but thereās a better alternative.
Standard python comes with the isinstance function. As an example:
[image]
In that the Python Code:
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
#The inputs to this node will be stored as a list in the IN variables.
#Assign your output to the OUT variable.
OUT = mapā¦
I took another look at this, but had to turn to python to make it work:
[image]
(Edit: Python is updated, center and bottom had swapped places)
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB.Structure import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
#Functions for list handling
def ProcessList(_funcā¦
@Chad_Clary ,
This is indeed a little tricky because these elements donāt have a Parameter called name, but instead its a property. Hereās how you can handle it.
[image]
Hereās the code thatās inside of Python:
# Copyright(c) 2016, Konrad K Sobon
# @arch_laboratory, http://archi-lab.net
# Import Element wrapper extension methods
import clr
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# Import DocumentManager and TransactionManager
clr.AddReference("Revitā¦
I wrote a 30 page handout for my AU class on Python for Dynamo, thought I would leave this here
13 Likes
Yna_Db
November 17, 2017, 8:11pm
16
This is a very good document that let you get started with a clear view on the possibilities opened by this language, along with a few tips that will make it all fun from the start. I add a link into the introductory post so it can be found easily. Thanks a lot
Yna_Db
November 17, 2017, 10:13pm
18
It seems consistent to add this other nice tutorial here:
VIDEO
7 Likes
For a non-programmer like myself, which would be the natural course then?
I am assuming first learning the basics of Python, for which I am following some course on edX and reading some tutorials, but this doesnāt seem to relate to geometric or graphical capabilities at all (Which I assume is because of the introductory level of the course).
So what would be next after learning the basic stuff?
How can I connect Revit or Dynamo or both to Python? This is like the missing link for me. I am sure you will guide me, and many others after me, on the right path.
Thank you all.
For most Dynamo users, I would say that Python only really shines when dealing with lists (especially of multiple levels) and Revit API work (which are things usually done in C# but can be done in python nodes). For geometric capabilities, I can only think of python being useful for its import libraries, math functions/capabilities, looping, or if you can find a python function online that already has what you want.
Someone please correct me if I am wrong though.
1 Like