#if _NEVER
using System;
using System.Collections.Generic;
using Rhino.Geometry;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;
using Grasshopper.Kernel.Parameters;
using FeMM.Common.Models;
using FeMM.Common.Helpers;
using FeMM.Grasshopper.DataTypes;

namespace FeMM.Grasshopper.Components
{
    public class RCPillarRebarsComponent : GH_Component
    {
        private const SteelFrameChecksComponent.LengthUnits _destinationUnits = SteelFrameChecksComponent.LengthUnits.cm;

        /// <summary>
        /// Initializes a new instance of the BeamComponent class.
        /// </summary>
        public RCPillarRebarsComponent()
          : base("RC column rebars", "RCCReb", "Create the column rebars starting from the reinforcement areas",CategoryNameConstants.CATEGORYCHECKS, CategoryNameConstants.SUBCATEGORY_MECHECK)
        {
        }

        /// <summary>
        /// Registers all the input parameters for this component.
        /// </summary>
        protected override void RegisterInputParams(GH_InputParamManager pManager)
        {
            int n;
            pManager.AddGenericParameter("RC Pillars", "RCPs", "RC pillars", GH_ParamAccess.list);
            pManager.AddNumberParameter("Long As", "LAs", "Longitudial reinforcement area of columns in all sections", GH_ParamAccess.tree);
            pManager.AddNumberParameter("Shear As", "VAs", "Shear reinforcement area of columns in all sections", GH_ParamAccess.tree);
            pManager.AddNumberParameter("Ascissas", "Ls", "Location of sections of beams", GH_ParamAccess.tree);
            pManager.AddNumberParameter("Cover", "C", "Cover of columns", GH_ParamAccess.list);
            pManager.AddNumberParameter(char.ConvertFromUtf32(0x3A6) + ",longs", char.ConvertFromUtf32(0x3A6) + ",l",
                                        "Diameters chosen to dispose longitudinal reinforcements [mm]", GH_ParamAccess.list);
            pManager.AddNumberParameter(char.ConvertFromUtf32(0x3A6) + ",st", char.ConvertFromUtf32(0x3A6) + ",st",
                                        "Diameter of stirrups [mm]", GH_ParamAccess.item);
            pManager.AddNumberParameter("Mandrel ratio", "MR", "Ratio between mandrel diameter and bar diameter", GH_ParamAccess.item);
            pManager.AddNumberParameter("Anchor multiplier", "AM", "Ratio between anchor length and diameter", GH_ParamAccess.item);
            pManager.AddTextParameter("Output folder", "OF", "Output folder for .txt rebar data file for revit", GH_ParamAccess.item);
            n = pManager.AddIntegerParameter("Length unit", "LU", "Units of the length", GH_ParamAccess.item);
            Param_Integer length_param = (Param_Integer)pManager[n];
            foreach (SteelFrameChecksComponent.LengthUnits value in Enum.GetValues(typeof(SteelFrameChecksComponent.LengthUnits)))
                length_param.AddNamedValue(value.GetDescription(), (int)value);
            pManager.AddGenericParameter("Elements", "Es", "All elements that compose the model", GH_ParamAccess.list);
            pManager.AddNumberParameter("Weigth multiplier", "WM", "Weigth multiplier of reinforcement", GH_ParamAccess.item);
        }

        /// <summary>
        /// Registers all the output parameters for this component.
        /// </summary>
        protected override void RegisterOutputParams(GH_OutputParamManager pManager)
        {
            pManager.AddNumberParameter("ReinfWeigth", "RW", "Reinforcement weigth [kg]", GH_ParamAccess.item);
        }

        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            var pillars = new List<GH_Beam>();
            GH_Structure<GH_Number> longAs;
            GH_Structure<GH_Number> shearAs;
            GH_Structure<GH_Number> Ls;
            var covers = new List<double>();
            var diametersMm = new List<double>();
            double stirrupDiameterMm = 0;
            double mandrelRatio = 0;
            double anchorMultiplier = 0;
            string outputFile = null;
            int lengthValue = 0;
            SteelFrameChecksComponent.LengthUnits lengthUnits;
            var elements = new List<IGH_Goo>();
            double weigthFactor = 0;

            if (!DA.GetDataList(0, pillars))
                return;
            if (!DA.GetDataTree(1, out longAs))
                return;
            if (!DA.GetDataTree(2, out shearAs))
                return;
            if (!DA.GetDataTree(3, out Ls))
                return;
            if (!DA.GetDataList(4, covers))
                return;
            if (!DA.GetDataList(5, diametersMm))
                return;
            if (!DA.GetData(6, ref stirrupDiameterMm))
                return;
            if (!DA.GetData(7, ref mandrelRatio))
                return;
            if (!DA.GetData(8, ref anchorMultiplier))
                return;
            if (!DA.GetData(9, ref outputFile))
                return;
            if (!DA.GetData(10, ref lengthValue))
                return;
            if (!DA.GetDataList(11, elements))
                return;
            if (!DA.GetData(12, ref weigthFactor))
                return;

            lengthUnits = (SteelFrameChecksComponent.LengthUnits)lengthValue;

            if ((pillars.Count != longAs.Branches.Count) ||
                (pillars.Count != shearAs.Branches.Count) ||
                (pillars.Count != covers.Count) ||
                (pillars.Count != Ls.Branches.Count))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid data dimension");
                return;
            }
            for (int i = 0; i < pillars.Count; i++)
            {
                if ((longAs[i].Count != shearAs[i].Count) ||
                    (longAs[i].Count != Ls[i].Count))
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid data dimension");
                    return;
                }
            }
            if (System.IO.Directory.Exists(outputFile))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Folder not exist");
                return;
            }


            //starting reinforcement calculation
            List<PillarReinfData> disjoinedPillars;
            disjoinedPillars = new List<PillarReinfData>();
            for (int i = 0; i < pillars.Count; i++)
            {
                double[] lAs, ascissas, shear;
                lAs = new double[longAs[i].Count];
                for (int j = 0; j < longAs[i].Count; j++)
                {
                    lAs[j] = RCBeamRebarsComponent.ConvertLengthTo(longAs[i][j].Value, lengthUnits, _destinationUnits, 2);
                }
                ascissas = new double[Ls[i].Count];
                for (int j = 0; j < Ls[i].Count; j++)
                {
                    ascissas[j] = RCBeamRebarsComponent.ConvertLengthTo(Ls[i][j].Value, lengthUnits, _destinationUnits, 1);
                }
                shear = new double[shearAs[i].Count];
                for (int j = 0; j < shearAs[i].Count; j++)
                {
                    //shear area are L2/L=L
                    shear[j] = RCBeamRebarsComponent.ConvertLengthTo(shearAs[i][j].Value, lengthUnits, _destinationUnits, 1);
                }
                disjoinedPillars.Add(new PillarReinfData(pillars[i].Value, lAs, shear, ascissas,
                                                     RCBeamRebarsComponent.ConvertLengthTo(covers[i], lengthUnits, _destinationUnits, 1)));
            }

            //attaching subsequent beams
            List<PillarReinfDataSequence> seqs;
            seqs = new List<PillarReinfDataSequence>();
            do
            {
                PillarReinfDataSequence seq;
                seq = null;
                for (int i = 0; i < disjoinedPillars.Count; i++)
                {
                    if (disjoinedPillars[i] != null)
                    {
                        seq = new PillarReinfDataSequence(disjoinedPillars[i], 0.01);
                        disjoinedPillars[i] = null;
                        break;
                    }
                }

                if (seq == null) { break; }
                do
                {
                    bool found;
                    found = false;
                    for (int i = 0; i < disjoinedPillars.Count; i++)
                    {
                        if ((disjoinedPillars[i] != null) &&
                            seq.Attach(disjoinedPillars[i]))
                        {
                            disjoinedPillars[i] = null;
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        //ended the sequence of parallel items
                        seqs.Add(seq);
                        break;
                    }
                } while (true == true);

            } while (true == true);

            System.Text.StringBuilder sb;
            double weigth;
            //polylines = new List<Polyline>();
            //xShift = 0;
            sb = new System.Text.StringBuilder();
            weigth = 0;
            foreach (PillarReinfDataSequence seq in seqs)
            {
                List<double> longReinfs, ascissas, stirrupReinf;
                double lengthFromStart;
                double cover;
                //RectangularBeamDraw draw;
                List<double> interruption;
                List<double> lengths;
                double dataLength;
                double totalLength;

                longReinfs = new List<double>();
                ascissas = new List<double>();
                stirrupReinf = new List<double>();
                BeamPropertyModel prop;
                ConcreteUtils.Reinforcement.LongitudinalReinforcements[] longitudinals;
                ConcreteUtils.Reinforcement.StirrupReinforcements[] stirrups;

                lengthFromStart = 0;
                cover = 0;
                totalLength = 0;
                lengths = new List<double>();
                foreach (PillarReinfData data in seq.Sequence)
                {
                    Point3d startP, endP;

                    startP = data.Beam.PointFrom;
                    endP = data.Beam.PointTo;
                    dataLength = RCBeamRebarsComponent.ConvertLengthTo((startP - endP).Length, lengthUnits, _destinationUnits, 1);
                    totalLength += dataLength;
                    //topInterruption.Add(lengthFromStart + 0.5 * seqLength);
                    if (seq.IsEquiverseTo(data))
                    {
                        longReinfs.AddRange(data.LongAs);
                        stirrupReinf.AddRange(data.ShearAs);
                        foreach (double x in data.Ascissas)
                        {
                            ascissas.Add(x + lengthFromStart);
                        }


                        lengthFromStart += dataLength;
                    }
                    else
                    {
                        lengthFromStart += dataLength;
                        for (int i = data.Ascissas.Length - 1; i >= 0; i--)
                        {
                            ascissas.Add(lengthFromStart - data.Ascissas[i]);
                            longReinfs.Add(data.LongAs[i]);
                            stirrupReinf.Add(data.ShearAs[i]);
                        }

                    }
                    cover = System.Math.Max(cover, data.Cover);
                    lengths.Add(dataLength);
                }

                interruption = new List<double>();
                for (int i = 0; i < lengths.Count - 1; i++)
                {
                    interruption.Add(lengths[i]);
                }

                prop = seq.Sequence[0].Beam.BeamProperty;
                switch (prop.Section)
                {
                    case SectionType.SolidRectangle:
                        {
                            double b, h;
                            Maffeis.Geometry.Vector3d axesDir, xDir;
                            Maffeis.Geometry.Point3d origin;
                            Maffeis.Geometry.Trans3d trans;
                            b = RCBeamRebarsComponent.ConvertLengthTo(prop.B, lengthUnits, _destinationUnits, 1);
                            h = RCBeamRebarsComponent.ConvertLengthTo(prop.D, lengthUnits, _destinationUnits, 1);
                            seq.GetDirs(out axesDir, out xDir);
                            //trans positioned in lower left of ascissa 0;
                            trans = new Maffeis.Geometry.Trans3d(Maffeis.Geometry.Point3d.Origin,
                                                          Maffeis.Geometry.Point3d.Origin + xDir,
                                                          Maffeis.Geometry.Point3d.Origin,
                                                          Maffeis.Geometry.Point3d.Origin + axesDir);
                            origin = seq.GetStartingAxesPoint(lengthUnits);
                            origin += trans.PointGlobal(new Maffeis.Geometry.Point3d(-0.5 * b, -0.5 * h, 0));
                            trans = new Maffeis.Geometry.Trans3d(origin, origin + xDir, origin, origin + axesDir);
                            try
                            {
                                ConcreteUtils.FrameBarDrawer.GetRectangularColumnsReinforcements(ascissas.ToArray(),
                                                                                                 longReinfs.ToArray(),
                                                                                                 stirrupReinf.ToArray(),
                                                                                                 b, h, lengths.ToArray(),
                                                                                                 cover,
                                                                                                 diametersMm,
                                                                                                 stirrupDiameterMm,
                                                                                                 mandrelRatio,
                                                                                                 anchorMultiplier,
                                                                                                 trans,
                                                                                                 interruption.ToArray(),
                                                                                                 out longitudinals,
                                                                                                 out stirrups);
                            }
                            catch
                            {
                                longitudinals = null;
                                stirrups = null;
                                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Unable to add reinforcement to a pillar");
                            }
                            //draw = new RectangularBeamDraw(seq, b, h, lengthFromStart, trans, xShift);
                            break;
                        }
                    default:
                        throw new NotImplementedException("Section type " + seq.Sequence[0].Beam.BeamProperty.Section + " not implemented");

                }

                //writing reinfs
                const string SEP = ",";
                string refID;
                Maffeis.Geometry.Point3d refPoint;
                Maffeis.Geometry.Vector3d dir;

                refID = seq.Sequence[0].Beam.BeamId;

                //searching the ref point
                //revit want a middle point (origin of the central bbox)
                Point3d middle = 0.5 * (seq.Sequence[0].Beam.PointFrom + seq.Sequence[0].Beam.PointTo);
                refPoint = new Maffeis.Geometry.Point3d(RCBeamRebarsComponent.ConvertLengthTo(middle.X, lengthUnits, _destinationUnits, 1),
                                                 RCBeamRebarsComponent.ConvertLengthTo(middle.Y, lengthUnits, _destinationUnits, 1),
                                                 RCBeamRebarsComponent.ConvertLengthTo(middle.Z, lengthUnits, _destinationUnits, 1));
                var p0 = new Maffeis.Geometry.Point3d(seq.Sequence[0].Beam.PointFrom.X, seq.Sequence[0].Beam.PointFrom.Y, seq.Sequence[0].Beam.PointFrom.Z);
                var p1 = new Maffeis.Geometry.Point3d(seq.Sequence[0].Beam.PointTo.X, seq.Sequence[0].Beam.PointTo.Y, seq.Sequence[0].Beam.PointTo.Z);
                dir = new Maffeis.Geometry.Vector3d(p0-p1);
                dir.Unitize();

                if (longitudinals != null)
                {
                    foreach (ConcreteUtils.Reinforcement.LongitudinalReinforcements lReinfs in longitudinals)
                    {
                        string line;
                        double iniPos;
                        double endPos;

                        //ID
                        line = refID.ToString();
                        line += SEP;

                        //Pos
                        line += "C";
                        line += SEP;

                        //Number
                        line += lReinfs.Count.ToString();
                        line += SEP;

                        //Diam mm
                        line += (lReinfs.DiameterCm * 10).ToString("F0");
                        line += SEP;

                        //Pos mm
                        iniPos = double.MaxValue;
                        endPos = double.MinValue;
                        foreach (ConcreteUtils.Reinforcement.LongitudinalReinforcement lReinf in lReinfs)
                        {
                            foreach (Maffeis.Geometry.Point3d p in lReinf.GetAxesPoints())
                            {
                                double pos;
                                pos = (p - refPoint) * dir;

                                iniPos = System.Math.Min(pos, iniPos);
                                endPos = System.Math.Max(pos, endPos);
                            }
                        }
                        line += (iniPos * 10).ToString("F1");
                        line += SEP;
                        line += (endPos * 10).ToString("F1");

                        sb.AppendLine(line);
                    }
                }

                if (stirrups != null)
                {
                    foreach (ConcreteUtils.Reinforcement.StirrupReinforcements sReinfs in stirrups)
                    {
                        string line;
                        double iniPos;
                        double endPos;

                        //ID
                        line = refID.ToString();
                        line += SEP;

                        //Pos
                        line += "S";
                        line += SEP;

                        //Passo mm
                        line += (sReinfs.GetInterasse() * 10).ToString("F1");
                        line += SEP;

                        //Diam mm
                        line += (sReinfs.DiameterCm * 10).ToString("F0");
                        line += SEP;

                        //Pos
                        iniPos = double.MaxValue;
                        endPos = double.MinValue;
                        foreach (ConcreteUtils.Reinforcement.StirrupReinforcement sReinf in sReinfs)
                        {
                            foreach (Maffeis.Geometry.Point3d p in sReinf.GetAxesPoints())
                            {
                                double pos;
                                pos = (p - refPoint) * dir;

                                iniPos = System.Math.Min(pos, iniPos);
                                endPos = System.Math.Max(pos, endPos);
                            }
                        }
                        line += (iniPos * 10).ToString("F1");
                        line += SEP;
                        line += (endPos * 10).ToString("F1");

                        sb.AppendLine(line);
                    }
                }


                //Weigth
                if (longitudinals != null)
                {
                    foreach (ConcreteUtils.Reinforcement.LongitudinalReinforcements lReinfs in longitudinals)
                    {
                        weigth += lReinfs.GetWeigth();
                    }

                }
                if (stirrups != null)
                {
                    foreach (ConcreteUtils.Reinforcement.StirrupReinforcements sReinfs in stirrups)
                    {
                        weigth += sReinfs.GetWeigth();
                    }
                }

            }
            //Writing
            using (var sw = new System.IO.StreamWriter(System.IO.Path.GetDirectoryName(outputFile) + @"\ColumnBars.txt"))
            {
                sw.Write(sb);
                sw.Flush();
                sw.Close();
            }

            weigth *= weigthFactor;
            DA.SetData(0, weigth);
        }

        private class PillarReinfData
        {
            public readonly BeamModel Beam;
            public readonly double[] LongAs;
            public readonly double[] ShearAs;
            public readonly double[] Ascissas;
            public readonly double Cover;

            public PillarReinfData(BeamModel beam,
                                 double[] longAs,
                                 double[] shearAs,
                                 double[] ascissas,
                                 double cover)
            {
                this.Beam = beam;
                this.LongAs = longAs;
                this.ShearAs = shearAs;
                this.Ascissas = ascissas;
                this.Cover = cover;
            }
        }

        private class PillarReinfDataSequence
        {
            private readonly Vector3d _firstVector;
            public readonly List<PillarReinfData> Sequence;
            private double TOLL;

            public PillarReinfDataSequence(PillarReinfData first,
                                           double TOLL)
            {
                _firstVector = GetBeamDir(first);
                Sequence = new List<PillarReinfData>();
                Sequence.Add(first);
                this.TOLL = TOLL;
            }

            public bool Attach(PillarReinfData other)
            {
                if ((other.Beam.BeamProperty.Name == Sequence[0].Beam.BeamProperty.Name) &&
                    (System.Math.Abs(other.Beam.AngleDeg - Sequence[0].Beam.AngleDeg) < 0.01))
                {
                    int isParallel;
                    Vector3d otherVect;
                    otherVect = GetBeamDir(other);
                    isParallel = otherVect.IsParallelTo(_firstVector);
                    if (isParallel != 0)
                    {
                        Point3d start, end;
                        //checking if attached to first node or last node
                        isParallel = GetBeamDir(Sequence[0]).IsParallelTo(_firstVector);
                        if (isParallel == 1)
                        {
                            start = Sequence[0].Beam.PointFrom;
                        }
                        else if (isParallel == -1)
                        {
                            start = Sequence[0].Beam.PointTo;
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                        isParallel = GetBeamDir(Sequence[Sequence.Count - 1]).IsParallelTo(_firstVector);
                        if (isParallel == 1)
                        {
                            end = Sequence[Sequence.Count - 1].Beam.PointTo;
                        }
                        else if (isParallel == -1)
                        {
                            end = Sequence[Sequence.Count - 1].Beam.PointFrom;
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                        if ((other.Beam.PointFrom.DistanceToSquared(start) < TOLL) ||
                            (other.Beam.PointTo.DistanceToSquared(start) < TOLL))
                        {
                            Sequence.Insert(0, other);
                            return true;
                        }
                        else if ((other.Beam.PointFrom.DistanceToSquared(end) < TOLL) ||
                                 (other.Beam.PointTo.DistanceTo(end) < TOLL))
                        {
                            Sequence.Add(other);
                            return true;
                        }
                    }
                }
                return false;
            }

            private Vector3d GetBeamDir(PillarReinfData beam)
            {
                return beam.Beam.PointTo - beam.Beam.PointFrom;
            }

            public bool IsEquiverseTo(PillarReinfData other)
            {
                return GetBeamDir(other).IsParallelTo(_firstVector) > 0;
            }

            public void GetDirs(out Maffeis.Geometry.Vector3d axesDir,
                                out Maffeis.Geometry.Vector3d xDir)
            {
                Vector3d rhinoDir;
                double angle;

                rhinoDir = _firstVector / _firstVector.Length;
                axesDir = new Maffeis.Geometry.Point3d(rhinoDir.X, rhinoDir.Y, rhinoDir.Z);
                angle = Sequence[0].Beam.AngleDeg * System.Math.PI / 180;
                if (System.Math.Abs(axesDir * Maffeis.Geometry.Vector3d.ZAxis) > 0.999)
                {
                    xDir = new Maffeis.Geometry.Point3d(System.Math.Cos(angle), System.Math.Sin(angle), 0);
                }
                else
                {
                    xDir = (Maffeis.Geometry.Vector3d.ZAxis ^ axesDir) ^ Maffeis.Geometry.Vector3d.ZAxis;
                }
            }

            public Maffeis.Geometry.Point3d GetStartingAxesPoint(SteelFrameChecksComponent.LengthUnits lengthCode)
            {
                Point3d n;
                if (GetBeamDir(Sequence[0]).IsParallelTo(_firstVector) > 0)
                {
                    n = Sequence[0].Beam.PointFrom;
                }
                else
                {
                    n = Sequence[0].Beam.PointTo;
                }
                return new Maffeis.Geometry.Point3d(RCBeamRebarsComponent.ConvertLengthTo(n.X, lengthCode, _destinationUnits, 1),
                                             RCBeamRebarsComponent.ConvertLengthTo(n.Y, lengthCode, _destinationUnits, 1),
                                             RCBeamRebarsComponent.ConvertLengthTo(n.Z, lengthCode, _destinationUnits, 1));
            }

        }

        public override GH_Exposure Exposure => GH_Exposure.secondary;

        /// <summary>
        /// Provides an Icon for the component.
        /// </summary>
        protected override System.Drawing.Bitmap Icon => Properties.Resources.RCPillarRebarsIcon;

        /// <summary>
        /// Gets the unique ID for this component. Do not change this ID after release.
        /// </summary>
        public override Guid ComponentGuid => new Guid("7594D13A-05B2-48D7-8F7D-CC2064941788");
    }
}
#endif
303 files24 directories