I am trying to transform a dc<%> instance in order to set the origin (0,0) to be the lower left hand corner. In principle, this question answers my question, however I am struggling to understand the detail of how it works as well as why I am seeing the behavior that I am. For starters, here is the code I am working with. Note that the line I draw starts from (0,0) in the upper left-hand corner.
#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)
From there, I believe I should be able to send my dc instance a set-transformation message with an appropriate transformation matrix. However, an appropriate transformation data structure that is still elusive to me.
The 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, and the transformation parameters x origin, y origin, x scale, y scale, and rotation.
My naive first attack on this has me constructing the transformation data structure as follows, getting the initial matrix via get-initial-matrix for the first part, and then flipping the y scale:
#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)
That results in an empty drawing, presumably with the line translated somewhere out of view.
Reading the comments on this other question, it suggests that I need to add an offset to the y origin (i.e. both the scale needs to be flipped and the origin translated). My next attempt adds this:
#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)
This appears to bring the drawing elements back into the frame, but I'm not quite at the origin:
In that drawing, I notice my origin still appears to be shifted vertically about a quarter of the way up the drawing context. I can add another bit to my y origin (excerpted from full example):
(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
That looks pretty okay, but still perhaps a little off:
The last comment in the linked SO thread suggests that I need to supply a function that modifies the initial transformation matrix. This makes little sense to me, as I infer from the documentation that the initial transformation matrix is a starting point, not an ending point. Also, at this point, it seems like quite a lot of additional effort to do something that seems like it should be simple, and that seems logical that would be part of a function like set-transformation.
Sorry for the lengthy question context here, but I'm hoping someone can show me where I'm trivially misunderstanding something that's otherwise obvious.
Your approach is the correct one. You simply missed a small detail.
PDF and postscript files often are meant to be printed. Printed documents need a margin (the printer needs grab the edge of the paper). The settings in (current-ps-setup) is used for the paper size, margin size and the scaling. Setting the scaling to 1 and the margin size to 0 will give you the results you expected.
#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)
Related
I have a set of elements and I need to distribute them on a circular curve like the one in the picture below, so that the maximum possible number of elements is 10 and the minimum number is 3.
I need a mathematical equation or any other method in order to distribute these elements in a circular shape, with the Dart language.
Thank
I don't know anything about Dart, but this is how you can solve it mathematically:
(x,y): center of the circle
r: radius of the circle
a: start angle of the distribution in radians
b: end angle of the distribution in radians
n: number of elements
The element with index i should be positioned at:
x_new = x + r * cos(a + i * (b - a) / (max(2, n - 1)))
y_new = y + r * sin(a + i * (b - a) / (max(2, n - 1)))
I am trying to find out how to check if there are any turtles near another (which we will call the base turtle, or base). I need this to include diagonals, as I am spawning people around these bases and so need 1 full square around the base empty. Thus. when spawning bases I need to make sure there are no others within 2 squares, including diagonal.
I tried using "turtles in-radius (2,3,4,...)" and it doesn't work, since it seems that the radius command is circular. How would I go about this?
NetLogo's neighbors gives you the 8 patches surrounding the patch the turtle is on. Do you need the 16 surrounding patches, or will 8 do?
A simple procedure for neighbors16 in a non-wrapping world might be
to-report neighbors16
; can be called by a patch or a turtle
; assumes there is no wrapping of the world
let xm max (list (pxcor - 2) min-pxcor)
let xh min (list (pxcor + 2) max-pxcor)
let ym max (list (pycor - 2) min-pycor)
let yh min (list (pycor + 2) max-pycor)
let ptchs no-patches
foreach (range xm (xh + 1) 1) [x ->
foreach (range ym (yh + 1) 1) [y ->
set ptchs (patch-set patch x y ptchs)
]
]
report ptchs with [self != patch [pxcor] of myself [pycor] of myself]
end
Hope this helps,
Charles
There is an object A. I want to create a object B. I'm trying to avoid that A covers B:
I have thinking how to achieve that. Take a look of the following drawing:
I have been thinking in a solution in a math - geometry way before searching for some Unity3D function to solve the problem. I have realise A and B would be on the same surface if the camera is within a sphere with radius c-A. So I guess the solution can be related to get a point at a B at a distance A-B from A on the surface of the sphere with radius c-A. Does it has sense? Any other idea? How to do it with maths and Unity?
What you are describing is a ring on the sphere's surface whose plane is perpendicular to the direction c-A.
This is fairly simple to compute. First we need to find 2 perpendicular vectors to c-A (we'll call this d):
Call the vector "c-A" = d, the radius of the sphere R = abs(d) and the distance "A-B" = D.
If d.X / R < 0.5, set a temporary vector w = X, else set w = Y.
Compute the first perpendicular vector u = normalize(cross(w, d)).
Compute the second one v = normalize(cross(d, u)).
The center point of this ring is given by c + d * cos(D / R). From here we can generate any point on the ring with
p(t) = c + d * cos(D / R) + u * cos(t) + v * sin(t) , 0 ≤ t ≤ 2π
UPDATE:
I'm trying to find a procedure to hatch a turtle based on random probability:
40% for A
30% for B
30% for C
How do you hatch a turtle depending on that probability? What procedure/s should I use?
It looks like A, B, and C are breeds? Then
to weighted-hatch ;; turtle-proc
let p random-float 100
if (p >= 60) [hatch-As 1 [init-A]]
if (if p >= 30 and p < 60) [hatch-Bs 1 [init-B]]
if (p < 30) [hatch-Cs 1 [init-C]]
end
to init-A
;;put any desired initializations here
end
Etc.
You could alternatively use the rnd extension; see NetLogo, weighted random draw from a list: how to use rnd-extension?
Throw a dice mate! : ) Generate a random number, since you have 3 probable options you can use something like random-float 1 this gives a number in [0,1).
Then, if 0>= number <=0.4 hatch A, else if 0.4< number <=0.7 hatch B and so on for C.
Happy coding!
I need to have a martix of patches which axis are long a power of 2 ( 2^n ) for example 16.
I thought this can be done or having the corner but i need to do this with a line of code because i want it to be set with the setup button.
You can do this with resize-world:
resize-world 0 (2 ^ n - 1) 0 (2 ^ n - 1)
You may also want to set the patch size with set-patch-size so that the view remains stays the same size no matter how many patches you have:
set-patch-size 400 / (2 ^ n)