Growth branching pattern

Dear All (Developers, Architects and Engineers),

I am a master student at TU Vienna.

I am working on a housing project , in which I want to add a 2D population of points, then I connect the points with branches that are generated from a seed (an initial point). After this I array my units (houses) on the generated network of lines. At the end I will optimize my results in relation to solar gain using Galapagos.
Unfortunatley I am facing 2 problems with my python script : 1- After adding the populate 2d component and connecting it to python , I get an error or null results when I use the points as a list.
2- Which is the more important, I can’t find the way I add lines between each 2 points after arranging them according to PointArrayClosestPoint in python, I have found an interesting example on design analyze.com, which adds circles on the branches instead of connecting them.
you can find this tutorial here :
[http://designalyze.com/intro-scripting-python-rhino/intro-python-scripting-17-simple-growth-01]
For more obvious picture of what I am writing, kindly check the photos to get my idea

Picture%C3%A41

Hi @kareem2292,

Here is one way of doing the branching with python, although without knowing the constraints its a bit hard to get right. I just grouped by closest point. Maybe this can help you further along.

branchingPaths.gh (6.1 KB)

1 Like

Wow ! that’s great. I just wonder if I want to have a border with a particular shape (ex. triangle or circle) should I do it in python or it can be achieved from a grasshopper component ?.

I would do it with vanilla GH components, since its quick and requires only few components.

You could simply start with your desired boundary curve - which must be a planar, closed curve for this to work -, generate the random points for its flat, rectangular bounding box, and cull the points which lie outside the polygonal boundary edge.

In GHPython, it could look something like this:

rc, plane = boundaryCrv.TryGetPlane() # boundary curve plane
tol = 0.001 # tolerance for point containment check

in_pts = [] # points inside curve boundary

for pt in listPts:
    rc = boundaryCrv.Contains(pt, plane, tol)
    if rc == Rhino.Geometry.PointContainment.Inside or \
        rc == Rhino.Geometry.PointContainment.Coincident:
        in_pts.append(pt)

# continue with the inside points (in_pts) for Lando's script portion

For this to work, you need to add an input, called boundaryCrv with a type hint of Curve to your existing GHPython component.

Furthermore, your picture references above show two distinct systems: Diffusion-limited Aggregation and L-systems, which you could further look into, in order to optimise your script, and maybe avoid path intersections.

3 Likes

trial.gh (6.7 KB)

Thanks very much ! I also hope if you can tell me what’s wrong with this script, as after generating my points and arranging them in order using Array closest point , when I add a line from p to p+1 it doesn’t generate the lines !! I am sorry , I am very beginner in python

for pt in pts:
    print pt

Here you loop over each point in your points list, like so: point 1, point 2, … point x.

If you want to iterate by item count, for instance 0, 1, 2, …, x, you should use:

for i in range(len(pts)):
    print i

Since, you want to add lines between the current and the next point, you could try this:

lines = [] # empty list for the lines
for j in range(len(pts)-1):
    line = rs.AddLine(pts[j], pts[j+1])
    lines.append(line)

You need the list lines to store each new line that is produced in the loop. Other than RhinoPython, GHPython does not add objects directly to the Rhino canvas, at least not like this!

for i in range(len(pts)-1) loops over the integer range from 0 to the length of your point list. If there are for instance five points in the list, your range will look like this: 0, 1, 2, 3, 4
We subtract 1 from the list length, since the last point does not have a next point in the list, which would otherwise cause an error. Your range now looks like this: 0, 1, 2, 3

Inside the loop, you can access the list items/points by index. j is the current point index and j+1 the index of the next point.

lines.append(line) means that you append your new line at each iteration to the external list lines.

1 Like

trial_lines.gh (5.0 KB)

I am sorry for my constant disturbance, actually the code has no errors but it doesn’t generate lines at all :frowning: , I have tried to use cp in my code instead of pts ( as cp is the new list with points arrayed based on distance from my origin point) but actually no way …

It doesn’t work, because cp is only in scope of your highlighted for loop. Outside the loop, it is out of scope and thus can’t be used for further processing. What happens inside a loop at a given iteration expires at the next iteration, unless you save the data inside an outside variable (e.g. list, tuple, string, int, float, #etc.).

Example:

lines = [] # empty, outised list for the lines, generated inside the for loop
for j in range(len(pts)-1):
    line = rs.AddLine(pts[j], pts[j+1]) # new line at each iteration of the loop
    lines.append(line) # new line is saved at each iteration inside the lines list that is outside the loop

Again, you can simply create a new, empty list above your loop, and populate it with the individual, closest points that you find at each iteration of the loop.

closest_pts = []

for i in range(100): # no neep to specify the start of the range if it is 0
    pt = rs.AddPoint(placePt(100, 100, 0))
    idx = rs.PointArrayClosestPoint(pts, pt) # index of the closest point
    closest_pts.append(pts[idx])

What are trying to accomplish exactly?

1 Like

Wow that is an extensive reply, you helped me to gain a whole idea about the logical thinking of scripting. I have tried first to use this lines you wrote:
for j in range(len(pts)-1):
line = rs.AddLine(pts[j], pts[j+1])
lines.append(line) , however they didn’t generate the lines and also the output of points can’t be used seperatley because it is a list of a list (I always get the message: can’t convert Goo to geometry), then I have tried with no reason or logic to use cp, which totally didn’t work also.

I was trying to rearrange my list of random points, according to the distance from my origin point , then I connect each 2 successive points in the list with a line.

Best Regards

To get started with coding in python, gh isn’t your best choice imho. I’d first start by using the Python editor to draw some things to Rhino directly and once you are somewhat comfortable switch to grasshopper as it brings additional difficulty to the mix, like you experienced here.

1 Like

Your points list only includes a single point. This means that the for loop would iterate only once, but since you subtract 1 from the list length of points, it becomes 0, and the for loop doesn’t run.

Your problem with the nested list is caused by your points. They are lists (e.g. [50,50,0]), not points, and if added to another list, it becomes a list of list. The conversion problem is probably also caused by this.

I don’t know if this is exactly what you’re looking for, but it should at least point you into the right direction:

The script looks like this:

import rhinoscriptsyntax as rs
import random

random.seed(1) # fixes a random seed (remove if necessary!)


def random_point(x_range=100, y_range=100, z_range=0):
    x = random.uniform(0, x_range)
    y = random.uniform(0, y_range)
    z = random.uniform(0, z_range)
    pt = rs.AddPoint([x,y,z])
    return pt # guid of the point


# Define your start point
start_pt = rs.AddPoint([50,50,0])

# Generate your random point population
random_pts = []
for i in range(100):
    random_pt = random_point()
    random_pts.append(random_pt)

# Define the current point as a copy of the start point
curr_pt = rs.AddPoint(start_pt)
# Define the temporary random points list as a copy of the random points list
temp_pts = list(random_pts)

lines = [] # list for the new lines generated below
while True and len(temp_pts) > 0: # as long as there are points left to check
    # Find the index of the closest temporary point to the current point
    closest_idx = rs.PointArrayClosestPoint(temp_pts, curr_pt)
    closest_pt = temp_pts[closest_idx]
    # Construct the line between the current and closest point
    line = rs.AddLine(closest_pt, curr_pt)
    # Store the new line in the lines list
    lines.append(line)
    # Set the current point to the closest point for the next iteration
    curr_pt = closest_pt
    # Remove the closest point from the temporary points
    temp_pts.pop(closest_idx)


# OUTPUTS
RandomPoints = random_pts
StartPoint = start_pt
Connections = lines

trial_lines_2.gh (7.2 KB)

1 Like

Thanks Very much , I am sorry for any confusion !

1 Like