I want to create 3D pipes that grow from a small base to a larger base, making many turns but only along cardinal directions (taking turns but mostly moving upward and outward). I want a realistic look without self-intersections. Could you please give me some guidance?
After searching up, minimum spanning tree is somewhat similar to this, except the line segments don’t snap to cardinal directions.
MST has rather nothing to do with that. Given a collection of base Pts you should grow in Z (according a random amplitude) and in XY (according also a random amplitude and a random - or restricted - rotation). Clash checks/events (i.e. every candidate axis or Pipe VS the already sampled/valid ones) would been performed either via Trigonometry of classic Ccx Brep/Brep events (waaaaaaay slower). Obviously some clearance value is required as well.
In the past I have written something similar for entirely different purposes (truss weird [and very ugly] columns etc etc) . If you are familiar with C# I could post it (requires some mods - here and there - in order to fully comply with your goals).
I wanted to test an idea combining voxel + shortest walk, then realized it’s probably useless, but kind of fun to play with - a bunch of sliders can be swapped/combined/disconnected - kind of overwhelming lol: walkuprandom.gh (27.3 KB)
The tube paths (Lines and Arcs [fillets]) are sampled on a per DataTree basis (of Type Curve) where rhe 1st dim is the index of the base (start) pt.
Two nested Loops are required: the outer [say via i] is from i = 0 to i < loops (see snaps above) and the inner [say via j] is from j = 0 to j < basePts.Count. If i is even (i.e. i%2 == 0) then we move (randomly) up. If not we rotate (randomly)/move(randomly) in a XY plane. For each zigzag pair we create the Fillet as well with R = radius + filletDelta.
Any candidate path segment should been tested (clash) against all the existed (and sampled) segments. That’s done via a classic while(true) Loop where the break happens if the segment is valid (clash free). Obviously more elaborated questions are required: for instance if we go up and there’s a clash against a segment in XY … this means that the path should become locked (unless backtracing is used - but this is a very simple zigzag thingy so why bother?).
A simple crvA.ClosestPoints(crvB, out pA, out pB) check is OK (where pA.DistanceTo(pB) should be greater or equal to: 2 * radius + clearance).
The fillet radius is tube radius + some filletDelta value. Meaning that the min/max amplitudes (vertical/horizontal) require a pre-check as well.