#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 RCBeamRebarsComponent : GH_Component
    {
        private const SteelFrameChecksComponent.LengthUnits _destinationUnits = SteelFrameChecksComponent.LengthUnits.cm;

        /// <summary>
        /// Initializes a new instance of the BeamComponent class.
        /// </summary>
        public RCBeamRebarsComponent()
          : base("RC beam rebars", "RCBReb", "Create the beam 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 Beams", "RCBs", "RC beams", GH_ParamAccess.list);
            pManager.AddNumberParameter("Top As", "TAs", "Top reinforcement area of beams in all sections", GH_ParamAccess.tree);
            pManager.AddNumberParameter("Bottom As", "BAs", "Bottom reinforcement area of beams in all sections", GH_ParamAccess.tree);
            pManager.AddNumberParameter("Shear As", "VAs", "Shear reinforcement area of beams in all sections", GH_ParamAccess.tree);
            pManager.AddNumberParameter("Ascissas", "Ls", "Location of sections of beams", GH_ParamAccess.tree);
            pManager.AddNumberParameter("Top cover", "Tc", "TopCover of beams", GH_ParamAccess.list);
            pManager.AddNumberParameter("Bottom cover", "Bc", "BottomCover of beams", 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.AddNumberParameter("Max lenght", "ML", "Max length of bars", 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 beams = new List<GH_Beam>();
            GH_Structure<GH_Number> topAs;
            GH_Structure<GH_Number> bottomAs;
            GH_Structure<GH_Number> shearAs;
            GH_Structure<GH_Number> Ls;
            var topCovers = new List<double>();
            var bottomCovers = new List<double>();
            var diametersMm = new List<double>();
            double stirrupDiameterMm = 0;
            double mandrelRatio = 0;
            double anchorMultiplier = 0;
            double maxLength = 0;
            double maxLengthCm;
            List<Polyline> polylines;
            string outputFile = null;
            int lengthValue = 0;
            SteelFrameChecksComponent.LengthUnits lengthUnits;
            var elements = new List<IGH_Goo>();
            double weigthFactor = 0;

            if (!DA.GetDataList(0, beams))
                return;
            if (!DA.GetDataTree(1, out topAs))
                return;
            if (!DA.GetDataTree(2, out bottomAs))
                return;
            if (!DA.GetDataTree(3, out shearAs))
                return;
            if (!DA.GetDataTree(4, out Ls))
                return;
            if (!DA.GetDataList(5, topCovers))
                return;
            if (!DA.GetDataList(6, bottomCovers))
                return;
            if (!DA.GetDataList(7, diametersMm))
                return;
            if (!DA.GetData(8, ref stirrupDiameterMm))
                return;
            if (!DA.GetData(9, ref mandrelRatio))
                return;
            if (!DA.GetData(10, ref anchorMultiplier))
                return;
            if (!DA.GetData(11, ref maxLength))
                return;
            if (!DA.GetData(12, ref outputFile))
                return;
            if (!DA.GetData(13, ref lengthValue))
                return;
            if (!DA.GetDataList(14, elements))
                return;
            if (!DA.GetData(15, ref weigthFactor))
                return;

            if ((beams.Count != topAs.Branches.Count) ||
                (beams.Count != bottomAs.Branches.Count) ||
                (beams.Count != shearAs.Branches.Count) ||
                (beams.Count != topCovers.Count) ||
                (beams.Count != bottomCovers.Count) ||
                (beams.Count != Ls.Branches.Count))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid data dimension");
                return;
            }
            for (int i = 0; i < beams.Count; i++)
            {
                if ((topAs[i].Count != bottomAs[i].Count) ||
                    (topAs[i].Count != shearAs[i].Count) ||
                    (topAs[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;
            }
            lengthUnits = (SteelFrameChecksComponent.LengthUnits)lengthValue;

            maxLengthCm = ConvertLengthTo(maxLength, lengthUnits, _destinationUnits, 1);
            if (maxLengthCm < 100)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Bar lengths have to be > 100 cm");
            }

            //starting reinforcement calculation
            List<BeamData> disjoinedBeams;
            System.Text.StringBuilder sb;
            double weigth;

            disjoinedBeams = new List<BeamData>();
            sb = new System.Text.StringBuilder();
            weigth = 0;
            for (int i = 0; i < beams.Count; i++)
            {
                double[] bAs, tAs, ascissas, shear;
                bAs = new double[bottomAs[i].Count];
                for (int j = 0; j < bottomAs[i].Count; j++)
                {
                    bAs[j] = ConvertLengthTo(bottomAs[i][j].Value, lengthUnits, _destinationUnits, 2);
                }
                tAs = new double[topAs[i].Count];
                for (int j = 0; j < topAs[i].Count; j++)
                {
                    tAs[j] = ConvertLengthTo(topAs[i][j].Value, lengthUnits, _destinationUnits, 2);
                }
                ascissas = new double[Ls[i].Count];
                for (int j = 0; j < Ls[i].Count; j++)
                {
                    ascissas[j] = 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] = ConvertLengthTo(shearAs[i][j].Value, lengthUnits, _destinationUnits, 1);
                }
                disjoinedBeams.Add(new BeamReinfData(beams[i].Value, bAs, tAs, shear, ascissas,
                                                     ConvertLengthTo(topCovers[i], lengthUnits, _destinationUnits, 1),
                                                     ConvertLengthTo(bottomCovers[i], lengthUnits, _destinationUnits, 1)));
            }

            //attaching subsequent beams
            List<BeamDataSequence> seqs;
            seqs = BeamDataSequence.GetSequences(disjoinedBeams, 0.01);

            polylines = new List<Polyline>();
            //xShift = 0;
            foreach (BeamDataSequence seq in seqs)
            {
                List<double> bottomReinfs, topReinfs, ascissas, stirrupReinf;
                double lengthFromStart;
                double topCover, bottomCover;
                //RectangularBeamDraw draw;
                List<double> bottomInterruption, topInterruption;
                List<double> lengths;
                double dataLength;
                List<double> pillarPos;
                double totalLength;

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

                lengthFromStart = 0;
                topCover = 0;
                bottomCover = 0;
                pillarPos = new List<double>();
                totalLength = 0;
                foreach (BeamReinfData data in seq.Sequence)
                {
                    Point3d startP, endP;

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

                        //searching pillars3
                        AddPillar(data, elements, lengthUnits, lengthFromStart, data.Beam.PointFrom, ref pillarPos);
                        lengthFromStart += dataLength;
                        AddPillar(data, elements, lengthUnits, lengthFromStart, data.Beam.PointTo, ref pillarPos);
                    }
                    else
                    {
                        AddPillar(data, elements, lengthUnits, lengthFromStart, data.Beam.PointTo, ref pillarPos);
                        lengthFromStart += dataLength;
                        for (int i = data.Ascissas.Length - 1; i >= 0; i--)
                        {
                            ascissas.Add(lengthFromStart - data.Ascissas[i]);
                            bottomReinfs.Add(data.BottomAs[i]);
                            topReinfs.Add(data.TopAs[i]);
                            stirrupReinf.Add(data.ShearAs[i]);
                        }
                        AddPillar(data, elements, lengthUnits, lengthFromStart, data.Beam.PointFrom, ref pillarPos);
                    }

                    topCover = System.Math.Max(topCover, data.TopCover);
                    bottomCover = System.Math.Max(bottomCover, data.BottomCover);
                }
                pillarPos.Sort();

                lengths = new List<double>();

                if (pillarPos.Count > 0)
                {
                    for (int count = 0; count < pillarPos.Count - 1; count++)
                    {
                        lengths.Add(pillarPos[count + 1] - pillarPos[count]);
                    }

                    if (System.Math.Abs(pillarPos[0]) > 1)
                    {
                        lengths.Insert(0, 0);
                    }
                    if (System.Math.Abs(pillarPos[pillarPos.Count - 1] - totalLength) > 1)
                    {
                        lengths.Add(totalLength);
                    }
                }
                else
                {
                    lengths.Add(totalLength);
                }


                for (int counter = 0; counter < pillarPos.Count; counter++)
                {
                    if (pillarPos[counter] > 100 && pillarPos[counter] < totalLength - 100)
                    {
                        bottomInterruption.Add(pillarPos[counter]);
                    }
                    if (counter != pillarPos.Count - 1)
                    {
                        topInterruption.Add((pillarPos[counter] + pillarPos[counter + 1]) / 2);
                    }
                }

                prop = seq.Sequence[0].Beam.BeamProperty;
                switch (prop.Section)
                {
                    case SectionType.SolidRectangle:
                        {
                            double b, h;
                            Maffeis.Geometry.Point3d axesDir, xDir, origin;
                            Maffeis.Geometry.Trans3d trans;
                            if (seq.Sequence[0].Beam.AngleDeg == 0)
                            {
                                h = ConvertLengthTo(prop.B, lengthUnits, _destinationUnits, 1);
                                b = ConvertLengthTo(prop.D, lengthUnits, _destinationUnits, 1);
                            }
                            else if (seq.Sequence[0].Beam.AngleDeg == 90)
                            {
                                b = ConvertLengthTo(prop.B, lengthUnits, _destinationUnits, 1);
                                h = ConvertLengthTo(prop.D, lengthUnits, _destinationUnits, 1);
                            }
                            else
                                throw new NotSupportedException("Angle different from 0 and 90 not supported");
                            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.GetRectangularBeamReinforcements(ascissas.ToArray(),
                                                         bottomReinfs.ToArray(),
                                                         topReinfs.ToArray(),
                                                         stirrupReinf.ToArray(),
                                                         b, h, lengths.ToArray(),
                                                         bottomCover,
                                                         topCover,
                                                         diametersMm,
                                                         stirrupDiameterMm,
                                                         mandrelRatio,
                                                         anchorMultiplier,
                                                         trans,
                                                         maxLengthCm,
                                                         topInterruption.ToArray(),
                                                         bottomInterruption.ToArray(),
                                                         out longitudinals,
                                                         out stirrups);
                            }
                            catch (Exception ex)
                            {
                                longitudinals = null;
                                stirrups = null;
                                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Unable to reinforce a beam");
                                System.Diagnostics.Debug.WriteLine(ex.Message, "RCBeamRebarsComponent.SolveInstance");
                            }

                            //draw = new RectangularBeamDraw(seq, b, h, lengthFromStart, trans, xShift);
                            break;
                        }
                    default:
                        throw new NotImplementedException("Section type " + prop.Section.ToString() + " not implemented");
                }

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

                refID = seq.Sequence[0].Beam.BeamId;
                Point3d middle = 0.5 * (seq.Sequence[0].Beam.PointFrom + seq.Sequence[0].Beam.PointTo);
                //searching the ref point
                //revit want a middle point (origin of the central bbox)

                refPoint = new Maffeis.Geometry.Point3d(ConvertLengthTo(middle.X, lengthUnits, _destinationUnits, 1),
                                                 ConvertLengthTo(middle.Y, lengthUnits, _destinationUnits, 1),
                                                 ConvertLengthTo(middle.Z, lengthUnits, _destinationUnits, 1));
                var p1 = new Maffeis.Geometry.Point3d(seq.Sequence[0].Beam.PointFrom.X, seq.Sequence[0].Beam.PointFrom.Y, seq.Sequence[0].Beam.PointFrom.Z);
                var p2 = new Maffeis.Geometry.Point3d(seq.Sequence[0].Beam.PointTo.X, seq.Sequence[0].Beam.PointTo.Y, seq.Sequence[0].Beam.PointTo.Z);
                dir = p2 - p1;

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

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

                        //Pos
                        switch (lReinfs.PositionCode)
                        {
                            case ConcreteUtils.Reinforcement.LongitudinalReinforcement.PositionCodes.Top:
                                {
                                    line += "T";
                                    break;
                                }
                            case ConcreteUtils.Reinforcement.LongitudinalReinforcement.PositionCodes.Bottom:
                                {
                                    line += "B";
                                    break;
                                }
                            default:
                                throw new NotSupportedException();
                        }
                        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) + @"\BeamBars.txt"))
            {
                sw.Write(sb);
                sw.Flush();
                sw.Close();
            }
            weigth *= weigthFactor;
            DA.SetData(0, weigth);
        }

        public static double ConvertLengthTo(
            double length, 
            SteelFrameChecksComponent.LengthUnits startingUnit, 
            SteelFrameChecksComponent.LengthUnits destinationUnit,
            uint exponent)
        {
            double result;
            if (exponent < 1)
            {
                throw new NotSupportedException();
            }
            //moving to mm
            switch (startingUnit)
            {
                case SteelFrameChecksComponent.LengthUnits.mm:
                    result = 1;
                    break;
                case SteelFrameChecksComponent.LengthUnits.cm:
                    result = 10;
                    break;
                case SteelFrameChecksComponent.LengthUnits.m:
                    result = 1000;
                    break;
                default:
                    throw new NotImplementedException("Not supported unit");
            }
            //moving from mm to destinationUnit
            switch (destinationUnit)
            {
                case SteelFrameChecksComponent.LengthUnits.mm:
                    result *= 1;
                    break;
                case SteelFrameChecksComponent.LengthUnits.cm:
                    result *= 0.1;
                    break;
                case SteelFrameChecksComponent.LengthUnits.m:
                    result *= 0.001;
                    break;
                default:
                    throw new NotImplementedException("Not supported unit");
            }
            result = System.Math.Pow(result, exponent);
            result *= length;
            return result;
        }

        private static void AddPillar(
            BeamData data,
            List<IGH_Goo> elements,
            SteelFrameChecksComponent.LengthUnits lengthCode,
            double lengthFromStart,
            Point3d dataPoint,
            ref List<double> pillarPos)
        {
            double toll, squareToll;
            switch (lengthCode)
            {
                case SteelFrameChecksComponent.LengthUnits.mm:
                    {
                        toll = 10;
                        break;
                    }
                case SteelFrameChecksComponent.LengthUnits.cm:
                    {
                        toll = 1;
                        break;
                    }
                case SteelFrameChecksComponent.LengthUnits.m:
                    {
                        toll = 0.01;
                        break;
                    }
                default:
                    throw new NotSupportedException();
            }
            squareToll = toll * toll;

            foreach (IGH_Goo elem in elements)
            {
                if (elem is GH_Beam)
                {
                    BeamModel beam;
                    bool isElem;
                    bool isConnected;

                    beam = ((GH_Beam)elem).Value;
                    isElem = ((beam.PointFrom.DistanceToSquared(data.Beam.PointFrom) < squareToll) &&
                              (beam.PointTo.DistanceToSquared(data.Beam.PointTo) < squareToll)) ||
                             ((beam.PointTo.DistanceToSquared(data.Beam.PointFrom) < squareToll) &&
                              (beam.PointFrom.DistanceToSquared(data.Beam.PointTo) < squareToll));
                    isConnected = (dataPoint.DistanceToSquared(beam.PointFrom) < squareToll) ||
                                  (dataPoint.DistanceToSquared(beam.PointTo) < squareToll);

                    if ((!isElem) && isConnected)
                    {
                        Vector3d dir;
                        dir = beam.PointTo - beam.PointFrom;
                        dir.Unitize();
                        //test if pseudo-vertical and not above the beam
                        if ((dir * Vector3d.ZAxis > 0.8) &&
                            (beam.PointFrom.Z <= dataPoint.Z + toll) && (beam.PointTo.Z <= dataPoint.Z + toll))
                        {
                            bool add;
                            add = true;
                            foreach (double other in pillarPos)
                            {
                                if (System.Math.Abs(other - lengthFromStart) < 10)
                                {
                                    add = false;
                                    break;
                                }
                            }
                            if (add)
                            {
                                pillarPos.Add(lengthFromStart);
                            }
                            break;
                        }
                    }
                }
                else if (elem is GH_Plate)
                {
                    PlateModel p = ((GH_Plate)elem).Value;
                    //testing connection with beam
                    foreach (Point3d point in p.Points)
                    {
                        if (point.DistanceToSquared(dataPoint) < squareToll)
                        {
                            //testing if vertical
                            Point3d p0, p1, p2;
                            Vector3d normal;
                            p0 = p.Points[0];
                            p1 = p.Points[1];
                            p2 = p.Points[2];
                            normal = Vector3d.CrossProduct(p1 - p0, p2 - p0);
                            normal.Unitize();
                            if (normal * Vector3d.ZAxis < 0.001)
                            {
                                bool add;
                                add = true;
                                foreach (double other in pillarPos)
                                {
                                    if (System.Math.Abs(other - lengthFromStart) < 10)
                                    {
                                        add = false;
                                        break;
                                    }
                                }
                                if (add)
                                {
                                    pillarPos.Add(lengthFromStart);
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }

#region BeamData

        private class BeamData
        {
            public readonly BeamModel Beam;

            public BeamData(BeamModel beam)
            {
                this.Beam = beam;
            }
        }

        private class BeamReinfData : BeamData
        {
            public readonly double[] BottomAs;
            public readonly double[] TopAs;
            public readonly double[] ShearAs;
            public readonly double[] Ascissas;
            public readonly double TopCover;
            public readonly double BottomCover;

            public BeamReinfData(BeamModel beam,
                                 double[] bottomAs,
                                 double[] topAs,
                                 double[] shearAs,
                                 double[] ascissas,
                                 double topCover,
                                 double bottomCover) : base(beam)
            {
                this.BottomAs = bottomAs;
                this.TopAs = topAs;
                this.ShearAs = shearAs;
                this.Ascissas = ascissas;
                this.TopCover = topCover;
                this.BottomCover = bottomCover;
            }
        }

#endregion

#region BeamResultsSequence

        private class BeamDataSequence
        {
            private readonly Vector3d _firstDir;
            public readonly List<BeamData> Sequence;
            private double TOLL;

            public BeamDataSequence(BeamData first,
                                       double TOLL)
            {
                _firstDir = GetBeamDir(first);
                Sequence = new List<BeamData>();
                Sequence.Add(first);
                this.TOLL = TOLL;
            }

            public static List<BeamDataSequence> GetSequences(List<BeamData> disjoinedBeams, double TOLL)
            {
                //attaching subsequent beams
                List<BeamDataSequence> seqs;
                seqs = new List<BeamDataSequence>();
                do
                {
                    BeamDataSequence seq;
                    seq = null;
                    for (int i = 0; i < disjoinedBeams.Count; i++)
                    {
                        if (disjoinedBeams[i] != null)
                        {
                            seq = new BeamDataSequence(disjoinedBeams[i], TOLL);
                            disjoinedBeams[i] = null;
                            break;
                        }
                    }

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

                } while (true == true);

                return seqs;
            }

            private bool Attach(BeamData 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(_firstDir);
                    if (isParallel != 0)
                    {
                        Point3d start, end;
                        //checking if attached to first node or last node
                        isParallel = GetBeamDir(Sequence[0]).IsParallelTo(_firstDir);
                        if (isParallel == 1)
                        {
                            start = Sequence[0].Beam.PointFrom;//   _model.GetNode(Sequence[0].Beam.StartNode);
                        }
                        else if (isParallel == -1)
                        {
                            start = Sequence[0].Beam.PointTo;//  _model.GetNode(Sequence[0].Beam.EndNode);
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                        isParallel = GetBeamDir(Sequence[Sequence.Count - 1]).IsParallelTo(_firstDir);
                        if (isParallel == 1)
                        {
                            end = Sequence[Sequence.Count - 1].Beam.PointTo;//_model.GetNode(Sequence[Sequence.Count - 1].Beam.EndNode);
                        }
                        else if (isParallel == -1)
                        {
                            end = Sequence[Sequence.Count - 1].Beam.PointFrom;//   _model.GetNode(Sequence[Sequence.Count - 1].Beam.StartNode);
                        }
                        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(BeamData beam)
            {
                return beam.Beam.PointTo - beam.Beam.PointFrom;
            }

            public bool IsEquiverseTo(BeamData other)
            {
                return GetBeamDir(other).IsParallelTo(_firstDir) > 0;
            }

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

                rhinoDir = _firstDir / _firstDir.Length;
                axesDir = new Maffeis.Geometry.Point3d(rhinoDir.X, rhinoDir.Y, rhinoDir.Z);
                if (System.Math.Abs(axesDir * Maffeis.Geometry.Vector3d.ZAxis) > 0.999)
                {
                    throw new NotSupportedException("Vertcial beams not admitted");
                }
                else
                {
                    xDir = -1 * ((Maffeis.Geometry.Vector3d) axesDir ^ Maffeis.Geometry.Vector3d.ZAxis);
                    ((Maffeis.Geometry.Vector3d)xDir).Unitize();
                    xDir = (Maffeis.Geometry.Point3d) xDir;
                }
            }

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

#endregion

        public override GH_Exposure Exposure => GH_Exposure.secondary;

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

        /// <summary>
        /// Gets the unique ID for this component. Do not change this ID after release.
        /// </summary>
        public override Guid ComponentGuid => new Guid("08D7360F-EFED-420E-8F32-28A6458D529C");
    }
}
#endif
303 files24 directories