Script to run an AutoLISP File - autocad

I want to draw about 1000 shapes of two circles with tangents using this lisp file, which draws one shape a time.
I wrote a script to draw all shapes (see below), however it waits after the first argument for the next argument although it is there in the script.
Could you please guide me how to fix my script or how to edit the lisp file so that I can draw all shapes without interactive input?
Here is my current Script:
ctan
0,0,0
5
0,10,0
10

The issue is that evaluation of both the Script & AutoLISP function occurs in the same processor thread, and therefore when you evaluate the AutoLISP function from within the Script file, the AutoLISP function takes focus away from the Script, and the remainder of the Script file will be evaluated after the AutoLISP function has completed its evaluation.
To solve this, I would suggest defining a separate AutoLISP function which accepts four arguments corresponding to the centers & radii of each circle, and which constructs the 2D LWPolyline in the same manner as that of my Circle Tangents application.
You can then either evaluate such function from your Script file (perhaps on multiple drawings if required), or evaluate the function from within another AutoLISP program.
Such a function might be:
(defun ctan ( c1 r1 c2 r2 / d1 d2 a1 a2 zv )
(if (< (abs (setq d1 (- r1 r2))) (setq d2 (distance c1 c2)))
(progn
(setq a1 (atan (sqrt (- (* d2 d2) (* d1 d1))) d1)
a2 (angle c1 c2)
zv (trans '(0.0 0.0 1.0) 1 0 t)
)
(entmake
(list
'(000 . "LWPOLYLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbPolyline")
'(090 . 04)
'(070 . 01)
(cons 010 (trans (polar c1 (+ a1 a2) r1) 1 zv))
(cons 042 (/ (sin (/ (- pi a1) 2.0)) (cos (/ (- pi a1) 2.0))))
(cons 010 (trans (polar c1 (- a2 a1) r1) 1 zv))
(cons 010 (trans (polar c2 (- a2 a1) r2) 1 zv))
(cons 042 (/ (sin (/ a1 2.0)) (cos (/ a1 2.0))))
(cons 010 (trans (polar c2 (+ a1 a2) r2) 1 zv))
(cons 210 zv)
)
)
)
)
)
Which, when loaded, you could call from your Script or another AutoLISP program using:
(ctan '(0 0 0) 5 '(0 10 0) 10)

Related

Scheme #!unspecific on display

I'm trying to figure out why I got #!unspecific on output.
I checked other post forum about it but still couldn't figure out what is causing it.
TEST 12: ----- process-square side=3.16228
Side = 3.16228
Perimeter = 12.64911
Area = 10.
#!unspecific
This is my code
;Calculate Distance
(define (get-dist-sq x1 y1 x2 y2)
(+ (expt (- x2 x1) 2)
(expt (- y2 y1) 2))
)
;Calculates the distance between two points
(define (dist-square p1 p2)
(get-dist-sq (get-x p1) (get-y p1) (get-x p2) (get-y p2))
)
;Check if it is a square
(define (is-square p1 p2 p3 p4)
(let ((d2 (dist-square p1 p2)) (d3 (dist-square p1 p3)) (d4 (dist-square p1 p4)))
(cond
((or (equal? d2 0) (equal? d3 0) (equal? d4 0)) #f)
((and (equal? d2 d3) (equal? (* 2 d2) d4) (equal? (* 2 (dist-square p2 p4)) (dist-square p2 p3))) #t)
((and (equal? d3 d4) (equal? (* 2 d3) d2) (equal? (* 2 (dist-square p3 p2)) (dist-square p3 p4))) #t)
((and (equal? d2 d4) (equal? (* 2 d2) d3) (equal? (* 2 (dist-square p2 p3)) (dist-square p2 p4))) #t)
(else #f))
)
)
;Calculate square side length
(define (sq-side-length p1 p2)
(distance p1 p2)
)
;Calculate square area, A= side^2
(define (square-area p1 p2 p3 p4)
(expt (sq-side-length p1 p2) 2)
)
;Calculate square perimeter, P= side * 4
(define (square-perimeter p1 p2 p3 p4)
(* (sq-side-length p1 p2) 4)
)
;Display square calculations
(define (display-square p1 p2 p3 p4)
(display "Side = ")
(display (round-five-decimal (sq-side-length p1 p2)))
(newline)
(display "Perimeter = ")
(display (round-five-decimal (square-perimeter p1 p2 p3 p4)))
(newline)
(display "Area = ")
(display (round (square-area p1 p2 p3 p4)))
(newline)
)
;Process square and display it
(define (process-square p1 p2 p3 p4)
(if (equal? #t (is-square p1 p2 p3 p4))
(display-square p1 p2 p3 p4)
(display "Error: The 4 points does not form a square"))
)
This is the test
(display "TEST 12: ----- process-square side=3.16228")
(newline)
(display (process-square (make-point 3 1) (make-point 2 4) (make-point 5 5) (make-point 6 2)))
(newline)
Your code prints something and returns a value.
The returned value is the same as the returned value of newline (at the end of the test), which is undefined by definition. For this undefined value your scheme implementation uses the symbol #!unspecific
Call your scheme interpreter with some --silent option to get rid of the returned value.
I cannot reproduce your code as I do not know what metaobject protocol are you using -- but this is not an important detail for your question.

Mutability in scheme

I'm working with modifying a list in scheme and was wondering basically how mutability is usually done (or if it's done at all). Here is one example of "adding positions to a chess board".
; representing a chess position as (col, row), using 1-based indexing
(define (make-position col row) (cons col (list row)))
(define empty-board '())
(define (add-new-position existing-positions col row)
(append existing-positions (list (make-position col row))))
And using them:
(define B1 empty-board)
(set! B1 (add-new-position B1 1 2))
(set! B1 (add-new-position B1 2 4))
(display "B1=") (display B1) (newline)
; B1=((1 2) (2 4))
(define B2 empty-board)
(add-new-position B2 1 2)
(add-new-position B2 2 4)
(display "B2=") (display B2) (newline)
; B2=()
Is the above usually how mutability is handled (using set!)? Is that fine to do, or usually discouraged in scheme or other functional programming languages? And if it's discouraged, how would someone, for example, debug in the middle of "building a list" ?

Scheme error when programming point-distance formula - attempt to apply non-procedure

I am attempting to program the point distance formula using Scheme. I am very close to getting it, except I am getting an error.
The exact error is:
Traceback (most recent call last):
File "In [54]", line 5, col 11, in 'application'
File "In [54]", line 5, col 11
RunTimeError: attempt to apply non-procedure '4'
Here is my code:
; code for the distance procedure
(define (distance p1 p2) (sqrt (+ (* (- (car(p2)) (car(p1))) (- (car(p2)) (car(p1)))) (* (- (car(cdr(p2))) (car(cdr(p1)))) (- (car(cdr(p2))) (car(cdr(p1))))))))
(distance (4 5) (3 2))
For reference, the point distance formula is:
√((x2 - x1)^2 + (y2 - y1)^2)
It is generally better to format Scheme code correctly instead of putting everything in just one line.
And it is useful to name intermediate values. If your formula contains x1, x2, y1 and y2, create Scheme variables with those names. This makes it easier to understand the solution.
Scheme hast several abbreviations for nested car and cdr functions. If you need the car of a cdr, you can use cadr.
Scheme allows you to use mathematic symbols in variable names. If a variable contains the difference of x2 and x1, you can name it x2-x1. This enhances the readability of Scheme's Polish notation.
(define (distance p1 p2)
(let ((x1 (car p1))
(y1 (cadr p1))
(x2 (car p2))
(y2 (cadr p2)))
(let ((x2-x1 (- x2 x1))
(y2-y1 (- y2 y1)))
(sqrt (+ (* x2-x1 x2-x1)
(* y2-y1 y2-y1))))))
If you want to pass list literals to functions, you have to quote them in order to prevent evaluation.
(distance '(4 5) '(3 2))
Or use evaluation correctly:
(distance (list 4 5) (list 3 2))

Mandelbrot set function does not perform as expected

Here is an example from Clojure Programming Paperback by Chas Emerick:
(import 'java.awt.image.BufferedImage
'(java.awt Color RenderingHints))
(defn- escape
[^double a0 ^double b0 ^long depth]
(loop [a a0, b b0, iteration 0]
(cond
(< 4 (+ (* a a) (* b b))) iteration
(>= iteration depth) -1
:else (recur (+ a0 (- (* a a) (* b b)))
(+ b0 (apply * [2 a b]))
(inc iteration)))))
(defn mandelbrot [rmin rmax imin imax
& {:keys [width height depth]
:or {width 80 height 40 depth 1000}}]
(let [mandelbrot-help
(fn [^double rmin ^double rmax
^double imin ^double imax
]
(let [stride-w (/ (- rmax rmin) width)
stride-h (/ (- imax imin) height)]
(loop [x 0
y (dec height)
escapes []]
(if (== x width)
(if (zero? y)
(partition width escapes)
(recur 0 (dec y) escapes))
(recur (inc x) y (conj escapes
(escape (+ rmin (* x stride-w))
(+ imin (* y stride-h))
depth)))))))]
(mandelbrot-help rmin rmax imin imax)))
(defn render-text
[mandelbrot-grid]
(doseq [row mandelbrot-grid]
(doseq [escape-iter row]
(print (if (neg? escape-iter)
\*
\space)))
(println)))
(defn render-image
[mandelbrot-grid]
(let [palette
(vec (for
[c (range 500)]
(Color/getHSBColor 0.0 0.0 (/ (Math/log c) (Math/log 500)))))
height (count mandelbrot-grid)
width (count (first mandelbrot-grid))
img (BufferedImage. width height BufferedImage/TYPE_INT_RGB)
^java.awt.Graphics2D g (.getGraphics img)]
(doseq [[y row] (map-indexed vector mandelbrot-grid)
[x escape-iter] (map-indexed vector row)]
(.setColor g (if (neg? escape-iter)
(palette 0)
(palette (mod (dec (count palette)) (inc escape-iter)))))
(.drawRect g x y 1 1))
(.dispose g)
img))
(do (time (mandelbrot -2.25 0.75 -1.5 1.5
:width 1600 :height 1200 :depth 1000))
nil)
Everything works except that it takes 60s on my machine, and only 8s according to the book (results on my laptop are consistently better in other examples).
Is there something that I did wrong?
Where did you get that code from? It is definitely not what appears either in the book (based on my PDF copy of it, page 449-452), or the code sample on github. In particular, the (apply * [2 a b]) in escape is crazy; that'll never be fast (at least not without any degree of [trivial] source-level optimization, which Clojure unfortunately doesn't apply). Even weirder, that particular snippet doesn't appear anywhere in the book, nor can I find it in the history of the git repo we used to collaborate on the writing of the book.
Maybe you were just tinkering with the examples? If not, I really would like to know where the sample you have came from, as it's absolutely not representative of our intent or best practice (obviously, given the timings you're seeing).
Anyway, here's the "fast escape" function from the book / github samples repo:
(defn- escape
[^double a0 ^double b0 depth]
(loop [a a0
b b0
iteration 0]
(cond
(< 4 (+ (* a a) (* b b))) iteration
(>= iteration depth) -1
:else (recur (+ a0 (- (* a a) (* b b)))
(+ b0 (* 2 (* a b)))
(inc iteration)))))
user> (do (time (mandelbrot -2.25 0.75 -1.5 1.5
:width 1600 :height 1200 :depth 1000))
nil)
"Elapsed time: 1987.460104 msecs"
Hinting the depth arg as ^long (something that I should have included in the book example) drops that to 1450ms on my laptop.

SICP 2.16 interval-arithmetic (scheme)

This isn't a homework question, I'm just left unsatisfied with my understanding of interval arithmetic and the implications of exercise 2.16.
The interval arithmetic defined by section 2.14 does not exhibit the properties of normal arithmetic. Two should be equivalent operations, (r1*r2)/(r1 + r2) and 1/(1/r1 + 1/r2),
give different results. The exercise asks why this is the case, and if it is possible to construct an interval-arithmetic system in which this is not the case.
The section is addressing the calculation of error margins of resistance of electrical components. I'm not sure I understand what it would mean, in these terms, to multiply and divide intervals. What is the application to multiplying two intervals together?
Is it possible to construct an interval-arithmetic system without the problem in this example?
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-14.html#%_sec_2.1.4
(define (make-interval a b)
(cons a b))
(define (make-center-width c w)
(make-interval (- c w) (+ c w)))
(define (make-center-percent c p)
(make-center-width c (* c (/ p 100.0))))
(define (lower-bound i)
(car i))
(define (upper-bound i)
(cdr i))
(define (center i)
(/ (+ (upper-bound i) (lower-bound i)) 2))
(define (width i)
(/ (- (upper-bound i) (lower-bound i)) 2))
(define (percent i)
(* 100.0 (/ (width i) (center i))))
(define (add-interval x y)
(make-interval (+ (lower-bound x) (lower-bound y))
(+ (upper-bound x) (upper-bound y))))
(define (sub-interval x y)
(make-interval (- (lower-bound x) (lower-bound y))
(- (upper-bound x) (upper-bound y))))
(define (mul-interval x y)
(let ((p1 (* (lower-bound x) (lower-bound y)))
(p2 (* (lower-bound x) (lower-bound y)))
(p3 (* (lower-bound x) (lower-bound y)))
(p4 (* (lower-bound x) (lower-bound y))))
(make-interval (min p1 p2 p3 p4)
(max p1 p2 p3 p4))))
(define (div-interval x y)
(if (= (width y ) 0)
(error "division by interval with width 0")
(mul-interval x
(make-interval (/ 1.0 (upper-bound y))
(/ 1.0 (lower-bound y))))))
(define (parl1 r1 r2)
(div-interval (mul-interval r1 r2)
(add-interval r1 r2)))
(define (parl2 r1 r2)
(let ((one (make-interval 1 1)))
(div-interval one
(add-interval (div-interval one r1)
(div-interval one r2))))
(define (r1 (make-interval 4.0 3.2)))
(define (r2 (make-interval 3.0 7.2)))
(center (parl1 r1 r2))
(width (parl1 r1 r2))
(newline)
(center (parl2 r1 r2))
(width (parl2 r1 r2))
This happens because the operations in the interval arithmetic do not have the arithmetic structure of a field.
As Sussman says, the exercise is difficult -- you need to check each of the operations of the field structure, and see which one is not satisfied.
The exercise asks us to show that the interval arithmetic is not the arithmetic of the ranges of functions.
A function like f (x) = x^2 defined on a domain [-1, 1] has the
range [0,1], which is included in [-1,1] * [-1,1] = [-1,1], obtained by replacing the symbol x by the domain of the symbol x.
If we define a similar function that uses a different variable for each dimension, like in f(x,y) = x * y, then the range of this function, when defined on the domain [-1,1] * [-1,1], is the same as the interval [-1,1] * [-1,1] = [-1, 1], because x is used once, and so with y.
It happens that all the time when the function f(.., x, ..) is continous in each variable x we have the range arithmetics to be identical with interval arithmetics if each symbol is used only once in definition of f.
In the first formula of Alice, parallel resistor is computed
repeating 2 times the variable R1, and 2 times the variable R2,
and using the same argument the range of this function is included
in the product of the corresponding intervals obtained from the
formula of the function, by replacing each name by corresponding
domain interval, but it is not strictly the same.
We are asked either to rewrite any function such that the range of the rewritten function be the same as the interval obtained by applying the rewritten function's formula, wih names replaced by intervals equal to the domain of the corresponding name from the rewritten function, or to show that this is not possible for each possible function.
This problem is called dependency problem, and it is a large
problem, whose understanding is out of the purpose of SICP, and requires differential equations in multiple variables to solve it.
The purpose of this exercise is , as Sussman himself said, just to show that data can be encoded in multiple ways. The focus is not on mathematics , but on data abstraction.
The easiest way to understand the problem is looking at the very simple expression e = x/x where x is in [2,3]. If we use interval arithmetic, we get that e is in [2/3, 3/2], however second grade arithmetic shows that e=x/x=1. So what gives?
Well it is actually very simple: when using interval arithmetic I made the mistake of assuming x can have two different values at the same time.
the maximum value of e is given when the numerator is 3 and the denominator is 2, however since both should always be the same this is not possible.
So, is it ever possible to use interval arithmetic? Yes, when all intervals appear only once, since then you would not have the problem of different values for the same variable in different interval calculations.
Is it possible to create an arithmetic package which does not have this problem? No, since not every function can be written where every variable appears only once. This problem is known as the dependency problem.

Resources