I am new to dynamo, have used python a bit. I am attempting to automate a process in Civil 3d by using dynamo and possibly python or vba. I begin with a file such as this
The blue and white are reference blocks (cannot assume on same layer) which will be used as reference points for my cad block created in another file. The green are other block references (therefore cannot just grab all block references)
2 cases for block placement:
(Not optimized) 1 block reference overlaying the current block references (sometimes the block references extend past the given block references which is ok)
(Optimized) must use length of row from given file and match to the best fit row of mine ! (image a triangle of lengths of cad blocks)
In civil 3D, general procedure is
check that given block reference and my cad block both in feet (sometimes given reference block drawing says its in feet, but when compared to my cad block, it is in meters or inches) *we can skip this part in code because its fairly easy to manually check but in the future would like this to be apart of it)
click block reference, and select 2 different types of polyline, right click select similar,
copybase point 0,0,0 and paste into new dwg with drawing template
save the file per parent folder/ excel inputs
Open new dwg and creating my reference block using .scr
Determine whether case 1 above or case 2
Case 1: copy and pasting my blocks over the other blocks using bottom left corner
Case 2: copy and pasting my blocks from triangle that are best fit (usually very close fit)
load lsp file, run specific command i call T_Analyze
Update drawing space from excel file
My thoughts in creating this in dynamo:
Select Object to pick supplied reference block
Select Object boxes to pick major and minor polylines i need
python code to select similar like in civil 3d
python code to copybase like in civil 3d, paste in new file with my dwg template
pick reference block again or have them all saved on certain layer, obtain left most bottom point and right most bottom point
Ask user if optimized or not
if not optimized, grab my reference block from another dwg
if opt, used triangle of blocks from another dwg
would likely measure the length of the cad blocks that are next to each other using the reference points, then going through an array of lengths for my cad block lengths, choosing best fit, copy and paste using bottom left reference point
Python to load .lsp file and run command? not sure on that one
If you have any questions let me know and I appreciate any assistance you could provide, because this has been quite a challenge for me thus far
Welcome! This is quite complex indeed. I’ve read through a few times and still have a little trouble understanding. Would you be able to upload the applicable sample DWGs and also a screen recording of the current process?
unfortunately i cannot provide dwgs. to start off, just create rectangles and make them block references. then create a new rectangle nearly the same size with a plus inside it to represent my reference block. if the provided reference blocks are very close that is a row, more than 25 ft of space would be considered a new row. if you replicate my image (each box is own reference block), and if your familiar with civil 3d you will know the select similar and other references. I tried to be as clear as i could be. if you have a more specific question, im happy to answer it. i know how to perform this in civil 3d well, it is replicating civil 3d commands in dynamo to automate the process that I am having the most difficulty with. So if you know any part of this, for example, breaking down a reference block to find the bottom left point and bottom right point, then just answer that question/ part. if we all work together, perhaps we can solve this thing.
OK following are some quick thoughts. I recommend that you download the Civil 3D Toolkit package (I’ll refer to it as “Toolkit”) if you don’t already have it.
Sounds like you’ve got this part - use the Select Object node. There is a node in the Toolkit to select multiple objects if you want to try and consolidate to one step for the user.
I think there could be a non-Python solution for this. If there are pre-set layers that you know ahead of time (or the user can provide them), then you can use the All Objects on Layer node to build the selection in Dynamo. There are other approaches too, like just selecting everything in modelspace and then filtering the list in Dynamo by the properties that you want (layer, linetype, property sets, etc.). The List.FilterByBoolMask is a go-to for this.
This will be tricky. Dynamo currently only works with the current DWG. You might have a look at the Python code @Paolo_Emilio_Serra1 wrote in this post:
It looks like your block references are rectangles. If that is true all of the time, then I think the Bounding Box nodes will work here. You can use Object.Extents to get the bounding box for the block references, and then use BoundingBox.MaxPoint and BoundingBox.MinPoint to get the corner points. There might also be opportunity to utilize the block reference insertion point, which you can get with the Toolkit node BlockReferenceExtensions.GetInsertionPoint.
This will take some work as well. The easiest way to get user input is to run the graph via Dynamo Player, but this means that all of the inputs have to be provided at the start. If you want to collect user input at an intermediate step, I suggest looking into the UI.MultipleInputForm++ node from the DataShapes package.
I’m thinking you could use the Block.Import node here.
Here is some quick Python code to send a string to the command line:
import System
from System import *
input = IN[0]
app = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application")
adoc = app.ActiveDocument
adoc.SendCommand(input)
OUT = str(input) + " sent to command line"
i do have the toolkit and a few others i told were useful
muti object select might be better, but there are lines in the background that could potentially get grabbed which is why i wanted to replicate select similar
I am originally given this file not knowing what layers are on it. I guess i could make a prestep as select object, select similar, place on layer of my own name and then begin automation, but again just seeing if it is possible to automate this as well, assuming they are not all on same layer as worst case scenario
i will check out paolo’s code, thanks!
I will try bounding box nodes, thanks!
Regarding user input, i will include that when the person is choosing reference block
block import will bring it into the current dwg which is great, but then i have to put them in the right place. also in the optimized there are 100 blocks, so it may get confused which to use. maybe you could clarify further how we could achieve both these situations (lets just assume right now i brought in my cad block or cad blocks triangle into current dwg)
That is awesome regarding sending command through python code, i think this will help the most!
Great great start. this definitely pushes me in the right direction, thanks @zachri.jensen
Once the block is imported to the current DWG, you could create coordinate systems at the desired insertion points and then use BlockReference.ByCoordinateSystem. In my experience this works better than BlockReference.Create.
This may work for non optimized, will have to test and see. one of my problems here is that the dwg file name will change depending on project. In my filepath I have C:\Users\username…*# - Proj name - client*\folder1\current cad dwg. I need to take out the part between the stars so i can automatically generate the cad dwg name. I have done this using an scr file, but dont know how to replicate in dynamo
for the optimized solution, my block reference file looks like this
my thought was to somehow copy paste from this dwg pictured to my current cad with the block references. I then thought of making each string into an array of distances. I would then measure the distance of the given row of reference blocks, and then check the array to see which is the closest, then follow the insertion method you described above. Thoughts?
which says it runs but i see no surface in my civil 3d (Not sure if i should create a new topic for this because it is still apart of this same large project)
Regarding block import you suggested, says value is null. should dwg file name be with .dwg or without?
So i tried an alternate approach using LinkDwg package. I tried both InsertExternalDWGAsBlock and a combo of ImportBlockFromDWG and InsertByName. neither seem to be working.
Last thing, i am trying to read code of existing dynamo library nodes, specifically the BlockReference.ByCoordinateSystem node, i found this forum post, but still struggled finding it
Any advice on these? Any help would be appreciated
That sequence of nodes would be looking for all of the block references of the Model Space block, which there are none. To get all the block references in Model Space, use Block.Objects and filter out everything that isn’t a BlockReference object using List.FilterByBoolMask.
Thanks for sharing the files. You’ve done a great job outlining the details of what you’re trying to accomplish, but I am a little unclear of the end goal. All of the steps you mentioned previously will become important when considering the details of the algorithm, but it would help my understanding if we can step back a little bit and look at the big picture.
First I’m going to break down what I am seeing (i.e. the inputs to the problem).
In TEST_Dynamo.dwg, it looks like there is a grid pattern of solar panels arranged on a topo surface with relatively consistent spacing. Furthermore, they seem to be arranged so that they fit within a boundary. Is this a correct assumption?
This is not always the case. what we know is that from most likely the insertion point is bottom left corner and looks like a square from top view, they are block reference with any name (unknown)
we can change insertion point of this file, but considering the block is being copied and pasted, it doesnt really matter where insertion point is.
Take a received dwg that has lets say 100 block reference in any formation (unknown) (provided dwg is one possible formation) and insert my block reference at same points. The end goal of this is a slope analysis => convert poly line to Tin surface. Place my cad blocks in same locations as given. Then run .lsp and run a specialized command i created. this completes the program.
Does that help? If you want, i can send you a video privately that does the steps in civil 3d (if that helps)
OK so the constant point we always want is the bottom left corner of the objects within the block, not necessarily the insertion point?
You are wanting to copy/paste this so that the lower left corner matches the point mentioned above, correct? If so, then I think the insertion point does matter and we should put it in the lower left corner so it is easier to line up.
OK I am starting to understand better now, thanks! Yes, if you’re able to send a recording, that would be very helpful.
yep you got it. i want the bottom left of the lines in the bock reference, i was just trying to make it easier by using insertion point. I am basically doing a block replace but keeping the old blocks so i can check for error. also sometimes the provided block reference do not match exactly with my block reference width, in which case neither insertion point or bottom left of block reference would work. I would have to take the total distance of one row, then measure my block width with a half of a foot spacing and get the closest approximation. but again, i am trying to start with the simplest solution. The main question is in my code, why is block reference from other dwg not being brought in and placed at locations from dynamo.