Tôi chưa làm việc thông qua các phương trình đầy đủ cho điều này, nhưng đây là một số hình ảnh để giúp giải quyết vấn đề. Nó sôi sùng sục xuống một số hình học:
( Biểu tượng xe hơi qua Kenney )
Từ bất kỳ điểm bắt đầu và hướng nào, chúng ta có thể vẽ hai vòng tròn với bán kính quay tối thiểu - một ở bên trái, một ở bên phải. Chúng mô tả các điểm trên bắt đầu chặt chẽ nhất có thể đến con đường của chúng tôi.
Chúng tôi có thể làm tương tự cho bất kỳ vị trí và định hướng kết thúc mong muốn. Những vòng tròn này mô tả kết thúc chặt chẽ nhất có thể trên con đường của chúng tôi.
Bây giờ vấn đề giảm xuống để tìm một đường dẫn nối một trong các vòng tròn bắt đầu đến một trong các vòng kết thúc, hôn từng người dọc theo tiếp tuyến của nó.
. để vượt qua, chúng ta có thể áp dụng phương pháp dưới đây cho từng phân đoạn của kế hoạch.)
Nếu, để đơn giản, chúng tôi sử dụng các đường thẳng, chúng tôi nhận được một cái gì đó như thế này:
Điều này cho chúng ta trường hợp hạn chế. Khi bạn đã tìm thấy một con đường bằng phương pháp này, bạn có thể thổi phồng một hoặc cả hai vòng tròn bắt đầu và kết thúc một cách giả tạo để có được một con đường ít trực tiếp hơn nhưng mượt mà hơn, cho đến khi hai vòng tròn hôn nhau.
Tính toán các đường dẫn này
Chúng ta hãy giải quyết các trường hợp cho một hướng rẽ - giả sử chúng ta bắt đầu con đường của mình bằng cách rẽ phải.
Trung tâm của vòng tròn bên phải của chúng tôi là:
startRightCenter = carStart.position + carStart.right * minRadius
Hãy gọi góc của phần thẳng của đường đi của chúng tôi (được đo từ trục x dương) pathAngle
Nếu chúng ta vẽ một vectơ từ rightCenter
đến điểm mà chúng ta rời khỏi vòng tròn xoay (tại điểm đó chúng ta phải đối mặt với pathAngle), thì vectơ đó là ...
startOffset = minRadius * (-cos(pathAngle), sin(pathAngle))
Điều đó có nghĩa là điểm chúng ta rời khỏi vòng tròn phải là ...
departure = startRightCenter + startOffset
Điểm mà chúng tôi nhập lại vòng tròn phụ thuộc vào việc chúng tôi đang nhắm đến kết thúc bằng rẽ trái hay rẽ phải:
// To end with a right turn:
reentry = endRightCenter + startOffset
// To end with a left turn: (crossover)
reentry = endLeftCenter - startOffset
Bây giờ, nếu chúng ta làm đúng công việc của chúng tôi, đường nối departure
đến reentry
nó đã có vuông góc với startOffset
:
dot(reentry - departure, startOffset) = 0
Và giải phương trình này sẽ cho chúng ta các góc mà điều này đúng. (Tôi sử dụng số nhiều ở đây vì về mặt kỹ thuật có hai góc như vậy, nhưng một trong số chúng liên quan đến việc lái xe ngược lại thường không phải là điều chúng ta muốn)
Hãy thay thế rẽ phải sang trường hợp rẽ phải làm ví dụ:
dot(endRightCenter + startOffset - startRightCenter - startOffset, startOffset) = 0
dot(endRightCenter - startRightCenter, startOffset) = 0
pathAngle = atan2(endRightCenter - startRightCenter)
Trường hợp chéo là phức tạp hơn - đó là trường hợp tôi chưa làm hết toán học. Bây giờ tôi sẽ đăng câu trả lời, trong trường hợp nó hữu ích cho bạn trong khi tôi tìm ra các chi tiết còn lại.
Chỉnh sửa: Điểm đến trong bán kính quay tối thiểu
Hóa ra, phương pháp này thường hoạt động vượt trội ngay cả khi đích đến gần hơn khoảng cách quay tối thiểu của chúng tôi. Ít nhất một phần của một trong các vòng tròn nhập lại kết thúc bên ngoài bán kính rẽ, cho phép chúng tôi tìm thấy một con đường khả thi miễn là chúng tôi không bận tâm rằng nó có một chút giống như bánh quy cây ...
Nếu chúng ta không thích con đường chúng ta đi theo cách đó (hoặc nếu không khả thi - tôi đã kiểm tra kỹ mọi trường hợp - có thể có những trường hợp không thể), chúng ta luôn có thể lái thẳng hoặc lùi cho đến khi chúng ta thấy phù hợp tiếp xúc hôn giữa một vòng tròn bắt đầu và kết thúc, như sơ đồ ở trên.