If I have an outer rectangle and need to create some of the small inner rectangles by random without intersecting each other
what is the best workflow to do that?
If I have an outer rectangle and need to create some of the small inner rectangles by random without intersecting each other
what is the best workflow to do that?
Two options are below.
Make it pseudorandom. Divide your surface into a 2 way grid and inset boxes in each cell by random ranges. This means no rectangle could overlap as they are bound to their cell.
Use Python and a while loop to generate shapes iteratively and test for intersections each time. If one occurs omit it from the results and keep the loop going until a desired number of rectangles are made. Quite complex and dangerous assuming you ask for too many rectangles to fit. Make sure to use an overload counter concurrently ro set a maximum number of iterations to run.
If 2 doesn’t make any sense I’d focus on 1 as it can be done without Python.
One need not use Python, but imperative Design Script would be a pre-req for the alternative.
You could also use some bin packing nodes followed up with a light relaxation algorithm to space them out. Without seeing the base inputs and constraints it is tough to give better guidance though.
Thanks for your reply, if this option need design script
I invite design script leader @Vikram_Subbaiah to help me for that
Will certainly contribute if I can, but as @JacobSmall suggested above, you will need to outline the goal better. Providing some context and samples of your attempts will help the rest of us understand your objective.
I may fold a similar exercise into a coming webinar. If so I will drop a definition which could get you started later.
Something to try:
def populateRectangles (srf,count)
{
rectangles = [Imperative]
{
attempts = 0;
results = [];
while (DSCore.List.Count(results) < count && attempts < 10)
{
attempts = attempts +1;
csSet =
Surface.CoordinateSystemAtParameter(
srf,
Math.RandomList(count),
Math.RandomList(count)
);
rects =
Rectangle.ByWidthLength(
Math.RandomList(count/2),
Math.RandomList(count/2)
);
rects =
Surface.ByPatch(
Geometry.Transform(
rects,
csSet
)
);
rects = DSCore.List.Join([results, rects]);
set = [];
for (i in0..DSCore.List.Count(rects))
{
set =
List.AllFalse(Geometry.DoesIntersect(rects[i],set))?
DSCore.List.Join([set,rects[i]]):
set;
};
results = set;
};
return = results;
rectangles = Geometry.Intersect(rects,srf);
};
rectSet = DSCore.List.Flatten(Geometry.Intersect(rectangles, srf),-1);
return = rectSet[0..count-1];
};
Having some formatting errors (posting from my phone due to some internet issues), but the actual definition can be seen in this screenshot, where I placed up to 1000 rectangles in a 5x5 square.
Wizardry. I stand corrected - glad to see someone proposed an option 3!
Awesome, Jacob
Scaled rectangles in a grid to create this …
rectSub.dyn (11.6 KB)
// Dimensions
wdt01 = 50;
lgt01 = 50;
cnt01 = 100;
// Divisions
are01 = wdt01 * lgt01;
sqr01 = Math.Ceiling(Math.Sqrt(cnt01));
prp01 = wdt01/lgt01;
wdv01 = Math.Ceiling(sqr01*prp01);
ldv01 = Math.Ceiling(cnt01/wdv01);
// Scaled
rct00 = Rectangle.ByWidthLength(wdt01,lgt01);
rct01 = Rectangle.ByWidthLength(wdt01/wdv01,lgt01/ldv01);
rct02 = rct01.Translate((-wdt01+(wdt01/wdv01))/2,(-lgt01+(lgt01/ldv01))/2,0);
rct03 = List.Flatten(rct02.Translate((0..#wdv01..(wdt01/wdv01))<1>,(0..#ldv01..(lgt01/ldv01))<2>,0));
rnd01 = Math.RemapRange(Math.RandomList(List.Count(rct03)),0.3,0.9);
rnd02 = Math.RemapRange(Math.RandomList(List.Count(rct03)),0.3,0.9);
pln01 = Plane.ByOriginNormal(rct03.Center(),Vector.ZAxis());
rct04 = List.TakeItems(List.Shuffle(rct03.Scale(pln01,rnd01,rnd02,1)),cnt01);
// Third Dimension
rnd03 = Math.RemapRange(Math.RandomList(List.Count(rct03)),1,5);
rnd04 = Math.Ceiling(List.Chop(Math.RemapRange(Math.RandomList(List.Count(rct03)*3),0,255),List.Count(rct03)));
clr01 = Color.ByARGB(200,rnd04[0],rnd04[1],rnd04[02]);
cbd01 = rct04.ExtrudeAsSolid(rnd03);
cbd02 = GeometryColor.ByGeometryColor(cbd01,clr01);
[rct00,cbd02];
Another Pythonic alternative
import sys
import clr
import System
import random
import math
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('DSCoreNodes')
from DSCore import *
clr.AddReference('GeometryColor')
from Modifiers import GeometryColor
def generator(container, nbr = 1, ratioMax = 5):
outrect = []
bbxcont = container.BoundingBox
minPoint = bbxcont.MinPoint
maxPoint = bbxcont.MaxPoint
w = maxPoint.X - minPoint.X
h = maxPoint.Y - minPoint.Y
minDim = minPoint.DistanceTo(maxPoint) / nbr
minSurf = (w * h) / nbr
i = 1
while len(outrect) < nbr and i < 200000:
pta = Point.ByCoordinates(random.uniform(minPoint.X, maxPoint.X ), random.uniform(minPoint.Y, maxPoint.Y ), 0)
ptd = Point.ByCoordinates(random.uniform(pta.X, w/nbr), random.uniform(pta.Y ,h/nbr), 0.1)
bbxCandiate = BoundingBox.ByCorners(pta, ptd)
w1 = bbxCandiate.MaxPoint.X - bbxCandiate.MinPoint.X
h1 = bbxCandiate.MaxPoint.Y - bbxCandiate.MinPoint.Y
if any((x[0].Intersects(bbxCandiate)) for x in outrect) or w1 * h1 > minSurf or w1 / h1 > ratioMax or h1 / w1 > ratioMax:
pass
else:
geom = bbxCandiate.ToCuboid()
color = Color.ByARGB(255,random.randint(0,255),random.randint(0,255),random.randint(0,255))
objColor = GeometryColor.ByGeometryColor(geom, color)
outrect.append([bbxCandiate, objColor])
i += 1
pta.Dispose()
ptd.Dispose()
return outrect
container = IN[0]
OUT = generator(container, IN[1])
Nice use of bounding boxes.
Now i have 3 option
Wow, awesome community here
cool!