绕圆轴的最短距离;使用学位
Shortest distance around a circular axis; using degrees
前提
一个实体(单个 dot/pixel)的简单 SDL 程序,它绕着(一个圆圈)旋转,然后朝那个方向移动。
问题
我无法正确计算从一个度数到另一个度数的最短距离;特别是当这些度数超过 360/0 标记的界限时。
目标
计算从 'origin' 度到 'destination' 的最短距离是顺时针还是逆时针,同时考虑 360 度标记的横向。
节目展示
尝试实现这些概念
代码
主要
void draw ( )
{
/* - - - - - - - - - - - - - - - - - Init - - - - - - - - - - - - - - - - - */
SDL_Event sdl_event;
WALKER walker;
walker = { POINT { WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 } }; // Entity in center
/* - - - - - - - - - - - - - - - - - Init - - - - - - - - - - - - - - - - - */
int degree = 0;
walker.rotation.set ( degree, generate_random ( 0, 360 ) );
while ( run_loop ) // Display Animation
{
set_render_draw_colors ( );
SDL_RenderDrawPoint ( renderer, walker.origin.x, walker.origin.y ); // Draw: entity dot
POINT point = walker.rotate ( degree ); // Create: pivot point & rotate per degree
SDL_RenderDrawLine ( renderer, walker.origin.x, walker.origin.y, point.x, point.y ); // Draw: sightline with acquired orientation
SDL_RenderPresent ( renderer );
degree++;
degree = ( degree > 359 ) ? 0 : degree;
if ( degree == walker.rotation.destination )
walker.rotation.set( walker.rotation.destination, generate_random ( 0, 360 ) );
while ( SDL_PollEvent ( &sdl_event ) )
{
if ( sdl_event.type == SDL_QUIT )
run_loop = false;
else
break;
}
}
}
沃克
struct WALKER
{
POINT origin = { 0, 0 };
POINT point = { 0, 0 };
ROTATION rotation;
int point_length = 35;
time_t time_seed;
// Constructors ......................................................... //
WALKER ( POINT origin, POINT point )
{
this->origin = origin;
this->point = point;
}
// Constructors (Generic) ... //
WALKER ( ) { };
~WALKER ( ) { };
// Functions ............................................................ //
double convertToRadian ( int degree )
{
return ( degree * PI / 180 );
}
int convertToDegree ( float radian )
{
return ( radian * 180 ) / PI;
}
POINT rotate ( int degree )
{
POINT point = { this->origin.x + this->point_length, this->origin.y };
double radians = convertToRadian ( degree );
double sine = sin ( radians );
double cosine = cos ( radians );
point.x -= this->origin.x; // translate point back to origin
point.y -= this->origin.y;
double x_new = point.x * cosine - point.y * sine; // rotate point
double y_new = point.x * sine - point.y * cosine;
point.x = x_new + this->origin.x; // translate point back
point.y = y_new + this->origin.y;
return point;
}
};
如果不是 0/360 交叉,这只是获得两个角度之间的差异的问题,该差异的符号会告诉您是否顺时针。
最重要的是,如果您得到最短路径穿过边界的两个角度之间的差异,您最终会得到绝对值大于 180 的差异(因为距离最终反过来绕一圈。
因此,您需要做的就是获取两个角度之间的差异,如果差异太大,则“修复”它。
int angle_diff(int from, int to) {
// Use a modulo to handle angles that go around the circle multiple times.
int result = to % 360 - from % 360;
if(result > 180) {
result -= 360;
}
if(result <= -180) {
result += 360;
}
return result;
}
前提
一个实体(单个 dot/pixel)的简单 SDL 程序,它绕着(一个圆圈)旋转,然后朝那个方向移动。
问题
我无法正确计算从一个度数到另一个度数的最短距离;特别是当这些度数超过 360/0 标记的界限时。
目标
计算从 'origin' 度到 'destination' 的最短距离是顺时针还是逆时针,同时考虑 360 度标记的横向。
节目展示
尝试实现这些概念
代码
主要
void draw ( )
{
/* - - - - - - - - - - - - - - - - - Init - - - - - - - - - - - - - - - - - */
SDL_Event sdl_event;
WALKER walker;
walker = { POINT { WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 } }; // Entity in center
/* - - - - - - - - - - - - - - - - - Init - - - - - - - - - - - - - - - - - */
int degree = 0;
walker.rotation.set ( degree, generate_random ( 0, 360 ) );
while ( run_loop ) // Display Animation
{
set_render_draw_colors ( );
SDL_RenderDrawPoint ( renderer, walker.origin.x, walker.origin.y ); // Draw: entity dot
POINT point = walker.rotate ( degree ); // Create: pivot point & rotate per degree
SDL_RenderDrawLine ( renderer, walker.origin.x, walker.origin.y, point.x, point.y ); // Draw: sightline with acquired orientation
SDL_RenderPresent ( renderer );
degree++;
degree = ( degree > 359 ) ? 0 : degree;
if ( degree == walker.rotation.destination )
walker.rotation.set( walker.rotation.destination, generate_random ( 0, 360 ) );
while ( SDL_PollEvent ( &sdl_event ) )
{
if ( sdl_event.type == SDL_QUIT )
run_loop = false;
else
break;
}
}
}
沃克
struct WALKER
{
POINT origin = { 0, 0 };
POINT point = { 0, 0 };
ROTATION rotation;
int point_length = 35;
time_t time_seed;
// Constructors ......................................................... //
WALKER ( POINT origin, POINT point )
{
this->origin = origin;
this->point = point;
}
// Constructors (Generic) ... //
WALKER ( ) { };
~WALKER ( ) { };
// Functions ............................................................ //
double convertToRadian ( int degree )
{
return ( degree * PI / 180 );
}
int convertToDegree ( float radian )
{
return ( radian * 180 ) / PI;
}
POINT rotate ( int degree )
{
POINT point = { this->origin.x + this->point_length, this->origin.y };
double radians = convertToRadian ( degree );
double sine = sin ( radians );
double cosine = cos ( radians );
point.x -= this->origin.x; // translate point back to origin
point.y -= this->origin.y;
double x_new = point.x * cosine - point.y * sine; // rotate point
double y_new = point.x * sine - point.y * cosine;
point.x = x_new + this->origin.x; // translate point back
point.y = y_new + this->origin.y;
return point;
}
};
如果不是 0/360 交叉,这只是获得两个角度之间的差异的问题,该差异的符号会告诉您是否顺时针。
最重要的是,如果您得到最短路径穿过边界的两个角度之间的差异,您最终会得到绝对值大于 180 的差异(因为距离最终反过来绕一圈。
因此,您需要做的就是获取两个角度之间的差异,如果差异太大,则“修复”它。
int angle_diff(int from, int to) {
// Use a modulo to handle angles that go around the circle multiple times.
int result = to % 360 - from % 360;
if(result > 180) {
result -= 360;
}
if(result <= -180) {
result += 360;
}
return result;
}