0

I am trying to sort a vector of pointers to a class A using std::sort, but am having some difficulties.

Imagine class A beings just a point, containing x and y coordinates. I want to sort the vector by y coordinates from biggest to lowest using some fixed offset value. And on top of this I want to sort it by x coordinatex, from lowest to biggest. I've had something like following in mind but as you can imagine its not working as wanted:

bool A::sortByCoordinates(const A *a, const A *b)
{
    if ((b->y < a->y - offset) || (b->y > a->y + offset)) {
        return false;
    } else if (b->x < a->x) {
        return true;
    }

    return false;
}


void A::recalculate(std::vector<A *> &test)
{
    std::sort(test.begin(), test.end(), sortByCoordinates);
}

In short, if b->y < a->y - offset or b->y > a->y + offset treat it as b->y == a->y and then sort by their x coordinates from lowest to biggest. If the above is not true sort it as b->y < a->y.

How can I achieve this?

EDIT:

Imagine a xy plane such as this: plane

where black dots represent class A with x and y coordinates. I want to split this plane into finitely many sections which are represented by the red lines and are wide as offset. Now I want to treat points in these sections as tho they had the same y coordinate and sort them only by their x coordinate.

1 Answer 1

1
(b->y < a->y - offset) || (b->y > a->y + offset)

These are two different cases, which should have different results. I suppose that b is "less" then a in first case, and "greater" in the other case, but your code returns false for both cases. See @Jonathan's answer on how to fix this.


But also note a that your approach (considering all y's that differ by less than offset equal) has a major flaw: it will not generate a strict total order. Assume you have offset=3 and three points A(x=0,y=0), B(x=-2,y=2) and C(x=-4,y=4).

You will have A and B falling within offset by y coordinate so you will compare A.x and B.x and get A<B. Similarly you get B<C, but A and C do not fall within offset distance, so you get A>C, that is A<B<C<A, which should never be. (Tweak the coordinates if I get your ordering wrong). Therefore you first need to reconsider your ordering concept.


If (as you specify in the edit) you want to divide into horizontal stripes, and sort points within a stripe by x, then you should not check whether the ys differ by no more than offset, because two points can have their ys differ by less then offset, but still be located in different stripes. I would suggest to explicitly calculate the stripe number and compare them, something like

bool A::sortByCoordinates(const A& a, const A& b)
{
    // get stripe numbers, assuming A::y to be positive int
    int stripeA = a.y / offset; // be careful if a.y can be negative!
    int stripeB = b.y / offset;
    if (stripeA != stripeB)
        return stripeA < stripeB;
    return a.x < b.x;
}
Sign up to request clarification or add additional context in comments.

7 Comments

x, y and offset are all integers. Could your code be simplified by knowing this?
@user1806687, see edit, but be careful as operator/ for ints has a weird behavior around zero, so you will most probably have to add a separate if for negative (or positive) numbers.
No worries, all of those are always positive and bigger than 0. I will try your code later on.
These results doesnt seem right to me: -- x=922,y=20 -- x=906,y=35 -- x=969,y=35 -- x=996,y=25 -- x=1006,y=24 -- x=928,y=39 -- x=835,y=70 -- x=901,y=78
@user1806687 , and what is your offset?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.