¿Cómo orderar una matriz de puntos de vértice X e Y? iOS / Objetivo C

Tengo una entidad de datos principales llamada Línea. Cada línea contiene una instancia de un VerticePoint que contiene una propiedad x e y. Estos vértices x e y forman simples polígonos 2D.

Lo que quiero hacer es orderar una matriz de estos objects de línea que está en order aleatorio, de modo que el origen de la forma, el punto inferior izquierdo, sea siempre el primer elemento de la matriz, seguido de los vértices restantes heridos en la contra- En el sentido de las agujas del reloj desde el origen.

Así que di los puntos en mi matriz original (el eje xy está centrado en 0,0):

x = 20, y = 20 x = 20 , y= 10 x = 10, y=10 x = 10, y =20 x = 15, y = 10 

Quiero clasificarlos así:

 x = 10, y=10 x = 15, y = 10 x = 20 , y= 10 x = 20, y = 20 x = 10, y =20 

Muchas gracias

Puedes usar

 - (NSArray *)sortedArrayUsingDescriptors:(NSArray *)sortDescriptors 

de NSArray.

Puede usar más de un descriptor. Simplemente inicialice dos descriptores uno con x, uno con la propiedad y.

Aquí hay una propuesta para una especificación precisa:

  1. Suponga un primer sistema de coorderadas de cuadrante (con el eje y apuntando hacia arriba).
  2. Encuentra el centro del eje alineado cuadro delimitador de todos los puntos.
  3. Ordena los puntos por el ángulo de un vector desde el centro hasta el punto. Para calcular el ángulo, considere un vector que apunta al sur oeste para estar a 0 ° con angularjs ascendentes en sentido contrario a las agujas del reloj.

Y he aquí una solución:

 NSArray *points = @[ [NSValue valueWithCGPoint:(CGPoint){20, 20}], [NSValue valueWithCGPoint:(CGPoint){20, 10}], [NSValue valueWithCGPoint:(CGPoint){10, 10}], [NSValue valueWithCGPoint:(CGPoint){10, 20}], [NSValue valueWithCGPoint:(CGPoint){15, 10}], ]; CGPoint min = [points[0] CGPointValue]; CGPoint max = min; for (NSValue *value in points) { CGPoint point = [value CGPointValue]; min.x = fminf(point.x, min.x); min.y = fminf(point.y, min.y); max.x = fmaxf(point.x, max.x); max.y = fmaxf(point.y, max.y); } CGPoint center = { 0.5f * (min.x + max.x), 0.5f * (min.y + max.y), }; NSLog(@"center: %@", NSStringFromCGPoint(center)); NSNumber *(^angleFromPoint)(id) = ^(NSValue *value){ CGPoint point = [value CGPointValue]; CGFloat theta = atan2f(point.y - center.y, point.x - center.x); CGFloat angle = fmodf(M_PI - M_PI_4 + theta, 2 * M_PI); return @(angle); }; NSArray *sortedPoints = [points sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { return [angleFromPoint(a) compare:angleFromPoint(b)]; }]; NSLog(@"sorted points: %@", sortedPoints); 

Debería implementar un método para su object VerticePoint que haga la comparación, algo así:

 - (NSComparisonResult)compare:(VerticePoint *)vpoint { if (self.x > vpiont.x) return NSOrdenetworkingAscending; else if (self.x < vpiont.x) return NSOrdenetworkingDescending; else if (self.y > vpiont.y) return NSOrdenetworkingAscending; else if (self.y < vpiont.y) return NSOrdenetworkingDescending; else return NSOrdenetworkingSame; } 

Y después de eso, si tiene su matriz con el object VerticePoint, debe llamar:

 NSArray *sortedArray = [yourArray sortedArrayUsingSelector:@selector(compare:)]; 

Espero que esto ayude.

//EXTENDIDO

Si no desea crear la subclass de NSManagedObject puede usar NSSortDescriptor:

 NSFetchRequest *request = [[NSFetchRequest alloc] init]; [request setEntity:[NSEntityDescription entityForName:@"ENTITYNAME" inManagedObjectContext:context]]; NSSortDescriptor *sortDescriptorX = [NSSortDescriptor sortDescriptorWithKey:@"yourObjecy.x" ascending:YES]; NSSortDescriptor *sortDescriptorY = [NSSortDescriptor sortDescriptorWithKey:@"yourObjecy.y" ascending:YES]; [request setSortDescriptors:[NSArray arrayWithObjects:sortDescriptorX, sortDescriptorY, nil]]; NSArray *sortedResults = [context executeFetchRequest:request error:nil]; 

// EXTENDIDO

O la solución más fácil es

 NSArray *returnedVertices = [verticesPassed sortedArrayUsingComparator:^(id obj1, id obj2) { //Cast to your object: VerticePoint *p1 = (VerticePoint*)obj1; VerticePoint *p2 = (VerticePoint*)obj2; if (p1.x > p2.x) return NSOrdenetworkingAscending; else if (p1.x < p2.x) return NSOrdenetworkingDescending; else if (p1.y > p2.y) return NSOrdenetworkingAscending; else if (p1.y < p2.y) return NSOrdenetworkingDescending; else return NSOrdenetworkingSame; } 

];