public void getForcesDiagram(AbstractCase ac, LineElement line, LineForceComponent component, float[,] controlPoints, out float fI, out float fJ)
        {
            Vector3 vI, vJ;
            switch (component)
            {
                case LineForceComponent.Axial:
                case LineForceComponent.Shear22:
                case LineForceComponent.Shear33:
                    vI = new Vector3(model.Results.ElementJointForces[line.Id, 0, 0],
                                     model.Results.ElementJointForces[line.Id, 0, 1],
                                     model.Results.ElementJointForces[line.Id, 0, 2]);
                    vJ = new Vector3(model.Results.ElementJointForces[line.Id, 1, 0],
                                     model.Results.ElementJointForces[line.Id, 1, 1],
                                     model.Results.ElementJointForces[line.Id, 1, 2]);
                    break;
                default:
                    vI = new Vector3(model.Results.ElementJointForces[line.Id, 0, 3],
                                     model.Results.ElementJointForces[line.Id, 0, 4],
                                     model.Results.ElementJointForces[line.Id, 0, 5]);
                    vJ = new Vector3(model.Results.ElementJointForces[line.Id, 1, 3],
                                     model.Results.ElementJointForces[line.Id, 1, 4],
                                     model.Results.ElementJointForces[line.Id, 1, 5]);
                    break;
            }

            // Transform to the line's local coordinate system
            // From the global system
            // (WARNING: This is supposed to come in the joint's local coordinate system)
            vI = toLocal(line, vI);
            vJ = toLocal(line, vJ);

            switch (component)
            {
                case LineForceComponent.Axial:
                case LineForceComponent.Torsion:
                    fI = vI.X;
                    fJ = vJ.X;
                    break;
                case LineForceComponent.Shear22:
                case LineForceComponent.Moment22:
                    fI = vI.Y;
                    fJ = vJ.Y;
                    break;
                default:
                    fI = vI.Z;
                    fJ = vJ.Z;
                    break;
            }

            //float fI = model.Results.ElementJointForces[line.Id, 0, (int)component];
            //float fJ = model.Results.ElementJointForces[line.Id, 1, (int)component];

            // Add Isostatic curves if there's a load on the LineElement
            addToShearMomentDiagram(ac, line, controlPoints, component, 1f);
        }
        public float[] GetForceAtPoint(AbstractCase ac, LineElement line, LineForceComponent component, float xPos)
        {
            if (!model.HasResults) return null;

            float[,] controlPoints = new float[1, 2];
            controlPoints[0, 0] = xPos;
            controlPoints[0, 1] = 0f;

            float fI, fJ;
            getForcesDiagram(ac, line, component, controlPoints, out fI, out fJ);

            // Los valores en los nodos se encuentran volteados. Del lado izquierdo positivo
            // es arriba, mientras del lado derecho positivo es abajo, por lo que si se tienen
            // dos valores positivos se debería pintar una recta con pendiente negativa y si
            // se tienen dos negativos al revés. DeltaY = Y1 + Y2 (por el cambio de signo).
            controlPoints[0, 1] += controlPoints[0, 0] * (fI + fJ) - fI;

            // Copy to 1-dimensional array
            float[] ret = new float[2];
            for (int i = 0; i < 2; i++)
                ret[i] = controlPoints[0, i];

            return ret;
        }
        private void addToShearMomentDiagram(AbstractCase ac, LineElement line, float[,] controlPoints, LineForceComponent component, float scale)
        {
            if (ac == null) return;

            if (ac is LoadCombination)
            {
                foreach (AbstractCaseFactor acf in ((LoadCombination)ac).Cases)
                    addToShearMomentDiagram(acf.Case, line, controlPoints, component, acf.Factor);
            }
            else if (ac is AnalysisCase)
            {
                if (((AnalysisCase)ac).Properties is StaticCaseProps)
                {
                    foreach (StaticCaseFactor staticCase in ((StaticCaseProps)((AnalysisCase)ac).Properties).Loads)
                    {
                        if (staticCase.AppliedLoad is LoadCase)
                        {
                            LoadCase lc = staticCase.AppliedLoad as LoadCase;
                            if (line.Loads[lc] != null)
                            {
                                foreach (Load load in line.Loads[lc])
                                    if (load is DirectionalLineLoad)
                                        addToShearMomentDiagram(line, load as DirectionalLineLoad, controlPoints, component, scale);
                            }

                            if (lc.SelfWeight > 0f)
                            {
                                if (line.Properties is StraightFrameProps)
                                {
                                    StraightFrameProps frameProps = line.Properties as StraightFrameProps;
                                    selfWeight.La = selfWeight.Lb = frameProps.Section.Area * frameProps.Section.Material.UnitWeight;
                                    addToShearMomentDiagram(line, selfWeight, controlPoints, component, lc.SelfWeight * scale);
                                }
                            }
                        }
                    }
                }
            }
        }
        private void addToShearMomentDiagram(LineElement line, DirectionalLineLoad load, float[,] controlPoints, LineForceComponent component, float scale)
        {
            if (load == null) return;

            float dirComponent = 0f, position;

            // Get Load direction in Local Coordinate frame
            Vector3 dir = getLocalDir(line, load.Direction);

            switch (component)
            {
                case LineForceComponent.Axial:
                case LineForceComponent.Torsion:
                    dirComponent = dir.X;
                    break;
                case LineForceComponent.Shear22:
                case LineForceComponent.Moment33:
                    dirComponent = dir.Y;
                    break;
                case LineForceComponent.Shear33:
                case LineForceComponent.Moment22:
                    dirComponent = dir.Z;
                    break;
            }

            int i;
            switch (component)
            {
                case LineForceComponent.Shear22:
                case LineForceComponent.Shear33:
                    for (i = 0; i < controlPoints.GetLength(0); i++)
                    {
                        position = controlPoints[i,0] * line.Length;
                        controlPoints[i, 1] += addToShearDiagram(load, dirComponent, position, line.Length) * scale;
                    }
                    break;
                case LineForceComponent.Moment33:
                    dirComponent = -dirComponent;
                    for (i = 0; i < controlPoints.GetLength(0); i++)
                    {
                        position = controlPoints[i,0] * line.Length;
                        controlPoints[i, 1] += addToMomentDiagram(load, dirComponent, position, line.Length) * scale;
                    }
                    break;
                case LineForceComponent.Moment22:
                    for (i = 0; i < controlPoints.GetLength(0); i++)
                    {
                        position = controlPoints[i,0] * line.Length;
                        controlPoints[i, 1] += addToMomentDiagram(load, dirComponent, position, line.Length) * scale;
                    }
                    break;
                default:
                    break;
            }
        }
        public float[,] GetForcesDiagram(AbstractCase ac, LineElement line, LineForceComponent component, int numPoints)
        {
            if (!model.HasResults) return null;

            float[,] controlPoints = new float[numPoints, 2];

            float[] controlPointsX = new float[1]; // requestXCtrlPts(load);
            for (int i = 0, bufi = 0; i < numPoints; i++)
            {
                controlPoints[i,0] = i / (numPoints - 1f);

                // Adjust control points
                if ((bufi < controlPointsX.Length) && (controlPointsX[bufi] <= controlPoints[i, 0]))
                    controlPoints[i, 0] = controlPointsX[bufi++];

                controlPoints[i, 1] = 0f; // controlPoints[i, 0] * (fdJ - fdI);
            }

            float fI, fJ;
            getForcesDiagram(ac, line, component, controlPoints, out fI, out fJ);

            for (int i = 0, bufi = 0; i < numPoints; i++)
            {
                // Los valores en los nodos se encuentran volteados. Del lado izquierdo positivo
                // es arriba, mientras del lado derecho positivo es abajo, por lo que si se tienen
                // dos valores positivos se debería pintar una recta con pendiente negativa y si
                // se tienen dos negativos al revés. DeltaY = Y1 + Y2 (por el cambio de signo).
                controlPoints[i, 1] += controlPoints[i, 0] * (fI + fJ) - fI;
            }

            return controlPoints;
        }