이번시간에는 Sirius 에서 레이저 가공시의 절차를 사용자 입맛에 맞도록 구현하는 방법에 대해 설명해 보겠습니다.
1. IMarker 인터페이스
Sirius 에서는 해당 기능을 마커(IMarker) 인터페이스에서 제공하고 있습니다. 즉 이 마커를 상속받아 사용자가 원하는 방식의 구현이 가능합니다.
예를 들어 마커의 핵심적인 함수를 보면
(상세한 구현 내용은 Demos 폴더의 8번 예제 참고)
- 가공할 데이타를 준비하는 Ready 함수
- 가공을 시작하는 Start 함수
- 가공을 중단하는 Stop 함수
- 에러상태를 해제하는 Reset 함수
앞서 살펴본 봐와 같이 가공 정보는 문서(Document)에 존재하고 있으며, 이 문서 데이타를 화면(View)에 그리는 등의 작업이 일어납니다. 마커(IMarker)는 많은 데이타 처리를 비동기적으로 해야 하므로, 가장 일반적인 구현방법은 마커 내부에 작업 쓰레드를 만들어 처리하는 방식입니다. 이때 주의할것은 화면에 다시 그리는 이벤트는 수시로 발생해 문서(Docment) 데이타에 수시로 접근되고, 마커(IMarker) 역시 쓰레드내에서 문서 데이타를 읽어 가공을 하게 되므로, 공유 데이타(Document)에 대한 크로스 쓰레드 문제가 발생하게 됩니다.
때문에 마커내에서 작업 쓰레드를 생성해 사용할 경우에는, 반드시 문서를 복제(Clone)한 복사본을 만들어 마커는 복사복만 접근하도록 제한해야 합니다.
즉, public bool Ready(IDocument doc, IRtc rtc, ILaser laser, IMotion motion=null)
함수로 가공데이타를 전달받을 경우, 인자로 전달된 doc 를 복제(doc.Clone()) 하여 변수에 저장후 작업 쓰레드에서 처리해 주셔야 합니다.
2. 문서(Document)의 기준점
자 그럼 마커에서 레이저 가공시 기준 위치를 설정하는 법을 살펴보겠습니다.
SIriusEditor 에디터에서는 위와 같이 문서 정보 버튼을 눌려줍니다.
그럼 위와 같이 현재 문서의 크기 정보(Dimension)를 입력할 수 있게 됩니다.
문서 크기의 핵심 데이타는 폭(Width), 높이(Height), 중심점(Center) 정보들입니다.
위와 같이 입력하였다면, 폭과 높이가 50mm 이고 가공 중심점(원점)은 X=25, Y=25 가 됩니다. 이때 가공 중심점이라는것은 스캐너의 원점을 의미합니다.
결국 위와 같이 HELLO 라는 마킹 텍스트 개체가 있을 경우 가공원점은 25,25 이므로 실제 스캐너를 이용해 가공시에는 우상단이 아닌, 상단 중앙에 "HELLO"가 가공되게 됩니다. 스캐너 장치는 기본적으로 원점(0,0) 을 기준으로 데이타를 처리하게 되는데, 위와 같이 사용자가 1사분면에만 가공데이타를 놓이게 하고 싶을경우 사용하는 방식입니다. 즉 기준 원점(Center)을 변경하는것은 스캐너의 원점을 변경하는 것과 동일합니다. (참고 : 개체를 선택후 Ctrl + H 단축키를 누르면 원점 정렬이 이루어집니다)
3. 문서(Document)의 회전 기준점
그러나 한가지 문제점이 있는데, 만약 위 데이타를 각도를 회전시켜 가공해야 할 경우가 있습니다. 회전 기준정보가 없는 상태에서는 기본적으로 수학적 원점(0, 0) 즉 예전 원점을 기준으로 회전되기 때문에 회전 기준점을 변경할 수 있어야 합니다.
때문에 위와 같이 Rotate Offset 에서는 회전 기준점을 설정할수있습니다. 즉 Dimension 에서 Center 점을 설정하고, 회전 기준점을 Center 점과 같은 값으로 설정할수도 있고 위와 같이 다른 위치를 설정할수도 있습니다.
4. 마커에서의 행렬 처리
마커에서는 위와 같이 문서의 기준점및 회전점을 처리한후 데이타를 가공해야 합니다. 더우기 가공시에는 오프셋(Offset)을 외부 측정 장치로 부터 연산하고 이 이동량, 회전량을 (DX, DY, Angle) 한번 더 변경하는것도 지원해야 합니다.
즉,
문서상의 가공 데이타(위 HELLO) =>
문서에 지정된 기준점(Center)으로 이동 =>
문서에 지정된 회전점(Rotate) 처리 =>
사용자가 입력한 오프셋(X,Y,Angle) 처리
가 모두 적용되어야 합니다.
(설명에서는 누락하였지만 만약 스캐너 장치를 누군가가 90 혹은 180 도 회전된채로 장착하였다면 이 역시 회전 처리가 되어야 겠지요.)
이 같은 선형변환을 위해 Rtc 인터페이스 내부에는 행렬 스택(Matrix Stack)을 지원합니다.
이 행렬 스택은 입력된 데이타의 선형변환 (회전, 이동 등)을 스택(Stack)에 Push 하게 되면, 레이저 가공시 스택에 존재하는 모든 행렬을 연산한 결과값을 적용한 최종 위치를 계산하게 됩니다.
데모 8번 코드를 예를 들면,
var matrix =
Matrix3x2.CreateTranslation(dx, dy) * /// 6. 오프셋 이동량
Matrix3x2.CreateRotation((float)(angle * Math.PI / 180.0)) * /// 5. 오프셋 회전량 Matrix3x2.CreateTranslation(Vector2.Negate(doc.Dimension.Center)) * ///4. 문서의 원점 위치 이동
Matrix3x2.CreateTranslation(doc.RotateOffset.X, doc.RotateOffset.X) * ///3. 회전 중심 위치 원복
Matrix3x2.CreateRotation((float)(doc.RotateOffset.Angle * Math.PI / 180.0)) * ///2. 문서에 설정된 회전량
Matrix3x2.CreateTranslation(-doc.RotateOffset.X, -doc.RotateOffset.X); ///1. 회전을 위해 회점 중심을 원점으로 이동
/// 연산된 행렬 스택을 IRtc 에 설정함
rtc.MatrixStack.Push(matrix);
위와 같이 선형 변환에 필요한 행렬을 스택에 넣고 그 결과값을 IRtc 에 처리해 주고 있습니다. 자세한 구현사항은 데모 8번 예제를 참고해 주시기 바랍니다.