등속도 및 등 가속도
장문석
현재 위치가 p이고 목표 위치가 p2일 때 등속도로 움직인다고 하자.
그리고, 현재 위치에서 목표 위치까지 stepcount 횟수만큼 이동한다고 할 때 각 step의 좌표는 어떻게 계산해야 할까?
해설
먼저, 목표 위치에서 현재 위치를 빼면 가야 할 총 거리이다. (p_2 – p)
하나의 step에서 갈 거리는 총 거리 / stepcount이므로 (p_2 – p)/stepcount
프로그램에서 세 가지 멤버가 정수일 경우에 stepcount가 총 거리보다 크면 해당 값이 0이 됨에 주의하자.
i번째 step에서의 위치는 p에서 i번 step을 이동한 거리이다. 즉,
p+((p_2 - p)*i / stepcount ) 가 된다.
I를 먼저 곱한 이유는 stepcount가 총 거리보다 클 경우도 있기 때문이다.
현재 위치가 p이고 목표 위치가 p2일 때 등가속도로 움직인다고 하자. (시작 속도는 0일 경우에 한한다.)
그리고, 현재 위치에서 목표 위치까지 stepcount 횟수만큼 이동한다고 할 때 각 step의 좌표는 어떻게 계산해야 할까?
해설
먼저, 목표 위치에서 현재 위치를 빼면 가야 할 총 거리이다. (p_2 – p)
가속도를 a라 하면 1step에서의 이동 거리는 a,
2step에서의 이동 거리는 2a,
3setp에서의 이동 거리는 3a,
nstep에서의 이동 거리는 na이다.
nstep까지 이동한 거리의 합은 a*(n+1)*n/2 이다.
stepcount동안 총 이동할 거리가 (p_2 –p)이고 가속도 a로 stepcount동안 이동한 거리의 합은 a*(setpcount+1)*setpcount/2이므로 가속도 a는 다음과 같다.
a = ((p_2-p) * 2) / (stepcount * (stepcount + 1))
따라서, istep에서의 좌표는 p에서 a*(n+1)*n/2만큼 더한 위치이므로 다음과 같다.
p + (((i + 1) * i) * (p_2-p) * 2) / (stepcount * (stepcount + 1))
모든 인수가 정수형이라 가정할 때 가속도 a가 0일 수 있으므로 (i + 1) * i)를 먼저 곱해 주었다.
3차원에서의 좌표 이동은 y,z를 무시하고 x좌표를 구하고 x,z를 무시하고 y를 구하고 x,y를 무시하고 z를 구하면 된다. 편 미분의 합 벡터가 전체 미분이 되는 것이고 편 적분이 합 벡터가 전체 벡터가 된다.
3차원에서의이동.zip
예제 코드
1. MoveIn3D.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace _3차원에서의이동
{
struct Point3D
{
public static Point3D Empty = new Point3D() { X=0, Y=0, Z=0 };
public int X
{
get;
set;
}
public int Y
{
get;
set;
}
public int Z
{
get;
set;
}
}
class MoveIn3D
{
Point3D[] points;
public MoveIn3D(Point3D start, Point3D end, int stepcount) {
MoveIn3DUniMotion(start, end, stepcount);
}
private void MoveIn3DUniMotion(Point3D start, Point3D end, int stepcount)
{
points = new Point3D[stepcount + 1];
int i = 0;
int dx, dy, dz;
points[0] = start;
for (i = 1; i <= stepcount; i++)
{
dx = NextStepUniMotion(start.X, end.X, stepcount, i);
dy = NextStepUniMotion(start.Y, end.Y, stepcount, i);
dz = NextStepUniMotion(start.Z, end.Z, stepcount, i);
points[i] = new Point3D() { X = dx, Y = dy, Z = dz };
}
}
private void MoveIn3DUniAccelMotion(Point3D start, Point3D end, int stepcount)
{
points = new Point3D[stepcount + 1];
int i = 0;
int dx, dy, dz;
points[0] = start;
for (i = 1; i <= stepcount; i++)
{
dx = NextStepUniAccel(start.X, end.X, stepcount, i);
dy = NextStepUniAccel(start.Y, end.Y, stepcount, i);
dz = NextStepUniAccel(start.Z, end.Z, stepcount, i);
points[i] = new Point3D() { X = dx, Y = dy, Z = dz };
}
}
private int NextStepUniAccel(int p, int p_2, int stepcount, int i)
{
int gap = p_2 - p;
int next = p + (((i + 1) * i) * gap * 2) / (stepcount * (stepcount + 1)) / 2;
return next;
}
public MoveIn3D(Point3D start, Point3D end, int stepcount, bool aflag)
{
if (!aflag)
{
MoveIn3DUniMotion(start, end, stepcount);
}
else
{
MoveIn3DUniAccelMotion(start, end, stepcount);
}
}
private int NextStepUniMotion(int p, int p_2, int stepcount, int i)
{
return p+((p_2 - p)*i / stepcount );
}
public Point3D this[int index]
{
get
{
if (AvailIndex(index))
{
return points[index];
}
return Point3D.Empty;
}
}
private bool AvailIndex(int index)
{
return (index>=0)&&(index<points.Length);
}
}
}
2. Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace _3차원에서의이동
{
class Program
{
static void Main(string[] args)
{
Point3D st = new Point3D(){ X=0, Y=0, Z=0 };
Point3D end = new Point3D() { X=10, Y=20,Z=15 };
MoveIn3D m3d = new MoveIn3D(st, end, 10);
int i = 0;
for (i = 0; i < 11; i++)
{
Console.WriteLine("{0}:{1}:{2}", m3d[i].X, m3d[i].Y, m3d[i].Z);
}
m3d = new MoveIn3D(st, end, 4, true);
for (i = 0; i < 5; i++)
{
Console.WriteLine("{0}:{1}:{2}", m3d[i].X, m3d[i].Y, m3d[i].Z);
}
}
}
}