public void setLatestJointDisplResult(jointDispl resultObject)
    {
        latestJointDisplResult = resultObject;
        jointDisplHistory.Insert(0, resultObject);
        if (jointDisplHistory.Count > resultHistorySlots)
        {
            jointDisplHistory.RemoveAt(frameJointForceHistory.Count - 1);
        }
        string debugMessage = "set latest JointDispl result:\n" + resultObject.ToString();

        Debug.Log(debugMessage);
    }
    public void sendString(string message)
    {
        if (pipeStreamString == null)
        {
            Debug.Log("Tried to send message \"" + message + "\" to SAPTranslator, but SAPTranslator has not connected to pipe.");
            return;
        }
        else
        {
            string pipeContent = pipeStreamString.ReadString();
            if (pipeContent != null)
            {
                Debug.Log(pipeContent);
            }
            if (pipeContent.Equals("SAPTranslator to VRE: awaiting command"))
            {
                Debug.Log(message);
                pipeStreamString.WriteString(message);
                pipeServer.WaitForPipeDrain();

                if (message.Contains("resultsFrameJointForce"))
                {
                    frameJointForce frameJointForceObject = readResponseResultsFrameJointForce();
                    myAnalysisController.setLatestFrameJointForceResult(frameJointForceObject);
                }
                else if (message.Contains("resultsFrameForce"))
                {
                    frameForce frameForceObject = readResponseResultsFrameForce();
                    myAnalysisController.setLatestFrameForceResult(frameForceObject);
                }
                else if (message.Contains("resultsJointDispl") || message.Contains("customResultsGetFrameSpecialPointDispl"))
                {
                    jointDispl jointDisplObject = readResponseResultsJointDispl();
                    myAnalysisController.setLatestJointDisplResult(jointDisplObject);
                }
            }
        }
    }
    public void visualizeDeformation(string frameName, jointDispl specialPointsJointDispl)
    {
        Frame targetFrame = myConstructorController.findFrame(frameName);

        targetFrame.setReleaseNeither();
        SplineMesh.Spline targetSpline = targetFrame.GetGameObject().GetComponentInChildren <SplineMesh.Spline>();
        int     numNodesPrevious       = targetSpline.nodes.Count;
        double  frameScale             = targetFrame.getTransform().lossyScale.y;
        double  frameLength            = targetFrame.getLength();
        double  baseX = 0;
        double  baseY = 0;
        double  baseZ = 0;
        Vector3 basePosition;

        while (targetSpline.nodes.Count < specialPointsJointDispl.numberResults)
        {
            targetSpline.AddNode(new SplineMesh.SplineNode(Vector3.zero, Vector3.zero));
        }

        int maxIndex = specialPointsJointDispl.numberResults - 1;

        for (int i = 0; i <= maxIndex; i++)
        {
            double u1 = specialPointsJointDispl.u1[i]; // WAIT global unity x
            double u2 = specialPointsJointDispl.u2[i]; // global unity z
            double u3 = specialPointsJointDispl.u3[i]; // global unity y
            double r1 = specialPointsJointDispl.r1[i];
            double r2 = specialPointsJointDispl.r2[i];
            double r3 = specialPointsJointDispl.r3[i];

            baseY = (double)i / (double)maxIndex;

            // Explanation for the following if-else-if block:
            // If a special point is set exactly at the end of a frame in SAP,
            // then that points will have a local coordinate system that may not align with every frame that ends on the point.
            // As a stopgap fix, SAPTranslator currently places the "end" points slightly into the length of the frame (by 0.001 of the frame's length).
            // This if-else block reflects that positioning in the VR visualization for accuracy.
            // Currently, the VR environment does not show those last 0.1% of the frame on either end, when showing deformation,
            // but that shouldn't be a problem just for a general visualization of the result.
            // It's a problem that needs to be solved if one wishes to be able to click on endpoints specifically and see their exact displacements in VR, though.
            if (baseY == 0)
            {
                baseY += 0.001;
            }
            else if (baseY == 1)
            {
                baseY -= 0.001;
            }


            Vector3 localBasePosition = new Vector3((float)baseX, (float)baseY, (float)baseZ);

            Vector3 globalBasePosition = targetFrame.getTransform().TransformPoint(localBasePosition);

            //float deltaX = (float)(u2 * visualizationScale);
            //float deltaY = (float)((u1 / frameScale) * visualizationScale);
            //float deltaZ = (float)(-1 * u3 * visualizationScale);
            //Vector3 deltaPosition = new Vector3(deltaX, deltaY, deltaZ);

            Vector3 globalDelta = new Vector3((float)(u1 * visualizationScale), (float)(u3 * visualizationScale), (float)(u2 * visualizationScale));

            //Vector3 globalFinal = globalBasePosition + globalDelta;

            //Vector3 localFinal = targetFrame.getTransform().InverseTransformPoint(globalFinal);
            Vector3 localDelta = targetFrame.getTransform().InverseTransformVector(globalDelta);
            localDelta.Set(localDelta.x, (float)(localDelta.y / 5.0), localDelta.z);
            //Vector3 iDontKnowWhyThisIsNecessary = new Vector3(localDelta.z, localDelta.x, localDelta.y);
            //localFinal.y =  (float)(localFinal.y / frameScale);



            Vector3 updatedNodePosition  = localBasePosition + localDelta;
            Vector3 updatedNodeDirection = new Vector3(updatedNodePosition.x, updatedNodePosition.y + (float)0.001, updatedNodePosition.z);
            Vector3 updatedNodeUp        = new Vector3(0, 0, -1);
            //lookAt = Quaternion.Euler((float)(r3 / frameScale), (float)(r1), (float)(r2 / frameScale)) * lookAt;

            //SplineMesh.SplineNode newSplineNode = new SplineMesh.SplineNode(nodePosition, lookAt);
            targetSpline.nodes[i].Position  = updatedNodePosition;
            targetSpline.nodes[i].Direction = updatedNodeDirection;
            targetSpline.nodes[i].Up        = updatedNodeUp;
        }
    }
    private jointDispl readResponseResultsJointDispl()
    {
        string[] results = new string[15];
        for (int i = 0; i < results.Length; i++)
        {
            results[i] = pipeStreamString.ReadString();
        }

        //Debug:
        string resultsAsOneString = String.Join("\n", results);

        Debug.Log(resultsAsOneString);
        string messageHeader = results[0];
        string name          = results[1];
        string itemType      = results[2];
        int    numberResults;

        try
        {
            numberResults = int.Parse(results[3], System.Globalization.NumberStyles.Integer);
        }
        catch (FormatException)
        {
            numberResults = 2;
        }
        string[] obj      = results[4].Split('`');
        string[] elm      = results[5].Split('`');
        string[] loadCase = results[6].Split('`');
        string[] stepType = results[7].Split('`');

        string[] stepNumStrings = results[8].Split('`');
        string[] u1Strings      = results[9].Split('`');
        string[] u2Strings      = results[10].Split('`');
        string[] u3Strings      = results[11].Split('`');
        string[] r1Strings      = results[12].Split('`');
        string[] r2Strings      = results[13].Split('`');
        string[] r3Strings      = results[14].Split('`');

        double[] stepNum = new double[numberResults];
        double[] u1      = new double[numberResults];
        double[] u2      = new double[numberResults];
        double[] u3      = new double[numberResults];
        double[] r1      = new double[numberResults];
        double[] r2      = new double[numberResults];
        double[] r3      = new double[numberResults];

        for (int i = 0; i < numberResults; i++)
        {
            stepNum[i] = Double.Parse(stepNumStrings[i]);
            u1[i]      = Double.Parse(u1Strings[i]);
            u2[i]      = Double.Parse(u2Strings[i]);
            u3[i]      = Double.Parse(u3Strings[i]);
            r1[i]      = Double.Parse(r1Strings[i]);
            r2[i]      = Double.Parse(r2Strings[i]);
            r3[i]      = Double.Parse(r3Strings[i]);
        }

        jointDispl result = new jointDispl(name,
                                           itemType, numberResults, obj, elm,
                                           loadCase, stepType, stepNum, u1, u2, u3, r1, r2, r3);

        return(result);
    }