2012-12-20 22 views
7

Devo fare un programma per trovare tutti i quadrilateri convessi dalla lista data di 2d punti. L'ho provato con il prodotto cross vettoriale ma non sembra essere una soluzione corretta.Algoritmo per trovare tutti i quadrilateri convessi dalla lista data di 2d punti

Forse c'è qualche algoritmo efficace per questo problema ma non riesco a trovarlo.

Questo è un caso di esempio con ingressi e uscite:

ingresso

 
Number of Points: 
6 
 
coordinates of points (x,y): 
0 0 
0 1 
1 0 
1 1 
2 0 
2 1 

uscita

 
Number of convex quadrilaterals: 
9 

+0

fare vuoi dire poligoni convessi? Non sono chiaro perché stai specificando un numero di punti se sono quadrilateri (4 lati). –

+0

Oh, è il numero di punti nella lista successiva, è così? –

+0

In ogni caso, penso che puoi controllare se 4 punti sono i vertici di un quadrilatero convesso controllando se il 4 ° punto è fuori dal triangolo definito dai primi tre punti. –

risposta

8

Un quadrilatero convesso se relative diagonali si intersecano. Viceversa, se due segmenti di linea si intersecano, i loro quattro endpoint formano un quadrilatero convesso.

convex quadrilateral on left, non-convex on right

Ogni coppia di punti che dà un segmento di linea, e ogni punto di intersezione tra due segmenti di linea corrisponde ad un quadrilatero convesso.

È possibile trovare lo points of intersection utilizzando l'algoritmo naïve che confronta tutte le coppie di segmenti o lo Bentley–Ottmann algorithm. Il primo prende O (n); e quest'ultimo O ((n + q ) log n) (dove q è il numero di quadrilateri convessi). Nel peggiore dei casi q = Θ (n ) - considerare n punti su un cerchio - così Bentley-Ottmann non è sempre più veloce.

Ecco la versione ingenua in Python:

import numpy as np 
from itertools import combinations 

def intersection(s1, s2): 
    """ 
    Return the intersection point of line segments `s1` and `s2`, or 
    None if they do not intersect. 
    """ 
    p, r = s1[0], s1[1] - s1[0] 
    q, s = s2[0], s2[1] - s2[0] 
    rxs = float(np.cross(r, s)) 
    if rxs == 0: return None 
    t = np.cross(q - p, s)/rxs 
    u = np.cross(q - p, r)/rxs 
    if 0 < t < 1 and 0 < u < 1: 
     return p + t * r 
    return None 

def convex_quadrilaterals(points): 
    """ 
    Generate the convex quadrilaterals among `points`. 
    """ 
    segments = combinations(points, 2) 
    for s1, s2 in combinations(segments, 2): 
     if intersection(s1, s2) != None: 
      yield s1, s2 

E una corsa esempio:

>>> points = map(np.array, [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]) 
>>> len(list(convex_quadrilaterals(points))) 
9 
Problemi correlati