2013-12-05 2 views
4

У меня есть объект Core Data, называемый Line. Каждая строка содержит экземпляр VerticePoint, который содержит свойства x и y. Эти х и у вершины образуют простые двумерные многоугольники.Сортировка массива точек вершины X и Y? iOS/Objective C

Что я хочу сделать, так это отсортировать массив этих объектов Line, который находится в случайном порядке, так что начало формы, нижняя левая точка, всегда является первым элементом в массиве, а затем остальные вершины рану в направлении против часовой стрелки от начала координат.

Так сказать, точки в моем исходном массиве есть (ху оси с центром в точке 0,0):

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

Я хочу, чтобы отсортировать их так:

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

Большое спасибо

+0

Это не совсем понятно, как вы хотите отсортировать вершины: «против часовой стрелки вокруг начала координат» звучит как вершины должны быть расположены примерно по кругу вокруг (0, 0), но ваш пример показывает, что они упорядочены вокруг их центра (15, 15). Вы должны более точно описать, как должна работать сортировка. –

+0

От источника - не вокруг. Это не то, что я написал. – GuybrushThreepwood

+0

Что означает «от начала координат»? Всегда ли точка происхождения? Или мы должны начать с точки, наиболее близкой к происхождению? –

ответ

1

Вы можете использовать

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

из NSArray.

Вы можете использовать более одного дескриптора. Просто инициализируйте два дескриптора, один с x, один с свойством y.

+0

Как это будет работать с объектами Core Data? Мой VerticePoint является дочерним объектом объекта Line. – GuybrushThreepwood

+0

Спасибо, это то, что я закончил делать. – GuybrushThreepwood

0

Вы должны реализовать метод для вашего объекта VerticePoint, который делает сравнение, что-то вроде этого:

- (NSComparisonResult)compare:(VerticePoint *)vpoint 
{ 
    if (self.x > vpiont.x) 
     return NSOrderedAscending; 
    else if (self.x < vpiont.x) 
     return NSOrderedDescending; 
    else if (self.y > vpiont.y) 
     return NSOrderedAscending; 
    else if (self.y < vpiont.y) 
     return NSOrderedDescending; 
    else 
     return NSOrderedSame; 
} 

И после этого, если у вас есть массив с VerticePoint объект, который вы звоните:

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

Надежда эта помощь.

// EXTENDED

Если вы не хотите, чтобы создать подкласс NSManagedObject вы можете использовать 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]; 

// EXTENDED

Или самое простое решение является

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 NSOrderedAscending; 
    else if (p1.x < p2.x) 
     return NSOrderedDescending; 
    else if (p1.y > p2.y) 
     return NSOrderedAscending; 
    else if (p1.y < p2.y) 
     return NSOrderedDescending; 
    else 
     return NSOrderedSame; 
} 

];

+0

Что такое self.x и self.y? – GuybrushThreepwood

+0

Я предполагаю, что ваш класс VerticePoint содержит свойство float x; и свойство float y ;. Вы добавляете этот метод в свой класс, который хотите отсортировать, и это VerticePoint, не так ли? И это условие, которое вы хотите использовать при сортировке. – Greg

+0

Нет - массив содержит объекты объектов ядра ядра вершины, но код отсутствует в этом классе. – GuybrushThreepwood

13

Вот предложение для точной спецификации:

  1. Предположим, первый квадрант системы координат (с осью у, направленная вверх).
  2. Найдите центр выровненной по оси ограничительной рамки всех точек.
  3. Сортируйте точки по углу вектора от центра к точке. Чтобы вычислить угол, рассмотрим вектор, указывающий на юго-запад, на 0 ° с ростом углов в направлении против часовой стрелки.

И вот решение:

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); 
Смежные вопросы