/// <summary>
        /// Determines if the inputted selection is valid. 
        /// </summary>
        /// <param name="SelType">The type of the selection<param>
        /// <param name="Selection">The Selected object</param>
        /// <param name="selBox">The Selection box that the selected object is in</param>
        /// <returns>returns true if the object is a valid limit selection</returns>
        public override bool IsValidLimitSelection(int SelType, object Selection, IPropertyManagerPageControl selBox)
        {
            if (Axis == null)//if there is no rotation axis then no selections can be valid
            {
                if (((SelectionMgr)modelDoc.SelectionManager).GetSelectedObject6(1, 2) != null)
                {
                    Axis = ((SelectionMgr)modelDoc.SelectionManager).GetSelectedObject6(1, 2);
                }
                else
                {
                    selBox.ShowBubbleTooltip("Error: no joint axis", "Select the first axis for this joint before selecting other features", "");
                    return false;
                }

            }

            string colinearErrorMsgTitle = "Error: Selection can not be Colinear with joint axis";
            string colinearErrorMsg = "The selected feature must no be colinear to the axis of rotation";
            string perpErrorMsgTitle = "Error: Selection must be perpendicular to joint axis";
            string perpErrorMsg = "The selected feature must be perpindicular to the axis of rotation";

            MathTransform componentTransform = null;
            if ((Component2)((IEntity)Selection).GetComponent() != null)//gets the component transform if one exists. this allows for conversion between the components local space and the global space
            {
                componentTransform = ((Component2)((IEntity)Selection).GetComponent()).Transform2;
            }
            double[] tempAxisNormalVector = { AxisX, AxisY, AxisZ };
            MathVector axisNormalVector = mathUtil.CreateVector(tempAxisNormalVector).Normalise();//creates a vector to represent the aXis of movment

            MathVector featureNormalVector = null;
            MathPoint jointOrigin = mathUtil.CreatePoint(Point);
            double[] tempArray;
            switch ((swSelectType_e)SelType)
            {
                case swSelectType_e.swSelDATUMAXES:
                    double[] refAxisPoints = ((IRefAxis)((IFeature)Selection).GetSpecificFeature2()).GetRefAxisParams();
                    tempArray = new double[] { refAxisPoints[3] - refAxisPoints[0], refAxisPoints[4] - refAxisPoints[1], refAxisPoints[5] - refAxisPoints[2] };
                    MathPoint refAxisPoint = VectorCalcs.CreatePoint(componentTransform,refAxisPoints.Take(3).ToArray());
                    featureNormalVector = VectorCalcs.CreateVector(componentTransform,tempArray);
                    if (VectorCalcs.IsParallel(featureNormalVector, axisNormalVector))
                    {
                        if (VectorCalcs.IsPointOnLine(featureNormalVector, refAxisPoint, jointOrigin))
                        {
                            selBox.ShowBubbleTooltip(colinearErrorMsgTitle, colinearErrorMsg, "");
                            return false;
                        }
                        else
                            return true;
                    }
                    else
                        return true;

                case swSelectType_e.swSelDATUMPLANES:
                    tempArray = new double[] { 0, 0, 1 };//temp vector used to find normal vector of plane
                    MathTransform tempTransform = ((IRefPlane)((IFeature)Selection).GetSpecificFeature2()).Transform; //represents the transform of the plane from being the xy plane
                    MathVector planeNormalVector = mathUtil.CreateVector(tempArray);
                    if (componentTransform != null)//finds normal vecor of plane and transforms it if needed
                    {
                        featureNormalVector = planeNormalVector.MultiplyTransform(tempTransform).MultiplyTransform(componentTransform).Normalise();
                    }
                    else
                    {
                        featureNormalVector = planeNormalVector.MultiplyTransform(tempTransform).Normalise();
                    }
                    if (!VectorCalcs.IsPerpendicular(axisNormalVector,featureNormalVector))
                    {
                        selBox.ShowBubbleTooltip(perpErrorMsgTitle, perpErrorMsg, "");
                        return false;
                    }
                    else
                        return true;

                case swSelectType_e.swSelDATUMPOINTS:
                    MathPoint refPoint = ((IRefPoint)((IFeature)Selection).GetSpecificFeature2()).GetRefPoint();
                    if (componentTransform != null)//if the point is part of a sub component, it is transformed to 3d space
                    {
                        refPoint = refPoint.MultiplyTransform(componentTransform);
                    }

                    if(VectorCalcs.IsPointOnLine(axisNormalVector,jointOrigin,refPoint))
                    {
                        selBox.ShowBubbleTooltip(colinearErrorMsgTitle, colinearErrorMsg, "");
                        return false;
                    }
                    else
                        return true;

                case swSelectType_e.swSelEDGES:
                    object[] faces = ((IEdge)Selection).GetTwoAdjacentFaces2();
                    if (faces[0] == null || faces[1] == null)
                    {
                        break;
                    }
                    MathVector faceVector1 = VectorCalcs.CreateVector(componentTransform,((IFace2)faces[0]).Normal);//gets normal vectors for each bordering face
                    MathVector faceVector2 = VectorCalcs.CreateVector(componentTransform,((IFace2)faces[1]).Normal);

                    double[] edgeCurveParams = null;
                    if (!(((IEdge)Selection).GetCurve().LineParams is DBNull))
                    {
                        edgeCurveParams = ((IEdge)Selection).GetCurve().LineParams;
                    }
                    //check if both adjacent faces are planar. If both are then the edge must be a line
                    if (edgeCurveParams != null)
                    {
                        tempArray = edgeCurveParams.Take(3).ToArray();
                        MathPoint edgePoint = VectorCalcs.CreatePoint(componentTransform,tempArray);
                        tempArray = new double[] { edgeCurveParams[3], edgeCurveParams[4], edgeCurveParams[5] };
                        featureNormalVector = VectorCalcs.CreateVector(componentTransform, tempArray);//creates a vector representing the linear edge
                        if (VectorCalcs.IsParallel(featureNormalVector, axisNormalVector))//if the edgevector and the axis are perpindicular it is valid
                        {
                            if(VectorCalcs.IsPointOnLine(featureNormalVector,edgePoint,jointOrigin))
                            {
                                selBox.ShowBubbleTooltip(colinearErrorMsgTitle, colinearErrorMsg, "");
                                return false;
                            }
                            else
                                return true;
                        }
                        else
                            return true;
                    }
                    else
                    {
                        if(faceVector1.GetLength()>0)
                            if(!VectorCalcs.IsPerpendicular(faceVector1,axisNormalVector))
                            {
                                selBox.ShowBubbleTooltip(perpErrorMsgTitle, perpErrorMsg, "");
                                return false;
                            }
                            else
                                return true;
                        if(faceVector2.GetLength() > 0)
                            if (!VectorCalcs.IsPerpendicular(faceVector2, axisNormalVector))
                            {
                                selBox.ShowBubbleTooltip(perpErrorMsgTitle, perpErrorMsg, "");
                                return false;
                            }
                            else
                                return true;

                        return false;
                    }

                case swSelectType_e.swSelFACES:
                    MathVector faceVector = mathUtil.CreateVector(((IFace2)Selection).Normal);
                    if (faceVector.GetLength() < errorVal)//makes sure face is valid
                    {
                        break;
                    }
                    featureNormalVector = (faceVector.MultiplyTransform(componentTransform)).Normalise();
                    if (!VectorCalcs.IsPerpendicular(featureNormalVector, axisNormalVector))
                    {
                        selBox.ShowBubbleTooltip(perpErrorMsgTitle, perpErrorMsg, "");
                        return false;
                    }
                    else
                        return true;

                case swSelectType_e.swSelVERTICES:
                    MathPoint vertPoint = VectorCalcs.CreatePoint(componentTransform, ((Vertex)Selection).GetPoint());

                    if(VectorCalcs.IsPointOnLine(axisNormalVector,jointOrigin,vertPoint))
                    {
                        selBox.ShowBubbleTooltip(colinearErrorMsgTitle, colinearErrorMsg, "");
                        return false;
                    }
                    else
                        return true;
            }
            return false;
        }
        /// <summary>
        /// checks that the axis is valid. 
        /// if a axis is defined, it must be parallel to new/current base plane
        /// </summary>
        /// <param name="SelType"> The type of the Selected object, of form swSelectType_e </param>
        /// <param name="Selection"> The selected object </param>
        /// <param name="selBox"> The selection box that the object will be added to </param>
        /// <returns> returns true if the axis is valid </returns>
        private bool IsValidAxisSelection(int SelType, object Selection, IPropertyManagerPageControl selBox)
        {
            if (selBox == basePlaneSelectionbox)
            {
                if (robot.Direction != null)
                {
                    double[] directionVectorArray = { robot.AxisX, robot.AxisY, robot.AxisZ };
                    MathVector directionVector = mathUtil.CreateVector(directionVectorArray).Normalise();//creates a vector to represent the aXis of direction

                    MathVector normalVector = CalcNormalVector(robot.BasePlane);

                    if (!VectorCalcs.IsPerpendicular(directionVector, normalVector))
                    {

                        directionAxisSelectionbox.SetSelectionFocus();
                        modelDoc.ClearSelection2(true);
                        ((IEntity)robot.OriginPt).SelectByMark(true, originPointSelectionbox.Mark);
                        robot.Direction = null;

                        ((IPropertyManagerPageControl)directionAxisSelectionbox).ShowBubbleTooltip(
                            "Error: axis not parallel to base plane", "Select a direction axis that is parallel to the base plane for this robot", "");
                        return false;
                    }
                }
                return true;
            }

            if (selBox == directionAxisSelectionbox)
            {
                // if baseplane == null, error in setting axis
                if (robot.BasePlane == null)
                {
                    selBox.ShowBubbleTooltip("Error: no base plane", "Select the base plane for this robot before selecting the directional axis", "");
                    return false; //cannot select direction axis before base plane
                }
                // else if axis not perpendicular to the normal vector of the plane, error in picking axis

                MathVector normalVector = CalcNormalVector(robot.BasePlane); // get normal vector of plane as MathVector
                MathVector directionVector = null; // get selected axis as MathVector

                double[] tempArray; //used to store the three values to make the MathVector

                MathTransform componentTransform = null;
                if ((Component2)((IEntity)Selection).GetComponent() != null)//gets the component transform if one exists. this allows for conversion between the components local space and the global space
                {
                    componentTransform = ((Component2)((IEntity)Selection).GetComponent()).Transform2;
                }

                //Selection is a reference axis. If refAxis is perpendicular to the normal of the plane, then the axis in parallel to the plane (valid)
                if (SelType == (int)swSelectType_e.swSelDATUMAXES)
                {
                    double[] points = ((IRefAxis)((IFeature)Selection).GetSpecificFeature2()).GetRefAxisParams();
                    tempArray = new double[] { points[3] - points[0], points[4] - points[1], points[5] - points[2] };
                    directionVector = VectorCalcs.CreateVector(componentTransform, tempArray);//creates a vector between the 2 points on the reference axis and transforms to global space if nessacary
                    if (VectorCalcs.IsPerpendicular(directionVector, normalVector))
                        return true;//if axis and the normal to the plane are perpendicular then axis is parallel to plane
                    else
                    {
                        selBox.ShowBubbleTooltip("Error: axis not parallel to base plane", "Select a direction axis that is parallel to the base plane for this robot", "");
                        return false; //cannot select direction axis before base plane
                    }
                }
                //Selection is an edge. If the edge is a line, the line must be perpindicular to the joint axis to be valid.
                //If the edge is not a line but is still planar the normal vector of the plane that the edge is in it must be the same as the axis of the joint
                if (SelType == (int)swSelectType_e.swSelEDGES)
                {
                    Object[] faces = ((IEdge)Selection).GetTwoAdjacentFaces2();
                    if (!(faces[0] == null || faces[1] == null))
                    {   //get normal vectors for each bordering face
                        MathVector faceVector1 = mathUtil.CreateVector(((IFace2)faces[0]).Normal);
                        MathVector faceVector2 = mathUtil.CreateVector(((IFace2)faces[1]).Normal);

                        double[] edgeCurveParams = null;
                        if (!(((IEdge)Selection).GetCurve().LineParams is DBNull))
                        {
                            edgeCurveParams = ((IEdge)Selection).GetCurve().LineParams;
                        }
                        //check if both adjacent faces are planar. If both are then the edge must be a line
                        if (edgeCurveParams != null)
                        {
                            tempArray = new double[] { edgeCurveParams[3], edgeCurveParams[4], edgeCurveParams[5] };
                            directionVector = VectorCalcs.CreateVector(componentTransform, tempArray);//creates a vector representing the linear edge/the axis
                            if (VectorCalcs.IsPerpendicular(directionVector, normalVector))
                                return true;//if axis and the normal to the plane are perpendicular then axis is parallel to plane
                            else
                            {
                                selBox.ShowBubbleTooltip("Error: axis not parallel to base plane", "Select a direction axis that is parallel to the base plane for this robot", "");
                                return false; //cannot select direction axis before base plane
                            }
                        }

                        //if at least one of the faces are planar and that face is normal to the plane, its valid
                        MathVector faceNormalVector = null;
                        if (faceVector1.GetLength() > 0)
                        {
                            faceNormalVector = (faceVector1.MultiplyTransform(componentTransform)).Normalise();//converts the face vector to global space
                        }
                        else if (faceVector2.GetLength() > 0)
                        {
                            faceNormalVector = (faceVector2.MultiplyTransform(componentTransform)).Normalise();
                        }
                        if (faceNormalVector != null)
                        {
                            if (VectorCalcs.IsParallel(faceNormalVector, normalVector))
                                return true;
                            else
                            {
                                selBox.ShowBubbleTooltip("Error: axis not parallel to base plane", "Select a direction axis that is parallel to the base plane for this robot", "");
                                return false; //cannot select direction axis before base plane
                            }

                        }
                    }
                }
            }

            return false;
        }
        /// <summary>
        /// Checks if the selected object would be a valid selection for the limit
        /// </summary>
        /// <param name="SelType"> The type of the Selected object, of form swSelectType_e </param>
        /// <param name="Selection"> The selected object </param>
        /// <param name="selBox"> The selection box that the object will be added to </param>
        /// <returns> returns true if the selected object is valid </returns>
        private bool IsValidLimitSelection(int SelType, object Selection, IPropertyManagerPageControl selBox)
        {
            /*if (currentLink.ParentConnection.Axis1 == null)//if there is no rotation axis then no selections can be valid
            {
                if (((SelectionMgr)modelDoc.SelectionManager).GetSelectedObject6(1, 4) != null)
                {
                    currentLink.ParentConnection.Axis1 = ((SelectionMgr)modelDoc.SelectionManager).GetSelectedObject6(1, 4);
                }
                else
                {
                    selBox.ShowBubbleTooltip("Error: no joint axis", "Select an axis for this joint before selecting limits", "");
                    return false;
                }

            }
            IMathUtility mathUtil = ((IMathUtility)swApp.GetMathUtility());
            MathTransform componentTransform = null;
            if ((Component2)((IEntity)Selection).GetComponent() != null)//gets the component transform if one exists. this allows for conversion between the components local space and the global space
            {
                componentTransform = ((Component2)((IEntity)Selection).GetComponent()).Transform2;
            }
            double[] tempAxisNormalVector = { currentLink.ParentConnection.AxisX, currentLink.ParentConnection.AxisY, currentLink.ParentConnection.AxisZ };
            MathVector axisNormalVector = mathUtil.CreateVector(tempAxisNormalVector).Normalise();//creates a vector to represent the aXis of movment
            MathVector featureNormalVector = null;
            double errorVal = .00000001;
            double[] tempArray;
            //prismatic joint
            if (currentLink.ParentConnection.Type == (int)Joint.JointType.Prismatic)
            {

                switch (SelType)
                {
                    //Selection is a reference axis. If refAxis is perpendicular to the joint axis it is a valid selection
                    case (int)swSelectType_e.swSelDATUMAXES:

                        double[] points = ((IRefAxis)((IFeature)Selection).GetSpecificFeature2()).GetRefAxisParams();
                        tempArray = new double[] { points[3] - points[0], points[4] - points[1], points[5] - points[2] };
                        if (componentTransform != null)//creates a vector between the 2 points on the reference axis and transforms to global space if nessacary
                        {
                            featureNormalVector = mathUtil.CreateVector(tempArray).MultiplyTransform(componentTransform).Normalise();
                        }
                        else
                        {
                            featureNormalVector = mathUtil.CreateVector(tempArray).Normalise();
                        }

                        if (Math.Abs(featureNormalVector.Dot(axisNormalVector)) < errorVal)//if the joint axis and the referance axis are perpindicular then the selection is valid
                        {
                            return true;
                        }
                        break;

                    //Selection is a reference point. All reference points are valid.
                    case (int)swSelectType_e.swSelDATUMPOINTS:
                        return true;
                        break;
                    //Selection is a reference plane. If the plane's normal vector is the same as the joint axis it is valid.
                    case (int)swSelectType_e.swSelDATUMPLANES:
                        tempArray = new double[] { 0, 0, 1 };//temp vector used to find normal vector of plane
                        MathVector planeNormalVector = mathUtil.CreateVector(tempArray);
                        if (componentTransform != null)//finds normal vecor of plane and transforms it if needed
                        {
                            featureNormalVector = planeNormalVector.MultiplyTransform(((IRefPlane)((IFeature)Selection).GetSpecificFeature2()).Transform).MultiplyTransform(componentTransform).Normalise();
                        }
                        else
                        {
                            featureNormalVector = planeNormalVector.MultiplyTransform(((IRefPlane)((IFeature)Selection).GetSpecificFeature2()).Transform).Normalise();
                        }
                        if (Math.Abs(featureNormalVector.Cross(axisNormalVector).GetLength()) < errorVal)//if the plane normal vector and the joint axis are parallel the selection is valid
                        {
                            return true;
                        }
                        break;

                    //Selection is an edge. If the edge is a line, the line must be perpindicular to the joint axis to be valid.
                    //If the edge is not a line but is still planar the normal vector of the plane that the edge is in must be the same asw the axis of the joint
                    case (int)swSelectType_e.swSelEDGES:
                        Object[] faces = ((IEdge)Selection).GetTwoAdjacentFaces2();
                        if (faces[0] == null || faces[1] == null)
                        {
                            break;
                        }
                        MathVector faceVector1 = mathUtil.CreateVector(((IFace2)faces[0]).Normal);//gets normal vectors for each bordering face
                        MathVector faceVector2 = mathUtil.CreateVector(((IFace2)faces[1]).Normal);

                        double[] edgeCurveParams =null;
                        if (!(((IEdge)Selection).GetCurve().LineParams is DBNull))
                        {
                            edgeCurveParams = ((IEdge)Selection).GetCurve().LineParams;
                        }
                        //check if both adjacent faces are planar. If both are then the edge must be a line
                        if (edgeCurveParams!=null)
                        {
                            tempArray = new double[] { edgeCurveParams[3],edgeCurveParams[4],edgeCurveParams[5] };
                            featureNormalVector = mathUtil.CreateVector(tempArray).MultiplyTransform(componentTransform).Normalise();//creates a vector representing the linear edge
                            if (Math.Abs(featureNormalVector.Dot(axisNormalVector)) < errorVal)//if the edgevector and the axis are parallel it is valid
                            {
                                return true;
                            }
                            break;
                        }
                        else if (faceVector1.GetLength() > 0)
                        {
                            featureNormalVector = (faceVector1.MultiplyTransform(componentTransform)).Normalise();//converts the face vector to global space
                        }
                        else if (faceVector2.GetLength() > 0)
                        {
                            featureNormalVector = (faceVector2.MultiplyTransform(componentTransform)).Normalise();
                        }

                        if (featureNormalVector != null)//if at least one of the faces are planar and that face is normal to the plane, its valid
                        {
                            if (Math.Abs(featureNormalVector.Cross(axisNormalVector).GetLength()) < errorVal)
                            {
                                return true;
                            }
                        }
                        break;
                    //Selection is a face. The normal vector of the face must be the same as the joint axis to be valid
                    case (int)swSelectType_e.swSelFACES:
                        MathVector faceVector = mathUtil.CreateVector(((IFace2)Selection).Normal);
                        if (faceVector.GetLength() == 0)//makes sure face is valid
                        {
                            break;
                        }
                        featureNormalVector = (faceVector.MultiplyTransform(componentTransform)).Normalise(); //converts the face vector to the corect coordinate orientation

                        if (Math.Abs(featureNormalVector.Cross(axisNormalVector).GetLength()) < errorVal)
                        {
                            return true;
                        }
                        break;
                    //Selection is a vertice. All verticies are valid
                    case (int)swSelectType_e.swSelVERTICES:
                        return true;
                    default:
                        return false;
                }
                System.Diagnostics.Debug.WriteLine("AxisVector: " + String.Join(" ", (double[])axisNormalVector.ArrayData));
                System.Diagnostics.Debug.WriteLine("NormalVector: " + String.Join(" ", (double[])featureNormalVector.ArrayData));
                selBox.ShowBubbleTooltip("Error: Feature not normal to joint axis", "The selected feature must be normal to the axis of movement", "");
            }
            //if the joint is revolute
            else if (currentLink.ParentConnection.Type == (int)Joint.JointType.Revolute)
            {
                int errorCode = 0; //type of error that selection has. 0 is not coincident, 1 is colinear
                switch (SelType)
                {
                    //Selection is a reference axis. If refAxis is parallel to the joint axis or intersects it it is a valid selection
                    case (int)swSelectType_e.swSelDATUMAXES:

                        double[] points = ((IRefAxis)((IFeature)Selection).GetSpecificFeature2()).GetRefAxisParams();
                        tempArray = new double[] { points[3] - points[0], points[4] - points[1], points[5] - points[2] };
                        if (componentTransform != null)
                        {
                            featureNormalVector = mathUtil.CreateVector(tempArray).MultiplyTransform(componentTransform).Normalise();
                        }
                        else
                        {
                            featureNormalVector = mathUtil.CreateVector(tempArray).Normalise();
                        }

                        MathVector pointVector;
                        if (componentTransform != null)
                        {
                            MathPoint arbPoint = mathUtil.CreatePoint(new double[] { points[0], points[1], points[2] }).MultiplyTransform(componentTransform);
                            pointVector = mathUtil.CreatePoint(new double[] { currentLink.ParentConnection.OriginX - arbPoint.ArrayData[0], currentLink.ParentConnection.OriginY - arbPoint.ArrayData[1], currentLink.ParentConnection.OriginZ - arbPoint.ArrayData[2] }).ConvertToVector().Normalise();
                        }
                        else
                        {
                            pointVector = mathUtil.CreatePoint(new double[] { currentLink.ParentConnection.OriginX - points[0], currentLink.ParentConnection.OriginY - points[1], currentLink.ParentConnection.OriginZ - points[2] }).ConvertToVector().Normalise();
                        }
                        //check if vectors are parallel
                        if (Math.Abs(featureNormalVector.Cross(axisNormalVector).GetLength()) < errorVal)
                        {
                            if (Math.Abs(pointVector.Cross(axisNormalVector).GetLength()) > errorVal)
                            {
                                return true;
                            }
                            else
                            {
                                errorCode = 1;
                                break;
                            }

                        }
                        //check if vectors intersect
                        if (Math.Abs(pointVector.Cross(axisNormalVector).GetLength()) < errorVal ||
                            (Math.Abs(featureNormalVector.Cross(axisNormalVector).Normalise().Cross(pointVector.Cross(axisNormalVector).Normalise()).GetLength()) < errorVal))
                        {
                            return true;
                        }
                        errorCode = 0;
                        break;
                    //Selection is a reference point. Reference points are valid if they do not lie on a the axis line.
                    case (int)swSelectType_e.swSelDATUMPOINTS:
                        double[] point;
                        if (componentTransform != null)
                        {
                            point = mathUtil.CreatePoint(((IRefPoint)((IFeature)Selection).GetSpecificFeature2()).GetRefPoint().ArrayData).MultiplyTransform(componentTransform).ArrayData;
                        }
                        else
                        {
                            point = ((IRefPoint)((IFeature)Selection).GetSpecificFeature2()).GetRefPoint().ArrayData;
                        }
                        featureNormalVector = mathUtil.CreateVector(new double[] { point[0] - currentLink.ParentConnection.OriginX, point[1] - currentLink.ParentConnection.OriginY, point[2] - currentLink.ParentConnection.OriginZ }).Normalise();
                        if (Math.Abs(featureNormalVector.Cross(axisNormalVector).GetLength()) > errorVal)
                        {
                            return true;
                        }
                        errorCode = 1;
                        break;
                    //Selection is a reference plane. If the plane intersects the joint axis and its normal vector is perpindicular it is valid.
                    case (int)swSelectType_e.swSelDATUMPLANES:
                        errorCode = 0;
                        tempArray = new double[] { 0, 0, 1 };
                        MathVector planeNormalVector = mathUtil.CreateVector(tempArray);
                        MathTransform planeTransform = ((IRefPlane)((IFeature)Selection).GetSpecificFeature2()).Transform;
                        if (componentTransform != null)
                        {
                            planeTransform = planeTransform.Multiply(componentTransform);
                        }
                        //System.Diagnostics.Debug.WriteLine("planeTransform: " + string.Join(" ", (double[])planeTransform.ArrayData));
                        featureNormalVector = planeNormalVector.MultiplyTransform(planeTransform).Normalise();
                        tempArray = new double[] { planeTransform.ArrayData[9] - currentLink.ParentConnection.OriginX, planeTransform.ArrayData[10] - currentLink.ParentConnection.OriginY, planeTransform.ArrayData[11] - currentLink.ParentConnection.OriginZ };
                        MathVector originVector = mathUtil.CreateVector(tempArray);
                        if (Math.Abs(featureNormalVector.Dot(axisNormalVector)) < errorVal && Math.Abs(featureNormalVector.Dot(originVector)) < errorVal)
                        {
                            return true;
                        }
                        break;
                    //Selection is an edge. If the edge is a line, the line must be parallel to the joint axis or intersect it to be valid.
                    //If the edge is not a line but is still planar the normal vector of the plane that the edge is in must intersect the axis of the joint and its normalvector must be perpindicular to the axis
                    case (int)swSelectType_e.swSelEDGES:
                        Object[] faces = ((IEdge)Selection).GetTwoAdjacentFaces2();
                        if (faces[0] == null || faces[1] == null)
                        {
                            break;
                        }
                        MathVector faceVector1 = mathUtil.CreateVector(((IFace2)faces[0]).Normal);
                        MathVector faceVector2 = mathUtil.CreateVector(((IFace2)faces[1]).Normal);
                        MathVector originVect;
                        //check if both adjacent faces are planar. If both are then the edge must be a line
                        if (faceVector1.GetLength() > 0 && faceVector2.GetLength() > 0)
                        {
                            double[] startPoint = mathUtil.CreateVector(((IEdge)Selection).GetStartVertex().getPoint()).MultiplyTransform(componentTransform).ArrayData;
                            double[] endPoint = mathUtil.CreateVector(((IEdge)Selection).GetEndVertex().getPoint()).MultiplyTransform(componentTransform).ArrayData;
                            tempArray = new double[] { endPoint[0] - startPoint[0], endPoint[1] - startPoint[1], endPoint[2] - startPoint[2] };
                            featureNormalVector = mathUtil.CreateVector(tempArray).Normalise;
                            MathVector pointVect = mathUtil.CreatePoint(new double[] { currentLink.ParentConnection.OriginX - startPoint[0], currentLink.ParentConnection.OriginY - startPoint[1], currentLink.ParentConnection.OriginZ - startPoint[2] }).ConvertToVector();

                            //check if edges are parallel
                            if (Math.Abs(featureNormalVector.Cross(axisNormalVector).GetLength()) < errorVal)
                            {
                                if (Math.Abs(pointVect.Cross(axisNormalVector).GetLength()) > errorVal)
                                {
                                    return true;
                                }
                                else
                                {
                                    errorCode = 1;
                                    break;
                                }
                            }

                            //check if vectors intersect
                            if (Math.Abs(pointVect.Cross(axisNormalVector).GetLength()) < errorVal ||
                                (Math.Abs(featureNormalVector.Cross(axisNormalVector).Normalise().Cross(pointVect.Cross(axisNormalVector).Normalise()).GetLength()) < errorVal))
                            {
                                return true;
                            }
                            errorCode = 0;
                            break;
                        }
                        else if (faceVector1.GetLength() > 0)
                        {
                            featureNormalVector = (faceVector1.MultiplyTransform(componentTransform)).Normalise();
                        }
                        else if (faceVector2.GetLength() > 0)
                        {
                            featureNormalVector = (faceVector2.MultiplyTransform(componentTransform)).Normalise();
                        }
                        tempArray = ((IEdge)Selection).GetClosestPointOn(currentLink.ParentConnection.OriginX, currentLink.ParentConnection.OriginY, currentLink.ParentConnection.OriginZ);
                        double[] facePoint = mathUtil.CreatePoint(tempArray).MultiplyTransform(componentTransform).ArrayData;
                        tempArray = new double[] { facePoint[0] - currentLink.ParentConnection.OriginX, facePoint[1] - currentLink.ParentConnection.OriginY, facePoint[2] - currentLink.ParentConnection.OriginZ };
                        originVect = mathUtil.CreateVector(tempArray);
                        if (featureNormalVector != null)
                        {
                            if (Math.Abs(featureNormalVector.Dot(axisNormalVector)) < errorVal && Math.Abs(featureNormalVector.Dot(originVect)) < errorVal)
                            {
                                return true;
                            }
                        }
                        errorCode = 0;
                        break;
                    //Selection is a face. The face must intersect the joint axis and its normal vector must be perpindicular to be valid
                    case (int)swSelectType_e.swSelFACES:
                        errorCode = 0;
                        MathVector faceVector = mathUtil.CreateVector(((IFace2)Selection).Normal);
                        featureNormalVector = (faceVector.MultiplyTransform(componentTransform)).Normalise(); //converts the face vector to the corect coordinate orientation
                        tempArray = ((IFace2)Selection).GetClosestPointOn(currentLink.ParentConnection.OriginX, currentLink.ParentConnection.OriginY, currentLink.ParentConnection.OriginZ);
                        double[] facePnt = mathUtil.CreatePoint(tempArray).MultiplyTransform(componentTransform).ArrayData;
                        tempArray = new double[] { facePnt[0] - currentLink.ParentConnection.OriginX, facePnt[1] - currentLink.ParentConnection.OriginY, facePnt[2] - currentLink.ParentConnection.OriginZ };
                        MathVector origVect = mathUtil.CreateVector(tempArray);
                        if (faceVector.GetLength() > errorVal && (Math.Abs(featureNormalVector.Dot(axisNormalVector)) < errorVal && Math.Abs(featureNormalVector.Dot(origVect)) < errorVal))
                        {
                            return true;
                        }
                        break;
                    //Selection is a vertice. Verticies are valid if they do not lie on a the axis line
                    case (int)swSelectType_e.swSelVERTICES:
                        errorCode = 1;
                        MathPoint vertPoint = mathUtil.CreatePoint(((IVertex)Selection).GetPoint()).MultiplyTransform(componentTransform); ;
                        featureNormalVector = mathUtil.CreateVector(new double[] { vertPoint.ArrayData[0] - currentLink.ParentConnection.OriginX, vertPoint.ArrayData[1] - currentLink.ParentConnection.OriginY, vertPoint.ArrayData[2] - currentLink.ParentConnection.OriginZ }).Normalise();
                        if (Math.Abs(featureNormalVector.Cross(axisNormalVector).GetLength()) > errorVal)
                        {
                            return true;
                        }
                        break;
                    default:
                        break;
                }
                switch (errorCode)
                {
                    case 0: //feature not coincident to axis
                        selBox.ShowBubbleTooltip("Error: Feature not coincident to joint axis", "The selected feature must be coincident to the axis of rotation", "");
                        break;
                    case 1: //feature is colinear to axis
                        selBox.ShowBubbleTooltip("Error: Feature is colinear to joint axis", "The selected feature must not be colinear to the axis of movement", "");
                        break;
                }

            }*/
            return false;
        }
        /// <summary>
        /// Determines if the inputted selection is valid
        /// </summary>
        /// <param name="SelType">The type of the selection<param>
        /// <param name="Selection">The Selected object</param>
        /// <param name="selBox">The Selection box that the selected object is in</param>
        /// <returns>returns true if the object is a valid limit selection</returns>
        public override bool IsValidLimitSelection(int SelType, object Selection, IPropertyManagerPageControl selBox)
        {
            if (Axis == null)//if there is no rotation axis then no selections can be valid
            {
                if (((SelectionMgr)modelDoc.SelectionManager).GetSelectedObject6(1, 2) != null)
                {
                    Axis = ((SelectionMgr)modelDoc.SelectionManager).GetSelectedObject6(1, 2);
                }
                else
                {
                    selBox.ShowBubbleTooltip("Error: no joint axis", "Select the first axis for this joint before selecting other features", "");
                    return false;
                }

            }

            MathTransform componentTransform = null;
            if ((Component2)((IEntity)Selection).GetComponent() != null)//gets the component transform if one exists. this allows for conversion between the components local space and the global space
            {
                componentTransform = ((Component2)((IEntity)Selection).GetComponent()).Transform2;
            }
            double[] tempAxisNormalVector = { AxisX, AxisY, AxisZ };
            MathVector axisNormalVector = mathUtil.CreateVector(tempAxisNormalVector).Normalise();//creates a vector to represent the aXis of movment

            MathVector featureNormalVector = null;
            double[] tempArray;
            switch ((swSelectType_e)SelType)
            {
                //Selection is a reference axis. If refAxis is perpendicular to the joint axis it is a valid selection
                case swSelectType_e.swSelDATUMAXES:

                    double[] points = ((IRefAxis)((IFeature)Selection).GetSpecificFeature2()).GetRefAxisParams();
                    tempArray = new double[] { points[3] - points[0], points[4] - points[1], points[5] - points[2] };
                    featureNormalVector = VectorCalcs.CreateVector(componentTransform, tempArray);//creates a vector between the 2 points on the reference axis and transforms to global space if nessacary

                    if (VectorCalcs.IsPerpendicular(featureNormalVector, axisNormalVector))//if the joint axis and the referance axis are perpindicular then the selection is valid
                    {
                        return true;
                    }
                    break;

                //Selection is a reference point. All reference points are valid.
                case swSelectType_e.swSelDATUMPOINTS:
                    return true;
                    break;
                //Selection is a reference plane. If the plane's normal vector is the same as the joint axis it is valid.
                case swSelectType_e.swSelDATUMPLANES:
                    tempArray = new double[] { 0, 0, 1 };//temp vector used to find normal vector of plane
                    MathTransform tempTransform = ((IRefPlane)((IFeature)Selection).GetSpecificFeature2()).Transform; //represents the transform of the plane from being the xy plane
                    MathVector planeNormalVector = mathUtil.CreateVector(tempArray);
                    if (componentTransform != null)//finds normal vecor of plane and transforms it if needed
                    {
                        featureNormalVector = planeNormalVector.MultiplyTransform(tempTransform).MultiplyTransform(componentTransform).Normalise();
                    }
                    else
                    {
                        featureNormalVector = planeNormalVector.MultiplyTransform(tempTransform).Normalise();
                    }
                    if (VectorCalcs.IsParallel(featureNormalVector, axisNormalVector))//if the plane normal vector and the joint axis are parallel the selection is valid
                    {
                        return true;
                    }
                    break;

                //Selection is an edge. If the edge is a line, the line must be perpindicular to the joint axis to be valid.
                //If the edge is not a line but is still planar the normal vector of the plane that the edge is in it must be the same as the axis of the joint
                case swSelectType_e.swSelEDGES:
                    object[] faces = ((IEdge)Selection).GetTwoAdjacentFaces2();
                    if (faces[0] == null || faces[1] == null)
                    {
                        break;
                    }
                    MathVector faceVector1 = mathUtil.CreateVector(((IFace2)faces[0]).Normal);//gets normal vectors for each bordering face
                    MathVector faceVector2 = mathUtil.CreateVector(((IFace2)faces[1]).Normal);

                    double[] edgeCurveParams = null;
                    if (!(((IEdge)Selection).GetCurve().LineParams is DBNull))
                    {
                        edgeCurveParams = ((IEdge)Selection).GetCurve().LineParams;
                    }
                    //check if both adjacent faces are planar. If both are then the edge must be a line
                    if (edgeCurveParams != null)
                    {
                        tempArray = new double[] { edgeCurveParams[3], edgeCurveParams[4], edgeCurveParams[5] };
                        featureNormalVector = VectorCalcs.CreateVector(componentTransform, tempArray);//creates a vector representing the linear edge
                        if (VectorCalcs.IsPerpendicular(featureNormalVector, axisNormalVector))//if the edgevector and the axis are perpindicular it is valid
                        {
                            return true;
                        }
                        break;
                    }
                    else if (faceVector1.GetLength() > 0)
                    {
                        featureNormalVector = (faceVector1.MultiplyTransform(componentTransform)).Normalise();//converts the face vector to global space
                    }
                    else if (faceVector2.GetLength() > 0)
                    {
                        featureNormalVector = (faceVector2.MultiplyTransform(componentTransform)).Normalise();
                    }

                    if (featureNormalVector != null)//if at least one of the faces are planar and that face is normal to the plane, its valid
                    {
                        if (VectorCalcs.IsParallel(featureNormalVector, axisNormalVector))
                        {
                            return true;
                        }
                    }
                    break;
                //Selection is a face. The normal vector of the face must be the same as the joint axis to be valid
                case swSelectType_e.swSelFACES:
                    MathVector faceVector = mathUtil.CreateVector(((IFace2)Selection).Normal);
                    if (faceVector.GetLength() < errorVal)//makes sure face is valid
                    {
                        break;
                    }
                    featureNormalVector = (faceVector.MultiplyTransform(componentTransform)).Normalise(); //converts the face vector to the corect coordinate orientation

                    if (VectorCalcs.IsParallel(featureNormalVector, axisNormalVector))
                    {
                        return true;
                    }
                    break;
                //Selection is a vertice. All verticies are valid
                case swSelectType_e.swSelVERTICES:
                    return true;
                default:
                    return false;
            }
            //System.Diagnostics.Debug.WriteLine("AxisVector: " + String.Join(" ", (double[])axisNormalVector.ArrayData));
            //System.Diagnostics.Debug.WriteLine("NormalVector: " + String.Join(" ", (double[])featureNormalVector.ArrayData));
            selBox.ShowBubbleTooltip("Error: Feature not normal to joint axis", "The selected feature must be normal to the axis of movement", "");
            return false;
        }
 /// <summary>
 /// Determines if the inputted selection is valid
 /// </summary>
 /// <param name="SelType">The type of the selection<param>
 /// <param name="Selection">The Selected object</param>
 /// <param name="selBox">The Selection box that the selected object is in</param>
 /// <returns>returns true if the object is a valid limit selection</returns>
 public abstract bool IsValidLimitSelection(int SelType, object Selection, IPropertyManagerPageControl selBox);