You should be automatically redirected . If not, visit
http://newlisper.wordpress.com
and update your bookmarks.

26/09/2006

Poor man's CAD

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:

    #!/usr/bin/newlisp

    ; 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
    pointslist' 
    [/text])))

    ; 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
        (exit))

    (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)))
    (exit)

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

3 Comments:

At 19:22, Blogger don Lucio said...

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).

 
At 00:20, Blogger bob bae said...

This is a very enlightening post. Very clever.

 
At 08:39, Blogger newlisper said...

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.

 

Post a Comment

Links to this post:

Create a Link

<< Home