Esempio n. 1
0
 public abstract ProductionScope[] Repeat(RepeatProduction repeater);
Esempio n. 2
0
 public override ProductionScope[] Repeat(RepeatProduction repeater)
 {
     throw new NotImplementedException();
 }
Esempio n. 3
0
        /// <summary>
        /// Create scopes for each repetition of the repeat production.
        /// Add snap planes at the replicand bounds if a snap id is given in the repeater.
        /// If any snap planes in the selector list are found within a replicand scope, snap the bounds to match the nearest snap plane of that selector type.
        ///
        /// Some replicand scopes may vary in size depending on the volume remainder and a specified remainder mode.
        /// Remainders below RepeatEpsilon epsilon are always distributed (to avoid teeny-tiny inserts).
        /// </summary>
        /// <param name="repeater"> </param>
        /// <returns></returns>
        public override ProductionScope[] Repeat(RepeatProduction repeater)
        {
            if (repeater.Magnitude > Bounds.size[(int)repeater.RepetitionAxis] || Math.Abs(repeater.Magnitude - 0) < Mathf.Epsilon)
            {
                throw new Exception("Repetition length is invalid.");
            }

            var repetitionAxisExtent = Vector3.zero;

            repetitionAxisExtent[(int)repeater.RepetitionAxis] = Bounds.extents[(int)repeater.RepetitionAxis];
            var frontierPoint = Bounds.center - Rotation * (repetitionAxisExtent);

            var repetitions  = Bounds.size[(int)repeater.RepetitionAxis] / repeater.Magnitude;
            var repRemainder = repetitions - (int)repetitions;

            Vector3 firstRepSize;
            var     replicandSize = Vector3.zero;
            Vector3 lastRepSize;

            ProductionScope[] replicands;
            if (repeater.RemainderMode == RepeatRemainderMode.DistributeRemainder || repRemainder < RepetitionEpsilon)
            {
                // evenly distribute remainder (if any) to replicands
                replicands = new ProductionScope[(int)repetitions];

                replicandSize[(int)repeater.RepetitionAxis] = Bounds.size[(int)repeater.RepetitionAxis] / repetitions;
                firstRepSize = replicandSize;
                lastRepSize  = replicandSize;
            }
            else
            {
                replicandSize[(int)repeater.RepetitionAxis] = repeater.Magnitude;
                firstRepSize = replicandSize;
                lastRepSize  = replicandSize;

                if (repeater.RemainderMode == RepeatRemainderMode.MergeFirst ||
                    repeater.RemainderMode == RepeatRemainderMode.MergeLast ||
                    repeater.RemainderMode == RepeatRemainderMode.MergeFirstAndLast)
                {
                    replicands = new ProductionScope[(int)repetitions];

                    if (repeater.RemainderMode == RepeatRemainderMode.MergeFirst)
                    {
                        firstRepSize[(int)repeater.RepetitionAxis] = replicandSize[(int)repeater.RepetitionAxis] + Bounds.size[(int)repeater.RepetitionAxis] % repeater.Magnitude;
                    }
                    else if (repeater.RemainderMode == RepeatRemainderMode.MergeLast)
                    {
                        lastRepSize[(int)repeater.RepetitionAxis] = replicandSize[(int)repeater.RepetitionAxis] + Bounds.size[(int)repeater.RepetitionAxis] % repeater.Magnitude;
                    }
                    else // if (repeater.RemainderMode == RepeatRemainderMode.MergeFirstAndLast)
                    {
                        firstRepSize[(int)repeater.RepetitionAxis] = replicandSize[(int)repeater.RepetitionAxis] + (Bounds.size[(int)repeater.RepetitionAxis] % repeater.Magnitude / 2);
                        lastRepSize[(int)repeater.RepetitionAxis]  = replicandSize[(int)repeater.RepetitionAxis] + (Bounds.size[(int)repeater.RepetitionAxis] % repeater.Magnitude / 2);
                    }
                }
                else
                {
                    //if (repeater.RemainderMode == RepeatRemainderMode.InsertFirst || repeater.RemainderMode == RepeatRemainderMode.InsertLast || repeater.RemainderMode == RepeatRemainderMode.InsertFirstAndLast)
                    replicands = new ProductionScope[(int)repetitions + 1];

                    if (repeater.RemainderMode == RepeatRemainderMode.InsertFirst)
                    {
                        // insert replicand for remainder at first position
                        firstRepSize[(int)repeater.RepetitionAxis] = Bounds.size[(int)repeater.RepetitionAxis] % repeater.Magnitude;
                    }
                    else if (repeater.RemainderMode == RepeatRemainderMode.InsertLast)
                    {
                        // insert replicand for remainder at last position
                        lastRepSize[(int)repeater.RepetitionAxis] = Bounds.size[(int)repeater.RepetitionAxis] % repeater.Magnitude;
                    }
                    else //if (repeater.RemainderMode == RepeatRemainderMode.InsertFirstAndLast)
                    {
                        // insert replicands for remainder at first and last positions
                        replicands = new ProductionScope[(int)repetitions + 2];

                        firstRepSize[(int)repeater.RepetitionAxis] = Bounds.size[(int)repeater.RepetitionAxis] % repeater.Magnitude / 2;
                        lastRepSize[(int)repeater.RepetitionAxis]  = Bounds.size[(int)repeater.RepetitionAxis] % repeater.Magnitude / 2;
                    }
                }
            }

            for (var i = 0; i < replicands.Length; ++i)
            {
                Vector3 replicandCenter;
                Bounds  proposedBounds;

                if (i == 0)
                {
                    replicandCenter = frontierPoint + Rotation * (firstRepSize / 2f);
                    frontierPoint   = frontierPoint + Rotation * (firstRepSize);
                    var s = Bounds.size;
                    s[(int)repeater.RepetitionAxis] = firstRepSize[(int)repeater.RepetitionAxis];
                    proposedBounds = new Bounds(replicandCenter, s);
                }
                else if (i == replicands.Length - 1)
                {
                    replicandCenter = frontierPoint + Rotation * (lastRepSize / 2f);
                    frontierPoint   = frontierPoint + Rotation * (lastRepSize);
                    var s = Bounds.size;
                    s[(int)repeater.RepetitionAxis] = lastRepSize[(int)repeater.RepetitionAxis];
                    proposedBounds = new Bounds(replicandCenter, s);
                }
                else
                {
                    // compute dividend volume's center; just move from frontier point (min) to terminal point (max) along the division axis
                    replicandCenter = frontierPoint + Rotation * (replicandSize / 2f);
                    frontierPoint   = frontierPoint + Rotation * (replicandSize);
                    var s = Bounds.size;
                    s[(int)repeater.RepetitionAxis] = replicandSize[(int)repeater.RepetitionAxis];
                    proposedBounds = new Bounds(replicandCenter, s);
                }

                // todo: will also need to update frontier point in a case where bounds get snapped to some plane
                replicands[i] = new CubeProductionScope(
                    SnapBoundsToSnapPlanes(repeater.RepetitionAxis, SelectSnapPlanes(repeater.RepetitionAxis, repeater.SnapToPlanes), proposedBounds),
                    Rotation);

                if (!string.IsNullOrEmpty(repeater.SnapPlaneKey))
                {
                    // add another snap plane to the module
                    AddSnapPlane(repeater.RepetitionAxis, repeater.SnapPlaneKey, replicands[i].Bounds);
                }
            }

            return(replicands);
        }