Sort a list by polar angle in counterclockwise ord

2019-08-16 08:45发布

问题:

I have a List L with some terms like range(2,3), where the first element is the term with the lowest Y, now I need to sort the other elements of the list L (the first element will remain unchanged), I need to sort them by polar angle in counterclockwise order. If polar angle of two points is same, then I need to put the nearest term first. I defined the predicate angle2d/2:

angle2d(A, B, R) :-
   A =.. [_,Ax,Ay],
   B =.. [_,Bx,By],
   R is atan2((Ay-By),(Ax-Bx)).

that give me the counter clockwise angle between 2 points, but i didn't get how to create the predicate sort_list/2 that will sort my n-1 points (the first one element of the list will remain unchanged) by their counter clockwise angle with the first element (point) of the list.

回答1:

As a general method for sorting by some weird custom criterion, first define you compare_custom/3 predicate, and then use it with a known sorting algorithm. In SWI you can use the predsort/3 predicate that is defined as following:

predsort(+Pred, +List, -Sorted)
Sorts similar to sort/2, but determines the order of two terms by calling Pred(-Delta, +E1, +E2) . This call must unify Delta with one of <, > or =. If the built-in predicate compare/3 is used, the result is the same as sort/2. See also keysort/2.

You should also take a look at the predefined compare/3:

compare(?Order, @Term1, @Term2)
Determine or test the Order between two terms in the standard order of terms. Order is one of <, > or =, with the obvious meaning.



回答2:

I did this:

sort_angle([], _).
sort_angle([_|[]], _).
sort_angle([_,_|[]], _).
sort_angle(List, SortedList) :-
   predsort(sort_me,[_|List], SortedList).

sort_me(<, A, B) :- angle2d(H,A,X), angle2d(H,B,Y), X<Y.
sort_me(>, A, B) :- angle2d(H,A,X), angle2d(H,B,Y), X>Y.
sort_me(=, A, B) :- angle2d(H,A,X), angle2d(H,B, Y), X=Y.

But I don't know, in the sort_me predicate how to tell that H is the first element of my list... how can I tell it ?



标签: prolog