Rectangular Compartments
Divide an irregular closed polygon into component Rectangles
Last updated
Divide an irregular closed polygon into component Rectangles
Last updated
def Rect(srf:var[]..[])
{
srf01 = List.Flatten(srf.Explode(),-1);
srf02 = List.FilterByBoolMask(srf01,List.Count(srf01.Vertices.PointGeometry<1>)>3)["in"];
crv00 = srf02.PerimeterCurves();
pcv01 = PolyCurve.ByJoinedCurves(crv00);
vtx01 = List.Flatten(srf02.Vertices.PointGeometry,-1);
//Offset Perimter Curves Outwards
seg01 = 100;
off01 = List.Flatten(crv00,-1)[0].Length/seg01;
pcv02 = pcv01<1>.Offset([off01,-off01]);
pcv03 = List.FirstItem(pcv02<1>);
pcv04 = List.LastItem(pcv02<1>);
pcv05 = pcv03.Length > pcv04.Length ? pcv03 : pcv04;
//Inward Vectors
acc01 = 8;
pnt01 = crv00<1><2>.PointAtParameter((0..1..#acc01));
vct00 = crv00<1><2>.NormalAtParameter((0..1..#acc01));
vct01 = List.GetItemAtIndex(vct00<1><2>,Math.Floor(acc01/2));
pnt02 = List.Flatten(pnt01.Project(pcv05,vct01)<1><2>,-1);
bln01 = List.AllTrue((pnt01.DistanceTo(pnt02)!=off01)<1><2>);
vct02 = bln01 ? vct01 : vct01.Reverse();
//Rectangle aligned to Surface Boundaries
pnt03 = List.Flatten(pnt01.Project(pcv05,vct02)<1><2>,-1);
dis01 = Math.Round(pnt01.DistanceTo(pnt03)-off01,6);
bln02 = List.DropItems(dis01<1><2>,-1)==List.DropItems(dis01<1><2>,1);
fil01 = List.IndexOf(bln02<1><2>,true);
fil02 = fil01==-1 ? acc01 : fil01;
fil03 = List.DropItems(bln02<1><2>,fil02<1><2>);
fil04 = List.IndexOf(fil03<1><2>,false);
fil05 = fil04 == -1 ? acc01-1 : fil04+1;
fil06 = List.DropItems(pnt01<1><2>,fil02<1><2>);
pnt04 = List.TakeItems(fil06<1><2>,fil05<1><2>);
fil07 = List.DropItems(pnt03<1><2>,fil02<1><2>);
pnt05 = List.TakeItems(fil07<1><2>,fil05<1><2>);
lin01 = List.Clean(Line.ByStartPointEndPoint(pnt04,pnt05).ExtendEnd(-off01),false);
bln03 = List.Count(List.RemoveIfNot(lin01.Intersect(pcv01)<1><2><3>,"Point")<1><2><3>)>2;
lin02 = List.FilterByBoolMask(lin01,bln03)["out"];
lin03 = List.FirstItem(lin02<1><2>);
lin04 = List.LastItem(lin02<1><2>);
vct03 = Vector.ByTwoPoints(lin03.PointAtParameter(0.5),lin04.PointAtParameter(0.5));
vct04 = Vector.ByTwoPoints(lin04.PointAtParameter(0.5),lin03.PointAtParameter(0.5));
//Shift edge towards Closest Vertex
pnt06 = List.Transpose(vtx01<3>.Project(lin03<1><2>,vct03<1><2>)<1>);
bln04 = DSCore.Object.IsNull(List.Count(pnt06<1><2><3>)>0)?true:List.Count(pnt06<1><2><3>)>0;
dis02 = lin03.DistanceTo(List.FilterByBoolMask(vtx01,bln04<1><2>)["in"]);
lin05 = lin03.Translate(vct04,List.MinimumItem(dis02));
pnt07 = List.Transpose(vtx01<3>.Project(lin04<2><1>,vct04<2><1>)<1>);
bln05 = DSCore.Object.IsNull(List.Count(pnt07<1><2><3>)>0)?true:List.Count(pnt07<1><2><3>)>0;
dis03 = lin04.DistanceTo(List.FilterByBoolMask(vtx01,bln05<1><2>)["in"]);
lin06 = lin04.Translate(vct03,List.MinimumItem(dis03));
//Largest Rectangle
lin07 = List.Transpose([lin05,lin06]);
edg01 = List.FirstItem(lin07<1>);
edg02 = List.LastItem(lin07<1>);
pnt08 = List.Transpose(List.Transpose([edg01.StartPoint,edg01.EndPoint,edg02.EndPoint,edg02.StartPoint])<1>);
rct01 = Rectangle.ByCornerPoints(pnt08);
are01 = rct01.Patch().Area;
rct02 = List.LastItem(List.SortByKey(rct01<1>,are01<1>)["sorted list"]<1>);
return rct02;
};
def Divs(srf:var[]..[])
{
divs = [Imperative]
{
c = 0;
r = [];
n = true;
s = [];
while (n)
{
r [c] = Rect(srf);
sld01 = Surface.ByPatch(List.Flatten(r[c],-1));
sld02 = Solid.ByUnion(Surface.Thicken(sld01,10));
s [c] = Surface.SubtractFrom(srf,sld02);
srf = List.Flatten(s[c],-1);
n = List.Count(List.Flatten(r[c],-1))>0;
c = c+1;
}
rct01 = List.DropItems(List.Flatten(r,-1),-1);
prm01 = (List.LastItem(List.DropItems(List.Flatten(s,-1),-1)).Explode());
return [rct01,prm01];
}
crv01 = PolyCurve.ByJoinedCurves(divs[1].PerimeterCurves());
crv02 = List.Flatten([divs[0],crv01],1);
return crv02;
};