home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1990 / 08 / lauzzana.lst < prev    next >
File List  |  1990-06-20  |  9KB  |  310 lines

  1. _IMPLEMENTING BICUBIC SPLINES_
  2. by G. Raymond Lauzzana and Denise E.M. Penrose
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. /* include all of the files that you might need. */
  8.  
  9. #include <ctype.h>
  10. #include <memory.h>
  11. #include <math.h>
  12. #include <types.h>
  13. #include <quickdraw.h>
  14. #include <palette.h>
  15. #include <toolutils.h>
  16. #include <fonts.h>
  17. #include <events.h>
  18. #include <windows.h>
  19. #include <dialogs.h>
  20. #include <stdio.h>
  21. #include <menus.h>
  22. #include <desk.h>
  23. #include <textedit.h>
  24. #include <scrap.h>
  25. #include <segload.h>
  26. #include <controls.h>
  27. #include <packages.h>
  28. #include <slots.h>
  29. #include <ShutDown.h>
  30. #include <errors.h>
  31. #include <files.h>
  32.  
  33. /* --------------------------------------------------------------------- */
  34. /* The low-level help functions for graphics. */
  35.  
  36. /* Mean-squared distance between to coordinate pairs. */
  37.  
  38. int distance(i0, j0, i1, j1)
  39. int i0, j0, i1, j1;
  40. { int res;
  41.   double x1, x2, y1, y2;
  42.  
  43.   x1 = i0; x2 = i1; y1 = j0; y2 = j1;
  44.   res = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
  45.   return(res);
  46. }
  47.  
  48. /* --------------------------------------------------------------------- */
  49. /* The low-level SPLINE function. This function calculates and draws a 
  50. curved line along the path of a bi-cubic spline the equation for a coordinate 
  51. of the points on the spline is:
  52. j = j1*t + j2*(1 - t) + W*(j2-j3)*t*(1 - t)*(1 - t) + W*(j1-j0)*t*t*(1 - t);
  53.    where:    j : the coordinate being calculated.
  54.         t : the cubic variable.
  55.         W : a weighting factor.
  56.         (j1, j2) : the end-coordinates of the spline.
  57.         (j0, j3) : The control coordinates.
  58. */
  59.  
  60. _Spline (i0, j0, i1, j1, i2, j2, i3, j3)
  61. int i0, j0, i1, j1, i2, j2, i3, j3;
  62. { float dt, t0, t1, t2, t3, t5, inc, dist, W;
  63.    int i, j, i5, j5, count;
  64.  
  65.    inc = 2.5;                /* Two pixel wide sampling rate */
  66.    W = 0.9;                /* Set the weighting factor. */
  67.    MoveTo(j1, i1);            /* Move to P1 */
  68.    dist = distance(i1, j1, i2, j2); /* The distance between the two points*/
  69.    if (inc < dist)
  70.    { j5 = j1-j0;
  71.      i5 = i1-i0;
  72.      j3 = j2-j3;
  73.      i3 = i2-i3;
  74.      dt = inc/dist;    /* Transform the sampling rate to a function of T */
  75.      count = 1.0/dt;    /* Number of samples to be taken in a unit interval */
  76.      while (count-- > 0)
  77.      { t1 = dt*count;         /* calculate I and J as a function of T */
  78.        t2 = 1.0 - t1;               /*  (1 - t)     */
  79.        t5 = W*t1*t1*t2;            /*  W*t*t*(1 - t)  */
  80.        t3 = W*t1*t2*t2;            /*  W*t*(1 - t)*(1 - t) */
  81.        j = j1*t1 + j2*t2 + t3*j3 + j5*t5;
  82.        i = i1*t1 + i2*t2 + t3*i3 + i5*t5;
  83.        LineTo(j, i);
  84.    } }
  85.    else LineTo(i2, j2);
  86. }
  87.  
  88.  
  89.  
  90.  
  91. [LISTING TWO]
  92.  
  93. ;; ----------------------------------------------------------------------
  94. ;; You need to change this to the directory where you have stored FF.fasl
  95. (load "Lauzzana:Ray:Projects:Artifex:LLIB:FF") 
  96.  
  97. ;; ----------------------------------------------------------------------
  98. ;; You need to change this to the directory where C libraries is stored
  99. (def-logical-pathname "CLIB;" "Lauzzana:Ray:Projects:Artifex:CLIB")
  100.  
  101. ;; ----------------------------------------------------------------------
  102. ;; The high-level SPLINE function
  103. (defun SPLINE (&rest p)
  104. "   
  105.    SPLINE (&rest point-list)
  106.  
  107.    Sets up the front window as a graphics port to draw in, and calls
  108.    DO-SPLINE to do the actual work of drawing a spline.
  109.  
  110. "
  111.   (with-port (ask (front-window) wptr) (do-spline p)))
  112.  
  113. (defun DO-SPLINE (p)
  114. "
  115.    D0-SPLINE (point-list)
  116.  
  117.    A smooth curve coonecting the points.
  118.  
  119. "
  120. (let ((p1 (car p)) 
  121.      (p2 (cadr p)) 
  122.      (p3 (caddr p))
  123.      (p4 (cadr (cddr p))) 
  124.      (p5 (cadr (cdddr p))))
  125.      (cond ((or (null (pointp p1)) (null (pointp p4))) nil)
  126.        ((and (pointp p1) (pointp p2) (pointp p3) (pointp p4))  
  127.           (_Spline (I-coord p1)
  128.               (J-coord p1)
  129.               (I-coord p2)
  130.               (J-coord p2)
  131.               (I-coord p3)
  132.               (J-coord p3)
  133.               (I-coord p4)
  134.               (J-coord p4))
  135.           (if (pointp p5)
  136.         (append (list 'SPLINE p1) (cdr (DO-SPLINE (cdr p))))
  137.         (cons 'SPLINE p))))))
  138.  
  139. ;; ----------------------------------------------------------------------
  140. ;; The high-level help functions for graphics
  141. ;; @@, representation for a point.
  142. (defun @@ (a &optional b)
  143. "
  144.   @@ () or (I-coordinate J-coordinate) or (integer)
  145.   A single user point or a point.
  146.  
  147.   A screen location, in physical coordinates. (@@ 0 0) is the upper-left
  148.   corner. If single integer is recieved it is interpretted as a packed point,
  149.   and it is unpacked into a coordinate pair.
  150.  
  151. "
  152.   (cond ((and (numberp a) (numberp b)) (list '@@ (round a) (round b)))
  153.      ((numberp a) (let ((i (floor (/ a 65536))))
  154.               (list '@@  i (- a (* 65536 i)))))))
  155.  
  156. ;; The type test for a POINT.
  157. (defun POINTP (p)
  158. "
  159.   POINTP (item)
  160.  
  161.   If the item is a point represented in in coordinates, ie. (@@ I J)
  162.   then TRUE, else NIL.
  163.  
  164. "
  165.   (and (listp p) 
  166.        (or (= 3 (length p)) (= 2 (length p))) (equal (car p) '@@)))
  167.  
  168. ;; I-COORDINATE
  169. (defun I-COORD (p)
  170. "
  171.     I-COORD (point)
  172.  
  173.     Returns the vertical screen coordinate of a point.
  174.  
  175. "
  176.     (if (pointp p) (cadr p)))
  177.  
  178. ;; J-COORDINATE
  179. (defun J-COORD (p)
  180. "
  181.     J-COORD (point)
  182.  
  183.     Returns the horizontal screen coordinate of a point.
  184.  
  185. "
  186.     (if (pointp p) (caddr p)))
  187. ;; ----------------------------------------------------------------------
  188. ;; The binding to the low-level SPLINE function
  189. ;; There are two methods to bind a C function to Allegro. 
  190. ;; The first method uses DEFFCFUN. Though this is a simpler function,
  191. ;; The binding will be lost if you build a stand-alone application.
  192. ;; Using DEFFCFUN the code would be:
  193. ;; (deffcfun (Mac_Spline "_Spline") 
  194. ;;  (integer integer integer integer integer integer integer integer) :novalue)
  195. ;; The second and preferred method uses MULTIPLE-VALUE-BIND and FF-CALL
  196. ;; to  bind a physical entry-point to a symbol. This is a hardware dependent
  197. ;; solution,  in that you need to represent the binding in terms of the
  198. ;; physical size and ordering of the machines stack. In the case of the
  199. ;; Mac II, parameters are stored in reverse order on the stack. Therefore,
  200. ;; the foreign function call  must reverse the order of the parameters.
  201. ;; MULTIPLE-VALUE-BIND is used to perform the mapping of parametes.
  202. ;; FF-LOOKUP-ENTRY find the physical address of the entry-point for function.
  203. ;; FF-CALL executes the coda stored at a physical address.
  204.  
  205. (defun _Spline (a b c d e f g h)
  206. "
  207.    _Spline (i0 j0 i1 j1 i2 j2 i3 j3)
  208.  
  209.    Draws a spline between p1 and p2 to the control points p0 and p3.
  210. "
  211.   (multiple-value-bind (entry a5) (ff-lookup-entry "_Spline")
  212.       (ff-call entry
  213.     :a5 a5 :long h :long g :long f :long e :long d :long c :long b :long a 
  214.     :novalue)))
  215.  
  216. ;; ----------------------------------------------------------------------
  217. ;; The loading the low-level SPLINE function
  218. ;; FF-LOAD is used to load binary files and their associated libraries.
  219. ;; In this case the object module for the function _Spline is stored in
  220. ;; the file <spline.c.o>. FF-LOAD searches this file for the symbolic name
  221. ;; _Spline and load the binary code associated with it.
  222. ;; In addition, it searches the libraries for unsatisfied symbolic references
  223. ;; which which may have occurred within the code and loads them as well.
  224. ;; In otherwords, it links and loads.
  225. ;; You need to change this to the directory where you have stored your C spline
  226.  
  227. (ff-load "Lauzzana:Ray:Papers:Spline:spline.c.o"
  228.      :entry-names 
  229.      (list "_Spline" )
  230.      :libraries
  231.      (list "CLIB;StdCLib.o" "CLIB;CRuntime.o" "CLIB;CInterface.o"
  232.            "CLIB;math.o" "CLIB;CSANElib.o"))
  233.  
  234.  
  235.  
  236. [Example 1: Cubic equations] 
  237.  
  238. j = j1t + j2(1 - t) + W(j2 - j3)(1 - t)2t + W(j1 - j0)(1 - t)t2
  239. i = i1t + i2(1 - t) + W(i2 - i3)(1 - t)2t + W(i1 - i0)(1 - t)t2
  240.  
  241.  
  242. [Example 2: Calculating coordinates]
  243.  
  244. while (t < 1)
  245. { j = j1*t  + j2*(1 - t)  + W*(j2-j3)*t*(1 - t)*(1 - t)  + W*(j1-j0)*t*t*(1 - t);
  246.    i = i1*t  + i2*(1 - t)  + W*(i2-i3)*t*(1 - t)*(1 - t)  + W*(i1-i0)*t*t*(1 - t);
  247.   t = t + dt;
  248.   LineTo(i,j);
  249. }
  250.  
  251.  
  252. [Example 3: Partitioning the equation shown in Example 2.]
  253.  
  254.  
  255. while (t1 <  1)
  256. { t1 = t1 + dt; 
  257.    t2 = 1.0 - t1;
  258.    t5 = W*t1*t1*t2;
  259.    t3 = W*t1*t2*t2;
  260.     j = j1*t1 + j2*t2 + t3*j3 + j5*t5;
  261.     i = i1*t1 + i2*t2 + t3*i3 + i5*t5;
  262.     LineTo(j, i);
  263.  
  264.  
  265. [Example 4: Loading the C routine]
  266.  
  267. (a)
  268.  
  269. (require 'FF)
  270.  
  271. (b)
  272.  
  273. (load "<pathname>:FF.fasl")
  274.  
  275. (c)
  276.  
  277. (def-logical-pathname "CLIB;"  "<pathname>:MPW:CLibrary")
  278.  
  279. (d)
  280.  
  281. (ff-load "<pathname>:spline.c.o"
  282.          :entry-names
  283.          (list "_Spline" )
  284.          :libraries
  285.          (list "CLIB;StdCLib.o" "CLIB;CRuntime.o" "CLIB;CInterface.o"
  286.                  "CLIB;math.o" "CLIB;CSANElib.o"))
  287.  
  288.  
  289. [Example 5: Binding C to Lisp]
  290.  
  291. (a)
  292.  
  293. (deffcfun (Mac_Spline "_Spline")
  294.  (integer integer integer integer integer integer integer integer) :novalue)
  295.  
  296. (b)  
  297.  
  298. (defun Mac_Spline (a b c d e f g h)
  299.  (multiple-value-bind (entry a5) (ff-lookup-entry "_Spline")
  300.       (ff-call entry
  301.        :a5 a5 :long h :long g :long f :long e :long d :long c :long b :long a :novalue)))
  302.  
  303.  
  304. (c)
  305.  
  306. (Mac_Spline  3  4 120  140  300  260 490 600)
  307.  
  308.  
  309.