Vector Graphics in Lil
Lil로 다루는 벡터 그래픽
Decker의 스크립트 언어 Lil에서 중첩 리스트로 벡터 경로를 표현하고 그리는 방법을 설명합니다. 암묵적 리스트 연산과 몇 가지 원시 연산자를 조합해 확대·이동·기울이기·회전부터 흔들림 효과까지 구현하며, 인덱스 반복문 없이 다루는 방식을 코드로 보여줍니다.
- 주제
에디터 노트
이 글의 설득력은 벡터 변환을 별도 그래픽 API의 호출 목록으로 풀지 않고, Lil의 중첩 리스트 연산으로 일관되게 설명하는 데 있습니다. 같은 자료 구조에 곱셈과 덧셈을 적용해 확대와 이동을 만들고, 좌표를 peel한 뒤 다시 경로에 맞춰 조립해 기울이기와 회전을 구현합니다. 예제는 경로의 구조를 이해하면 작은 원시 연산자 조합으로 효과를 확장할 수 있음을 보여줍니다. 다만 비균일 확대와 기울이기처럼 리스트를 여러 단계 감싸는 표현은 처음 읽을 때 자료 구조를 추적해야 합니다. 글은 실제 경로 예제와 중간 결과를 함께 제시해 그 과정을 드러내지만, 정형적인 행렬 변환 API와 비교하거나 두 표현의 장단점을 평가하지는 않습니다. 따라서 이 설명은 Lil의 연산 방식과 실용적인 관용구를 익히는 데 초점이 있으며, 다른 그래픽 시스템보다 우수하다는 주장으로 읽을 근거는 없습니다.
AI 요약
Decker 생태계의 hershey 모듈은 1967년 Allen Vincent Hershey가 발표한 선분 기반 디지털 서체를 사용해 텍스트를 배치합니다. 이 글은 Decker의 APL 계열 스크립트 언어 Lil에서 글자와 도형을 2차원 벡터 그래픽으로 표현하고 변형하는 방식을 설명합니다.
점, 선, 경로
점은 캔버스의 좌표를 나타내는 숫자 두 개짜리 리스트입니다. 여러 점을 이은 리스트는 스트로크(stroke), 즉 폴리라인(polyline)이 됩니다. 점이 N개라면 연결 선분은 N-1개입니다. 스트로크 여러 개를 다시 묶으면 경로(path)가 됩니다. 글자 하나의 획이나 문장 전체를 경로 하나로 표현할 수 있으며, 각 스트로크의 점 개수는 서로 달라도 됩니다.
hershey.textpath[]는 글꼴과 문자열을 받아 글자 경로를 만듭니다. 만든 경로는 각 스트로크를 순회하며 canvas.line[]에 전달하거나, Lil의 @ 연산자로 한꺼번에 그릴 수 있습니다. canvas.line[]이 선분 하나가 아니라 점 리스트를 받아 폴리라인을 그리므로, 점과 선분 개수 차이를 직접 계산하는 인덱스 반복문이 필요하지 않습니다. 저자는 이처럼 컬렉션 전체에 적용하는 API가 반복문과 경계값 처리를 줄이고 코드에서 의도를 드러낸다고 설명합니다.
중첩 리스트와 변환
Lil의 쉼표 연산자는 리스트를 이어 붙입니다. 산술 연산자는 중첩 리스트 안쪽까지 재귀적으로 적용되므로 경로 전체에 스칼라를 곱하면 모든 좌표가 같은 비율로 확대됩니다. 반면 x축과 y축을 서로 다른 비율로 조절하려면 리스트 구조를 맞춰야 합니다. 길이가 다른 두 리스트를 곱하면 오른쪽 리스트를 반복하거나 잘라 왼쪽 길이에 맞춥니다. 오른쪽 값을 list로 한 번 감싸면 각 점에 좌표별 배율을 적용하고, 경로의 스트로크와 점 단계에 맞춰 두 번 감싸면 비균일 확대를 구현합니다.
같은 패턴으로 x 또는 y 배율을 음수로 설정해 좌우·상하 반전을 만들 수 있습니다. 좌표별 이동은 곱셈 대신 덧셈을 사용합니다. 수평 기울이기(shear)는 각 점의 y좌표를 추출해 x좌표에 비례하는 값을 더하고, 수직 기울이기는 x좌표를 이용해 y좌표를 바꿉니다. 저자는 경로에서 좌표 하나씩 뽑아 다시 경로 형태로 적용하는 중첩 리스트를 peel이라고 부릅니다. rev를 두 단계에 적용하면 각 점의 좌표 순서를 바꿔 전치할 수 있으며, 반전과 함께 쓰면 90도 회전도 가능합니다.
극좌표 회전과 효과
일반적인 회전에는 mag, heading, unit 원시 연산자를 사용합니다. mag는 점의 원점까지 거리를, heading은 원점과 점을 잇는 벡터의 라디안 각도를 계산합니다. 두 연산자는 중첩 리스트 안의 좌표 쌍까지 내려가 결과를 경로 구조에 맞춘 리스트로 돌려줍니다. unit은 각도에서 단위 길이 벡터를 만듭니다. 따라서 mag로 길이를 보존하고 heading에 회전각을 더한 뒤 unit을 적용하면 원점 기준 회전 경로를 얻습니다.
같은 원리를 이용해 정다각형, 호, 타원에 필요한 점을 반복문 없이 만들 수 있습니다. 글은 여기에 경로의 각 점을 거리값에 비례해 움직이는 원근 왜곡, 무작위 오프셋을 더하는 선 떨림 효과, 프레임 카운터와 사인·코사인 값을 조합하는 물결 효과를 덧붙입니다. 무작위 오프셋 리스트는 + 연산이 길이를 자동으로 맞추므로 길이가 정확히 같을 필요는 없지만, 경로에서 가장 긴 스트로크에 가까운 점 개수로 만들면 결과가 더 나아진다고 설명합니다.
원문: Beyond Loom / 번역·요약: Trawling