Refining CAD lines to points to Topo

Hi, I’ve made this to try make a more accurate topo then the Revit import from instance. It dosnt handle retaining walls well. So I’m taking the curves from the CAD import and making points along them to make a topo. However different curves have different lengths and I’m ending up with 38000 points which the prune duplicates is not handling well. Just loads forever. Any of you smart fellas got a better way I can do this? :slight_smile:

Uuuh! That looks good!

Have you tried to check the length of the curves with node Curve.Length and filter those that are shorter than a certain length and add points to the rest?

1 Like

Curve.PointAtSegmentLength might be a better use there. Maybe add a code block to get your distances as well? 0…LengthOfCurve…#(LengthOfCurve / Spacing).

As long as your topo lines don’t touch due to a messy import, and they are polycurves not individual segments, you shouldn’t have overlapping sets so no need to prune.

If that’s still to slow, try using segments of curves, reducing your spacing, or leverage Civil 3D with BIM360 and use the link topo tool.


Thanks Jacob. This sounds really good. I dont understand code blocks enough to implement what your saying though.

Update, hunted forums and found this which is getting the points at a spacing along a curve however getting this error creating topo. Pruning duplicate points is killing the script though. Same with the duplicate curves node I have from somwhere :confused: Trying to find a more efficient way to remove same XY coordinates

Depending on how accurate you need to be, you might try Curve.Simplify to reduce the number of curves/points. You may even want to use it a few times to keep some of the sharper transitions.

1 Like

Issue you’re having now is that some of the curves have a total length that is less than your spacing value. What are your project units?

1 Like


Just had to filter the very short lines out! thank you!

1 Like

Likely you don’t want to discard lines less than 2m long (short is relevant and that’s ‘longer’ than I am tall), So I’m going to give a somewhat wordy description on how to solve this problem using a bit of design script. This more or less follows how I ‘teach’ this content to others in my role at Autodesk, but that’s always done via the phone or in person where I can ‘skip’ stuff that’s readily understood, or elaborate on the parts the user is having difficulty with. Since I can’t get ‘real time’ feed back here I’m likely going more in depth than need be, and as such the format my not be ideal. Hopefully you’ll get something out of it anyway.

That said, let’s learn together. :smiley:

Start by defining the length of each curve. You don’t have to know how to use design script (or any other coding language) to do this thanks to the node to code function of Dynamo. Place a single Curve.Length node and right click somewhere in the workspace (not on a node or group or anything else - aim for the in between bits of space) and select ‘node to code’. You should see something like “t1 = Curve.Length(line1);” or “Autodesk.Curve.Length(line1);” depending on what packages you have installed. The resulting value of that code is is the length of the curve. This is the rather easy part.

Next we need to define the sequence of numbers where we want to take parameter values. This method isn’t a range or a sequence, but a highbred in between which is only accessible via design script. There are 3 bits of coding syntax you need to know which require a specific knowledge gain that is learning some code:

  1. The code S..E..T; builds a sequence of values starting from S, ending before it passes E, stepping by T. So 0…10…11; will give you [0], and 0…13…11; will give you [0,11]. This is the same as a Range node, where if the value didn’t fit it discards the leftover. This ensures your ‘last’ value is equal to or less than the upper limit E. This method is good for figuring out how to place items (parking spots, desks, etc.) in a row using a set distance - if it doesn’t fit then discard the leftover space (you don’t put a parking spot on the neighbor’s lot, or in the classroom next door).

  2. The code S..#C..T; builds a sequence of values starting from S, ending after the number C times, moving by step T. So 0…#3…11; will give you [0,11,22] and 0…#5…11 will give you [0,11,22,33,44]. It doesn’t matter what the upper value is - you’ll get C items spaced T units apart starting at S. This is useful when you have a fixed number of items at a known distance, but (relatively) infinite space to work with (C parking spots/desks in a lot/classroom which will be sized to fit the need).

  3. The code S..E..#C; builds a sequence starting at S, ending at E, and ensuring there are C steps in between. So 0…11…#3 will give you [0, 5.5, 11], and 0…13…#5 will give you [0, 3.25, 6.5, 9.75, 13]. It ensures your start value and your end value are used, while giving you C-2 values in between. It’s useful when you know where you want to end, and how many you want to fit, but the space between in variable (such as C parking spots/desks evenly spaces in a lot/room in a way that leverages both ends).

Since in your case you want to go from 0 units along the curve, to the full length of the curve, we know we want to use a ‘S…E…#C’ method, where S = 0 and C = t1 (remember that is the curve length from before). But the number of values in between isn’t necessarily immediately clear and requires another calculation. So before we define the sequence, let’s figure out that last bit.

Since you know a ‘hard coded’ spacing limit you can divide the total length (t1) by the spacing value (use a new variable not something hard coded), add one (because division is the lines, not the points which define them) and round up. In the next line of the code block define cnt as t1 and divided by s and add one, or cnt = t1/s+1;. This does everything up to the ‘round up’ bit. You likely know that can be accomplished by a Math.Ceiling node, so place that on the canvas, and wire the output from the last line of the code block into it. Select the Math.Ceiling node, right click the background, and viola! you get Math.Ceiling(t1); in a new code block. The important part there is the Math.Ceiling part, as that is how you call the relevant function. Wrap the previous function that defined cnt in that function, and you get the total count. It should look like this cnt = Math.Ceiling(t1/s+1);.

Now that we have the start value, the end value, and the number of values needed overall we can finally move onto building our sequence. 0..t1..#cnt;.

Hopefully that reads well - if not let me know. In this instance I am I’m not giving a screenshot or completed code block as it’s in your best interest to learn this skill - without it you’re handicapping your capacity as a computational designer, process automation expert, and dynamo user. However because it’s typically it’s best to use a sample data set instead of a large complex one I will give you this screen shot that you can use to help build your lines.

Give it a shot and see where you get. I promise to respond if I see something posted (even if it’s just an image of where you got and a statement like I’m struggling and can only get this far - please just give me the code :cry:).


Thank you kindly for your response! I have read everything. When I get some time I will give it a bash. Makes enough sense for me I think and is written well :slight_smile:

Thanks for the kind words. :slight_smile:

I’m here if you get stuck.