2013-03-29 10 views
9

Non so da dove cominciare. Ovviamente lo CGRectIntersectsRect non funzionerà in questo caso, e vedrai perché.Objective-C controlla se le visualizzazioni secondarie di UIViews ruotate si intersecano?

Ho una sottoclasse di UIView che ha un'UIImageView interno che è posta al centro esatto del UIView:

UIView before rotation

Ho poi ruotare l'UIView personalizzata per mantenere il telaio della UIImageView interno pur essendo ancora in grado di eseguire un CGAffineRotation. Il telaio risulta simile a questa:

UIView after rotation

ho bisogno di impedire agli utenti di fare queste UIImageViews si intersecano, ma non ho idea di come controllare intersezione tra le due UIImageViews, dal momento che non solo non si applicano le loro strutture alla UIView genitore, ma anche, essi vengono ruotati senza che ciò influisca sui loro frame.

Gli unici risultati dei miei tentativi non hanno avuto successo.

Qualche idea?

risposta

8

Il seguente algoritmo può essere utilizzato per verificare se due (ruotato o altrimenti trasformati) visite sovrappongono:

  • Usa [view convertPoint:point toView:nil] per convertire i 4 punti di confine dei due viste ad un sistema di coordinate comune (le coordinate finestra).
  • I punti convertiti formano due quadrilateri convessi.
  • Utilizzare SAT (Separating Axis Theorem) per verificare se i quadrilateri si intersecano.

Questo: http://www.geometrictools.com/Documentation/MethodOfSeparatingAxes.pdf è un'altra descrizione dell'algoritmo contenente pseudo-codice, più può essere trovato da googling "Separazione asse Teorema".


Update: Ho cercato di creare un metodo di Objective-C per la "Separazione Asse Teorema", e questo è quello che ho ottenuto. Fino ad ora, ho fatto solo alcuni test, quindi spero che non ci siano troppi errori.

- (BOOL)convexPolygon:(CGPoint *)poly1 count:(int)count1 intersectsWith:(CGPoint *)poly2 count:(int)count2; 

test se 2 poligoni convessi si intersecano. Entrambi i poligoni vengono forniti come una serie CGPoint dei vertici.

- (BOOL)view:(UIView *)view1 intersectsWith:(UIView *)view2 

test (come descritto sopra) se due viste arbitrarie si intersecano.

Implementazione:

- (void)projectionOfPolygon:(CGPoint *)poly count:(int)count onto:(CGPoint)perp min:(CGFloat *)minp max:(CGFloat *)maxp 
{ 
    CGFloat minproj = MAXFLOAT; 
    CGFloat maxproj = -MAXFLOAT; 
    for (int j = 0; j < count; j++) { 
     CGFloat proj = poly[j].x * perp.x + poly[j].y * perp.y; 
     if (proj > maxproj) 
      maxproj = proj; 
     if (proj < minproj) 
      minproj = proj; 
    } 
    *minp = minproj; 
    *maxp = maxproj; 
} 

-(BOOL)convexPolygon:(CGPoint *)poly1 count:(int)count1 intersectsWith:(CGPoint *)poly2 count:(int)count2 
{ 
    for (int i = 0; i < count1; i++) { 
     // Perpendicular vector for one edge of poly1: 
     CGPoint p1 = poly1[i]; 
     CGPoint p2 = poly1[(i+1) % count1]; 
     CGPoint perp = CGPointMake(- (p2.y - p1.y), p2.x - p1.x); 

     // Projection intervals of poly1, poly2 onto perpendicular vector: 
     CGFloat minp1, maxp1, minp2, maxp2; 
     [self projectionOfPolygon:poly1 count:count1 onto:perp min:&minp1 max:&maxp1]; 
     [self projectionOfPolygon:poly2 count:count1 onto:perp min:&minp2 max:&maxp2]; 

     // If projections do not overlap then we have a "separating axis" 
     // which means that the polygons do not intersect: 
     if (maxp1 < minp2 || maxp2 < minp1) 
      return NO; 
    } 

    // And now the other way around with edges from poly2: 
    for (int i = 0; i < count2; i++) { 
     CGPoint p1 = poly2[i]; 
     CGPoint p2 = poly2[(i+1) % count2]; 
     CGPoint perp = CGPointMake(- (p2.y - p1.y), p2.x - p1.x); 

     CGFloat minp1, maxp1, minp2, maxp2; 
     [self projectionOfPolygon:poly1 count:count1 onto:perp min:&minp1 max:&maxp1]; 
     [self projectionOfPolygon:poly2 count:count1 onto:perp min:&minp2 max:&maxp2]; 

     if (maxp1 < minp2 || maxp2 < minp1) 
      return NO; 
    } 

    // No separating axis found, then the polygons must intersect: 
    return YES; 
} 

- (BOOL)view:(UIView *)view1 intersectsWith:(UIView *)view2 
{ 
    CGPoint poly1[4]; 
    CGRect bounds1 = view1.bounds; 
    poly1[0] = [view1 convertPoint:bounds1.origin toView:nil]; 
    poly1[1] = [view1 convertPoint:CGPointMake(bounds1.origin.x + bounds1.size.width, bounds1.origin.y) toView:nil]; 
    poly1[2] = [view1 convertPoint:CGPointMake(bounds1.origin.x + bounds1.size.width, bounds1.origin.y + bounds1.size.height) toView:nil]; 
    poly1[3] = [view1 convertPoint:CGPointMake(bounds1.origin.x, bounds1.origin.y + bounds1.size.height) toView:nil]; 

    CGPoint poly2[4]; 
    CGRect bounds2 = view2.bounds; 
    poly2[0] = [view2 convertPoint:bounds2.origin toView:nil]; 
    poly2[1] = [view2 convertPoint:CGPointMake(bounds2.origin.x + bounds2.size.width, bounds2.origin.y) toView:nil]; 
    poly2[2] = [view2 convertPoint:CGPointMake(bounds2.origin.x + bounds2.size.width, bounds2.origin.y + bounds2.size.height) toView:nil]; 
    poly2[3] = [view2 convertPoint:CGPointMake(bounds2.origin.x, bounds2.origin.y + bounds2.size.height) toView:nil]; 

    return [self convexPolygon:poly1 count:4 intersectsWith:poly2 count:4]; 
} 
+1

Un'altra descrizione dell'algoritmo: http://stackoverflow.com/a/115520/1187415. –

+0

Brillante! Grazie mille! – David

+0

@MartinR Ho posto una nuova domanda [qui] (http://stackoverflow.com/questions/26821725/determine-if-crop-rect-is-entally-contained-within-rotated-uiview) basata su questa domanda/risposta. Ti chiedi se puoi dargli un'occhiata vedi? – brandonscript