二维笛卡尔坐标系旋转问题可以描述如下:有两套笛卡尔坐标系,分别是XOY和X'O'Y',X'O'Y'相对于XOY坐标系进行了平移(x_shift, y_shift)和旋转angle(弧度)变换,一个点在XOY坐标系中的坐标为:(x, y),计算该点在X'O'Y'坐标系中的坐标:(x_prime, y_prime),并计算转化时间。
对于笛卡尔坐标系的转换,通过C++标准库<cmath>中的三角函数可以实现平移和旋转,现提供一种方法-使用C++中复数模板模板complex<>实现。核心思想是将笛卡尔坐标系转换为极坐标系,然后调用模板算法很容易就能实现,废话少说,核心代码:
typedefstruct_DC_COORD {
double x;
double y;
}ST_DC_COORD, *PST_DC_COORD;
typedefstruct_RT_DC_COORD {
double x_shift;
double y_shift;
double angle;
}ST_RT_DC_COORD,*PST_RT_DC_COORD;
CoordTf(ST_RT_DC_COORD coordRt, ST_DC_COORD &coord,double &timeSpend){
complex<double> cCoord(coord.x, -coord.y);//将坐标转换为极坐标
complex<double> cShift(coordRt.x_shift, -coordRt.y_shift);//平移极坐标
auto f_shift = [](complex<double> source, complex<double> shift) {return (source-shift); };//定义平移lambda表达式
auto start =chrono::system_clock::now();
cCoord = f_shift(cCoord, cShift);
complex<double> cRotateRes = polar(abs(cCoord),arg(cCoord) + coordRt.angle);
//重新生成新的极坐标,模不变为abs(cCoord),角度变化量仍为旋转角度
coord.x = cRotateRes.real();
coord.y =-cRotateRes.imag();
//分别提取实部和虚部得到新的笛卡尔坐标
auto end = chrono::system_clock::now();
auto duration =chrono::duration_cast<chrono::microseconds>(end- start);
double temp = double(duration.count()) * chrono::nanoseconds::period::num / chrono::seconds::period::den;//使用chrono计算转换时间
timeSpend = temp;//ns
returntrue;
}
随机生成10个坐标进行验证,初始坐标x,y值范围均为[-100,100], VS环境下完整代码如下:
Coord.h文件:
#ifndef COORD_H_
#defineCOORD_H_
#include<vector>
typedefstruct_DC_COORD {
double x;
double y;
}ST_DC_COORD, *PST_DC_COORD;
typedefstruct_RT_DC_COORD {
double x_shift;
double y_shift;
double angle;
}ST_RT_DC_COORD,*PST_RT_DC_COORD;
classCoord
{
public:
Coord();
~Coord();
public:
bool CoordTf(ST_RT_DC_COORD coordRt, ST_DC_COORD &coord,double &timeSpend);
bool CoordGeneration(double rangeMin, double rangeMax, int num);
int GetCoordPointsNum();
bool GetCoordPoint(int id, ST_DC_COORD &coord);
protected:
void GetRandData(double rangeMin, double rangeMax, int num, double* pData);
private:
std::vector<ST_DC_COORD> coordVector;
};
#endif
Coord.cpp文件:
#include"Coord.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<complex>
#include<random>
#include<chrono>
#include<ctime>
#include<cmath>
usingnamespace std;
Coord::Coord()
{
this->coordVector.clear();
}
Coord::~Coord()
{
this->coordVector.clear();
}
boolCoord::CoordTf(ST_RT_DC_COORD coordRt, ST_DC_COORD &coord,double &timeSpend){
complex<double> cCoord(coord.x, -coord.y);
complex<double> cShift(coordRt.x_shift, -coordRt.y_shift);
auto f_shift = [](complex<double> source, complex<double> shift) {return (source-shift); };
auto start =chrono::system_clock::now();
cCoord = f_shift(cCoord, cShift);
complex<double> cRotateRes = polar(abs(cCoord),arg(cCoord) + coordRt.angle);
coord.x =cRotateRes.real();
coord.y =-cRotateRes.imag();
auto end = chrono::system_clock::now();
auto duration =chrono::duration_cast<chrono::microseconds>(end- start);
double temp = double(duration.count()) * chrono::nanoseconds::period::num / chrono::seconds::period::den;
timeSpend = temp;//ns
returntrue;
}
boolCoord::CoordGeneration(doublerangeMin, doublerangeMax, intnum){
bool bRet = false;
int i = 0;
ST_DC_COORD coord;
double* pData = NULL;
pData = newdouble[2 * num];
this->GetRandData(rangeMin, rangeMax, 2 * num, pData);
for (i = 0; i < num; i++) {
coord.x = pData[i];
coord.y = pData[num+i];
this->coordVector.push_back(coord);
}
delete[] pData;
if (!this->coordVector.empty()){
bRet = true;
}
return bRet;
}
intCoord::GetCoordPointsNum(){
returnthis->coordVector.size();
}
boolCoord::GetCoordPoint(intid, ST_DC_COORD &coord) {
if (id >= this->GetCoordPointsNum()) {
returnfalse;
}
coord=this->coordVector[id];
returntrue;
}
voidCoord::GetRandData(doublerangeMin, doublerangeMax,intnum,double* pData) {
int i = 0;
default_random_engine generator(time(NULL));
uniform_real_distribution<double> dist(rangeMin, rangeMax);
for (i = 0; i < num; i++){
auto temp = dist(generator);
pData[i] = static_cast<double>(temp);
}
}
App.cpp文件:
#include"Coord.h"
#include<iostream>
void TaskTest();
int main()
{
while (1) {
TaskTest();
}
return 0;
}
void TaskTest()
{
int i = 0;
bool bRet = false;
Coord* pCoord = new Coord;
ST_DC_COORD coord,tempCoord;
double timeSpend = 0;
ST_RT_DC_COORD coordRf;
std::cout <<"please input x_shift:"<< std::endl;
std::cin >> coordRf.x_shift;
std::cout <<"please input y_shift:"<< std::endl;
std::cin >> coordRf.y_shift;
std::cout <<"please input angle:"<< std::endl;
std::cin >> coordRf.angle;
if(pCoord->CoordGeneration(-100, 100, 10)) {
int tempNum = pCoord->GetCoordPointsNum();
for (i = 0; i < tempNum; i++) {
if (pCoord->GetCoordPoint(i, coord)) {
tempCoord = coord;
bRet =pCoord->CoordTf(coordRf, coord, timeSpend);
if (bRet) {
std::cout <<"the "<< i+1 <<"th "<<"result:"<< std::endl;
std::cout <<"initial coord(x,y):"<<"("<< tempCoord.x <<","<< tempCoord.y <<")"<<std::endl;
std::cout <<"final coord(x,y) :"<<"("<< coord.x <<","<< coord.y <<")"<< std::endl;
std::cout <<"it spends time:"<< timeSpend <<"ns"<< std::endl;
}
}
}
}
delete pCoord;
}
设置平移坐标(1,1),旋转角度为45度,进行Debug,运行结果如下:
please input x_shift:
1
please input y_shift:
1
please input angle:
0.78539816
the1th result:
initial coord(x,y):(-38.3971,-35.8599)
final coord(x,y) :(-53.9218,1.79406)
it spends time:14ns
the 2th result:
initial coord(x,y):(-39.8357,84.4626)
final coord(x,y) :(30.1418,87.8922)
it spends time:2ns
the 3th result:
initial coord(x,y):(17.5412,-66.5742)
final coord(x,y) :(-36.0858,-59.4786)
it spends time:1ns
the 4th result:
initial coord(x,y):(58.8106,-65.6458)
final coord(x,y) :(-6.24741,-88.004)
it spends time:1ns
the 5th result:
initial coord(x,y):(-14.0353,37.6078)
final coord(x,y) :(15.2541,36.5172)
it spends time:1ns
the 6th result:
initial coord(x,y):(-73.222,50.5119)
final coord(x,y) :(-17.4726,87.4931)
it spends time:1ns
the 7th result:
initial coord(x,y):(30.4505,81.4555)
final coord(x,y) :(77.7153,36.0659)
it spends time:3ns
the 8th result:
initial coord(x,y):(-58.4805,65.981)
final coord(x,y) :(3.88944,88.0076)
it spends time:2ns
the 9th result:
initial coord(x,y):(53.6765,-52.5575)
final coord(x,y) :(-0.622969,-75.1188)
it spends time:2ns
the10th result:
initial coord(x,y):(5.31381,8.17389)
final coord(x,y) :(8.12303,2.02238)
it spends time:2ns
please input x_shift: |