/// <summary> /// Divide a grid by a pattern of lengths. Type names will be automatically generated, repetition will be governed by PatternMode, /// and remainder handling will be governed by DivisionMode. /// </summary> /// <param name="lengthPattern">A pattern of lengths to apply to the grid</param> /// <param name="patternMode">How to apply/repeat the pattern</param> /// <param name="divisionMode">How to handle leftover/remainder length</param> public void DivideByPattern(IList <double> lengthPattern, PatternMode patternMode = PatternMode.Cycle, FixedDivisionMode divisionMode = FixedDivisionMode.RemainderAtEnd) { var patternwithNames = new List <(string typeName, double length)>(); for (int i = 0; i < lengthPattern.Count; i++) { patternwithNames.Add((StringExtensions.NumberToString(i), lengthPattern[i])); } DivideByPattern(patternwithNames, patternMode, divisionMode); }
/// <summary> /// Divide a grid by constant length subdivisions, with a variable division mode to control how leftover /// space is handled. /// </summary> /// <param name="length">The division length</param> /// <param name="divisionMode">How to handle leftover / partial remainder panels </param> /// <param name="sacrificialPanels">How many full length panels to sacrifice to make remainder panels longer.</param> public void DivideByFixedLength(double length, FixedDivisionMode divisionMode = FixedDivisionMode.RemainderAtEnd, int sacrificialPanels = 0) { if (length <= Vector3.EPSILON) { throw new ArgumentException($"Unable to divide by length {length}: smaller than tolerance."); } var lengthToFill = Domain.Length; var maxPanelCount = (int)Math.Floor(lengthToFill / length) - sacrificialPanels; if (maxPanelCount < 1) { return; } var remainderSize = lengthToFill - maxPanelCount * length; if (remainderSize < 0.01) { DivideByCount(maxPanelCount); return; } switch (divisionMode) { case FixedDivisionMode.RemainderAtBothEnds: for (double i = remainderSize / 2.0; i < lengthToFill; i += length) { SplitAtOffset(i); } break; case FixedDivisionMode.RemainderAtStart: for (double i = remainderSize; i < lengthToFill; i += length) { SplitAtOffset(i); } break; case FixedDivisionMode.RemainderAtEnd: for (int i = 1; i < maxPanelCount + 1; i++) { SplitAtOffset(i * length); } break; case FixedDivisionMode.RemainderNearMiddle: // assumes we must have at least 2 full-size panels int panelsOnLeft = maxPanelCount / 2; //integer division, on purpose //make left panels for (int i = 1; i <= panelsOnLeft; i++) { SplitAtOffset(i * length); } //make middle + right panels for (double i = panelsOnLeft * length + remainderSize; i < lengthToFill; i += length) { SplitAtOffset(i); } break; } }