/// <summary>
 /// Method to create a absolute joint movement with an empty robot tool (no override).
 /// </summary>
 /// <param name="name">Name of joint target, must be unique.</param>
 /// <param name="internalAxisValues">List of internal axis values. The length of the list should be equal to 6.</param>
 /// <param name="externalAxisValues">List of external axis values. </param>
 /// <param name="speedData"> The SpeedData as a SpeedData </param>
 /// <param name="precision"> Robot movement precision. This value will be casted to the nearest predefined zonedata value. Use -1 for fine. </param>
 public AbsoluteJointMovement(string name, List <double> internalAxisValues, List <double> externalAxisValues, SpeedData speedData, int precision)
 {
     _name = name;
     _internalAxisValues = CheckInternalAxisValues(internalAxisValues);
     _externalAxisValues = CheckExternalAxisValues(externalAxisValues);
     _speedData          = speedData;
     _movementType       = MovementType.MoveAbsJ; // The movement type is always an Absolute Joint Movement
     _zoneData           = new ZoneData(precision);
     _robotTool          = new RobotTool();       // Default Robot Tool tool0
     _robotTool.Clear();                          // Empty Robot Tool
 }
 /// <summary>
 /// Method to create an absolute joint movement with internal and external axis values.
 /// </summary>
 /// <param name="name">Name of joint target, must be unique.</param>
 /// <param name="internalAxisValues">List of internal axis values. The length of the list should be equal to 6.</param>
 /// <param name="externalAxisValues">List of external axis values. </param>
 public AbsoluteJointMovement(string name, List <double> internalAxisValues, List <double> externalAxisValues)
 {
     _name = name;
     _internalAxisValues = CheckInternalAxisValues(internalAxisValues);
     _externalAxisValues = CheckExternalAxisValues(externalAxisValues);
     _speedData          = new SpeedData(5);      // Slowest predefined tcp speed
     _movementType       = MovementType.MoveAbsJ; // The movementType is always an Absolute Joint Movement
     _zoneData           = new ZoneData(0);
     _robotTool          = new RobotTool();       // Default Robot Tool tool0
     _robotTool.Clear();                          // Empty Robot Tool
 }
 /// <summary>
 /// Initializes a new instance of the Movement class.
 /// This constructor is typically used to cast a Robot Target to a movement.
 /// </summary>
 /// <param name="target"> The Target. </param>
 public Movement(ITarget target)
 {
     _movementType = 0;
     _target       = target;
     _id           = -1;
     _speedData    = new SpeedData(5);     // Slowest predefined tcp speed
     _zoneData     = new ZoneData(0);
     _robotTool    = new RobotTool();      // Default Robot Tool tool0
     _robotTool.Clear();                   // Empty Robot Tool
     _workObject    = new WorkObject();    // Default work object wobj0
     _digitalOutput = new DigitalOutput(); // InValid / empty DO
 }
 /// <summary>
 /// Initializes a new instance of the Movement class with an empty Robot Tool (no override) and a default Work Object (wobj0)
 /// </summary>
 /// <param name="movementType"> The Movement Type. </param>
 /// <param name="target"> The Target. </param>
 /// <param name="speedData"> The Speed Data.</param>
 /// <param name="zoneData"> The Zone Data. </param>
 /// <param name="digitalOutput"> The Digital Output. When set this will define a MoveLDO or a MoveJDO instruction. </param>
 public Movement(MovementType movementType, ITarget target, SpeedData speedData, ZoneData zoneData, DigitalOutput digitalOutput)
 {
     _movementType = movementType;
     _target       = target;
     _id           = -1;
     _speedData    = speedData;
     _zoneData     = zoneData;
     _robotTool    = new RobotTool();   // Default Robot Tool tool0
     _robotTool.Clear();                // Empty Robot Tool
     _workObject    = new WorkObject(); // Default work object wobj0
     _digitalOutput = digitalOutput;
     CheckCombination();
 }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // Warning that this component is OBSOLETE
            AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "This component is OBSOLETE and will be removed in the future. Instead, " +
                              "combine Joint Targets with Movements.");

            // Input variables
            List <string>            names = new List <string>();
            GH_Structure <GH_Number> internalAxisValuesTree = new GH_Structure <GH_Number>();
            GH_Structure <GH_Number> externalAxisValuesTree = new GH_Structure <GH_Number>();
            List <SpeedData>         speedDatas             = new List <SpeedData>();
            List <ZoneData>          zoneDatas  = new List <ZoneData>();
            List <RobotTool>         robotTools = new List <RobotTool>();

            // Create an empty Robot Tool
            RobotTool emptyRobotTool = new RobotTool();

            emptyRobotTool.Clear();

            // Catch the input data from the fixed parameters
            if (!DA.GetDataList(0, names))
            {
                return;
            }
            if (!DA.GetDataTree(1, out internalAxisValuesTree))
            {
                return;
            }
            if (!DA.GetDataTree(2, out externalAxisValuesTree))
            {
                return;
            }
            if (!DA.GetDataList(3, speedDatas))
            {
                return;
            }
            if (!DA.GetDataList(4, zoneDatas))
            {
                zoneDatas = new List <ZoneData>()
                {
                    new ZoneData(0)
                };
            }

            // Catch the input data from the variable parameteres
            if (Params.Input.Any(x => x.Name == variableInputParameters[0].Name))
            {
                if (!DA.GetDataList(variableInputParameters[0].Name, robotTools))
                {
                    robotTools = new List <RobotTool>()
                    {
                        new RobotTool(emptyRobotTool)
                    };
                }
            }

            // Make sure variable input parameters have a default value
            if (robotTools.Count == 0)
            {
                robotTools.Add(new RobotTool(emptyRobotTool)); // Empty Robot Tool
            }

            // Get longest Input List
            int[] sizeValues = new int[6];
            sizeValues[0] = names.Count;
            sizeValues[1] = internalAxisValuesTree.PathCount;
            sizeValues[2] = externalAxisValuesTree.PathCount;
            sizeValues[3] = speedDatas.Count;
            sizeValues[4] = zoneDatas.Count;
            sizeValues[5] = robotTools.Count;

            int biggestSize = HelperMethods.GetBiggestValue(sizeValues);

            // Keeps track of used indicies
            int namesCounter         = -1;
            int internalValueCounter = -1;
            int externalValueCounter = -1;
            int speedDataCounter     = -1;
            int precisionCounter     = -1;
            int robotToolCounter     = -1;

            // Clear list
            _jointMovements.Clear();

            // Creates movements
            for (int i = 0; i < biggestSize; i++)
            {
                string        name;
                List <double> internalAxisValues = new List <double>();
                List <double> externalAxisValues = new List <double>();

                SpeedData speedData;
                ZoneData  zoneData;
                RobotTool robotTool;

                // Target counter
                if (i < sizeValues[0])
                {
                    name = names[i];
                    namesCounter++;
                }
                else
                {
                    name = names[namesCounter] + "_" + (i - namesCounter);
                }

                // internal axis values counter
                if (i < sizeValues[1])
                {
                    internalAxisValues = internalAxisValuesTree[i].ConvertAll(x => (double)x.Value);
                    internalValueCounter++;
                }
                else
                {
                    internalAxisValues = internalAxisValuesTree[internalValueCounter].ConvertAll(x => (double)x.Value);
                }

                // External axis values counter
                if (sizeValues[2] == 0) // In case no external axis values are defined.
                {
                    externalAxisValues = new List <double>()
                    {
                    };
                }

                else
                {
                    if (i < sizeValues[2])
                    {
                        externalAxisValues = externalAxisValuesTree[i].ConvertAll(x => (double)x.Value);
                        externalValueCounter++;
                    }
                    else
                    {
                        externalAxisValues = externalAxisValuesTree[externalValueCounter].ConvertAll(x => (double)x.Value);
                    }
                }

                // SpeedData counter
                if (i < sizeValues[3])
                {
                    speedData = speedDatas[i];
                    speedDataCounter++;
                }
                else
                {
                    speedData = speedDatas[speedDataCounter];
                }

                // Precision counter
                if (i < sizeValues[4])
                {
                    zoneData = zoneDatas[i];
                    precisionCounter++;
                }
                else
                {
                    zoneData = zoneDatas[precisionCounter];
                }

                // Robot tool counter
                if (i < sizeValues[5])
                {
                    robotTool = robotTools[i];
                    robotToolCounter++;
                }
                else
                {
                    robotTool = robotTools[robotToolCounter];
                }

                // JointMovement constructor
                AbsoluteJointMovement jointMovement = new AbsoluteJointMovement(name, internalAxisValues, externalAxisValues, speedData, zoneData, robotTool);
                _jointMovements.Add(jointMovement);
            }

            // Check if an exact predefined zonedata value is used
            for (int i = 0; i < zoneDatas.Count; i++)
            {
                if (zoneDatas[i].ExactPredefinedValue == false & zoneDatas[i].PreDefinied == true)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Predefined zonedata value <" + i + "> is invalid. " +
                                      "The nearest valid predefined speeddata value is used. Valid predefined zonedata values are -1, " +
                                      "0, 1, 5, 10, 15, 20, 30, 40, 50, 60, 80, 100, 150 or 200. " +
                                      "A value of -1 will be interpreted as fine movement in RAPID Code.");
                    break;
                }
            }

            // Check if an exact predefined speeddata value is used
            for (int i = 0; i < speedDatas.Count; i++)
            {
                if (speedDatas[i].ExactPredefinedValue == false & speedDatas[i].PreDefinied == true)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Predefined speeddata value <" + i + "> is invalid. " +
                                      "The nearest valid predefined speeddata value is used. Valid predefined speeddata values are 5, 10, " +
                                      "20, 30, 40, 50, 60, 80, 100, 150, 200, 300, 400, 500, 600, 800, 1000, 1500, 2000, 2500, 3000, 4000, " +
                                      "5000, 6000 and 7000.");
                    break;
                }
            }

            // Output
            DA.SetDataList(0, _jointMovements);

            #region Object manager
            // Gets ObjectManager of this document
            _objectManager = DocumentManager.GetDocumentObjectManager(this.OnPingDocument());

            // Clears targetNames
            for (int i = 0; i < _targetNames.Count; i++)
            {
                _objectManager.TargetNames.Remove(_targetNames[i]);
            }
            _targetNames.Clear();

            // Removes lastName from targetNameList
            if (_objectManager.TargetNames.Contains(_lastName))
            {
                _objectManager.TargetNames.Remove(_lastName);
            }

            // Adds Component to JointTargetsByGuid Dictionary
            if (!_objectManager.OldJointTargetsByGuid2.ContainsKey(this.InstanceGuid))
            {
                _objectManager.OldJointTargetsByGuid2.Add(this.InstanceGuid, this);
            }

            // Checks if target name is already in use and counts duplicates
            #region Check name in object manager
            _namesUnique = true;
            for (int i = 0; i < names.Count; i++)
            {
                if (_objectManager.TargetNames.Contains(names[i]))
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Target Name already in use.");
                    _namesUnique = false;
                    _lastName    = "";
                    break;
                }
                else
                {
                    // Adds Target Name to list
                    _targetNames.Add(names[i]);
                    _objectManager.TargetNames.Add(names[i]);

                    // Run SolveInstance on other Targets with no unique Name to check if their name is now available
                    _objectManager.UpdateTargets();

                    _lastName = names[i];
                }

                // Checks if variable name exceeds max character limit for RAPID Code
                if (HelperMethods.VariableExeedsCharacterLimit32(names[i]))
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Target Name exceeds character limit of 32 characters.");
                    break;
                }

                // Checks if variable name starts with a number
                if (HelperMethods.VariableStartsWithNumber(names[i]))
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Target Name starts with a number which is not allowed in RAPID Code.");
                    break;
                }
            }
            #endregion

            // Recognizes if Component is Deleted and removes it from Object Managers target and name list
            GH_Document doc = this.OnPingDocument();
            if (doc != null)
            {
                doc.ObjectsDeleted += DocumentObjectsDeleted;
            }
            #endregion
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // Warning that this component is OBSOLETE
            AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "This component is OBSOLETE and will be removed " +
                              "in the future. Remove this component from your canvas and replace it by picking the new component " +
                              "from the ribbon.");

            // Creates the input value list and attachs it to the input parameter
            CreateValueList();

            // Expire solution of this component
            if (_expire == true)
            {
                _expire = false;
                this.ExpireSolution(true);
            }

            // Input variables
            List <ITarget>       targets        = new List <ITarget>();
            List <SpeedData>     speedDatas     = new List <SpeedData>();
            List <int>           movementTypes  = new List <int>();
            List <ZoneData>      zoneDatas      = new List <ZoneData>();
            List <RobotTool>     robotTools     = new List <RobotTool>();
            List <WorkObject>    workObjects    = new List <WorkObject>();
            List <DigitalOutput> digitalOutputs = new List <DigitalOutput>();

            // Create an empty Robot Tool
            RobotTool emptyRobotTool = new RobotTool();

            emptyRobotTool.Clear();

            // Catch the input data from the fixed parameters
            if (!DA.GetDataList(0, targets))
            {
                return;
            }
            if (!DA.GetDataList(1, speedDatas))
            {
                return;
            }
            if (!DA.GetDataList(2, movementTypes))
            {
                return;
            }
            if (!DA.GetDataList(3, zoneDatas))
            {
                zoneDatas = new List <ZoneData>()
                {
                    new ZoneData(0)
                };
            }

            // Catch the input data from the variable parameteres
            if (Params.Input.Any(x => x.Name == variableInputParameters[0].Name))
            {
                if (!DA.GetDataList(variableInputParameters[0].Name, robotTools))
                {
                    robotTools = new List <RobotTool>()
                    {
                        new RobotTool(emptyRobotTool)
                    };
                }
            }
            if (Params.Input.Any(x => x.Name == variableInputParameters[1].Name))
            {
                if (!DA.GetDataList(variableInputParameters[1].Name, workObjects))
                {
                    workObjects = new List <WorkObject>()
                    {
                        new WorkObject()
                    };
                }
            }
            if (Params.Input.Any(x => x.Name == variableInputParameters[2].Name))
            {
                if (!DA.GetDataList(variableInputParameters[2].Name, digitalOutputs))
                {
                    digitalOutputs = new List <DigitalOutput>()
                    {
                        new DigitalOutput()
                    };
                }
            }

            // Make sure variable input parameters have a default value
            if (robotTools.Count == 0)
            {
                robotTools.Add(new RobotTool(emptyRobotTool)); // Empty Robot Tool
            }
            if (workObjects.Count == 0)
            {
                workObjects.Add(new WorkObject()); // Makes a default WorkObject (wobj0)
            }
            if (digitalOutputs.Count == 0)
            {
                digitalOutputs.Add(new DigitalOutput()); // InValid / empty DO
            }

            // Get longest Input List
            int[] sizeValues = new int[7];
            sizeValues[0] = targets.Count;
            sizeValues[1] = speedDatas.Count;
            sizeValues[2] = movementTypes.Count;
            sizeValues[3] = zoneDatas.Count;
            sizeValues[4] = robotTools.Count;
            sizeValues[5] = workObjects.Count;
            sizeValues[6] = digitalOutputs.Count;

            int biggestSize = HelperMethods.GetBiggestValue(sizeValues);

            // Keeps track of used indicies
            int targetGooCounter        = -1;
            int speedDataCounter        = -1;
            int movementTypeCounter     = -1;
            int zoneDataCounter         = -1;
            int robotToolGooCounter     = -1;
            int workObjectGooCounter    = -1;
            int digitalOutputGooCounter = -1;

            // Creates movements
            List <Movement> movements = new List <Movement>();

            for (int i = 0; i < biggestSize; i++)
            {
                ITarget       target;
                SpeedData     speedData;
                int           movementType;
                ZoneData      zoneData;
                RobotTool     robotTool;
                WorkObject    workObject;
                DigitalOutput digitalOutput;

                // Target counter
                if (i < sizeValues[0])
                {
                    target = targets[i];
                    targetGooCounter++;
                }
                else
                {
                    target = targets[targetGooCounter];
                }

                // Workobject counter
                if (i < sizeValues[1])
                {
                    speedData = speedDatas[i];
                    speedDataCounter++;
                }
                else
                {
                    speedData = speedDatas[speedDataCounter];
                }

                // Movement type counter
                if (i < sizeValues[2])
                {
                    movementType = movementTypes[i];
                    movementTypeCounter++;
                }
                else
                {
                    movementType = movementTypes[movementTypeCounter];
                }

                // Precision counter
                if (i < sizeValues[3])
                {
                    zoneData = zoneDatas[i];
                    zoneDataCounter++;
                }
                else
                {
                    zoneData = zoneDatas[zoneDataCounter];
                }

                // Robot tool counter
                if (i < sizeValues[4])
                {
                    robotTool = robotTools[i];
                    robotToolGooCounter++;
                }
                else
                {
                    robotTool = robotTools[robotToolGooCounter];
                }

                // Work Object counter
                if (i < sizeValues[5])
                {
                    workObject = workObjects[i];
                    workObjectGooCounter++;
                }
                else
                {
                    workObject = workObjects[workObjectGooCounter];
                }

                // Digital Output counter
                if (i < sizeValues[6])
                {
                    digitalOutput = digitalOutputs[i];
                    digitalOutputGooCounter++;
                }
                else
                {
                    digitalOutput = digitalOutputs[digitalOutputGooCounter];
                }

                // Movement constructor
                Movement movement = new Movement((MovementType)movementType, target, speedData, zoneData, robotTool, workObject, digitalOutput);
                movements.Add(movement);
            }

            // Check if a right value is used for the movement type
            for (int i = 0; i < movementTypes.Count; i++)
            {
                if (movementTypes[i] != 0 && movementTypes[i] != 1 && movementTypes[i] != 2)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Movement type value <" + i + "> is invalid. " +
                                      "In can only be set to 0, 1 and 2. Use 0 for MoveAbsJ, 1 for MoveL and 2 for MoveJ.");
                    break;
                }
            }

            // Check if an exact predefined zonedata value is used
            for (int i = 0; i < zoneDatas.Count; i++)
            {
                if (zoneDatas[i].ExactPredefinedValue == false & zoneDatas[i].PreDefinied == true)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Predefined zonedata value <" + i + "> is invalid. " +
                                      "The nearest valid predefined speeddata value is used. Valid predefined zonedata values are -1, " +
                                      "0, 1, 5, 10, 15, 20, 30, 40, 50, 60, 80, 100, 150 or 200. " +
                                      "A value of -1 will be interpreted as fine movement in RAPID Code.");
                    break;
                }
            }

            // Check if an exact predefined speeddata value is used
            for (int i = 0; i < speedDatas.Count; i++)
            {
                if (speedDatas[i].ExactPredefinedValue == false & speedDatas[i].PreDefinied == true)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Predefined speeddata value <" + i + "> is invalid. " +
                                      "The nearest valid predefined speed data value is used. Valid predefined speeddata values are 5, 10, " +
                                      "20, 30, 40, 50, 60, 80, 100, 150, 200, 300, 400, 500, 600, 800, 1000, 1500, 2000, 2500, 3000, 4000, " +
                                      "5000, 6000 and 7000.");
                    break;
                }
            }

            // Output
            DA.SetDataList(0, movements);
        }