How to iterate through multiple object types

I am running into this issue on a couple different, but similar scripts I am trying to develop. I have project sites with multiple AutoCAD Block References being placed on a project site which different variations of the same piece of equipment - basically there is a lot of repetition on these sites. I have been able to generate scripts that work for a single AutoCAD block, but I need this process to be dynamic and adapt to each project. Each project/site will have a varied amount of equipment variations with unique names that I need to be able to accommodate.

To try and give a more specific example, I have a small area that I am trying to generate a fence boundary for. I am trying to generate “surface” of the equpiment boundaries and then offset these “surfaces”, join them, and extract a boundary from them to give me a rough fence line. Below are my current steps on an example project/site with 6 AutoCAD block variations:

  1. Pull property set data of X location, Y location, and block name,.
  2. I then sort through all blocks in the file by using a select objects node
    —Here starts the looping/iterations
  3. I take the first block name, then find the indices from the block name property set
  4. Take the same indicies found in step 3 for X and Y locations to establish the insertion point of those block names
  5. Use the Bounding box nodes min and max values to then generate a new shape from the insertion point found in step 4.
  6. Repeat this 5 more times for each other variation.

Any ideas on how I can achieve this when the next site has different AutoCAD Block names? And when I have more or less than 6 AutoCAD block variations on site?

Attached is my current Dynamo Graph (work in progress, of course). All feedback is welcomed and thank you in advance!
Solar Fence Creation.dyn (176.9 KB)

  1. Instead of any manual selection of block references, get them all (by layer, by object type, whatever means). Then get the block of each, then the objects in rack, then the geometry and create simplified forms if you can (patch closed curves to surfaces; extrude lines on the z axis slightly; union all surfaces into polysurfaces, etc.). Transform the result by the block reference’s coordinate system. You now have simplified geometry for each block reference.

  2. Get all the plots, pull the outline, patch each to a surface.

  3. Use a Geometry.DoesIntersect to test all simplified block reference geometry for intersection with each plot - watch lacing and list levels closely. Filter the block references by the associated test results - remember lacing and levels.

Proceed with your bounding box process (or filter the simplified geometry instead of or in addition to the block references) from here.

Can you attached example drawing

Thank you for the feedback! @jacob.small
I am confused on what you mean by getting “the objects in rack” here. Before I was attempting to isolate the blocks I need to use by utilizing the Select Objects node. I have now switched this step to look for block references on a unique layer (_WORKING LAYER). but I am unsure what my next step would be now.

Screenshot below and .dwg attached for reference.


Solar Fence Generation.dwg (3.2 MB)

Hi @jbrunkhorst,

Is it required to property set data for this? If not, you can just use the Object.Location node to get the insertion point of a block reference directly.

If you’re trying to get the bounding boxes of each individual block reference, it would be simpler to just use the Object.Extents node. The Block.Extents node gives you the bounding box of the block definition in local coordinates. So in your case, this will give a bunch of bounding boxes that are essentially on top of each other near the origin.Object.Extents gives you the bounding box in world coordinates, like this:

I’m assuming this will be more useful for you, as you likely are eventually wanting to generate the fence lines in world coordinates.

1 Like

Pretty sure I meant “Objects in the Block”, but my phone somehow autocorrected my poor typing. I’ll try and put a sample together.

So… I see what you’re up to and I’d like to make a recommendation: In each block put a single 2d polyline which outlines the extent of your equipment on a unique layer. This is far more useful than a bounding box (aligned to the instance or not) as it won’t require building new geometry for each instance (generating 5000 bounding box from 20000 points is going to cause some headaches), and as BOundingBox.ToCuboid generates an invalid solid we can’t rely on that for much of anything. By pulling the polycurves you can generate the shape once per block type, offset it once per block type, and patch to a surface once per block type, and then modify to the coordinate system 5000 times. By using the bounding boxes you get 5000 objects to create, 20000 points to generate, 5000 objects to create, 5000 offsets to perform, and then 5000 patches… a total of 40000 objects in memory - about 800% more.

You seem to almost have this geometry in the blocks anyway (the content on the layers with “(optimized)” in the name), so we can do a quick filtering to get what we’re after.

Sot he steps are:

  1. Get the blocks you want to analyze (either by layer or by name, or name filter, or…).
  2. Get the objects on the block you want to use to perform the analysis. There is likely block.objects > filter by layer process here.
  3. Patch to a surface, union them into one surface, pull and offset the perimeter boundary by your ‘miss distance’, and patch that to a new surface. This is your ‘footprint’ with walkway clearance.
  4. Get the block references for each block (step 1), and pull their coordinate system. Transform the ‘footprints’ by their associated coordinate systems.
  5. Union the footprints into a polysurface, and pull the perimeter curves thereoff. This is the basis of your fence.

@zachri.jensen Oh man, this is gonna save me a ton of time! How do you transfer the bounding box node to a closed curve node to get a shape to display in model space?

A bounding box is a rectangle, so you can just get it’s min and max points and to create a Dynamo rectangle. Then you should be able to create a polyline from that.

Keep in mind, however, that both Object.Extents and Block.Extents are always going to return what’s referred to as an axis-aligned bounding box. This effectively means that it won’t always be a perfect “shrinkwrap” of the block references, unless their geometry is also rectangular without any rotation. That might cause issues when things are not perfectly aligned to X and Y, hence Jacob’s comments above :point_up:

This is what I have so far, and I am unable to get the rectangle to create. It says the points don’t create a valid shape.

Also the time to extract the data to build a surface is excessive. You have to pull the bounding box (quick,e ven for 5000 instances), but then extract and manipulate those points (for rectangle creation there isn’t a “by two points” which I know of so you have to do some XY component value work), and then offset each individual rectangle, and patch it (all time consuming options).

Better to do what AutoCAD does and process the source geometry in the block and go from there. Learn from the best, right?

Anyway, this is my solution:


The areas where it looks like the shapes should union are due to a change in the Z coordinate for the rows - most instances are at an elevation of 5 units and change and the small sections are over 11. Pulling the coordinate systems onto a single plane will resolve that, but I am not sure if that’s desired or not.

The graph:

Note that it does make use of the “Smart Surface Union” which I provided the Python for here: Help Consolidating Dynamo Graphs - #12 by jacob.small

1 Like

This is awesome! Thank you! @jacob.small

I do need it to go one step further and would be curious you would handle that. I realistically need this to generate a border around the whole site (more or less). More like my very rough sketch from your screenshot above (see below). The red line I drew in would need to be 20’ away from the original AutoCAD blocks. I can worry about refining the shape more later, but right now if I increase the offset to a point where the individual colors you see above overlap each other and I would think would allow the smart union to make a larger overall perimeter, it fails at the PolyCurve.ByJoinedCurves with the following error (see below).


  1. Start from the polycurves which were sent to Civil 3D.
  2. Offset those by your 20 foot distance.
  3. Patch those into surfaces.
  4. Use the same Python to merge them into one surface (or a few, depending on the site and spacing between - I have seen solar panel fields on both sides of a highway as one example).
  5. Pull the perimeter curves from that, merge to a polycurve, and send that to Civil 3D as was done in the other part of the graph.
  6. Optionally, set the layer and other properties of the created polylines, or drape onto your surface and such.

@jacob.small

I must be missing something. I have modified the script a bit and attached below that script and the dwg again for ease.

I am trying to offset the perimeter by 50’, now, and I am getting the following error when trying to use the PolyCurve.ByJoinedCurves node. My idea behind the greater offset of 50’, is that that will help remove some of the extra vertices of the boundary, and then at the end I can offset the line 30’ inward to get back to my original 50’ offset.


Solar Fence Generation.dwg (3.0 MB)
Solar Fence Creation_v3.dyn (60.9 KB)

Did you change your geometry scaling off of medium? Cuz this is usually what you get if you change your geometry scaling off of medium. Ignore any warning - that has been changed to an ‘information’ pop up in current builds as it really only impacts geometry display in Dynamo - the real data is clear.

It’s set to medium. I made that mistake earlier haha

1 Like

Try PolyCurve.ByGroupedCurves. Guessing you have an opening in the surface. :slight_smile:

1 Like

You are THE BEST! Thank you, once again, @jacob.small!!!