1982. I'm not even sure if I already had my first computer back then - but that's the year
when Peter Henderson published an article about
Functional Geometry, in which he
describes how to build images from equations, and how to create big images from
smaller ones using functional composition.
The original implementation was in UCSD Pascal.
A while ago, part-time Lisp hacker Frank Buß ported it to Lisp
and added Postscript output, and he also posted a
very nice description
of his approach, illustrating how this example helped him understand
how valuable support for higher-order functions in a language can be.
Frank's code is clear and compact, and the platform dependencies are all in one
function, which made it easy to adapt to CoCreate Modeling's dialect
of Common Lisp. In fact, all that's needed to run the code is the following
loader code:
;; -*-Lisp-*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Description: Wrapper to run Frank Buss' functional geometry code
;; in CoCreate Modeling
;; Author: Claus Brod
;; Language: Lisp
;;
;; (C) Copyright 2008 Claus Brod, all rights reserved
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
(in-package :clausbrod.de)
(use-package :oli)
(export '(plot-escher))
;; Allow using lambda without quoting it via #' first
;; (No longer required in CoCreate Modeling 2008 and later.)
(defmacro lambda (&rest body)
`(function (lambda ,@body)))
(defparameter *our-loadpath* *load-truename*)
(load (format nil "~A/functional.lsp"
(directory-namestring *our-loadpath*)))
;; Modeling-specific plotter function
(defun plot-annotation (p)
(let ((tempfile (format nil "~A/test.mac" (oli:sd-inq-temp-dir)))
(scale 500.0))
(startup::activate-annotation)
(with-open-file (s tempfile
:direction :output :if-exists :supersede)
(format s "line~%")
(dolist (line (funcall p '(0 0) '(1 0) '(0 1)))
(destructuring-bind ((x0 y0) (x1 y1)) line
(format s " ~D,~D ~D,~D~%"
(* scale (float x0))
(* scale (float y0))
(* scale (float x1))
(* scale (float y1)))))
(format s "end"))
(oli:sd-execute-annotator-command
:cmd (format nil "input '~A'" tempfile))
(docu::docu_vp :fit_vp)
(delete-file tempfile)))
;; Shortcut for the Escher fish drawing
(defun plot-escher()
(plot-annotation *fishes*))
The loader code adds the definition for the
lambda macro
which is missing so far in CoCreate Modeling, loads Frank's code, and then adds a
plotter function which creates output in a 2D Annotation window.
Usage instructions:
- Download Frank's code from his site
and save it as
functional.lsp
.
- Download the loader code and save it
into the same directory.
- Load the loader Lisp code into CoCreate Modeling 2007 or higher.
- In the user input line, enter
(clausbrod.de:plot-escher)
Thanks to Frank for this cute demo code!
Revision: r1.1 - 31 Mar 2008 - 18:03 - ClausBrod