Description

Bindings to the C API for AquaTerm

Author

Thomas Chust

Version

Usage

(require-extension aquaterm)

Download

aquaterm.egg

Documentation

This documentation page is acutally a rewrite of the documentation for the Objective C AQTAdapter class. The C API this binding is relying on is not documented in its own right.

For in-depth information on the functionality of the routines and general information you should consult the original AquaTerm documentation as well as this manual.

Please not that the whole AquaTerm library is using the unit pt for its plot coordinates and sizes unless stated otherwise.

Initializing and Deinitializing the Library

procedure: (aqt:init) => <boolean>

Initializes the library and return whether it was successful. You should call this routine before using any of the other functions.

procedure: (aqt:terminate) => <void>

Deinitializes the library, call it as the last thing before terminating your program.

Controlling Plots

procedure: (aqt:open-plot (id <exact>)) => <void>

Creates a new plot with an arbitrary identification number that can be used in calls to aqt:select-plot to reference that plot.

Note that the plot is not displayed before you call aqt:render-plot!

procedure: (aqt:select-plot (id <exact>)) => <void>

Selects the plot identified by id as the target for subsequent commands.

procedure: (aqt:set-plot-size! (width <number>) (height <float>)) => <void>

Defines the limits of the current plot area.

This function must be called before any drawing command following an aqt:open-plot or aqt:clear-plot! command, otherwise behaviour is undefined.

procedure: (aqt:set-plot-title! (title <string>)) => <void>

Sets a title for the current plot, which will be displayed in the plot window's titlebar and will be used as a default filename when saving the plot from AquaTerm.

procedure: (aqt:render-plot!) => <void>

Displays the current plot in an AquaTerm window rendering all drawing operations performed so far.

procedure: (aqt:clear-plot!) => <void>

Clears the current plot and resets all its attributes. Remeber to call aqt:set-plot-size! again after using this function.

To clear the plot without resetting it, use the aqt:erase-rect! procedure.

procedure: (aqt:close-plot!) => <void>

Closes the connection to the current plot and disables event handling.

Note that this function does not cause the plot window to disappear if it was shown before.

Clipping

procedure: (aqt:set-clip-rect! (x <number>) (y <number>) (width <number>) (height <number>)) => <void>

Set a rectangular clipping region to apply to all subsequent operations, until changed again by aqt:set-clip-rect! or aqt:set-default-clip-rect!

procedure: (aqt:set-default-clip-rect!) => <void>

Reset the clipping region to the entire plot for all subsequent operations, until changed again by aqt:set-clip-rect! or aqt:set-default-clip-rect!

Managing Colors

procedure: (aqt:set-color! (red <number>) (green <number>) (blue <number>)) => <void>

Set the drawing color in the active plot to the given red, green and blue intensities between 0 and 1.

procedure: (aqt:set-background-color! (red <number>) (green <number>) (blue <number>)) => <void>

Set the background color in the active plot to the given red, green and blue intensities between 0 and 1.

procedure: (aqt:get-color) => <number>, <number>, <number>

Retrieves the drawing color of the active plot and returns three values for its red, green and blue intensities between 0 and 1.

procedure: (aqt:get-background-color) => <number>, <number>, <number>

Retrieves the background color of the active plot and returns three values for its red, green and blue intensities between 0 and 1.

Managing the Colormap

procedure: (aqt:colormap-size) => <exact>

Returns the number of colormap entries available for the programmer.

procedure: (aqt:set-colormap-entry! (idx <exact>) (red <number>) (green <number>) (blue <number>)) => <void>

Set the entry at position idx in the colormap to the given red, green and blue intensities between 0 and 1.

procedure: (aqt:get-colormap-entry (idx <exact>)) => <number>, <number>, <number>

Retrieves the color at index idx in the colormap and returns three values for its red, green and blue intensities between 0 and 1.

procedure: (aqt:take-color-from-colormap-entry! (idx <exact>)) => <void>

Set the drawing color in the active plot to the value of the colormap entry indicated by idx.

procedure: (aqt:take-background-color-from-colormap-entry! (idx <exact>)) => <void>

Set the background color in the active plot to the value of the colormap entry indicated by idx.

Drawing Text

procedure: (aqt:set-fontname! (name <string>)) => <void>

Sets the font to be used for future operations.

The default font is "Times-Roman".

procedure: (aqt:set-fontsize! (size <number>)) => <void>

Sets the font size in points for future operations.

The default font size are 14 pt.

procedure: (aqt:add-label! (text <string>) (x <number>) (y <number>) (angle <number>) #!optional ((h-align <symbol>) 'left) ((v-align <symbol>) 'baseline)) => <void>

Adds text at position x, y, rotated by angle degrees and aligned vertically and horizontally (with respect to position and rotation) according to h-align and v-align.

The following values are allowed for the alignment parameters:

h-align -- Horizontal Alignment
left
center
right

v-align -- Vertical Alignment
middle
baseline
bottom
top

procedure: (aqt:add-sheared-label! (text <string>) (x <number>) (y <number>) (angle <number>) (shear-angle <number>) (h-align <symbol>) (v-align <symbol>)) => <void>

Works like aqt:add-label! but additionally shears the text by shear-angle degrees in order to look right in 3D images for example.

Drawing Lines

procedure: (aqt:set-linewidth! (width <number>)) => <void>

Sets the current linewidth to width points, used for all subsequent lines.

Any line currently being built by aqt:move-to! and aqt:add-line-to! will be considered finished since any coalesced sequence of line segments must share the same linewidth.

The default linewidth is 1 pt.

procedure: (aqt:set-linestyle-pattern! (phase <number>) . pattern) => <void>

Set the current line style to pattern style, used for all subsequent lines. The linestyle is specified as at most 8 numbers, where even positions in the list correspond to dash-lengths and odd positions correspond to gap-lengths.

To produce e.g. a dash-dotted line, use the command (aqt:set-linestyle-pattern! 0 4 2 1 2).

procedure: (aqt:set-linestyle-solid!) => <void>

Sets the current line style to solid, used for all subsequent lines.

This is the default setting.

procedure: (aqt:set-line-cap-style! (style <symbol>)) => <void>

Sets the current line cap style, used for all subsequent lines.

Any line currently being built by aqt:move-to! and aqt:add-line-to! will be considered finished since any coalesced sequence of line segments must share the same cap style.

The style parameter can have the following values:

Style Meaning
butt Lines do not extend beyond their endpoint.
round Lines extend into a half-circle beyond their endpoint.
square Lines extend into a half-square beyond their endpoint.

The default line cap style is round.

procedure: (aqt:move-to! (x <number>) (y <number>)) => <void>

Moves the current point to x, y in preparation for a new sequence of line segments.

procedure: (aqt:add-line-to! (x <number>) (y <number>)) => <void>

Adds a line segment from the current point (given by a previous aqt:move-to! or aqt:add-line-to!) to x, y and sets the target position as the new current point.

procedure: (aqt:add-polyline! (points <list>)) => <void>

Adds a sequence of line segments specified by a list of start-, join-, and endpoint(s) in points, a list of two number lists.

Drawing Rectangles and Polygons

procedure: (aqt:move-to-vertex! (x <number>) (y <number>)) => <void>

Moves the current point to x, y in preparation for a new sequence of polygon edges.

procedure: (aqt:add-edge-to-vertex! (x <number>) (y <number>)) => <void>

Adds a polygon edge from the current point (given by a previous aqt:move-to-vertex! or aqt:add-edge-to-vertex!) to x, y and sets the target position as the new current point.

procedure: (aqt:add-polygon! (points <list>)) => <void>

Adds a polygon specified by a list of vertices in points, a list of two number lists.

procedure: (aqt:add-filled-rect! (x <number>) (y <number>) (width <number>) (height <number>)) => <void>

Adds a filled rectangle and attempts to remove any objects that will be covered by it.

procedure: (aqt:erase-rect! (x <number>) (y <number>) (width <number>) (height <number>)) => <void>

Removes any objects completely inside aRect. Does not force a redraw of the plot.

Drawing Bitmaps

procedure: (aqt:set-image-transform! (M-11 <number>) (M-12 <number>) (M-21 <number>) (M-22 <number>) (t-x <number>) (t-y <number>)) => <void>

Sets a transformation matrix for images added by aqt:add-transformed-image-with-bitmap!, see the ADC Reference Documentation on Basic Drawing for more information how this works.

procedure: (aqt:reset-image-transform!) => <void>

Sets the transformation matrix to unity, i.e. no transform.

procedure: (aqt:add-image-with-bitmap! (data <string|byte-vector>) (data-width <exact>) (data-height <exact>) (x <number>) (y <number>) (width <number>) (height <number>)) => <void>

Adds a bitmap image of size data-width * data-height pixels to the plot at position x, y, scaling it to width x height plot units.

The bitmap must be stored in data as 24 bit per pixel, 8 bit per color channel raw RGB data.

Does not apply transform.

procedure: (aqt:add-transformed-image-with-bitmap! (data <string|byte-vector>) (data-width <exact>) (data-height <exact>) (x <number>) (y <number>) (width <number>) (height <number>)) => <void>

Adds a bitmap image of size data-width * data-height pixels to the plot at position x, y, scaling it to width x height plot units and applying the stored transformation matrix to it.

The bitmap must be stored in data as 24 bit per pixel, 8 bit per color channel raw RGB data.

Handling Events

procedure: (aqt:set-accepting-events! (yes <boolean>)) => <void>

Inform AquaTerm whether or not events should be passed from the currently selected plot. Deactivates event passing from any plot previously set to pass events.

procedure: (aqt:get-last-event) => <list|boolean>

Reads the last event logged by the viewer. Will always return #f unless aqt:set-accepting-events! was called with a #t argument.

The event is returned by AquaTerm as a string but is decoded internally and passed back as follows:

Return value Meaning
#f No event was received.
('mouse (x y) button) The mouse-button with the number button was clicked at the position x, y in plot coordinates.
('key (x y) key) The key corresponding to the character key was clicked while the mouse was at the position x, y in plot coordinates.

Should the event returned from the library encode an error, a continuable exception of the composite kind (exn aquaterm) is thrown, which has an additional property type holding either the symbol server or general depending on the source of the error.

procedure: (aqt:wait-next-event) => <list|boolean>

Works analogous to aqt:get-last-event but blocks and waits for an event instead of returning immediately.

Examples

The following code is a free translation of the C API demo program shipped with AquaTerm. Most of the functionality of the library is demonstrated here.

(use extras aquaterm)

;; initialize the library
(unless (aqt:init) (error "could not initialize AquaTerm"))

;; open a plot for drawing
(aqt:open-plot 1)
(aqt:set-plot-size! 620 420)
(aqt:set-plot-title! "Testview")

;; set colormap
(let next ((i 0)
	   (colors
	    '((1.0 1.0 1.0) ;; white
	      (0.0 0.0 0.0) ;; black
	      (1.0 0.0 0.0) ;; red
	      (0.0 1.0 0.0) ;; green
	      (0.0 0.0 1.0) ;; blue
	      (1.0 0.0 1.0) ;; purple
	      (1.0 1.0 0.5) ;; yellow
	      (0.0 0.5 0.5)))) ;; dark-green
  (apply aqt:set-colormap-entry! i (car colors))
  (unless (null? (cdr colors))
    (next (add1 i) (cdr colors))))

;; set color explicitly
(aqt:set-color! 0.0 0.0 0.0)
(aqt:set-fontname! "Helvetica")
(aqt:set-fontsize! 12)
(aqt:add-label! "Testview 620x420 pt"  4 412 0 'left 'middle)

;; frame the plot
(aqt:move-to! 20 20)
(for-each
 (cute apply aqt:add-line-to! <>)
 '((600  20)
   (600 400)
   ( 20 400)
   ( 20  20)))
(aqt:add-label! "Frame 600x400 pt" 24 30 0 'left 'middle)

;; colormap
(aqt:add-label!
 (sprintf "Custom colormap (8 out of ~a)" (aqt:colormap-size))
 30 390 0 'left 'middle)

(aqt:set-color! 0.8 0.8 0.8)
(aqt:add-filled-rect! 28 348 24 24)
(do ((i 0 (add1 i))) ((>= i 8))
  (aqt:take-color-from-colormap-entry! i)
  (aqt:add-filled-rect! (+ 30 (* i 30)) 350 20 20)
  (aqt:set-color! 0.5 0.5 0.5)
  (aqt:add-label! (number->string i) (+ 40 (* i 30)) 360 0 'center 'middle))

;; continuous colors
(aqt:take-color-from-colormap-entry! 1)
(aqt:add-label! "\"Any color you like\"" 320 390 0 'left 'middle)
(aqt:set-linewidth! 1)
(do ((i 0 (add1 i))) ((>= i 256))
  (let* ((f (/ i 255)) (g (- 1 f)))
    (aqt:set-color! 1 f (/ f 2))
    (aqt:add-filled-rect! (+ 320 i) 350 1 20)
    (aqt:set-color! 0 f g)
    (aqt:add-filled-rect! (+ 320 i) 328 1 20)
    (aqt:set-color! g g g)
    (aqt:add-filled-rect! (+ 320 i) 306 1 20)))

;; lines
(aqt:take-color-from-colormap-entry! 1)
(do ((f 1 (+ f 2))) ((>= f 13))
  (let ((lw (/ f 2)) (g (+ 200.5 (* f 10))))
    (aqt:set-linewidth! lw)
    (aqt:move-to! 30 g)
    (aqt:add-line-to! 200 g)
    (aqt:add-label!
     (sprintf "linewidth ~a" lw) 210 (add1 g) 0 'left 'middle)))

;; linecap styles
(aqt:add-label! "(aqt:set-linecap-style! ..." 43 190.5 0 'left 'middle)
(let next ((styles '(butt round square)) (y 170.5))
  (aqt:set-linewidth! 11)
  (aqt:take-color-from-colormap-entry! 1)
  (aqt:set-line-cap-style! (car styles))
  (aqt:move-to! 40.5 y)
  (aqt:add-line-to! 150.5 y)
  (aqt:add-label!
   (sprintf "... '~a)" (car styles))
   160.5 y 0 'left 'middle)
  (aqt:set-linewidth! 1)
  (aqt:take-color-from-colormap-entry! 6)
  (aqt:move-to! 40.5 y)
  (aqt:add-line-to! 150.5 y)
  (unless (null? (cdr styles))
    (next (cdr styles) (- y 20))))

;; line joins
(aqt:take-color-from-colormap-entry! 1)
(aqt:add-label! "Line joins:" 43 90 0 'left 'middle)

(for-each
 (lambda (xs)
   (aqt:set-linewidth! 11)
   (aqt:take-color-from-colormap-entry! 1)
   (aqt:set-line-cap-style! 'butt)
   (aqt:move-to! (vector-ref xs 0) 50)
   (aqt:add-line-to! (vector-ref xs 1) 70)
   (aqt:add-line-to! (vector-ref xs 2) 50)
   (aqt:set-linewidth! 1)
   (aqt:take-color-from-colormap-entry! 6)
   (aqt:move-to! (vector-ref xs 0) 50)
   (aqt:add-line-to! (vector-ref xs 1) 70)
   (aqt:add-line-to! (vector-ref xs 2) 50))
 '(#(40 75 110)
   #(130 150 170)
   #(190 200 210)))

;; polygons
(aqt:take-color-from-colormap-entry! 1)
(aqt:add-label! "Polygons" 320 290 0 'left 'middle)

(aqt:take-color-from-colormap-entry! 2)
(aqt:add-polygon!
 (let more ((i 0))
   (if (< i 4)
       (cons
	(let ((rad (* i (asin 1))))
	  (list (+ 340 (* 20 (cos rad))) (+ 255 (* 20 (sin rad)))))
	(more (add1 i)))
       '())))

(let ((ps (let more ((i 0))
	    (if (< i 5)
		(cons
		 (let ((rad (* i (acos -1) 0.8)))
		   (list
		    (+ 400 (* 20 (cos rad)))
		    (+ 255 (* 20 (sin rad)))))
		 (more (add1 i)))
		'()))))
  (aqt:take-color-from-colormap-entry! 3)
  (aqt:add-polygon! ps)
  (aqt:take-color-from-colormap-entry! 1)
  (aqt:add-polyline! (append ps (list (car ps)))))

(aqt:take-color-from-colormap-entry! 4)
(aqt:add-polygon!
 (let more ((i 0))
   (if (< i 8)
       (cons
	(let ((rad (* i (asin 1) 0.5)))
	  (list (+ 460 (* 20 (cos rad))) (+ 255 (* 20 (sin rad)))))
	(more (add1 i)))
       '())))

(aqt:take-color-from-colormap-entry! 5)
(aqt:add-polygon!
 (let more ((i 0))
   (if (< i 32)
       (cons
	(let ((rad (* i (asin 1) 0.125)))
	  (list (+ 520 (* 20 (cos rad))) (+ 255 (* 20 (sin rad)))))
	(more (add1 i)))
       '())))

;; images
(aqt:take-color-from-colormap-entry! 1)
(aqt:add-label! "Images" 320 220 0 'left 'middle)

(let ((img "\xFF\x00\x00\x00\xFF\x00\x00\x00\xFF\x00\x00\x00"))
  (aqt:add-image-with-bitmap! img 2 2 328 200 4 4)
  (aqt:add-label! "bits" 330 180 0 'center 'middle)
  (aqt:add-image-with-bitmap! img 2 2 360 190 40 15)
  (aqt:add-label! "fit bounds" 380 180 0 'center 'middle)
  (aqt:set-image-transform! 9.23880 3.82683 -3.82683 9.23880 494.6 186.9)
  (aqt:add-transformed-image-with-bitmap! img 2 2 0 0 600 400)
  (aqt:add-label! "scale, rotate and translate" 500 180 0 'center 'middle)
  (aqt:reset-image-transform!))

;; text
(for-each
 (lambda (as)
   (aqt:take-color-from-colormap-entry! (vector-ref as 0))
   (aqt:set-fontname! (vector-ref as 1))
   (aqt:set-fontsize! (vector-ref as 2))
   (aqt:add-label!
    (sprintf "~a ~a pt" (vector-ref as 1) (vector-ref as 2))
    320 (vector-ref as 3) 0 'left 'middle))
 '(#(1 "Times-Roman" 16 150)
   #(2 "Times-Italic" 16 130)
   #(4 "Zapfino" 12 100)))

(aqt:take-color-from-colormap-entry! 2)
(aqt:set-linewidth! 0.5)
(aqt:move-to! 510.5 160)
(aqt:add-line-to! 510.5 100)

(aqt:add-polyline!
 '((545.5 75.5) (535.5 75.5) (540.5 75.5) (540.5 70.5) (540.5 80.5)))

(aqt:take-color-from-colormap-entry! 1)
(aqt:set-fontname! "Verdana")
(aqt:set-fontsize! 10)
(let next ((as '(left center right)) (y 150))
  (aqt:add-label! (sprintf "~a-aligned" (car as)) 510.5 y 0 (car as) 'middle)
  (unless (null? (cdr as))
    (next (cdr as) (- y 20))))

(aqt:set-fontname! "Times-Roman")
(aqt:set-fontsize! 14)
(for-each
 (cute aqt:add-label! "-rotate" 540.5 75.5 <> 'left 'middle)
 '(90 45 -30 -60 -90))

;; string styling is not possible through the C interface
(aqt:set-fontsize! 12)
(aqt:add-label!
 "No string styling from Scheme, sorry" 320 75 0 'left 'middle)

(aqt:take-color-from-colormap-entry! 2)
(aqt:set-linewidth! 0.5)
(aqt:move-to! 320 45.5)
(aqt:add-line-to! 520 45.5)
(aqt:take-color-from-colormap-entry! 1)
(aqt:set-fontname! "Times-Italic")
(aqt:set-fontsize! 14)
(let next ((as '(top bottom middle baseline)) (x 330))
  (aqt:add-label! (symbol->string (car as)) x 45.5 0 'left (car as))
  (unless (null? (cdr as))
    (next (cdr as) (+ x 45))))

;; draw it all
(aqt:render-plot!)

;; wait for events
(let loop ()
  (let ((evt (aqt:wait-next-event)))
    (unless (and evt (pair? evt) (eq? (car evt) 'key) (eq? (caddr evt) #\q))
      (display "unhandled event: ") (write evt) (newline)
      (loop))))

;; let go of it when done
(aqt:close-plot!)
(aqt:terminate)

License

Copyright (c) 2005, Thomas Chust <chust@web.de>.  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

  Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer. Redistributions in
  binary form must reproduce the above copyright notice, this list of
  conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution. Neither the name of the
  author nor the names of its contributors may be used to endorse or
  promote products derived from this software without specific prior
  written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.