Use AdaptiveComponent.ByPoints in Python script

Hi,
this question is not new, but the last thread didn’t get an answer:

I need to use this node in a script, because i want to place different adaptiv families in a specific order on a line. But the node works only with one family.

I tryed different things, but every time i get another error.

 import clr
 clr.AddReference("RevitAPI")
 clr.AddReference("ProtoGeometry")
 clr.AddReference("RevitNodes")
 clr.AddReference("RevitServices")
 clr.AddReference('RevitAPIUI')
 clr.AddReference('DSCoreNodes') 
 import DSCore
 from DSCore import *
 import Autodesk
 import Revit
 clr.ImportExtensions(Revit.GeometryConversion)
 import RevitServices
 from Autodesk.Revit.DB import *
 from Autodesk.DesignScript.Geometry import *
 from RevitServices.Persistence import DocumentManager
 from RevitServices.Transactions import TransactionManager
 from System import Array

plist = IN[0]
typelist= IN[1]

result=[]
i=0
#ids = List[ElementId](e.Id for e in typelist)
for p in plist:
	pp = Array.CreateInstance(Array[Point], 1)
	result.append(Revit.Elements.AdaptiveComponent.ByPoints(pp,typelist[i]))
	i+=1
		
OUT = result

plist = IN[0]
typelist= IN[1]

result=[]
i=0
ids = List[ElementId](e.Id for e in typelist)
for p in plist:
	#pp = Array.CreateInstance(Array[Point], 1)
	result.append(Revit.Elements.AdaptiveComponent.ByPoints(ids,typelist[i]))
	i+=1
		
OUT = result

Any ideas how i can use this node in a python script?
adaptiv_component_forum.dyn (321.5 KB) Forum_project.rvt (1.5 MB)

Hi Fiesta,
First of all - nice nickname. I like it.

There are 2 ways to create an adaptive component from a python node:

  1. Using the API directly.
  2. Using the Revit nodes from Dynamo.

Revit.Elements.AdaptiveComponent.ByPoints() is the Revit nodes method so the inputs should be exactly as the inputs to the node - a list of placement points for each family type.
So you don’t need arrays or or elementIds.
Using this node in Python also means that you have to do the lacing and the list management yourself as opposed to using levels and lacing in the node.
So briefly in the brackets you need a list of placement points and a family type:
Revit.Elements.AdaptiveComponent.ByPoints(pointlist, family type)

Hello, @Fiesta! Please, read this material: RevitPythonShell: Adaptive Components - THE PROVING GROUND

Here is solution for your task:

import clr
clr.AddReference("RevitAPI")
clr.AddReference("ProtoGeometry")
clr.AddReference("RevitNodes")
clr.AddReference("RevitServices")
clr.AddReference('RevitAPIUI')
clr.AddReference('DSCoreNodes') 
import DSCore
from DSCore import *
import Autodesk
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
import RevitServices
from Autodesk.Revit.DB import *
from Autodesk.DesignScript.Geometry import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from System import Array
doc = DocumentManager.Instance.CurrentDBDocument
plist = IN[0]
typelist= UnwrapElement(IN[1])
typelist_final=[]
count=0
for i in plist:
	try:
		typelist_final.append(typelist[count])
		count+=1
	except:
		count=0
		typelist_final.append(typelist[count])
		count+=1
TransactionManager.Instance.EnsureInTransaction(doc)
count = 0
for p in plist:
	point = p.ToXyz()
	adaptComp = AdaptiveComponentInstanceUtils.CreateAdaptiveComponentInstance(doc, doc.GetElement(typelist_final[count].Id))
	count+=1
	adaptPoint = AdaptiveComponentInstanceUtils.GetInstancePlacementPointElementRefIds(adaptComp)
	aPt1 = doc.GetElement(adaptPoint[0])
	trans1 = point.Subtract(aPt1.Position)
	new_el = ElementTransformUtils.MoveElement(doc, aPt1.Id, trans1)
TransactionManager.Instance.TransactionTaskDone()		
OUT = 0

The only thing, I played a bit with input lists because, as i think, there can be more points then your family types input

for i in plist:
	try:
		typelist_final.append(typelist[count])
		count+=1
	except:
		count=0
		typelist_final.append(typelist[count])
		count+=1

Hope, this will be helpfull

2 Likes

Hi Viktor,
thx for you help!
The node can handle only one placement point and one family type. But i can’t reproduce this behavier in the script.

import clr
clr.AddReference("RevitAPI")
clr.AddReference("ProtoGeometry")
clr.AddReference("RevitNodes")
clr.AddReference("RevitServices")
clr.AddReference('RevitAPIUI')
clr.AddReference('DSCoreNodes') 
import DSCore
from DSCore import *
import Autodesk
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
import RevitServices
from Autodesk.Revit.DB import *
from Autodesk.DesignScript.Geometry import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from System import Array

plist = IN[0]
typelist= IN[1]

result=[]

for p,t in zip(plist,typelist):
	result.append(Revit.Elements.AdaptiveComponent.ByPoints(p,t))
	
OUT = result

Hi Dmytro,
thx for help.
Your solution works great.
I will learn how to code direct with the Revit Api, but i have not enough time to learn it now;)

1 Like

Well yeah, apparently it needs a point array and not a list
Something like this should work:

it’s not advisable to use these methods from code (unless you want element binding behavior) - they have element binding I think and might not behave how a normal function call would.

Thx for the information.
There is an abnormal behavior that I noticed so far.
The families i placed are not bound to the dynamo node. So every time i run my script the families gets placed again and again.