Page 1 of 1

Proxies vs Instances

PostPosted: Mon Nov 09, 2015 2:17 pm
by ebanta11053
Hi Paul - I have a quick question concerning proxies and instances in Revit. I had a large landscape and I placed about 100 Revit tree families (simple geometry with an outline) to use as placeholders for an ORBX proxy. I assign each family instance a high poly ORBX proxy. When I went to render, Revit locked up during voxelization - I waited about 20 minutes before killing the render.

I then took the same model, deleted all but one tree instance and used PhantomScatter to place probably 500 trees. I assigned an ORBX proxy to the singular Revit tree family and attached the PhantomScatter generated CSV fie. The voxelization process took about a minute, the render started and the results were amazing.

It seems to me that both processes are quite similar, but with drastically different results. PhantomScatter is great, but it works outside of Revit. Sometimes I want to precisely locate ORBX-proxy geometry within Revit. Is there some way that placing several hundred instances within Revit could work the same way as it does when using a CSV file with a proxy?

Thanks,

Ed

Re: Proxies vs Instances

PostPosted: Mon Nov 09, 2015 10:02 pm
by face_off
Hi Ed. If the high poly proxy has 1 million polygons, and you can assigned it to 20 trees, then that's 20 million polygons for the scene plus you normal scene geometry, which exceeds the 19.6 million triangle count limit in Octane 2. When you scatter/instance 20 times, Octane is counting the 1 million polygons only once, not 20 times, so the total scene triangle count will be much lower and render OK.

Sometimes I want to precisely locate ORBX-proxy geometry within Revit. Is there some way that placing several hundred instances within Revit could work the same way as it does when using a CSV file with a proxy?
In theory it should be easy to write some Revit python code to get the transform for each tree and write it to a SCV scatter file - along the lines described in this post http://poserphysics.blogspot.com/2014/11/randomizing-family-instances-in-revit.html. You would just need to change the "# Apply a random rotation" to output that elements transform to the CSV file. I will see if it's something I code put into code in the future, but if you are handle with python you should be able to do it yourself.

Paul

Re: Proxies vs Instances

PostPosted: Tue Nov 10, 2015 4:26 pm
by ebanta11053
Hi Paul - Your explanation made a lot of sense and I suspected as much. I'm not a coder but have seen Dynamo used inside of Revit and think it might be possible to query the coordinates of all tree locations and export the data to a CSV file. Of course, if you made it part of the plugin interface that would be awesome.

Thanks again for all the hard work you put into the plugin. It makes rendering life SO much easier now that the model doesn't have to be exported to 3ds Max.

Ed

Re: Proxies vs Instances

PostPosted: Thu Nov 12, 2015 2:35 am
by face_off
I haven't had time to look into this properly - but if you want just the POSITIONS of the family instances (and not the rotations), use the following code in the RevitPythonShell as per the blog article I posted above. Change the "d:/scatter_files/my_scatter_file2.csv" line to whatever file you want the transforms saved to.

Code: Select all
# Run in a RevitPythonShell - in Non-Model Shell Model

import clr 
import System 
import csv
   
clr.AddReference('RevitAPI') 
clr.AddReference('RevitAPIUI') 
from Autodesk.Revit.DB import * 
   
app = __revit__.Application 
doc = __revit__.ActiveUIDocument.Document 
   
# Get the current selection 
selection = __revit__.ActiveUIDocument.Selection.Elements 
if selection.Size != 1: 
   print "A single family instance must be selected" 
else: 
   for item in selection: 
     currentElement = item   
   print "Current Selection = " + currentElement.Name 
 
   ofile = open("d:/scatter_files/my_scatter_file2.csv", 'wb')
   writer = csv.writer(ofile, dialect='excel-tab', delimiter=",")
           
   collector = FilteredElementCollector(doc)   
   collector.OfClass(FamilyInstance) 
   
   famtypeitr = collector.GetElementIdIterator() 
   famtypeitr.Reset() 
     
   count = 0 
       
   for item in famtypeitr: 
     famtypeID = item 
     faminst = doc.GetElement(famtypeID) 
     if faminst.Name == currentElement.Name: 
       # Setup the rotation axis 
       p1 = faminst.Location.Point; 
       matrix = [0, 0, 0, p1.X, 0, 0, 0, p1.Y, 0, 0, 0, p1.Z]
       writer.writerow(matrix)
           
       count += 1 
       
   print "Saved " + str(count) + " family instances of " + currentElement.Name 
   ofile.close()

Re: Proxies vs Instances

PostPosted: Sat Feb 06, 2016 5:47 pm
by ebanta11053
Hi Paul - With the help you gave me in another thread viewtopic.php?f=76&t=51654&p=257713#p257713 and with the help of an intern who is good at coding I was able to put together some Python code to output a CSV file for all the instances of a selected family. I haven't put the latest information you provided about the rotation into the code (although I tried it manually with an excel file and it worked really well) but am really stumped on how to access the rotation of the families.

I've spent a lot of time searching around but since I'm not a programmer (just an architect) I don't really understand how to take the example you gave of randomly rotating instances and reversing it to identify all the rotations of families that are placed.

Can you help me with the missing parts? I think this would be really valuable to all the Revit for Octane users out there who want to place cars, trees, furniture etc. on topo or flat surfaces while staying inside the Revit interface. I use PhantomScatter for all of the area scatters but it doesn't work well (currently) in the per-tri method with any type of extruded surface (which all families have). It also is a generic interface that does a lot more than most of our in-house architects need. Putting this code into a Revit Macro would make life so much easier for our guys.

I understand if you don't want to do this as it's a custom piece of software and not really part of the Octane engine. If you can't then maybe someone else reading this can.

The stuff you've put together so far into the interface has been wonderful, it's all greatly appreciated.

As always, thanks

Ed


import clr
import System
import csv

# These imports give access to the Revit API
clr.AddReference('RevitAPI')
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.DB import *

app = __revit__.Application
doc = uidoc.Document
# 'uidoc' is the pre-define Revit API varible (uidoc = __revit__.ActiveUIDocument)
# These two lines set the active Revit/Vasari application and document for use


# Get the currently selected instance of a family
selectedInstance = uidoc.Selection.Elements
if selectedInstance.Size != 1:
print "Error: A single family instance must be selected"
else:
for item in selectedInstance:
currentElement = item
print "Current Selection = " + currentElement.Name

ofile_address = "C:/scatter_files/" + currentElement.Name + "_scatter.csv"

ofile = open(ofile_address, 'wb')
# creates output file to write to based on family name
writer = csv.writer(ofile, dialect= 'excel', delimiter=",")
# creates csv.writer object

# writer for testing purposes
testFile = open("C://scatter_files/matrixTest.csv", 'wb')
testWriter = csv.writer(testFile, dialect = 'excel', delimiter = ",")
NonCSVTest = open("C://scatter_files/OtherTest.txt",'w')

# create a collector for elements
collector = FilteredElementCollector(doc)
collector.OfClass(FamilyInstance)

famtypeitr = collector.GetElementIdIterator()
famtypeitr.Reset()

count = 0

for item in famtypeitr:
famtypeID = item
faminst = doc.GetElement(famtypeID)
if faminst.Name == currentElement.Name:
# Retrieve the point location of the family instance
p1 = faminst.Location.Point;
# need a way to find displacement from axis, scaling, and rotation

# get geometry of family instance
elementGeometry = faminst.get_Geometry
# get transform of family instance
elementTransform = faminst.GetTransform()


print str(elementTransform)
#testWriter.writerow(elementTransform)
#testWriter.writerow(elementGeometry)
NonCSVTest.write(str(elementTransform) + "test")

matrix = [0, 0.0, 0.0, p1.X, 0.0, 0.0, 0.0, p1.Y, 0.0, 0.0, 0.0, p1.Z]
writer.writerow(matrix)
# write the new matrix to the csv file
# this creates a row of 12 floats in for each family instance
count += 1

print "Saved " + str(count) + " family instances of " + currentElement.Name
ofile.close()
testFile.close()

Re: Proxies vs Instances

PostPosted: Sun Feb 07, 2016 3:49 am
by face_off
As per https://render.otoy.com/forum/viewtopic.php?f=76&t=51654&p=263961#p263961 it will be something like....

transform material = [X Scale * cos(y Rot), 0, sin(y Rot), X Transform, 0, Y Scale, 0, Y Transform, -sin(y Rot), 0, Z Scale * cos(y Rot), Z Transform]

which will code as something like....

Code: Select all
p1 = faminst.Location.Point;
rot = faminst.Location.Rotation # NOTE: If this is in degrees, convert to radians by * PI / 180
matrix = [cos(rot), 0, sin(rot), p1.X, 0, 0, 0, p1.Y, -sin(rot), 0, cos(rot), p1.Z] # Assume the scale hasn't changed (ie. is 1).
writer.writerow(matrix)


Paul

Re: Proxies vs Instances

PostPosted: Sun Feb 07, 2016 1:49 pm
by ebanta11053
Thanks Paul - we spent hours searching through the Revit API and the web looking for a way to access the rotation of a family. This piece of code "rot = faminst.Location.Rotation" is exactly what we were looking for.

Ed