[英]C++ std::sort with custom function
I have a structure Point: 我有一个结构点:
typedef struct Point
{
double x;
double y;
Point operator-(const Point &b)
{
Point pt;
pt.x = this->x - b.x;
pt.y = this->y - b.y;
return pt;
}
friend std::ostream& operator<<(std::ostream& os, const Point& pt)
{
return os << "X: " << pt.x << "\t\t\tY: " <<pt.y << std::endl;
}
friend std::istream& operator>>(std::istream& is, Point& pt)
{
return is >> pt.x >> pt.y;
}
}Point;
I am trying to find the minimum element from the vector<Point>
and then sort based on angles against this minimum point. 我试图从vector<Point>
找到最小元素,然后根据该最小点的角度进行排序。
Below is the respective code: 以下是相应的代码:
bool lex_yx(const Point &a, const Point &b)
{
if(a.y < b.y)
return true;
if (a.y == b.y)
return (a.x < b.x);
return false;
}
bool CalcAngRad_Compare (const Point &p_min, Point &a, Point &b)
{
Point subPt_1, subPt_2;
double a_r, b_r, a_angle, b_angle;
subPt_1 = a - p_min, subPt_2 = b - p_min;
a_angle = atan2(subPt_1.y, subPt_1.x);
b_angle = atan2(subPt_2.y, subPt_2.x);
if (a_angle < b_angle) {return true;}
if (a_angle > b_angle) {return false;}
a_r = subPt_1.x * subPt_1.x * subPt_1.y * subPt_1.y;
b_r = subPt_2.x * subPt_2.x * subPt_2.y * subPt_2.y;
return (a_r < b_r); // return (a_r <= b_r); // Code crashes, saying invalid operator <. I do not know why. Pl tell me.
}
auto it = std::min_element(V.begin(), V.end(), lex_yx);
std::sort( V.begin(), V.end(), boost::bind(CalcAngRad_Compare, *it, _1, _2));
When I pass in a simple test input such as 当我传入一个简单的测试输入,如
2 2
3 3
4 4
1 1 // this should be first element in the sorted array
5 5
it works, I get the sorted array. 它工作,我得到排序的数组。 But now take a look at this another simple input: 但现在看看另一个简单的输入:
-0.5 -0.1
-0.1 -0.1
0 1
-1 -0.1 // this should be first element is sorted array. BUT IT IS NOT!!
5 5
I do not think I have done anything wrong. 我认为我没有做错任何事。 One issue might be that when y coordinate is equal, angle is 0 or pi. 一个问题可能是当y坐标相等时,角度为0或pi。 In that case, if radius is also equal, then I return false
. 在这种情况下,如果radius也相等,那么我return false
。 I tried to change this to return (a_r <= b_r)
, but this seems not possible. 我试图将其更改为return (a_r <= b_r)
,但这似乎不可能。 Code crashes saying invalid operator <. 代码崩溃说无效运算符<。 (in the file xutility
with true at this line: else if (_Pred(_Right, _Left))
. I do not understand what is being tested, may be some precedence is checked.) (在文件xutility
,此行为true: else if (_Pred(_Right, _Left))
。我不明白正在测试什么,可能会检查一些优先级。)
What I want you to answer: 我想让你回答:
Your first sort criteria is angle calculated by atan2
. 您的第一个排序标准是由atan2
计算的角度。 In your case p_min
is -1.0/-0.1. 在你的情况下, p_min
是-1.0 / -0.1。 If a
is -1.0/-0.1 and b
is -0.5/-0.1, you will calcualte atan2( -0.1 + 0.1, -1.0 + 1.0 );
如果a
为-1.0 / -0.1且b
为-0.5 / -0.1,则计算atan2( -0.1 + 0.1, -1.0 + 1.0 );
( a-p_min
) and atan2( -0.1 + 0.1, -0.5 + 1.0 );
( a-p_min
)和atan2( -0.1 + 0.1, -0.5 + 1.0 );
( b-p_min
) which is 0.0
in both cases. ( b-p_min
)在两种情况下均为0.0
。 You continue to compare 0.0 * 0.0 * 0.0 * 0.0
( a
) with 0.5 * 0.5 * 0.0 * 0.0
( b
) which means 0.0 < 0.0
. 您继续将0.0 * 0.0 * 0.0 * 0.0
( a
)与0.5 * 0.5 * 0.0 * 0.0
( b
)进行比较,这意味着0.0 < 0.0
。 Consequently a
(-1.0/-0.1) is not less than b
(-0.5/-0.1). 因此a
( - 1.0 / -0.1)不小于b
(-0.5 / -0.1)。
To calculate angle between to vectors use DOT-product. 要计算矢量之间的角度,请使用DOT产品。 |A| | A | * |B| * | B | * cos(angle between A and B ) = Ax * Bx + Ay * By * cos(A和B之间的角度)= Ax * Bx + Ay * By
double len_p_min = sqrt( p_min.x*p_min.x + p_min.y*p_min.y ); // lenght of p_min
double len_a = sqrt( a.x*a.x + a.y*a.y ); // lenght of a
double len_b = sqrt( b.x*b.x + b.y*b.y ); // lenght of b
Point normalizedMin{ p_min.x / len_p_min, p_min.y / len_p_min }; // direction of p_min ( lenght == 1.0)
Point normalizedA{ a.x / len_a, a.y / len_a }; // direction of a ( lenght == 1.0)
Point normalizedB{ b.x / len_b, b.y / len_b }; // direction of b ( lenght == 1.0)
double cosAmin = normalizedMin.x*normalizedA.x + normalizedMin.y*normalizedA.y; // cos of angle between a and p_min
double angleAmin = acos( cosAmin );
double cosBmin = normalizedMin.x*normalizedB.x + normalizedMin.y*normalizedB.y; // cos of angle between b and p_min
double angleBmin = acos( cosBmin );
To compare angles it is not necessary to calculate acos
. 为了比较角度,不必计算acos
。 It is sufficient to compare cos of angles 比较角度的cos就足够了
if ( fabs( cosAmin ) < fabs( cosBmin ) ) {return true;}
if ( fabs( cosAmin ) > fabs( cosbmin ) ) {return false;}
If you like to sort vector by length use |v| 如果你想按长度排序矢量,请使用| v | = sqrt( vx * vx + vy * vy ) If only have to compare length of vectors, you don't need to calculate sqrt
, it will be sufficient to compare lentgth^2. = sqrt(vx * vx + vy * vy)如果只需要比较向量的长度,则不需要计算sqrt
,就足以比较lentgth ^ 2。
a_r = subPt_1.x * subPt_1.x + subPt_1.y * subPt_1.y; // |a|^2 (lenght of a pow 2)
b_r = subPt_2.x * subPt_2.x + subPt_2.y * subPt_2.y; // |b|^2 (lenght of b pow 2)
return (a_r < b_r);
How can I solve the issue and always get the (correctly) sorted vector Is there any other way of achieving what I am doing? 我如何解决问题并始终获得(正确)排序的向量是否还有其他方法可以实现我正在做的事情?
Not sure of the order you want, does less_yx
do the job ? 不确定你想要的订单, less_yx
是否less_yx
完成这项工作?
I am very much interested in learning what is problem in my thinking/implementation style? 我非常有兴趣了解我的思维/实施风格中的问题是什么?
Assuming IEEE floating-point arithmetic (else you have domain error for 0, 0
) 假设IEEE浮点运算(否则你有0, 0
域错误)
As your reference point is the lowest y
, second arg passed to atan2 is positive or null. 由于您的参考点是最低y
,因此传递给atan2的第二个arg为正或null。
- `atan2(0, 0) = 0`
- `atan2(+x, 0) = 0`
- `atan2(x, +y) > 0`
So any lowest y are equivalent according to atan2
. 因此根据atan2
任何最低y都是等价的。
a_r = subPt_1.x * subPt_1.x * subPt_1.y * subPt_1.y;
is always 0
for subPt_1.y == 0
. 始终是0
的subPt_1.y == 0
。 Do you mean 你的意思是
a_r = subPt_1.x * subPt_1.x + subPt_1.y * subPt_1.y;
instead ? 相反? (so it compare x
even when y == 0
) (所以即使y == 0
,它也要比较x
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.