转换绘图上下文的原点

Transforming origin of drawing context

我正在尝试转换 dc<%> 实例,以便将原点 (0,0) 设置为左​​下角。原则上,this question answers my question,但是我正在努力了解它如何工作的细节以及为什么我会看到我现在的行为。对于初学者,这是我正在使用的代码。注意我画的线是从左上角的(0,0)开始的。

#lang racket
(require racket/draw)


;;; Begin our drawing
(define w 200)
(define h 200)
(define dc (new pdf-dc%
                [interactive #f]
                [use-paper-bbox #f]
                [width w]
                [height h]
                [output "./foo.pdf"]))

(send dc start-doc "file output")
(send dc start-page)

(send dc draw-line 0 0 150 150)

(send dc end-page)
(send dc end-doc)

从那里,我相信我应该能够向我的 dc 实例发送一个带有适当转换矩阵的 set-transformation 消息。然而,一个合适的转换数据结构对我来说仍然是难以捉摸的。

documentation for set-transformation refers me to the documentation for get-transformation. Here I learn that I need to pass in a vector containing the initial transformation matrix, which I can retrieve via get-initial-matrix,以及变换参数 x 原点、y 原点、x 比例、y 比例和旋转。

我天真的第一次攻击这个让我构建转换数据结构如下,第一部分通过 get-initial-matrix 获得初始矩阵,然后翻转 y 比例:

#lang racket
(require racket/draw)

;;; Begin our drawing
(define w 50)
(define h 50)
(define dc (new pdf-dc%
                [interactive #f]
                [use-paper-bbox #f]
                [width w]
                [height h]
                [output "./foo.pdf"]))

(send dc start-doc "file output")
(send dc start-page)

;(send dc get-transformation)
;; returns '#(#(1.0 0.0 0.0 1.0 0.0 0.0) 0.0 0.0 1.0 1.0 0.0)

(send dc set-transformation
      (vector (send dc get-initial-matrix)
              0  0  ; x origin, y origin
              1  -1  ; x scale, y scale
              0))   ; rotation

(send dc draw-line 0 0 50 50)

(send dc end-page)
(send dc end-doc)

这会产生一个空的绘图,大概是在视线之外的某个地方翻译了一条线。

阅读 this other question 上的评论,它建议我需要向 y 原点添加一个偏移量(即需要翻转比例和平移原点)。我的下一次尝试添加了这个:

#lang racket
(require racket/draw)

;;; Begin our drawing
(define w 50)
(define h 50)
(define dc (new pdf-dc%
                [interactive #f]
                [use-paper-bbox #f]
                [width w]
                [height h]
                [output "./foo.pdf"]))

(send dc start-doc "file output")
(send dc start-page)

;(send dc get-transformation)
;; returns '#(#(1.0 0.0 0.0 1.0 0.0 0.0) 0.0 0.0 1.0 1.0 0.0)

(send dc set-transformation
      (vector (send dc get-initial-matrix)
              0  h  ; x origin, y origin
              1  -1  ; x scale, y scale
              0))   ; rotation

(send dc draw-line 0 0 50 50)

(send dc end-page)
(send dc end-doc)

这似乎将绘图元素带回了框架,但我在原点相当:

在那幅画中,我注意到我的原点似乎仍然垂直移动了大约四分之一的绘图上下文。我可以在我的 y 原点上再添加一点(摘自完整示例):

(send dc set-transformation
      (vector (send dc get-initial-matrix)
              0  (+ (* 0.25 h) h)  ; x origin, y origin
              1  -1  ; x scale, y scale
              0))   ; rotation

看起来不错,但可能还有点偏差:

链接的 SO 线程中的最后评论表明我需要提供一个函数来修改 initial 转换矩阵。这对我来说意义不大,因为我从文档中推断出初始转换矩阵是起点,而不是终点。此外,在这一点上,似乎需要付出很多额外的努力来做一些看起来应该很简单的事情,而且这似乎是合乎逻辑的,这将是像集合转换这样的函数的一部分。

对于冗长的问题上下文,我深表歉意,但我希望有人能告诉我我在哪里误解了一些其他显而易见的事情。

您的方法是正确的。你只是错过了一个小细节。

PDF 和 postscript 文件通常用于打印。打印的文档需要留边距(打印机需要抓住纸张的边缘)。 (current-ps-setup) 中的设置用于纸张大小、边距大小和缩放比例。将缩放比例设置为 1 并将边距大小设置为 0 将为您提供预期的结果。

#lang racket
(require racket/draw)

;;; Begin our drawing
(define w 200)
(define h 200)

(define setup (new ps-setup%))
(send setup set-paper-name "Peter")
; introduce margins such that the result is centered
(define α 1) ; a scale, try 0.9 to see how it works
(send setup set-margin (/ (* (- 1 α) w) 2) (/ (* (- 1 α) h) 2))
(send setup set-editor-margin 0 0)
(send setup set-scaling α α)
(current-ps-setup setup)

(define dc (new pdf-dc%
                [interactive #f]
                [use-paper-bbox #f]
                [width w]
                [height h]
                [output "./foo.pdf"]))

(send dc start-doc "file output")
(send dc start-page)

(send (current-ps-setup) set-margin 0 0) 
(send (current-ps-setup) set-scaling 1 1)
(send (current-ps-setup) set-translation 0 0)
(send (current-ps-setup) set-editor-margin 0 0)

(send dc set-transformation
      (vector (send dc get-initial-matrix)
              0  h  ; x origin, y origin
              1  -1  ; x scale, y scale
              0))   ; rotation

(send dc draw-line 0 0 150 150)
(send dc draw-line 0 200 200 0)

(send dc end-page)
(send dc end-doc)