/// <summary> /// Divide scope into portions as described by divisors list. /// Add snap planes at the dividend bounds if a snap id is given in the divisor. /// If any snap planes in the selector list are found within a dividend scope, snap the bounds to match the nearest snap plane of that selector type. /// </summary> /// <param name="divider"> </param> /// <returns></returns> public override ProductionScope[] Divide(DivideProduction divider) { // step 1: validate divisor magnitudes. scopeLength > absolute length; scopeLength - absolute lengths = availableRelLength var absSpan = divider.Divisors.Where(div => div.IsAbsolute).Sum(div => div.Magnitude); var relSpan = divider.Divisors.Where(div => !div.IsAbsolute).Sum(div => div.Magnitude); if (Math.Abs(relSpan - 1) > Mathf.Epsilon || absSpan > Bounds.size[(int)divider.DivisionAxis]) { throw new Exception("Division length is invalid."); } var divAxisExtent = Vector3.zero; divAxisExtent[(int)divider.DivisionAxis] = Bounds.extents[(int)divider.DivisionAxis]; var frontierPoint = Bounds.center - Rotation * (divAxisExtent); var dividends = new ProductionScope[divider.Divisors.Count()]; for (var i = 0; i < divider.Divisors.Length; i++) { var divisor = divider.Divisors[i]; // slice volume along our division axis, slicing off [magnitude] volume or [magnitude]% of the volume available for relative divisions Vector3 dividendSpan = Vector3.zero; dividendSpan[(int)divider.DivisionAxis] = divisor.IsAbsolute ? divisor.Magnitude : Bounds.size[(int)divider.DivisionAxis] * divisor.Magnitude; // compute dividend volume's center; just move from frontier point (min) to terminal point (max) along the division axis var dividendCenter = frontierPoint + (Rotation * (dividendSpan / 2f)); var s = Bounds.size; s[(int)divider.DivisionAxis] = dividendSpan[(int)divider.DivisionAxis]; var proposedBounds = new Bounds(dividendCenter, s); dividends[i] = new CubeProductionScope(SnapBoundsToSnapPlanes(divider.DivisionAxis, SelectSnapPlanes(divider.DivisionAxis, divider.SnapToPlanes), proposedBounds), Rotation); if (!string.IsNullOrEmpty(divisor.SnapPlaneKey)) { // add another snap plane to the module AddSnapPlane(divider.DivisionAxis, divisor.SnapPlaneKey, dividends[i].Bounds); } if (dividends[i].Bounds.size.x <= 0 || dividends[i].Bounds.size.y <= 0 || dividends[i].Bounds.size.z <= 0) { Debug.Log("Dividing to a negative size..."); } // update frontier point frontierPoint = frontierPoint + Rotation * dividendSpan; } return(dividends); }
public override ProductionScope[] Divide(DivideProduction divider) { throw new NotImplementedException(); }
public abstract ProductionScope[] Divide(DivideProduction divider);