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.
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)
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)
rand_point = rs.AddPoint(rand_x, rand_y, 0)
# 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()
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.