Yo estaría tentado a hacer esto utilizando los ángeles, casi como la línea de visión. Si durante la iteración de los vértices en la forma de los ángulos entre el vértice origen y destino vértice continuar en una dirección consistente, todos los puntos son candidatos para el antipodal. Si un ángulo cambia de dirección, entonces ese punto se oculta o se esconde en el punto anterior. Si está oculto por el punto anterior, el punto debe ser omitido. Si se oculta el punto anterior, el anterior punto(s) necesita ser removido de la lista de candidatos.
- Crear una lista PolygonCandidates
- Para cada vértice (punto k)
- Crear nueva lista de candidatos (Punto, Ángulo)
- Añadir el vértice actual a la lista de candidatos (punto k)
- Recorrer las agujas del reloj alrededor del polígono, para cada vértice (punto i)
- Si el ángulo del punto actual (desde el punto de k para el punto i) continúa en sentido horario
1.añadir el punto
- Si el ángulo de la corriente de punto continúa en dirección contra reloj
- Si las dos anteriores candidato puntos, y con el actual punto de formar un girar a la derecha.
- Eliminar el último punto de la lista, hasta que el ángulo actual y el último de la lista de candidatos ángulo en sentido antihorario.
- Agregar el punto actual a la lista de candidatos
- Agregar todos, pero los dos primeros, y el último candidato apunta a un PolygonCandidates lista
- Encontrar el punto más alejado en la PolygonCandidates lista.
No estoy seguro de qué hacer con los casos donde el origen y el de los otros dos vértices todos caen a lo largo de la misma línea. En ese caso, el ángulo sería el mismo. Si usted tuvo un polígono con agujeros, usted podría encontrar el min/max ángulo de cada agujero, y eliminar cualquier candidato punto que se encuentra dentro de ese rango.
La principal ventaja de este enfoque sería que usted no tiene que probar la línea de intersección entre el segmento de línea actual y todo el polígono bordes.
Esto funciona...creo. He actualizado el pseudo código de arriba y el de python con el fin de hacer más fácil la lectura.
Esta debe ser la última edición. El ejemplo de abajo, deben encontrar la mayor anitpole para una determinada geometría. He modificado la receta para que se utiliza los Puntos y Vectores, para intentar hacer más fácil la lectura.
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)])