Tôi sẽ bị cám dỗ để làm điều này bằng cách sử dụng các thiên thần, gần giống như đường ngắm. Nếu trong khi lặp lại các đỉnh trong hình dạng, các góc giữa đỉnh gốc và đỉnh đích tiếp tục theo một hướng nhất quán, thì tất cả các điểm đều là ứng cử viên cho phản đối. Nếu một góc chuyển hướng, thì điểm đó bị ẩn hoặc ẩn điểm trước đó. Nếu nó bị ẩn bởi điểm trước, điểm cần phải được bỏ qua. Nếu nó ẩn điểm trước đó, (các) điểm trước cần phải được xóa khỏi danh sách ứng cử viên.
- Tạo danh sách PolygonCandidates
- Đối với mỗi đỉnh (điểm k)
- Tạo danh sách mới cho các ứng cử viên (Điểm, Góc)
- Thêm đỉnh hiện tại vào danh sách ứng viên (điểm k)
- Lặp lại theo chiều kim đồng hồ xung quanh đa giác, cho mỗi đỉnh còn lại (điểm i)
- Nếu góc tới điểm hiện tại (từ điểm k đến điểm i) tiếp tục theo chiều kim đồng hồ 1. thêm điểm
- Nếu góc tới điểm hiện tại tiếp tục theo hướng ngược chiều kim đồng hồ
- Nếu hai điểm ứng cử viên trước, cộng với điểm hiện tại tạo thành một lượt rẽ phải.
- Xóa điểm cuối cùng trong danh sách cho đến góc hiện tại và góc danh sách ứng viên cuối cùng theo hướng ngược chiều kim đồng hồ.
- Thêm điểm hiện tại vào danh sách thí sinh
- Thêm tất cả trừ hai ứng cử viên đầu tiên và cuối cùng vào danh sách PolygonCandidates
- Tìm điểm xa nhất trong danh sách PolygonCandidates.
Tôi không biết phải làm gì với các trường hợp gốc tọa độ và hai đỉnh khác đều nằm trên cùng một đường thẳng. Trong trường hợp đó, góc sẽ giống nhau. Nếu bạn có một đa giác có lỗ, bạn có thể tìm góc tối thiểu / tối đa của mỗi lỗ và xóa bất kỳ điểm ứng cử viên nào nằm trong phạm vi đó.
Ưu điểm chính của phương pháp này là bạn không phải kiểm tra giao điểm giữa đường thẳng hiện tại và tất cả các cạnh đa giác.
Điều này hoạt động ... tôi nghĩ. Tôi đã cập nhật mã giả ở trên và python để dễ đọc hơn.
Đây phải là bản chỉnh sửa cuối cùng. Ví dụ dưới đây sẽ tìm thấy lỗ thông lớn nhất cho hình dạng đã cho. Tôi đã thay đổi tập lệnh để sử dụng Điểm và Vectơ, để thử và làm cho nó dễ đọc hơn.
import math
from collections import namedtuple
Point = namedtuple("Point", "position x y")
Vector = namedtuple("Vector", "source dest angle")
def isClockwise(angle1, angle2):
diff = angle2 - angle1
#print(" angle1:%s angle2:%s diff: %s" % (angle1, angle2, diff))
if(diff > math.pi/2):
diff = diff - math.pi/2
elif (diff < -math.pi/2):
diff = diff + math.pi/2
#print(" diff:%s" % (diff))
if(diff > 0):
return False
return True
def getAngle(origin, point):
return math.atan2(point.y - origin.y, point.x-origin.x)
#returns a list of candidate vertcies. This will include the first, second, and second to last points
#the first and last points in the polygon must be the same
#k is the starting position, only vertices after this position will be evaluated
def getCandidates (k, polygon):
origin = polygon[k]
candidates = [Vector(k,k,0)]
prevAngle = 0;
currentAngle = 0;
for i in range(k + 1, len(polygon) - 1):
current = polygon[i]
#print("vertex i:%s x:%s y:%s " % (i, current.x, current.y))
if(i == k+1):
prevAngle = getAngle(origin, current)
candidates.append(Vector(k,i,prevAngle))
else:
currentAngle = getAngle(origin, current)
#print(" prevAngle:%s currentAngle:%s " % (prevAngle, currentAngle))
if isClockwise(prevAngle, currentAngle):
#print(" append")
candidates.append(Vector(k,i,currentAngle))
prevAngle = currentAngle
else:
#look at the angle between current, candidate-1 and candidate-2
if(i >= 2):
lastCandinate = polygon[candidates[len(candidates) - 1].dest]
secondLastCandidate = polygon[candidates[len(candidates) - 2].dest]
isleft = ((lastCandinate.x - secondLastCandidate.x)*(current.y - secondLastCandidate.y) - (lastCandinate.y - secondLastCandidate.y)*(current.x - secondLastCandidate.x)) > 0
#print(" test for what side of polygon %s" % (isleft))
if(i-k >= 2 and not isleft):
while isClockwise(currentAngle, candidates[len(candidates) - 1].angle):
#print(" remove %s" % (len(candidates) - 1))
candidates.pop()
#print(" append (after remove)")
candidates.append(Vector(k,i,currentAngle))
prevAngle = currentAngle
#for i in range(len(candidates)):
# print("candidate i:%s x:%s y:%s a:%s " % (candidates[i][0], candidates[i][1], candidates[i][2], candidates[i][3]))
return candidates
def calcDistance(point1, point2):
return math.sqrt(math.pow(point2.x - point1.x, 2) + math.pow(point2.y - point1.y, 2))
def findMaxDistance(polygon, candidates):
#ignore the first 2 and last result
maxDistance = 0
maxVector = Vector(0,0,0);
for i in range(len(candidates)):
currentDistance = calcDistance(polygon[candidates[i].source], polygon[candidates[i].dest])
if(currentDistance > maxDistance):
maxDistance = currentDistance
maxVector = candidates[i];
if(maxDistance > 0):
print ("The Antipodal distance is %s from %s to %s" % (maxDistance, polygon[candidates[i].source], polygon[candidates[i].dest]))
else:
print ("There is no Antipodal distance")
def getAntipodalDist(polygon):
polygonCandidates = []
for j in range(0, len(polygon) - 1):
candidates = getCandidates(j, polygon)
for i in range(2, len(candidates) - 1):
#print("candidate i:%s->%s x:%s y:%s " % (candidates[i].source, candidates[i].dest, candidates[i].x, candidates[i].y))
polygonCandidates.append(candidates[i])
for i in range(len(polygonCandidates)):
print("candidate i:%s->%s" % (polygonCandidates[i].source, polygonCandidates[i].dest))
findMaxDistance(polygon, polygonCandidates)
getAntipodalDist([Point(0,0,0),Point(1,-2,0),Point(2,-2,3),Point(3,2,2),Point(4,-1,1),Point(5,4,0),Point(6,0,0)])
getAntipodalDist([Point(0,0,0),Point(1,2,1),Point(2,1,4),Point(3,3,5),Point(4,5,4),Point(5,4,1),Point(6,0,0)])
getAntipodalDist([Point(0,0,0),Point(1,1,1),Point(2,2,1),Point(3,1,4),Point(4,3,5),Point(5,5,4),Point(6,4,1),Point(7,0,0)])
getAntipodalDist([Point(0,0,0),Point(1,-1,3),Point(2,1,4),Point(3,3,3),Point(4,2,0),Point(5,-2,-1),Point(6,0,0)])