A packing procedure for placing and individually rotating packed objects onto a partitioned floor pattern to avoid intersections. Parameters for scaling and offsetting the pattern, cell padding and the maximum rotation angle.
The pattern code is taken from this example: https://procegen.konstantinmagnus.de/non-overlapping-tiles
The pcfind
-function is used to select objects that match the individual tile sizes: pcfind(1, 'shape', size, 10.0, 10);
// PARAMETER
float pad = chf('padding');
float angle_max = chf('max_angle');
// SIZE
vector size = getbbox_size(0, itoa(i@primnum));
size -= set(pad, 0.0, pad);
// ANGLE
float angle = (rand(i@primnum, 123) - 0.5) * angle_max * 2.0;
float theta = radians(angle);
float cos_theta = abs(cos(theta));
float sin_theta = abs(sin(theta));
// ROTATED SIZE
float x = size.x * cos_theta + size.z * sin_theta;
float z = size.x * sin_theta + size.z * cos_theta;
vector size_rot = set(x, 0.0, z);
float s = min(size.x / size_rot.x, size.z / size_rot.z);
size *= s;
// FIND SIMILAR SIZES
int num = npoints(1);
int pts[] = pcfind(1, 'shape', size, 10.0, 10);
// FIND BEST MATCH
int pt_near = -1;
foreach(int pt; pts){
vector shape_pt = point(1, 'shape', pt);
if(shape_pt.x < size.x && shape_pt.z < size.z){
// NAME
string name = itoa(pt);
int pt_add = addpoint(0, v@P);
setpointattrib(0, 'name', pt_add, name, 'set');
// ORIENTATION
matrix3 m = ident();
rotate(m, theta, {0,1,0});
vector4 orient = quaternion(m);
setpointattrib(0, 'orient', pt_add, orient, 'set');
// GROUP
setpointgroup(0, 'pivots', pt_add, 1, 'set');
break;
}
}