NewFamilyInstance on topo


#1

I’ve tried to place site families by a python-script. I once read that if you feed the NewFamilyInstance XYZs and a topo it will still pick the topo’s height in the points you specify.

The inspiration came from here: http://thebuildingcoder.typepad.com/blog/2010/11/place-site-component.html

However, once again, I come short. Is anyone willing to give me a pointer to what I should be doing with this script to achieve the stated?(I know I have a lot of imports at the top, but I’ll delete the unnecessary ones in the future.)

I hope someone grabs the challenge! :wink:

 

2

 

 

1


#2

Hello Jostein,

it would help if you could provide your script as text.

Copying it line by line seems like a waste of time… :wink:

EDIT: Alternatively, you should at least provide the error message that the Python Script node throws…


#3

Yeah, sorry:

 

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

Import RevitAPI

clr.AddReference(“RevitAPI”)
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.Creation import *

Import DocumentManager and TransactionManager

clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

Import ToDSType(bool) extension method

clr.AddReference(“RevitNodes”)
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

doc = DocumentManager.Instance.CurrentDBDocument
view= doc.ActiveView

#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN
list=IN[0]
symbol=IN[1]
topo=IN[2]
stype=IN[3]

unwrap=[]
xyzs=[]

for i in list:
unwrap.append(UnwrapElement(i))

for j in unwrap:
xyzs.append(unwrap.ToXyz())

try:
TransactionManager.Instance.EnsureInTransaction(doc)

for k in xyzs:
NewFamilyInstance(k, symbol, topo, stype)

TransactionManager.Instance.TransactionTaskDone()

OUT = "success."
except:
OUT = “failed…”


#4

Just guessing here, but it looks like you need to unwrap the topo element as well because it’s coming from a dynamo node.

The error from the python node would indeed be helpful :slight_smile:


#5

This should work. Note that this method will not place the site elements associatively like the tool in the GUI. Honestly, I don’t know how they do that, must be some secret sauce.

import clr

EDIT ### Here I removed the reference to ProtoGeometry - you usually won’t need that in a Revit-related script

Import RevitAPI

clr.AddReference(“RevitAPI”)
import Autodesk
from Autodesk.Revit.DB import *

EDIT ### Removed the reference to Revit.Creation

Import DocumentManager and TransactionManager

clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

Import ToDSType(bool) extension method

clr.AddReference(“RevitNodes”)
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

doc = DocumentManager.Instance.CurrentDBDocument

EDIT ### I can use this to call creation functions later on

doccreation = doc.Create
view= doc.ActiveView

EDIT ### Here’s a one-liner for getting all your xyzs

xyzs = [x.ToXyz() for x in UnwrapElement(IN[0])]
symbol = UnwrapElement(IN[1])
topo = UnwrapElement(IN[2])

EDIT ### Create an empty list for the new objects we’ll create

elementlist = list()

EDIT ### In this last bit I had to make some more changes

1. The transaction wraps around everything

2. Then we cycle through each xyz

3. Then we use try/except for each xyz - in some cases it might work, in others maybe not

4. There’s a bug in the Dynamo build I am currently using, so I am adding the structural type directly in Python, not from an input.

5. Elements that were created successfully get added to the output list, for failed elements we add an empty list (may become important if need to filter for success or failure)

TransactionManager.Instance.EnsureInTransaction(doc)

6. Each newobj should actually be returned as newobj.ToDSType(False), but that is broken in my current build as well…

for xyz in xyzs:
try:
newobj = doccreation.NewFamilyInstance(xyz, symbol, topo, Structure.StructuralType.NonStructural)
elementlist.append(newobj)
except:
elementlist.append(list())
TransactionManager.Instance.TransactionTaskDone()
OUT = elementlist


#6

Here’s a screenshot so you can see the indentation. Would be nice if the forum would not destroy that type of info when copy/pasting.

placeontopo-python


#7

Thanks Andreas! You must be very ideally driven to even bother responding, even better: you deliver a copy/paste solution, AND to top it off you annotate the py-script so that amateurs like me can learn. That’s inspirational right there!

However I’m not able to get the elements to “obtain” the Z-value from the topo. they all get set to whatever Z-value that was the input.

I based my hopes on the article above and the following line:

“<span style=“color: #232323;”>It turns out the Z coordinate can be zero, by specifying TopoSurface it will be anchored correctly”</span>

I’ve looked through this script in VB, but I can’t find anything. I can’t attach it here because the forum won’t let me, but look in the link above if you’r interested.

Anyways, thanks yet again.

 


#8

:slight_smile:

Well, I’ve been away from the forum for about three months now, so I figured a little extra effort was okay. Only took a couple of minutes in any case - your code was a good basis.

In your blog post (http://jbdynamo.blogspot.no/2014/11/extend-pile-length-to-topo-its-working.html) you are mentioning the ReferenceIntersector method. I had that working in 0.6.3 but haven’t managed to build a bug-free version for 0.7 yet. This may indeed be a good use case. But what really bugs me is the fact that if I place a site element on a topo using the GUI, I can drag that element across the topo and its height will adapt.