ChrisF
ChrisF

Reputation: 59

Rotate vector of points by point coordinate

Is there a simple way of shifting a set of points stored in a cv::vector<cv::Point> by an amount defined by a cv::Point? Something like std::rotate, but for only one coordinate of the point. It should take into account the size of the vector.

For example,

[1,0],[0,1],[1,2],[2,3] is shifted by [0,2] to [1,2],[0,3],[1,0],[2,1]

The only way I can think of is doing it manually with a for loop.

Upvotes: 2

Views: 408

Answers (1)

Miki
Miki

Reputation: 41775

You can:

  1. create a Mat from vector<Point>. It'll be a 2 channel matrix, Nx1
  2. reshape so that it becomes a 1 channel matrix, Nx2
  3. get the column that contains the x and y coordinates
  4. use rotate on that column using MatIterator

Note that Mat has no reverse iterator (to implement right rotation), so, when shift is negative, you should add the size of the vector<Point> to the shift and use the left rotation.

You're mostly playing around with matrix headers, so data won't be copied.

Here's the code:

#include <opencv2\opencv.hpp>
#include <vector>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    vector<Point> pts = { Point(1, 0), Point(0, 1), Point(1, 2), Point(2, 3) };
    Point shift(0,2);

    for (const Point& p : pts) { cout << "[" << p.x << ", " << p.y << "] "; } cout << endl;

    // [1, 0] [0, 1] [1, 2] [2, 3]

    // ----------------------------  

    Mat mpts(pts);
    Mat xy = mpts.reshape(1);
    Mat x = xy.col(0);
    Mat y = xy.col(1);

    if (shift.x < 0)
        shift.x += pts.size();

    std::rotate(x.begin<Point::value_type>(), x.begin<Point::value_type>() + shift.x, x.end<Point::value_type>());

    if (shift.y < 0)
        shift.y += pts.size();

    std::rotate(y.begin<Point::value_type>(), y.begin<Point::value_type>() + shift.y, y.end<Point::value_type>());

    // ----------------------------        

    for (const Point& p : pts) { cout << "[" << p.x << ", " << p.y << "] "; } cout << endl;

    // [1, 2] [0, 3] [1, 0] [2, 1]

    return 0;
}

Upvotes: 1

Related Questions