I could use some help from the big guns.
I’m trying to find a polyline that is entirely within a closed polyline. Essentially, I’m trying to capture the Time of Concentration path within a drainage area.
I looked through the massive list of packages for something that might exist to help, no luck. 
Through some roundabout searching I was led to a youtube video about the Point in Polygon problem, which led me to Dalton’s git repo (GitHub - DaltonGOO/All-Sorts-of-Dynamo-Scripts: This repo is a place for Dynamo scripts created based on the Intro to Parametric Modeling series from the ParametricCamp YouTube channel.). I thought I’d be able to reuse this to at least find that the points are inside the polygon, but I want to ensure the entire polycurve is inside the polygon. This, I think, would just be checking that the polycurve doesn’t intersect the polygon.
Here’s a copy of that first attempt, separated out as a custom node, since I was trying to condense down what I was working with.
PointIsWithinPolyCurve.dyf (26.9 KB)
So far, this isn’t getting me where I need to be. I’m hoping someone might have done something like this already and can help either point me in the right direction or tell me it can’t be done. I’m already leaning toward just developing another custom node that will do this, but I’d rather be able to have a graph if possible.
I have no idea what a ‘Time Of a Concentration Path’ is, but I think I can help. Would love an explain like I am five on it, doubly so if what I describe doesn’t seem to work for some reason.
I’m going to assume you can convert your Autocad PolyLines into PolyCurves here.
Given a set of PolyCurves, you can:
- Sort them by SurfaceArea
- Reverse the sort order
- Remove the outermost polycurve using a List.Deconstruct node.
- Patch the largest polygon into a surface.
- Get all polycurves inside of it using a Geometry.DoesIntersect and a List.FilterByBoolMask method. Anything which touched the surface is ‘inside’ the boundary of the original polycurve; anything that didn’t intersect the surface is not part of the set - pull it aside for later.
- From the remaining ‘in’ PolyCurves we can also filter out anything from the which touched the original largest polycurve using a Geometry.DoesIntersect method and a Not method as the mask for another List.FilterByBoolMask node. The stuff in the ‘out’ can be added to the list we put aside again.
- Anything remaining in the ‘in’ is completely inside the original polycurve.
- The remainder have a different ‘largest containing PolyCurve’ or cross a containing PolyCurve and I think therefore need to be unique ‘outermost’ containers of their own.
- Now for the hard part: you need to iterate over steps 1-8 until there are no more items in the ‘set aside’ list and report each container with all of it’s nested PolyCurves. This can readily be done using a while loop inside an imperative design script function; recursive use of a DYF node; Python; or a zero touch node written in C#. As far as which of those to work with, your personal preference will dictate the best method. For ‘just get it done’ I would go with Design Script. For ‘quick deployment’ I would go with Python in a custom node. For longevity and ease of use for users consuming your content zero touch.
I guess there’s potentially a lot baked into that statement (slope of the path, surface cover, etc.). Are you purely just looking at it as “what’s the longest flow path within the catchment”? Something like this perhaps…
3 Likes
That would actually be a great one to add in to the work flow, but what I was originally looking at was when we already had that path drawn manually, I wanted to be able to determine which path was inside the drainage area.
End goal of this specific workflow would be to automate creating the catchments with their flow paths.
I’m not understanding the first 3 steps. Not sure if I need those steps since I have all my drainage areas (closed polycurves) as one list, and all the paths as another list of polycurves.
So I skipped those and then created surfaces from the closed polycurves of the first list.
Using the DoesIntersect node, using the surfaces as the geometry and the polycurves as the other input, I get all false even though I can verify manually they are within the surface area and on the same plane.
So far, this is where I am with the graph replicating your steps:
Here are my working files.
You’ll need this specific version of Camber (which I’ve done some local mods to) in order for the graph to work 
Drainage Area Map.dwg (1.0 MB)
Set Tc on Parcel UDP.dyn (76.0 KB)
Camber.7z (431.4 KB)
1 Like
What? No fork and PR? 
Are we in 2024 or 2025 or?
lol. I’ve forked it, just haven’t pushed anything back until I’m happy with the output 
This is in 2025.
1 Like
Seeing this graph helps alot as I didn’t understand the assignment… Seeing this it feels like it’s more around “which closed polycurve contains each open polycurve”.
This should get you started, and if not I’m likely misunderstanding what you’re after so some further clarity on the goal might be required (removing the industry speak):
Set Tc on Parcel UDP_jws Edit.dyn (70.1 KB)
That is super helpful Jacob! I really appreciate the help 
Do you have any suggestions for how I can correlate those areas and internal polycurves back to the original source area? My end goal is to apply data derived from those paths to the original object or another object created from it.
Follow the instructions on the Pink area - you can filter the parcels instead of the geometry thereof as you have an association there. You also have an association to the original polycurves if you go back to those instead of the geometry. As a result you can push data from A into B as desired.
Duh. I misread that lol.
That works for getting me further along. Again, thanks a ton 
1 Like
I want to share the results of this work.
Ultimately, with this graph, I’m wanting to calculate the Time of Concentration in a drainage area, from just the paths previously drawn by the user. We use Parcels for those drainage areas, so we have to do some conversions, hence the custom Camber node provided earlier (PR submitted
).
This graph will do a basic Sheet Flow and Shallow Concentrated Flow calculation, based on the line work drawn inside a Parcel’s limits (thanks to @jacob.small for help on that part).
Once it works out which parcels have paths, it needs a surface from which to extract elevations for slope calculations. If the paths aren’t on the surface, it’ll provide a minimum slope. The SCF segment is defaulted to Paved and with a little work analyzing for crossing material types, it might be able to switch between Paved/Unpaved, but that’s for later 
I also have it check against a minimum Tc requirement and finally applies the Tc back to the original Parcel’s UDP.
Set Tc on Parcel UDP.dyn (189.3 KB)
3 Likes
our company has broken this workflow down into these discreet steps (see image). This way we can start/stop at any point in the process as project conditions change.
I don’t believe the “software is there yet” to auto calc T(c). I could go further into this, but have concluded this after personally investing many many hours trying to solve. Then having lengthy discussions with various people at my company and at Autodesk.
We are working on a custom python script that “do a water drop per each basin”. However, I think this effort will end in failure based upon the complexity of this task. “Limiting the Area of a Tin Surface” requires that you modify tin surface triangles. And this opens up pandoras box of problems which make this a bit too much for anyone except the smart people at autodesk…at this is not currently on the product roadmap.
Which brings me to my recommendation to my friends at the Civil Community table.
At the end of the day, most catchment areas have a 6min T(c), and those that are greater than 6mins require manual view. So if you just set them in the “half baked” that my friend Adamm has done (or the way the attached script is provided you have the '26 beta installed). It is prob “good enough”.
If you dive deep into this script you will see where we have contemplated other more complex methods. But the script currently creates a flow path that is the furthest distance from the reference structure. This get 75% of the catchments automatically. Then final 25% are prob gonna be manual reviewed anyway.
Hope that helps.
04 Catchment - Set Flow Path.dyn (766.6 KB)
the use of the same methods that my friend Adamm has done (which I think is a great method).
1 Like
It looks like you’re a bit further along than I am with all this 
I appreciate the background and thoughts too. I also think we’re still too far from having it auto analyze and create things for us, so I want to keep it up to the technical staff to do that and just take out the tedious part of round tripping the data (extracting the data into the calculations, putting the results back into the model).
So far, I’ve gotten to the point that I can extract impervious cover areas to develop the C value per drainage area, and now the Tc based on provided paths.
My next step is to convert our drainage areas to catchments and assign the Tc paths and appropriate structures to them, in preparation for streamlining the analysis steps.