# How to pack these curves into rectangle

The objective is to pack as tight as possible, and randomly the irregular curves into the rectangle shape, without using OpenNest as the algorithm leaves many gaps, and sorts the shapes from largest to smallest, which we don’t want.

No overlapping with the rectangle or each other.

curves into rectangle.gh (27.8 KB)

1 Like

Hi,
One possible way to do that could be the classic and simple bottom left to top algorithm.

``````import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

def NestingAlgorithmBFD():
rectangle_id = rs.GetObject("Select a rectangle", rs.filter.curve)
if rectangle_id is None:
return
rectangle_curve = rs.coercecurve(rectangle_id)
curves_ids = rs.GetObjects("Select curves to nest", rs.filter.curve)
if curves_ids is None:
return
curves = [rs.coercecurve(id) for id in curves_ids]
rectangle_bbox = rs.BoundingBox(rectangle_id)
# Sort the curves by their area in decreasing order
curves.sort(key=lambda curve: rs.CurveArea(curve)[0], reverse=True)
positions = [rectangle_bbox[0]]
for curve in curves:
curve_bbox = rs.BoundingBox(curve)
curve_width = abs(curve_bbox[0].X - curve_bbox[1].X)
curve_height = abs(curve_bbox[0].Y - curve_bbox[3].Y)

for position in positions:
if (position.X + curve_width <= rectangle_bbox[1].X and
position.Y + curve_height <= rectangle_bbox[3].Y):
vector = rs.VectorCreate(position, curve_bbox[0])
rs.MoveObject(curve, vector)

position.X += curve_width
break
else:
print("The curve does not fit into the rectangle.")

NestingAlgorithmBFD()

``````

A more complex solution we implement for our nesting platform https://www.youtube.com/channel/UCuzuZ22bHOSt_H0LS1iID_A is a No Fit Polygon (NFP) solution, which can get quite complex, unless you have a valid usecase to justify developing it, It’d be better to stick to exiting solutions (opennest)

When running this through opennest, it sorts from largest to smallest, which is not randomized.

``````

import random
import rhinoscriptsyntax as rs

def NestingAlgorithmRandom():
rectangle_id = rs.GetObject("Select a rectangle", rs.filter.curve)
if rectangle_id is None:
return
rectangle_curve = rs.coercecurve(rectangle_id)
curves_ids = rs.GetObjects("Select curves to nest", rs.filter.curve)
if curves_ids is None:
return
curves = [rs.coercecurve(id) for id in curves_ids]
rectangle_bbox = rs.BoundingBox(rectangle_id)

for curve in curves:
curve_bbox = rs.BoundingBox(curve)
curve_width = abs(curve_bbox[0].X - curve_bbox[1].X)
curve_height = abs(curve_bbox[0].Y - curve_bbox[3].Y)

# Generate random positions within the rectangle bounds
rand_x = random.uniform(rectangle_bbox[0].X, rectangle_bbox[1].X - curve_width)
rand_y = random.uniform(rectangle_bbox[0].Y, rectangle_bbox[3].Y - curve_height)

# Move the curve to the random position
vector = rs.VectorCreate(rs.coerce3dpoint(rand_point), curve_bbox[0])
rs.MoveObject(curve, vector)

rs.DeleteObject(rand_point)

NestingAlgorithmRandom()

``````

As you put this in the Kangaroo section, I’m guessing you’re after something like this

curves into rectangle.gh (37.2 KB)

CurveCollide accepts passive curves for the active ones to collide with, but note that these are always taken as exterior boundaries (we can’t make a rectangular hole from just one rectangular curve).
So here I’ve used a Γ shaped bit above and left of the active curves, and pushed another rectangle up into it to press them together. If you wanted you could add another to also press them in from the right.

4 Likes

I tried to adapt one of your definitions earlier today but couldn’t do it.

Here’s your solution from above with an automated slider:

curves into rectangle.gh (41.5 KB)

3 Likes