private static Point3D?CastRay_Line(out double clickDistanceSquared, Point3D point, Vector3D direction, RayHitTestParameters mouseDownClickRay, RayHitTestParameters mouseDownCenterRay, RayHitTestParameters currentClickRay) { // This is the offset along the drag line from the center to mouse down click Vector3D offset; Point3D?point1, point2, point3, point4; if (Math3D.GetClosestPoints_Line_Line(out point1, out point2, point, direction, mouseDownClickRay.Origin, mouseDownClickRay.Direction) && Math3D.GetClosestPoints_Line_Line(out point3, out point4, point, direction, mouseDownCenterRay.Origin, mouseDownCenterRay.Direction)) { offset = point3.Value - point1.Value; // clickpoint on drag line minus centerpoint on drag line } else { // The click ray is parallel to the drag axis. This should be extremely rare offset = new Vector3D(0, 0, 0); } // Now that the offset is known, project the current click ray onto the drag line if (Math3D.GetClosestPoints_Line_Line(out point1, out point2, point, direction, currentClickRay.Origin, currentClickRay.Direction)) { clickDistanceSquared = (point2.Value - point1.Value).LengthSquared; return(point1.Value + offset); } else { clickDistanceSquared = 0; return(null); } }
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); }
/// <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); }