Beispiel #1
0
        private static Point3D?CastRay_Circle(out double clickDistanceSquared, ITriangle plane, Point3D center, double radius, RayHitTestParameters mouseDownClickRay, RayHitTestParameters mouseDownCenterRay, RayHitTestParameters currentClickRay)
        {
            clickDistanceSquared = 0d;          // this will get overwritten, but without setting it globally, the compiler will complain

            // Get points on the circle
            Point3D?mouseDownClickPoint  = null;
            Point3D?mouseDownCenterPoint = null;
            Point3D?currentClickPoint    = null;

            Point3D[] nearestCirclePoints, nearestLinePoints;

            if (Math3D.GetClosestPoints_Circle_Line(out nearestCirclePoints, out nearestLinePoints, plane, center, radius, currentClickRay.Origin, currentClickRay.Direction, Math3D.RayCastReturn.ClosestToRay))
            {
                clickDistanceSquared = (nearestLinePoints[0] - nearestCirclePoints[0]).LengthSquared;
                currentClickPoint    = nearestCirclePoints[0];

                if (Math3D.GetClosestPoints_Circle_Line(out nearestCirclePoints, out nearestLinePoints, plane, center, radius, mouseDownClickRay.Origin, mouseDownClickRay.Direction, Math3D.RayCastReturn.ClosestToRay))
                {
                    mouseDownClickPoint = nearestCirclePoints[0];

                    if (Math3D.GetClosestPoints_Circle_Line(out nearestCirclePoints, out nearestLinePoints, plane, center, radius, mouseDownCenterRay.Origin, mouseDownCenterRay.Direction, Math3D.RayCastReturn.ClosestToRay))
                    {
                        mouseDownCenterPoint = nearestCirclePoints[0];
                    }
                }
            }

            if (mouseDownCenterPoint == null || mouseDownClickPoint == null || currentClickPoint == null)
            {
                clickDistanceSquared = 0d;
                return(currentClickPoint);               // it doesn't matter if this one is null or not, the offset can't be determined, so just return the raw click value
            }

            // Get the offset
            Vector3D mouseDownClickLine  = mouseDownClickPoint.Value - center;
            Vector3D mouseDownCenterLine = mouseDownCenterPoint.Value - center;

            Quaternion offset = Math3D.GetRotation(mouseDownClickLine, mouseDownCenterLine);

            // Convert to local, and rotate by offset
            Vector3D currentClickLine = currentClickPoint.Value - center;

            currentClickLine = new RotateTransform3D(new QuaternionRotation3D(offset)).Transform(currentClickLine);

            // Now convert back to world coords
            return(center + currentClickLine);
        }
Beispiel #2
0
        private static Point3D?CastRay_LinesCircles(IEnumerable <RayHitTestParameters> lines, IEnumerable <CircleDefinition> circles, RayHitTestParameters ray)
        {
            Point3D?retVal   = null;
            double  distance = double.MaxValue;

            if (lines != null)
            {
                // Cast onto each line, and return the point that's closest to the ray's origin
                foreach (RayHitTestParameters line in lines)
                {
                    Point3D?point1, point2;
                    if (Math3D.GetClosestPoints_Line_Line(out point1, out point2, line.Origin, line.Direction, ray.Origin, ray.Direction))
                    {
                        double localDistance = (point2.Value - point1.Value).LengthSquared;
                        if (retVal == null || localDistance < distance)
                        {
                            retVal   = point1.Value;
                            distance = localDistance;
                        }
                    }
                }
            }

            if (circles != null)
            {
                // Cast onto each circle, and return the point that's closest to the ray's origin
                foreach (CircleDefinition circle in circles)
                {
                    Point3D[] points1, points2;
                    if (Math3D.GetClosestPoints_Circle_Line(out points1, out points2, circle.Plane, circle.Center, circle.Radius, ray.Origin, ray.Direction, Math3D.RayCastReturn.ClosestToRay))
                    {
                        double localDistance = (points2[0] - points1[0]).LengthSquared;
                        if (retVal == null || localDistance < distance)
                        {
                            retVal   = points1[0];
                            distance = localDistance;
                        }
                    }
                }
            }

            return(retVal);
        }
Beispiel #3
0
        public override void DragItem(RayHitTestParameters ray)
        {
            if (_circleCenter == null || _circleOrientation == null)
            {
                throw new InvalidOperationException("CircleCenter and CircleOrientation need to be set before calling this method");
            }

            // See where on the circle they clicked
            // If the method comes back false, it's a very rare case, so just don't drag the ring
            Point3D[] nearestCirclePoints, nearestLinePoints;
            if (Math3D.GetClosestPoints_Circle_Line(out nearestCirclePoints, out nearestLinePoints, _circlePlane, _circleCenter.Value, _radius, ray.Origin, ray.Direction, Math3D.RayCastReturn.ClosestToRay))
            {
                // Figure out what angle they clicked on
                Quaternion clickQuat = GetAngle(nearestCirclePoints[0]);

                // Subtract off off where they first clicked (start drag already negated _mouseDownAngle and made it unit)
                clickQuat = Quaternion.Multiply(_mouseDownAngle, clickQuat.ToUnit());

                // Now store the new location
                _circleOrientation = Quaternion.Multiply(clickQuat.ToUnit(), _circleOrientation.Value.ToUnit());
            }
        }
Beispiel #4
0
        public override void StartDrag(RayHitTestParameters ray)
        {
            if (_circleCenter == null || _circleOrientation == null)
            {
                throw new InvalidOperationException("CircleCenter and CircleOrientation need to be set before calling this method");
            }

            _rotateTransform = new RotateTransform3D(new QuaternionRotation3D(_circleOrientation.Value));
            _circlePlane     = new Triangle(_circleCenter.Value, _circleCenter.Value + _rotateTransform.Transform(_intialAxisX), _circleCenter.Value + _rotateTransform.Transform(_intialAxisY));

            // Compare the ray with the drag ring to see where on the circle they clicked
            Point3D[] nearestCirclePoints, nearestLinePoints;
            if (Math3D.GetClosestPoints_Circle_Line(out nearestCirclePoints, out nearestLinePoints, _circlePlane, _circleCenter.Value, _radius, ray.Origin, ray.Direction, Math3D.RayCastReturn.ClosestToRay))
            {
                _mouseDownAngle = GetAngle(nearestCirclePoints[0]);
                _mouseDownAngle = new Quaternion(_mouseDownAngle.Axis, _mouseDownAngle.Angle * -1d).ToUnit();           // taking angle times -1 so that the drag just has to do a simple multiply
            }
            else
            {
                // The click ray is perpendicular to the circle plane, and they are clicking through the direct center of the circle (this should never happen)
                _mouseDownAngle = Quaternion.Identity;
            }
        }
Beispiel #5
0
        /// <summary>
        /// This overload is a straight ray cast, nothing extra
        /// </summary>
        public Point3D?CastRay(RayHitTestParameters ray)
        {
            Point3D?retVal = null;

            switch (_shape)
            {
            case ShapeType.Line:
                #region Line

                Point3D?point1, point2;
                if (Math3D.GetClosestPoints_Line_Line(out point1, out point2, _point, _direction, ray.Origin, ray.Direction))
                {
                    retVal = point1.Value;
                }

                #endregion
                break;

            case ShapeType.Lines:
                #region Lines

                retVal = CastRay_LinesCircles(_lines, null, ray);

                #endregion
                break;

            case ShapeType.Plane:
                #region Plane

                retVal = Math3D.GetIntersection_Plane_Line(_plane, ray.Origin, ray.Direction);

                #endregion
                break;

            case ShapeType.Circle:
                #region Circle

                Point3D[] nearestCirclePoints, nearestLinePoints;
                if (Math3D.GetClosestPoints_Circle_Line(out nearestCirclePoints, out nearestLinePoints, _plane, _point, _radius, ray.Origin, ray.Direction, Math3D.RayCastReturn.ClosestToRay))
                {
                    retVal = nearestCirclePoints[0];
                }

                #endregion
                break;

            case ShapeType.Circles:
                #region Circles

                retVal = CastRay_LinesCircles(null, _circles, ray);

                #endregion
                break;

            case ShapeType.LinesCircles:
                #region LinesCircles

                retVal = CastRay_LinesCircles(_lines, _circles, ray);

                #endregion
                break;

            case ShapeType.Cylinder:
                #region Cylinder

                Point3D[] nearestCylinderPoints, nearestLinePoints2;
                if (Math3D.GetClosestPoints_Cylinder_Line(out nearestCylinderPoints, out nearestLinePoints2, _point, _direction, _radius, ray.Origin, ray.Direction, Math3D.RayCastReturn.ClosestToRay))
                {
                    retVal = nearestCylinderPoints[0];
                }

                #endregion
                break;

            case ShapeType.Sphere:
                #region Sphere

                Point3D[] nearestSpherePoints, nearestLinePoints3;
                Math3D.GetClosestPoints_Sphere_Line(out nearestSpherePoints, out nearestLinePoints3, _point, _radius, ray.Origin, ray.Direction, Math3D.RayCastReturn.ClosestToRay);
                {
                    retVal = nearestSpherePoints[0];
                }

                #endregion
                break;

            case ShapeType.Mesh:
                throw new ApplicationException("finish this");

            case ShapeType.None:
                retVal = null;
                break;

            default:
                throw new ApplicationException("Unknown ShapeType: " + _shape.ToString());
            }

            return(retVal);
        }