생각해 볼 질문
페인터 하나가 정사각형과 기울어진 프레임과 크기가 다른 프레임 안에서 같은 그림을 어떻게 설명할까요? 생성자와 선택자 인터페이스로 벡터와 선분 나타내기 원점과 두 모서리 벡터로 프레임 나타내기 단위 정사각형 좌표를 구체적인 프레임으로 옮기기 프레임을 선분 목록으로 바꾸는 프로시저로 페인터 만들기 반환값을 유지하면서 기계가 읽을 수 있는 SEG 줄 출력하기 흑백 SVG를 실제 리스펙스 출력의 렌더링으로 읽기 선분 데이터는 단위 정사각형 좌표로 작성됩니다. frame-coordinate-map은 x와 y 성분을 상대 위치로 읽고 프레임 원점에 두 모서리 벡터의 비례값을 더합니다. segments->painter는 유한한 선분 목록을 캡처하고 나중에 받은 프레임을 통해 모든 끝점을 옮기는 프로시저를 반환합니다.
첫 실행은 테두리와 대각선 페인터를 정사각형 프레임에 놓습니다. 두 번째 실행은 마름모 페인터를 기울어진 프레임에 적용합니다. 페인터 정의에는 마지막 화면 좌표가 들어 있지 않습니다. 실행은 옮긴 선분마다 SEG 줄 하나를 출력하고 앱 로컬 시각화가 transcript 줄을 흑백 SVG로 읽습니다. 반환되는 (segments n) 값은 별도 관찰로 남습니다.
SICP 코드 UTF-8 2,452 / 1,048,576바이트
( begin
( define ( make-vect x y ) ( list x y ) )
( define ( xcor-vect vector ) ( car vector ) )
( define ( ycor-vect vector ) ( cadr vector ) )
( define ( add-vect left right )
( make-vect ( + ( xcor-vect left ) ( xcor-vect right ) )
( + ( ycor-vect left ) ( ycor-vect right ) ) ) )
( define ( scale-vect factor vector )
( make-vect ( * factor ( xcor-vect vector ) )
( * factor ( ycor-vect vector ) ) ) )
( define ( make-segment start end ) ( list start end ) )
( define ( start-segment segment ) ( car segment ) )
( define ( end-segment segment ) ( cadr segment ) )
( define ( make-frame origin edge1 edge2 )
( list origin edge1 edge2 ) )
( define ( origin-frame frame ) ( car frame ) )
( define ( edge1-frame frame ) ( cadr frame ) )
( define ( edge2-frame frame ) ( caddr frame ) )
( define ( frame-coordinate-map frame )
( lambda ( vector )
( add-vect
( origin-frame frame )
( add-vect
( scale-vect ( xcor-vect vector ) ( edge1-frame frame ) )
( scale-vect ( ycor-vect vector ) ( edge2-frame frame ) ) ) ) ) )
( define ( map-segment coordinate-map segment )
( make-segment
( coordinate-map ( start-segment segment ) )
( coordinate-map ( end-segment segment ) ) ) )
( define ( segments->painter segment-list )
( lambda ( frame )
( let ( ( coordinate-map ( frame-coordinate-map frame ) ) )
( map ( lambda ( segment )
( map-segment coordinate-map segment ) )
segment-list ) ) ) )
( define ( emit-segment segment )
( let ( ( start ( start-segment segment ) )
( end ( end-segment segment ) ) )
( display "SEG " )
( display ( xcor-vect start ) )
( display " " )
( display ( ycor-vect start ) )
( display " " )
( display ( xcor-vect end ) )
( display " " )
( display ( ycor-vect end ) )
( newline ) ) )
( define ( paint painter frame )
( let ( ( segments ( painter frame ) ) )
( for-each emit-segment segments )
( list ' segments ( length segments ) ) ) )
( define p00 ( make-vect 0.0 0.0 ) )
( define p10 ( make-vect 1.0 0.0 ) )
( define p11 ( make-vect 1.0 1.0 ) )
( define p01 ( make-vect 0.0 1.0 ) )
( define outline-and-cross
( segments->painter
( list
( make-segment p00 p10 )
( make-segment p10 p11 )
( make-segment p11 p01 )
( make-segment p01 p00 )
( make-segment p00 p11 )
( make-segment p01 p10 ) ) ) )
( paint outline-and-cross
( make-frame ( make-vect 0.08 0.08 )
( make-vect 0.84 0.0 )
( make-vect 0.0 0.84 ) ) ) ) 코드 실행Ctrl/⌘ Enter 파일 열기 코드 저장 코드 복사 편집기 지우기
예제 테두리와 대각선 그리기 기울어진 프레임에 마름모 그리기
실행은 브라우저 안에서 이루어지며 프로그램 결과와 실행 추적을 보여줍니다. 테두리와 대각선 그리기 기울어진 프레임에 마름모 그리기 실행 및 렌더링
이 실행에서는 유효한 SEG 라인이 생성되지 않았습니다.
프로그램 출력에서 0개의 선분이 렌더링되었습니다.
예제 테두리와 대각선 그리기
렌더링된 선분 0
형식이 잘못된 SEG 라인 0
프로그램 값 —
추적 상태 —
런타임 아티팩트 —선분 목록 SVG는 브라우저 실행에서 출력된 SEG 라인을 렌더링합니다. 예상 결과 첫 프로그램은 SEG 줄 여섯 개를 출력하고 (segments 6)을 반환합니다. 두 번째는 변환된 SEG 줄 네 개를 출력하고 (segments 4)를 반환합니다. 작업대 옆 SVG는 그 transcript 줄에서 만들어집니다.
실행 추적에서 볼 점 페인터 적용에서 frame-coordinate-map으로 들어간 뒤 각 끝점이 프레임 원점과 x 배의 첫 모서리와 y 배의 두 번째 모서리 합으로 만들어지는 과정을 따라가세요. transcript 출력과 반환한 선분 수는 서로 다른 관찰입니다.
직접 해보기 프로그램을 수정하고 결과를 비교해 보세요. 첫 페인터에 네 변의 중점을 잇는 내부 마름모 선분 네 개를 추가하세요. 새 선분 수를 예상한 뒤 SEG 출력에서 시각화가 추가 모양을 그리는지 확인하세요.
힌트 보기 네 중점은 (0.5, 0.0), (1.0, 0.5), (0.5, 1.0), (0.0, 0.5)입니다. 페인터는 마지막 프레임과 계속 분리됩니다.