/// <summary> /// 射线与圆相交交点 /// </summary> /// <param name="rayOrigin"></param> /// <param name="rayDirection"></param> /// <param name="circleCenter"></param> /// <param name="radius"></param> /// <returns></returns> public static IntersectionResult RayToCircleIntersection(Vector2 rayOrigin, Vector2 rayDirection, Vector2 circleCenter, float radius) { IntersectionResult result = new IntersectionResult(); rayDirection = rayDirection.normalized; Vector2 rayOriginToCircleCenter = circleCenter - rayOrigin; float rayOriginToCircleCenterLength = rayOriginToCircleCenter.sqrMagnitude; float dot = Vector2.Dot(rayDirection, rayOriginToCircleCenter.normalized); Vector2 pointOnRayVerticalWithCircleCenter = rayOrigin + rayDirection * (dot * Mathf.Sqrt(rayOriginToCircleCenterLength)); float squareDistanceToCenter = Vector2.Dot(pointOnRayVerticalWithCircleCenter - circleCenter, pointOnRayVerticalWithCircleCenter - circleCenter); if (squareDistanceToCenter > radius * radius) { return(result); } if (squareDistanceToCenter == radius * radius) { result.AddIntersectionPoint(pointOnRayVerticalWithCircleCenter); return(result); } float distanceToIntersection = 0f; float distanceToCenter = 0f; if (squareDistanceToCenter == 0) { distanceToIntersection = radius; } else { distanceToCenter = (float)Math.Sqrt(squareDistanceToCenter); distanceToIntersection = (float)Math.Sqrt(radius * radius - squareDistanceToCenter); } float lineSegmentLength = 1 / Mathf.Sqrt(rayOriginToCircleCenterLength); rayOriginToCircleCenter *= lineSegmentLength; rayOriginToCircleCenter *= distanceToIntersection; Vector2 solution1 = pointOnRayVerticalWithCircleCenter + rayOriginToCircleCenter; if (Vector2.Distance(solution1, rayOrigin) > 0) { result.AddIntersectionPoint(solution1); } Vector2 solution2 = pointOnRayVerticalWithCircleCenter - rayOriginToCircleCenter; if (Vector2.Distance(solution2, rayOrigin) > 0) { result.AddIntersectionPoint(solution2); } return(result); }
/// <summary> /// 两射线求交点 /// </summary> /// <param name="rayOrigin1"></param> /// <param name="rayDirection1"></param> /// <param name="rayOrigin2"></param> /// <param name="rayDirection2"></param> /// <returns></returns> public static IntersectionResult RayToRayIntersection(Vector2 rayOrigin1, Vector2 rayDirection1, Vector2 rayOrigin2, Vector2 rayDirection2) { IntersectionResult result = new IntersectionResult(); rayDirection1 = rayDirection1.normalized; rayDirection2 = rayDirection2.normalized; float r, s, d; if (rayDirection1 != rayDirection2) { d = Cross(rayDirection1, rayDirection2); if (d != 0) { Vector2 rayOrigin2ToRayOrigin1 = rayOrigin1 - rayOrigin2; r = Cross(rayDirection2, rayOrigin2ToRayOrigin1) / d; s = Cross(rayDirection1, rayOrigin2ToRayOrigin1) / d; if (r >= 0) { if (s >= 0) { Vector2 intersectionPoint = rayOrigin1 + rayDirection1 * r; result.AddIntersectionPoint(intersectionPoint); } } } } return(result); }
/// <summary> /// 射线与线段的交点 /// </summary> /// <param name="rayOrigin"></param> /// <param name="rayDirection"></param> /// <param name="lineStart"></param> /// <param name="lineEnd"></param> /// <returns></returns> public static IntersectionResult RayToLineSegmentIntersection(Vector2 rayOrigin, Vector2 rayDirection, Vector2 lineStart, Vector2 lineEnd) { IntersectionResult result = new IntersectionResult(); Vector2 v1 = rayOrigin - lineStart; Vector2 v2 = lineEnd - lineStart; Vector2 v3 = new Vector2(-rayDirection.y, rayDirection.x); var dot = Vector2.Dot(v2, v3); if (Math.Abs(dot) < float.Epsilon) { return(result); } var t1 = Cross(v2, v1) / dot; var t2 = Vector2.Dot(v1, v3) / dot; if (t1 >= 0.0 && (t2 >= 0.0 && t2 <= 1.0)) { result.AddIntersectionPoint(rayOrigin + t1 * rayDirection); } return(result); }
/// <summary> /// 射线与圆相交交点 /// </summary> /// <param name="rayOrigin"></param> /// <param name="rayDirection"></param> /// <param name="circleCenter"></param> /// <param name="radius"></param> /// <returns></returns> public static IntersectionResult RayToCircleIntersection(Vector2 rayOrigin, Vector2 rayDirection, Vector2 circleCenter, float radius, bool includeRayExtension = false) { IntersectionResult result = new IntersectionResult(); Vector2 d = rayOrigin - circleCenter; float a = Vector2.Dot(rayDirection, rayDirection); float b = Vector2.Dot(d, rayDirection); float c = Vector2.Dot(d, d) - radius * radius; float disc = b * b - a * c; if (disc < 0.0f) { return(result); } float sqrtDisc = Mathf.Sqrt(disc); float invA = 1.0f / a; float t = (-b - sqrtDisc) * invA; float s = (-b + sqrtDisc) * invA; float invRadius = 1.0f / radius; //相切,一个交点 if (sqrtDisc == 0) { if (includeRayExtension) { result.AddIntersectionPoint(rayOrigin + t * rayDirection); } else { if (t > 0) { result.AddIntersectionPoint(rayOrigin + t * rayDirection); } } return(result); } if (includeRayExtension) { result.AddIntersectionPoint(rayOrigin + t * rayDirection); result.AddIntersectionPoint(rayOrigin + s * rayDirection); } else { if (t > 0) { result.AddIntersectionPoint(rayOrigin + t * rayDirection); } if (s > 0) { result.AddIntersectionPoint(rayOrigin + s * rayDirection); } } return(result); }
/// <summary> /// 两直线求交点 /// </summary> /// <param name="line1Start"></param> /// <param name="line1End"></param> /// <param name="isSegmentLine1"></param> /// <param name="line2Start"></param> /// <param name="line2End"></param> /// <param name="isSegmentLine2"></param> /// <returns></returns> public static IntersectionResult LineToLineIntersection(Vector2 line1Start, Vector2 line1End, bool isSegmentLine1, Vector2 line2Start, Vector2 line2End, bool isSegmentLine2) { IntersectionResult result = new IntersectionResult(); Vector2 line1Direction = line1End - line1Start; Vector2 line2Direction = line2End - line2Start; if (line2Direction != line1Direction) { float d = Cross(line1Direction, line2Direction); if (d != 0) { Vector2 line1StartToLine2Start = line2Start - line1Start; float r = Cross(line1StartToLine2Start, line2Direction) / d; float s = Cross(line1StartToLine2Start, line1Direction) / d; Vector2 intersection = default(Vector2); //两条直线 if (!isSegmentLine1 && !isSegmentLine2) { intersection = line1Start + line1Direction * r; result.AddIntersectionPoint(intersection); return(result); } //两条线段 if (isSegmentLine1 && isSegmentLine2) { if (r >= 0 && r <= 1 && s >= 0 && s <= 1) { intersection = line1Start + line1Direction * r; result.AddIntersectionPoint(intersection); return(result); } } //第一个是线段,第二个是直线 if (isSegmentLine1 && !isSegmentLine2) { if (r >= 0 && r <= 1) { intersection = line1Start + line1Direction * r; result.AddIntersectionPoint(intersection); return(result); } } if (!isSegmentLine1 && isSegmentLine2) { if (r >= 0 && r <= 1) { intersection = line1Start + line1Direction * r; result.AddIntersectionPoint(intersection); return(result); } } } } return(result); }