행렬변환 사용하기

이번시간에는 행렬(Matrix)을 이용해 가공하는 좌표데이타 위치를 이동, 회전 등의 변환을 쉽게 하는 방법을 설명드리겠습니다.

IRtc 인터페이스 내부에는 행렬스택(MatrixStack)이라는 자료구조를 가지고 있는데, 쉽게 말해 변환을 넣고, 빼는 (Push/Pop) 것에 따라 실제 가공시 이 행렬의 최종 연산값과 가공해야할 좌표값이 서로 연산되어 최종 가공 위치가 자동 계산되는 방식을 제공합니다.

static void Main(string[] args)
{
    SpiralLab.Core.Initialize();
    var rtc = new Rtc5(0); //create Rtc5 controller
    float fov = 60.0f;    // scanner field of view : 60mm            
    float kfactor = (float)Math.Pow(2, 20) / fov; // k factor (bits/mm) = 2^20 / fov
    var correctionFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "correction", "cor_1to1.ct5");
    rtc.Initialize(kfactor, LaserMode.Yag1, correctionFile); 
    rtc.CtlFrequency(50 * 1000, 2); // laser frequency : 50KHz, pulse width : 2usec
    rtc.CtlSpeed(100, 100); // default jump and mark speed : 100mm/s
    rtc.CtlDelay(10, 100, 200, 200, 0); // scanner and laser delays
    ILaser laser = new LaserVirtual(0, "virtual", 20);
    ConsoleKeyInfo key;
    do
    {
        Console.WriteLine("Testcase for spirallab.sirius.");
        Console.WriteLine("");
        Console.WriteLine("'R' : draw rectangle with rotate");
        Console.WriteLine("'L' : draw lines with rotate");
        Console.WriteLine("'Q' : quit");
        Console.WriteLine("");
        Console.Write("select your target : ");
        key = Console.ReadKey(false);
        if (key.Key == ConsoleKey.Q)
            break;
        Console.WriteLine("\r\nWARNING !!! LASER IS BUSY ...");
        Console.WriteLine("");
        var timer = Stopwatch.StartNew();
        switch (key.Key)
        {
            case ConsoleKey.R:  // 회전하는 사각형 모양 가공 (가로 10, 세로 10 크기, 0 ~360 각도의 회전 형상)
                DrawRectangle(laser, rtc, 10, 10, 0, 360);
                break;
            case ConsoleKey.L:  //회전하는 직선 모양 가공
                DrawLinesWithRotate(laser, rtc, 0, 360);
                break;
        }
        rtc.ListExecute(true);
        Console.WriteLine($"processing time = {timer.ElapsedMilliseconds / 1000.0:F3}s");
    } while (true);
    rtc.Dispose();
}
       
private static void DrawRectangle(ILaser laser, IRtc rtc, double width, double height, double angleStart, double angleEnd)
{
    rtc.ListBegin(laser);
    for (double angle = angleStart; angle <= angleEnd; angle += 1)
    {
        //회전 각도를 행렬 스택에 push
        rtc.MatrixStack.Push(angle);
        rtc.ListJump(new Vector2((float)-width / 2, (float)height / 2));
        rtc.ListMark(new Vector2((float)width / 2, (float)height / 2));
        rtc.ListMark(new Vector2((float)width / 2, (float)-height / 2));
        rtc.ListMark(new Vector2((float)-width / 2, (float)-height / 2));
        rtc.ListMark(new Vector2((float)-width / 2, (float)height / 2));
        //이전에 push 된 행렬값을 pop 하여 삭제
        rtc.MatrixStack.Pop();
    }
    rtc.ListEnd();
}       

private static void DrawLinesWithRotate(ILaser laser, IRtc rtc, double angleStart, double angleEnd)
{
    rtc.ListBegin(laser);
    rtc.MatrixStack.Push(2, 4); // x=2mm, y=4mm 만큼 이동
    for (double angle = angleStart; angle <= angleEnd; angle += 1)
    {
        rtc.MatrixStack.Push(angle);
        rtc.ListJump(new Vector2(-10, 0));
        rtc.ListMark(new Vector2(10, 0));
        rtc.MatrixStack.Pop();
    }
    rtc.MatrixStack.Pop();
    rtc.ListEnd();
}

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Scroll to Top