hb-append vs hbl-append and ht-append vs htl-append in pict - image

Racket's pict, has several combinators for combining other pictures. These docs contain a nice table for how its *-append combinators work:
Most of these examples make sense. The first letter is v or h for vertical and horizontal respectively. The second letter is l, t, or r for vertical-left/center/right, or t c b, for horizontal-top/center/bottom.
However, this leaves out htl-append and hbl-append. Neither of them fit into this pattern. Additionally, they both seem to match hb-append on the table.
So, what is htl-append and hbl-append used for, and how does it differ from hb-append?

I wrote that example in the docs, so I guess this is sort of my fault and so I'll attempt to answer the question.
The example doesn't illustrate the difference very well because it's using shapes and not text.
Changing the example to use text + shapes shows that there is some differences between these functions:
#lang racket
(require pict)
(inset
(cbl-superimpose
(hb-append 10
(frame (text "g" "Helvetica" 30))
(rectangle 10 10 #:border-width 2))
(hline 200 2))
10)
(blank 1 30)
(inset
(cbl-superimpose
(hbl-append 10
(frame (text "g" "Helvetica" 30))
(rectangle 10 10 #:border-width 2))
(hline 200 2))
10)
(blank 1 30)
(inset
(ctl-superimpose
(ht-append 10
(frame (text "i" "Helvetica" 30))
(rectangle 10 10 #:border-width 2))
(hline 200 2))
10)
(blank 1 30)
(inset
(ctl-superimpose
(htl-append 10
(frame (text "i" "Helvetica" 30))
(rectangle 10 10 #:border-width 2))
(hline 200 2))
10)
If you run this example you'll get 4 pictures that show different cases. Depending on the letters, you get different alignments due to the ascenders/descenders. It would probably be more useful for the docs to show an example similar to this one with text.
If you want to mix pictures and text it often makes sense to use the l- variants to avoid an odd look where the picture sticks out:
#lang racket
(require pict)
(hb-append 10
(text "hug" "Helvetica" 30)
(rectangle 20 20 #:border-width 2)
(text "hug" "Helvetica" 30))
(hbl-append 10
(text "hug" "Helvetica" 30)
(rectangle 20 20 #:border-width 2)
(text "hug" "Helvetica" 30))

The slideshow tutorial uses this picture to explain hbl-append and htl-append :
(With hb-append and ht-append, the frames around each pict would be aligned.)

Related

text aligning by dxf groups

I have a bunch of text lines , iam drawing\showing them one in each line using entmake procedure. and for that i provide a insertion point , i want the text to be aligned from the left , the problem is that the lines lengths are different and the insertion point seems to be the center of text.
i was thinking of using the length of the text and the size\height of the text to calculate the pad i need to make so the text is aligned . if iam in the right path i cant find out how to do the calculation .
if I am not please help.
here is how i make text entities:
(defun text(point text)
(list ( cons 0 "TEXT")
(cons 11 point)
(cons 10 point)
(cons 40 0.4)
(cons 1 text)
(cons 41 1.0)
(cons 72 4)
(cons 73 0)
) )
thank you
You can create left-justified single-line TEXT entities using the following entmakex expression:
(defun mytext ( ins hgt str )
(entmakex
(list
'(000 . "TEXT")
(cons 010 ins)
(cons 040 hgt)
(cons 001 str)
)
)
)
Which may be called for example:
(mytext '(1.0 1.0 0.0) 0.4 "This is a test")
Here:
DXF group 0 is the entity type
DXF group 10 is the text insertion point
DXF group 40 is the text height
DXF group 1 is the text content
These four DXF groups are the minimum groups required to create a single-line TEXT entity.
For left-justified single-line text, only DXF group 10 is required to specify the position; for all other justifications, DXF group 11 represents the text alignment point and the value of DXF group 10 (the insertion point) is ignored if supplied (though, the group must be present).
For example, for middle-center justified single-line text, you might use the following:
(defun mytext ( ins hgt str )
(entmakex
(list
'(000 . "TEXT")
(cons 010 ins)
(cons 011 ins)
(cons 040 hgt)
(cons 001 str)
'(072 . 1)
'(073 . 2)
)
)
)
Here:
DXF group 0 is the entity type
DXF group 10 is the text insertion point (used if both DXF 72 and 73 are zero)
DXF group 11 is the text alignment point (used if either DXF 72 or 73 are non-zero)
DXF group 40 is the text height
DXF group 1 is the text content
DXF group 72 determines the horizontal alignment
DXF group 73 determines the vertical alignment
If you want to create single-line text which adheres to the properties of the active UCS (for example, created in the UCS construction plane, rotated to align with the UCS x-axis), you can use the following:
(defun mytext ( ins hgt str )
(
(lambda ( ocs )
(entmakex
(list
'(000 . "TEXT")
(cons 010 (trans ins 1 ocs))
(cons 050 (angle '(0.0 0.0) (trans (getvar 'ucsxdir) 0 ocs t)))
(cons 040 hgt)
(cons 001 str)
(cons 210 ocs)
)
)
)
(trans '(0.0 0.0 1.0) 1 0 t)
)
)
This assumes that the insertion point will be supplied relative to the active UCS, e.g.:
(defun c:test ( )
(mytext
(progn
(initget 1)
(getpoint "\nSpecify insertion point: ")
)
(progn
(initget 7)
(getdist "\nSpecify text height: ")
)
(getstring t "\nSpecify text content: ")
)
)
A reference for all of the DXF groups applicable to a TEXT entity may be found here.

Scheme making matrix

I am new to scheme and I'm having problems with matrices in Scheme. I need to create a function that takes one big and one small square matrices (with the condition: the small's length should be divisor of big one) and make a new matrix with doing an operation on the big one with small one. I've successfully split the big matrix to size that I wanted and I’m successfully operating on it to get the result.
Here is how I did it:
(define (matrix-op big small x y)
(if (< y (/ (length big) (length small))))
(if (< x (/ (length big) (length small)))
(cons (calculate (split-y (split-x big small x) small y) small)
(matrix-op big small (+ x 1) y))
(matrix-op big small 0 (+ y 1)) ; <- this is where i need to split
)
'()
)
)
My calculate function returns only 1 atomic value so when I run the function like this it gives me an output like '(val val val val), but what i want is formatting the output like '((val val) (val val)). How can I do it? Thanks in advance.
I realized that I couldn't explain the problem properly. What i want to have is a function that takes two different square matrices one big and one small, Splits the big one to same size as smaller one, operates on them to create a new matrix that has the size m/n if the big one is mxm and small one is nxn. Example:
big '( small '(
(8 0 3 1 5 3 2 2) (8 4)
(7 1 1 4 3 7 1 4) (9 5)
(1 3 7 4 3 6 6 3) )
(0 9 8 6 5 6 4 3)
(1 7 6 9 6 6 7 2)
(5 7 1 0 2 9 5 3)
(0 5 4 6 6 6 3 0)
(3 6 2 7 7 5 7 0)
)
I need to split big over the same size as small and calculate results like:
for x=0 y=0 part is '( calculate result is 5
(8 0)
(7 1)
)
for x=1 y=0 part is '( calculate result is 2
(3 1)
(1 4)
)
I actually did returned the results calculated but with the method i gave above my return was like '(5 2 4 2 2 6 4 4 4 3 5 4 2 4 6 3) but I wanted to return as:
'(
(5 2 4 2)
(2 6 4 4)
(4 3 5 4)
(2 4 6 3)
)
So how can I manage to split the return list where i want to split?
I think you are trying to do too much at once. It is always OK to split a bigger problem into a smaller problem.
If I understand yours, the idea is to take two square matrics, one of which may be some multiple of the other’s dimensions, and perform a pair-wise operation on the elements. For example:
'((1 2 3) '((1 2 3) '((7 7 7) '(( 8 9 10)
(4 5 6) + '((7)) --> (4 5 6) + (7 7 7) --> (11 12 13)
(7 8 9)) (7 8 9)) (7 7 7)) (14 15 16))
I will continue with the assumption that this is what is desired.
Notice that if the two matrices were the same size, a simple nested map would easily combine all elements. What is left is the problem of the different sizes.
Solve that and you are golden.
Recap:
(define (f op small-M big-M)
(f-apply-pairwise-op
op
(f-biggify small-M (/ (length big-M) (length small-M)))
big-M))
Now you have broken the problem into two smaller pieces:
(define (f-apply-pairwise-op op A B) ...) ; produces pairwise 'A op B'
(define (f-biggify M n) ...) ; tile M n times wider and taller
Good luck!

Parsing strings representing lists of integers and integer spans

I am looking for a function that parses integer lists in Emacs Lisp, along the lines of Perl's Set::IntSpan. I.e., I would like to be able to do something like this:
(parse-integer-list "1-3, 4, 8, 18-21")
⇒ (1 2 3 4 8 18 19 20 21)
Is there an elisp library somewhere for this?
The following does what you want:
(defun parse-integer-list (str)
"Parse string representing a range of integers into a list of integers."
(let (start ranges)
(while (string-match "\\([0-9]+\\)\\(?:-\\([0-9]+\\)\\)?" str start)
(push
(apply 'number-sequence
(seq-map 'string-to-int
(seq-filter
'identity
(list (match-string 1 str) (match-string 2 str)))))
ranges)
(setq start (match-end 0)))
(nreverse (seq-mapcat 'nreverse ranges))))
The code loops over the incoming string searching for plain numbers or ranges of numbers. On each match it calls number-sequence with either just a number for a plain match or two numbers for a range match and pushes each resulting number sequence into a list. To account for push building the result backwards, at the end it reverses all ranges in the list, concatenates them, then reverses the result and returns it.
Calling parse-integer-list with your example input:
(parse-integer-list "1-3, 4, 8, 18-21")
produces:
(1 2 3 4 8 18 19 20 21)

how do I place my turtles within a square of 5 x 5 patches and 10 x 10 patches?

I am trying to randomly place my turtles within a square of 5 by 5 patches, I have 2 questions as below:
Is below code correct?
setxy (50 + random 5) (60 + random 5)
How do I make a 10 x 10 patch square?
Your code would place the turtles running it in a 5 X 5 square centered on patches with the bottom-left corner on patch 50 60.
If you want it to be 10 x 10
setxy (50 + random 10) (60 + random 10)
if you want them not to be have to centered on patches use random-float
thus. The patch center coordinates are integers.
setxy (50 + random-float 5) (60 + random-float 5)
If your world is not big enough they will wrap around.

Generating randoms numbers in a certain range for common lisp

I'm doing some homework and for one part I have to generate random numbers in the range 10 - 80. I know (random 80) will return a number less than 80 but how do I get it to get the numbers to be above 10 as well?
Hint: (+ 1 (random 80)) will give you a number between 1 and 80 inclusive.
This code will give you random numbers from 10 to 80:
(+ 10 (random 71))
even better, try this general formula:
(defun random-from-range (start end)
(+ start (random (+ 1 (- end start)))))

Resources