Parameter Values From Image for Dynamo

Apparently the ParameterValuesFromImage plugin for Vasari has been discontinued as of Vasari Beta 3. So I thought I'd try to recreate its functionality using Dynamo. Zach kindly included one of the first versions I made in one of his latest blog posts so it's time I shared this on the forum. As far as I know, Dynamo currently doesn't support populating a divided surface with pattern-based components, so I decided to go with adaptive components instead.


Here's how it works:



  • Choose number of elements in U/V direction

  • Choose a distribution algorithm (regular or by formula)

  • Select a surface

  • Select an adaptive component family to be distributed across the surface

  • Specify the name of the instance parameter of the AC that is to be driven by the data from the image

  • Point Dynamo to the path for the image file


Known limitations:



  • Distribution by formula so far only works on non-planar non-revolved surfaces (planar and revolved surfaces use different range of UV coordinates)

  • The Z-axis of AC's will currently always point upward (due to the placement method by XYZ coordinates instead of host geometry) so expect some weird results on vertical surfaces


The workspace needs some custom nodes that need to be copied to your definitions folder (typically C:AutodeskDynamoCoredefinitions) or at least that's how I think this works.


I will update this thread whenever I make changes to this workspace.


Feel free to suggest additional functionality or improve this node yourself and share it here.

Just a quick update.


As I learned here the other day, you can actually get all the panels on a divided surface - so I created another definition that does just that (which is much simpler than my original example posted here). The trick is to select the underlying face or form element when using the Select Divided Surface node - that'll give you a list of panels (even formatted into separate rows).


And as I learned yesterday, there's a new example (#20) in the latest daily Dynamo builds that feeds all kinds of data into a divided surface.


I also updated the original examples that work with adaptive components because Dynamo now allows us to place adaptive components by face (based on a UV value) - which means that they will inherit their point position from their host object (i.e. the surface normal).


Enjoy.

I got this email regarding the PVFI definition yesterday and thought I'd share my reply here as it's an interesting question:


I have used your file and had success but not in changing the color/material of the family. Now I'm stuck and trying to figure out how to produce the outcome I want.

Currently, working with materials in Dynamo is still a bit difficult - although that is probably going to change in the foreseeable future.


In the meantime, we can use an old Revit trick to control family materials parametrically.

The basic problem here is that material parameters cannot be controlled by formulas.
To circumvent this limitation, we will have to use a nested family structure and use family types to control the material as family types can in turn be controlled by formulas.

Assuming you already have your family set up, here's how it works:

1. First make sure that your material parameter is a *type* parameter.

2. Let's say you want to be able to parametrically assign three different materials to your geometry. In that case, create *as many* family types and assign a *different* material to the material parameter for each one.
3. Create a new adaptive component with the *same* amount of placement points as your family.

4. Load your family into the new AC and place it on the placement points.

5. Select your placed family instance and use the options bar to set up some family type (curtain panel) parameters: Create *as many type parameters* as there are family types in your nested family (in our case three: T1, T2, T3). Lastly, create *one instance parameter* that will remain assigned to the placed family instance - let's call it PanelType.

6. In the family types tool, create a number parameter as *instance* parameter (let's call it "controller").

7. Now add a formula to your PanelType parameter that will enable the controller parameter to drive the panel type of each family instance, like this:

if(controller < 1 / 3, T1, if(controller < 2 / 3, T2, T3))


Of course, if you have more than three types, you will have to nest more conditions.

And that's it.

A few days ago I received an email regarding this workspace with the following question:

Thank you for posting your work on the “Parameter Values From Image” Dynamo definition. I am stuck on what you have done in the ‘NormalizedSequenceByFunction’ and the ‘DropLastRowAnd ColumnFromUVField’ as I know they are custom nodes. Would you be willing to share a bit more of what you have done?



As I thought this might be interesting for others as well, I am posting my reply here.

First of all, the custom nodes actually contain comments, but for some reason they are invisible - I issued a bug report (#233) for that.

Here's a quick explanation of what the custom nodes do:

NormalizedSequenceByFunction

This contains another custom node simply called NormalizedSequence, so I'm starting with that one.


It will simply create a number sequence of N elements between 0 and 1. In Revit/Vasari conceptual modeling, values between 0 and 1 are great for controlling the position of a point on a curve or as a U or V coordinate on a non-planar non-revolved surface. (Planar and revolved surfaces unfortunately use a different range of coordinates)

The NormalizedSequence node can either be used on its own (if you want to have a regularly spaced list of values) or you can use the NormalizedSequenceByFunction node instead (that contains the NormalizedSequence node).

This node uses a Map node to feed the number sequence from the NormalizedSequence node into a function to achieve a non-regular distribution of values between 0 and 1. The easiest way to customize this in Dynamo is by using the Formula node as a function - in the example file the formula sin(u*pi/2) is used (which is a quarter of a sine cycle). The idea here is that you can use any formula that will return values between 0 and 1 for inputs between 0 and 1. Another example for that would be (cos((u+1)*pi)+1)/2 (giving you half a sine cycle). If you want to reverse the resulting sequence just subtract the formula from 1, e.g. 1-sin(u*pi/2).

In our AU2012 class "Echo Chamber: Complex Parametric Arrays in Autodesk Revit" (http://au.autodesk.com/?nd=event_class&session_id=10274&jid...), there's also an example of using the arcus tangent function (have a look at case study #2).

BTW: I always use a graph editor when trying out new formulas. I'm on a Mac, so I just use the Grapher app that comes pre-installed with Mac OS X, but I'm sure there's similar software for Windows.

DropLastRowAndColumnFromUVField

When building sublists from a UV grid of points, you will notice that the last elements in the list have shorter sublists.

That is because at the end of the UV grid (or to be more precise: in the last row of the UV field), Dynamo runs out of points to include in the sublist. You can visualize this by hooking up a Curve By Points node to the Build Sublists output.

You will also notice that some of the curves will connect points on one end of the grid to points on the opposite end of the grid. This happens in the last column of each row.

And that's why we need to trim the fat from the list: get rid of the last column and row of the UV field - and what remains are only the "correct" groups of XYZs for the adaptive components.

Enter the DropLastRowAndColumnFromUVField node...

Dropping the last row is fairly easy, just subtract U from the total number of elements in the list (U*V) and use the Take From List node to keep the rest.

When I created the workspace, there was no node available that would remove every Nth element from a list, so dropping the last column was a bit more complicated. My first approach was to use a recursive node, but that proved to be a performance killer (and not a very elegant solution for an essentially trivial problem). Instead I now flatten the list (which by now should only consist of multiples of the number of placement points P), create new sublists for each row (subtracting the last P points for each row in the process), flatten it again and build sublists of P elements again.

And that's it.

Apparently there is now a node that can remove every Nth element from a list (see issue #301), but I haven't tested yet whether it works with sublists. If it does, I'll post a new version of the workspace fairly soon.

cool, i actually never tested whether it would work with other configurations. i just assumed it would... ;-)


thanks for posting this.


i suspect you would have to make some changes to the DropLastRowAndColumn node to make it work for larger elements like the half-step pattern.






here's my little contribution, with a sample of 3 points AC setting

whaou...thanks for the lesson. lot of stuff to grab from this sample. many thanks.

Here's a variation of the workspace, this time driving family types instead of numerical parameters, i.e. if it's a dark pixel use component X, if it's a light pixel use component Y.


It works pretty much the same as the Parameter Values From Image workspace, but you'll have to choose two adaptive component family types and then use a slider to determine the threshold of when a pixel is counted as black or white. It also has the same limitations as the PVFI workspace.


This workspace might come in handy when divide & repeat patterning can't do the job because you have a highly irregular pattern that simply cannot be repeated.


While creating it, I learned a lot about how to use the IF node in conjunction with lists and, on a more general level, how functions work in Dynamo. Stephen Elliott took the time and wrote a great explanation that was really helpful.


This example only uses one custom IF node, but it could of course be cascaded to allow for more than two conditions.

1 Like

:-)


Well, the Dynamo team are my heroes. The pace of development is simply staggering!


And you're right, this method allows for other kinds of inputs as well. Plus, it can also be used to drive non-numerical family properties - I'll post an example for that later today.

Andreas,


First, is awesome and you are my hero.


Second, one interesting thing to note here is that you can use this same method to pipe just about any kind of data from an external source to family instances. That is, if you have a spreadsheet, you can write to this set of ordered family instances by using the "File Path" and "Read File" node to bring in the data, then parse it as you like.