(archive 'newLISPer)

September 25, 2006

Poor man's CAD

Filed under: newLISP — newlisper @ 23:51

I use Adobe Illustrator a fair bit, for graphics work. It’s not a bad program – it’s pretty good, in fact. But I occasionally get irritated by a particular lack of a certain feature – depending what I’m working on.

This week I’ve been getting fed up with the way Illustrator draws circles. In Illy, you can draw circles only by placing the centre point, or by dragging out a box that defines the circle’s left and right sides. There’s no way of doing those clever CAD things, such as drawing circles that pass through three points. And it’s been getting to me…

But I thought it was worth trying to hack together a little CAD tool. The task breaks down into three parts: get the three points from Illy, calculate the radius and centre point of the circle that passes through these points, then finally draw the circle. The first and last parts have to be done using a bit of AppleScript, because that’s all that Illy understands. But the middle bit can be done using newLISP. And the whole script – a newLISP file – can sit in the Scripts menu on the menu bar ready for selection while you’re working.

Here’s the contents of this hackish CADdery:


    ; given three points, draw a circle through them
    ; geometry info from http://cgafaq.info/wiki/Circle_Through_Three_Points

    ; get the three points
    (set 'pointslist (exec (format [text]osascript  -e 'tell application "Adobe Illustrator 10"
        tell front document
            set s to selection
            set pointslist to ""
            repeat with p in s
                set firstItem to p
                set pathinfo to entire path of firstItem
                repeat with p1 in pathinfo
                    set a to anchor of p1
                    set pointslist to pointslist & " " & item 1 of a
                    set pointslist to pointslist & " " & item 2 of a
                end repeat
            end repeat
        end tell
    end tell

    ; clean up Illy's output
    (set 'points (filter float? (map float (parse (first pointslist) { } 0))))

    (set    'ax (points 0)
                'ay (points 1)
                'bx (points 2)
                'by (points 3)
                'cx (points 4)
                'cy (points 5))

    (set    'A (sub bx ax)
                'B (sub by ay)
                'C (sub cx ax)
                'D (sub cy ay)
                'E (add
                        (mul A (add ax bx))
                        (mul B (add ay by)))
                'F (add
                        (mul C (add ax cx))
                        (mul D (add ay cy)))
                'G (mul 2 (sub (mul A (sub cy by)) (mul B (sub cx bx)))))

    (if (= G 0) ; points are collinear, forget it

    (set    'centre-x (div (sub (mul D E) (mul B F)) G)
                'centre-y (div (sub (mul A F) (mul C E)) G)
                'r (sqrt (add (pow (sub ax centre-x)) (pow (sub ay centre-y)))))

    ; we have coords of centre and the radius
    ; Illustrator bounds are left-x, top-y, right-x, bottom-y

    (set 'bounds-string
        (string "{" (sub centre-x r) ", " (add centre-y r) ", " (add centre-x r) ", " (sub centre-y r) "}"))

    (set 'draw-circle
        (exec (format [text]osascript  -e 'tell application "Adobe Illustrator 10"
        tell front document
            set e to make new ellipse at beginning with properties {bounds:%s}
        end tell
    end tell
    [/text] bounds-string)))

To use it, just select a path with at least three points. The first three define the location of the new circle.



  1. >This is an exciting post, because it shows one of newLISP’s strengths, which is integrating different applications.Just to be picky: the first time the usage of ‘format’ in ‘exec’ is redundant, because the text string doesn’t contain any % templates to expand (but the last ‘format’ does).

    Comment by don Lucio — September 26, 2006 @ 18:22 | Reply

  2. >This is a very enlightening post. Very clever.

    Comment by bob bae — September 26, 2006 @ 23:20 | Reply

  3. >Yes dl – now I’ve managed a reasonably general-purpose approach to running AppleScripts i tend to copy and paste it all the time, and just add or subtract % templates from the format expression – lazy really!One day I hope that the AppleScript parts will be unnecessary, replaced with a newLISP port of hamish sanderson’s appscript bridge.

    Comment by newlisper — September 27, 2006 @ 07:39 | Reply

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: