簡體   English   中英

C ++ std :: sort with custom function

[英]C++ std::sort with custom function

我有一個結構點:

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;

我試圖從vector<Point>找到最小元素,然后根據該最小點的角度進行排序。

以下是相應的代碼:

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)); 

當我傳入一個簡單的測試輸入,如

2 2
3 3
4 4
1 1 // this should be first element in the sorted array
5 5

它工作,我得到排序的數組。 但現在看看另一個簡單的輸入:

-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

我認為我沒有做錯任何事。 一個問題可能是當y坐標相等時,角度為0或pi。 在這種情況下,如果radius也相等,那么我return false 我試圖將其更改為return (a_r <= b_r) ,但這似乎不可能。 代碼崩潰說無效運算符<。 (在文件xutility ,此行為true: else if (_Pred(_Right, _Left)) 。我不明白正在測試什么,可能會檢查一些優先級。)

我想讓你回答:

  1. 如何解決問題並始終獲得(正確)排序的向量
  2. 有沒有其他方法可以實現我的目標?
  3. 我非常有興趣了解我的思維/實施風格中的問題是什么?

您的第一個排序標准是由atan2計算的角度。 在你的情況下, p_min是-1.0 / -0.1。 如果a為-1.0 / -0.1且b為-0.5 / -0.1,則計算atan2( -0.1 + 0.1, -1.0 + 1.0 ); a-p_min )和atan2( -0.1 + 0.1, -0.5 + 1.0 ); b-p_min )在兩種情況下均為0.0 您繼續將0.0 * 0.0 * 0.0 * 0.0a )與0.5 * 0.5 * 0.0 * 0.0b )進行比較,這意味着0.0 < 0.0 因此a ( - 1.0 / -0.1)不小於b (-0.5 / -0.1)。

要計算矢量之間的角度,請使用DOT產品。 | A | * | B | * 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 );

為了比較角度,不必計算acos 比較角度的cos就足夠了

if ( fabs( cosAmin ) < fabs( cosBmin ) ) {return true;}
if ( fabs( cosAmin ) > fabs( cosbmin ) ) {return false;}

如果你想按長度排序矢量,請使用| v | = 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);

我如何解決問題並始終獲得(正確)排序的向量是否還有其他方法可以實現我正在做的事情?

不確定你想要的訂單, less_yx是否less_yx完成這項工作?

我非常有興趣了解我的思維/實施風格中的問題是什么?

假設IEEE浮點運算(否則你有0, 0域錯誤)

由於您的參考點是最低y ,因此傳遞給atan2的第二個arg為正或null。

- `atan2(0, 0) = 0`
- `atan2(+x, 0) = 0`
- `atan2(x, +y) > 0`

因此根據atan2任何最低y都是等價的。

a_r = subPt_1.x * subPt_1.x * subPt_1.y * subPt_1.y;

始終是0subPt_1.y == 0 你的意思是

a_r = subPt_1.x * subPt_1.x + subPt_1.y * subPt_1.y;

相反? (所以即使y == 0 ,它也要比較x

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM