20090527

API Yi Yi

There are a gazillion little "samples" of plugin functionality code that come in your box of Revit, mostly tools that demonstrate simple repeatable tasks that can be automated by an API developer. They live in the "tools and utilities" section of the installation dvd, and once deployed, live deep in a set of subfolders where it is cool and dry. Although meant for hardcore API developers to cut and paste and assemble other functionality, these little snippets of code can become useful applications in the Revit environment with little alteration. For me, the problem has been how to turn these snippets from unintelligible bits of code into a button I can push and watch wonderful things happen. I FINALLY figured out how to do this, using the freely available Visual Studio Express to compile the code, and would like to start sharing some of these little treasures with you all. However, tonight I'd like to just show you how to hook up one of these compiled bits of code. If I was a real developer, I would give you an installer and we'd all just call it a night. But I'm not, so we can do this old school.

My favorite snippet is one that my friend Harry wrote for use in the 2010 Massing environment. Conceptually, it's really simple, it calculates the distance between curtain panel by pattern instances and some other placed family, then writes this number to an instance parameter in each panel. But once we hook this parameter up to some geometry and formulas . . . oh the fun we can have!

Direct relationship: farther from target, larger hole
Inverse Relationship: farther from target, smaller mullions
Decaying Sine Wave: oscillating opening and closing with less change after each oscillation
(Thanks to Dave B )
[Edit: Angela German has written an installer for this pluging, available on this post: http://buildz.blogspot.com/2009/07/api-yi-yi-installer-for-distance-to.html]
Now the hard part: boring instructions to adhere to, followed by the ability to make pretty things. Here are sample files and the ReadMe that comes with the code, as well as my compiled plugin, DistanceToPanels.dll, put it someplace on your hard drive, like C:\\Revitplugins\

[Assuming you have Revit 2010,] Locate a file called Revit.ini (usually in C:\\program folder\Autodesk Revit 2010\program\). Make a copy of this file before f-ing it up so you can back out changes if necessary. Open Revit.ini in a text editor like notepad or word. You are going to need to paste in the following information down at the bottom:

[ExternalCommands]
ECCount=1
ECName1 = Compute distance to panels
ECClassName1 = Revit.SDK.Samples.DistanceToPanels.CS.SetDistanceParam
ECAssembly1 = C:\Revitplugins\DistanceToPanels.dll
ECDescription1 = Compute the distance from a selected object to all panels and store in a panel instance parameter

Replace "Revitplugins" with the path to where you put your DistanceToPanels.dll
If you have already installed a plugin (like the stl exporter, you will already have the [External Command] section, and you'll need to append it to account for this new plugin. For instance, my Revit.ini looks like this:

[ExternalCommands]
ECCount=2
ECName1=Revit Extensions for Autodesk Revit Architecture 2010
ECClassName1=REX.AREXRevitMngr.Manager
ECAssembly1=C:\Program Files\Autodesk\REX\Revit 2010\AREXRevitMngr.dll
ECDescription1=Manager for Revit Extensions for Autodesk Revit Architecture 2010
ECName2=STLExport
ECClassName2=Autodesk.Revit.ExternalCommand.STLExport.Entry
ECAssembly2=C:\Program Files\Autodesk\STL Export for Autodesk Revit 2010\STLExport.dll
ECDescription2=Export model to stl file

So I would need to change ECCount=2 to now say ECCount=3 , and the rest gets updated to 3

ECName3 = Compute distance to panels
ECClassName3 = Revit.SDK.Samples.DistanceToPanels.CS.SetDistanceParam
ECAssembly3 = C:\Revit SDK 2010\DistanceToPanels.dll
ECDescription3 = Compute the distance from a selected object to all panels and store in a panel
Make a curtain panel by pattern with a length instance parameter "Distance", load it into a divided surface in a mass FAMILY (not an rvt). Select another family in the massing environment and push the magic button in the Add-Ins menu.
Caveat: I think this only works on rectangular panels.
If someone out there is handy with autohotkey or some other application, how about whipping up a little installer?
Happy Paneling!

23 comments:

  1. Zach - You are a saint for sharing this information and process. Awesome work, keep it up.

    ReplyDelete
  2. great looks like grasshopper topics come to revit:) could you give us more insight where to find those little snippets and the compile environment?

    ReplyDelete
  3. By changing these 2 lines (99 and 100) in DistanceToPanels:

    Point geomobjPoint = ds.GetGridNodeReference(gn).GeometryObject as Point;
    XYZ panelPoint = geomobjPoint.Coord;

    to:

    LocationPoint loc = familyinstance.Location as LocationPoint;
    XYZ panelPoint = loc.Point;

    it will then work with the HalfStep and maybe other patterns; however, depending on how you build your panel family, the code may not find the last row and last column of tiles on the HalfStep pattern and change their Distance parameter. When that occurs, it doesn't seem to pick up that there are SeedNodes (and therefore tiles) on the second to last row and column.

    ReplyDelete
  4. Hi! This looks so awesome! I am trying for a couple days to do the same but i am failing...

    Can u plz help me?
    I used the instaler and not the think with .ini file. Then i have to make a panel and one parameter i should name it "Distance" right? I am trying the plug in but...error:"...must have a distance instance parameter..." I should also mension that your .rfe works fine with the plug in!

    Lastly can u plz also tell me how i can achieve "Decaying Sine Wave" ? the plug in only has one option so i don;t see how this would be possible!
    Thanks in advance!

    ReplyDelete
  5. Hi Ψαρράς,
    A few things to check first. Is your "Distance" an instance a type parameter (default behavior for Revit is to create type parameters). Is "Distance" capitalized, as it is case sensitive. Lastly, can you manually edit the instance parameter in the family?

    The Decaying Sine Wave uses a cylindrical void with a radiaus based on this: Multiplier_decay * 1' * FormulaMultiplier
    where Multiplier_decay is: 10'/ (Distance / 20)
    and FormulaMultiplier is :abs(sin((Distance / (.25')) * 1°))
    Let me know how it goes.

    ReplyDelete
  6. Hi Zach!
    Thanka a lot!Yes now it works. My bad i didn't noticed the "instance" parameter!Now is there a way to adjust the effect beside moving the sphere? Invert it?

    I can't understand the Decaying Sine Wave though...
    The parameter of the radius is named "Distance"?
    Multiplier_Decay and FormulaMultiplier are new parameters? What should i make them define? Nothing?When i try to add them and i put the formula, it says "inconsistent units" probably because i am on a metric family, but i can't fix it by just removing the " ' " or adding "m"

    ReplyDelete
  7. The math at work here is this:
    The basic oscillation of the sine wave: sin x , where x is an angle
    Made into a revit formula you have : sin((Distance/1’)*1°)
    Distance is divided by 1’ to make a unitless number. The result is numbers from -1 to 1
    To keep the values positive, you have to use an absolute value
    abs (sin((Distance/1’)*1°)
    This gives an oscillation from 0 to 1
    To create a “decay” you want the oscillation to have a smaller variation over increased distance
    So you want to keep multiplying the oscillation by a smaller and smaller fraction as Distance increases, this is an inverse relationship or Constant/Distance. In my case, I have 200’/Distance, so at 1’ from target, my Multplier=200, at 50’ Multiplier= 4.
    Put it together and you have:
    (abs(sin((Distance/1’)*1°)))*(200’/Distance)
    This is unitless, so you then need to add back in your units to drive a length parameter:
    (abs(sin((Distance/1’)*1°)))*(200’/Distance) *1’
    I would just give you my family, but it has a bunch of other variables in it that confuse matters. I believe that I have corrected to for all the units in this final formula, but it might need some tinkering, and replace all the feet with meters.

    ReplyDelete
  8. Thank a lot u were realy helpfull! Now i understand the formula! But it doesn;t work! :P There is something wrong with the "sin" because i tried a simple formula with sin and it didn;t work..Anyways i will search it more when i will have time!

    On a slightly different subject i am having trouble assosiating one parameter with the width of the panel. So lets say that the panels are getting small in a curved surface,i want their frame to become smaller as well! Thanks a lot u were realy helpfull!!!!!

    ReplyDelete
  9. Ψαρράς,
    Try the plug in described here for getting panel geometry to react to changes in shape:
    http://buildz.blogspot.com/2009/07/api-yi-yi-measuring-panel-lengths-and.html

    ReplyDelete
  10. :S no pude me sale error en el comando del revit.ini que hago?

    ReplyDelete
  11. uh oh! now that you figured how to do some code, you will be really, really, dangerous :)

    ReplyDelete
  12. Thanks a lot for your great effort,
    When I tried to open one of my projects to edit one of the surfaces inside it, I inserted the panel, and applied it to the surface but when I tried to apply the effect of the grayscale map I was wondered that Add -Ins ---- external tools is completely not active!

    ReplyDelete
  13. Did you put the addin information in the folder appropriate to the release you are working in? These instructions are for r2010.

    ReplyDelete
  14. actualy I am using Revit 2012, I installed the correct plugin from your website for this version (20120502_RevitParameterValuesFromImage2012)
    and every thing is working fine with me when I make the design of my surface panels on your file named: Grayscale_test.rfa
    but when i want to insert the surface to *.rvt files, the Add-In externals tool will become inactive!

    ReplyDelete
  15. Actually I am using Revit 2012, I installed the correct plugin for this version from your great weblog (20120502_RevitParameterValuesFromImage2012).
    Everything is working fine when I create my surface inside your Grayscale_test.rfa file.
    But the problem starts when I want to create the same surface in rvt files.
    Thanks for your kind support
    AMFAH

    ReplyDelete
  16. @AMFAH: Yes, the tool is only available in a .rfa file. You can't run it in a project (.rvt) or inside an In-Place Mass (as the API is unavailable inside any in-place).

    ReplyDelete
  17. So is the solution by inserting the surface we did in .rfa file to .rvt file to be used in the project?

    ReplyDelete
  18. Hi Zach,
    Do you have an addin file for R2011 and R2012? Thanks :]

    ReplyDelete
  19. Hi Zach,
    I made an addin file for revit 2011 and somehow when i run the command, the Distance parameter remains the same. Same as in the sample file. What do you think is the problem?

    this is what i have for the addin:




    Compute distance to panels
    C:\Documents and Settings\All Users\Application Data\DistanceToPanels\DistanceToPanels.dll
    9F405E24-3799-4b56-828F-14842ABE4802
    Revit.SDK.Samples.DistanceToPanels.CS.SetDistanceParam
    Compute the distance from a selected object to all panels and store in a panel instance parameter

    ReplyDelete
  20. Anyone know how to get this to work in 2012...?

    ReplyDelete
  21. FM,
    The Revit 2012 SDK has this addin as a sample in Massing/DistanceToPanels. Here is the compiled version for 2012. I have not tested this at all, so try at your own risk. http://buildz.info/downloads/DistanceToPanels2012.zip

    ReplyDelete
  22. Hey zack, can you please make a video tutorial for this? I did everything but nothing happens when I click on compute distance to Panels. I really need this for my idea to work. I am mixing few of your tips. Will really be glad to share it with you guys. But I just want to get it working. I installed it via the installer. I double checked the revit.ini file also, checked the paths of the dll file and everything. But still, nothing happens.
    Please help. Need to submit the project in 3 days and only this part is left.

    Regards,
    Cody.

    ReplyDelete