[gsharp-cvs] CVS update: gsharp/drawing.lisp

Robert Strandh rstrandh at common-lisp.net
Wed Nov 30 05:52:48 UTC 2005


Update of /project/gsharp/cvsroot/gsharp
In directory common-lisp.net:/tmp/cvs-serv17460

Modified Files:
	drawing.lisp 
Log Message:
Added comments and documentation strings to explain a bit more about
the new spacing algorithm.

Date: Wed Nov 30 06:52:47 2005
Author: rstrandh

Index: gsharp/drawing.lisp
diff -u gsharp/drawing.lisp:1.39 gsharp/drawing.lisp:1.40
--- gsharp/drawing.lisp:1.39	Wed Nov 30 03:37:05 2005
+++ gsharp/drawing.lisp	Wed Nov 30 06:52:47 2005
@@ -96,6 +96,14 @@
 	  collect (/ (nat-width method (measure-coeff measure) min-dist)
 		     compress))))
 
+;;; Compute the elasticity of each timeline in each measure of the
+;;; measures of a system (line) by taking its duration to the power of
+;;; the spaceing style.  This metric is arbitrarily normalized to the
+;;; duration of a whole note, which means that the force to apply to a
+;;; line is not comparable between two different lines.  All we know
+;;; is that timelines with the same elasticity will grow and shrink in
+;;; parallel, and that proportions between two timelines of different
+;;; durations will be preserved. 
 (defun compute-elasticities (measures method)
   (loop for measure in measures
 	do (loop with timelines = (timelines measure)
@@ -104,8 +112,29 @@
 		 do (setf (elasticity timeline)
 			  (expt (duration timeline) (spacing-style method))))))
 
-(defgeneric left-bulge (element pane))
-(defgeneric right-bulge (element pane))
+;;; FIXME: there should be an :around method that adds the value
+;;; return by the main method to the explicit horizontal offset that
+;;; the user wants to impose on an element, and the existence of this 
+;;; around method should be documented.
+;;; FIXME: we should probably also allow for the user to introduce
+;;; explicit (positive or negative) bulges that will be added in by
+;;; the :around method, thus allowing the user to explicitly move two
+;;; adjacent elements further apart, or to bring them closer together. 
+(defgeneric left-bulge (element pane)
+  (:documentation "The amount by which an element sticks out to the
+left of the center of its timeline"))
+
+;;; FIXME: there should be an :around method that adds the value
+;;; return by the main method to the explicit horizontal offset that
+;;; the user wants to impose on an element, and the existence of this
+;;; around method should be documented.  
+;;; FIXME: we should probably also allow for the user to introduce
+;;; explicit (positive or negative) bulges that will be added in by
+;;; the :around method, thus allowing the user to explicitly move two
+;;; adjacent elements further apart, or to bring them closer together. 
+(defgeneric right-bulge (element pane)
+  (:documentation "The amount by which an element sticks out to the
+right of the center of its timeline"))
 
 (defmethod left-bulge ((element element) pane)
   (score-pane:staff-step 1))
@@ -121,6 +150,15 @@
   (+ (score-pane:staff-step 0.5)
      (/ (text-size pane (map 'string 'code-char (text element))) 2)))
 
+;;; As it turns out, the spacing algorithm would be very complicated
+;;; if we were to take into account exactly how elements with
+;;; arbitrarily many timelines between them might influence the
+;;; overall layout.  Instead we apprixmate by obtaining a closest gap
+;;; only between adjacent timelines as follows: first, we consider
+;;; adjacent elements whose timelines are also adjacent (and there is
+;;; a special case for the last element of a layer), and set the
+;;; smallest gap between the timelines to the closest possible
+;;; distance between the two elements...
 (defun compute-gaps-adjacent-timelines (bars method pane)
   (declare (ignore method))
   (loop for bar in bars
@@ -138,6 +176,27 @@
 				      (+ (right-bulge e1 pane)
 					 (left-bulge e2 pane)))))))))
 
+;;; ... Then we consider adjacent elements whose timelines are
+;;; separated by at least one other timeline.  If the sum of the
+;;; distances between individual timelines is greater than or equal to
+;;; the closest distance between the adjacent elements (which is
+;;; likely if we are talking melody), then there is nothing to do,
+;;; since the individual distances are more restrictive than that
+;;; imposed by the adjacent elements.  If not, we try to distribute
+;;; the closest distance between the two adjacent elements over the
+;;; individual timelines proportionally to the elasticity of the
+;;; timlines.  If in doing so, we find that some timeline already has
+;;; a smallest gap that is larger than the fraction of the closest
+;;; distance between adjacent elements that we attribute to it, then
+;;; that smallest gap is subtracted from the distance we need to
+;;; distribute, the timeline is removed from consideration, and we
+;;; start over.  This process must terminate (or else, the sum of the
+;;; closest gaps must have been larger than the distance to distribute
+;;; in the first place) with at least one timeline to distribute over.
+;;; There is a special case here, which occurs when all the
+;;; elasticites of the timelines to be considered is zero.  In this
+;;; case, instead of distributing proportionally to the elasticities
+;;; of individual timelies, we distribute evenly between the timelines.
 (defun compute-gaps-separated-timelines (bars method pane)
   (declare (ignore method))
   (flet ((handle-timelines (timelines element-gap)
@@ -198,6 +257,11 @@
 	;; whose corresponding timeline is not the last one in the meaure
 	do (compute-gaps-separated-timelines (measure-bars measure) method pane)))
 
+;;; When this function is called, each timeline has an elasticity and
+;;; a smallest gap to the next adjacent timline (or to the end of the
+;;; measure).  These values, together with an elasticity function at
+;;; the beginning of a measure, are used to compute the total
+;;; elasticity function of a measure.
 (defun compute-elasticity-functions (measures method)
   (loop for measure in measures
 	do (loop with result = (make-elementary-elasticity (min-width method) 0.0001)
@@ -272,8 +336,11 @@
 	   (compute-elasticities measures method)
 	   (compute-gaps measures method pane)
 	   (let* ((e-fun (compute-elasticity-functions measures method))
+		  ;; FIXME:  it would be much better to compress the system
+		  ;; proportionally, so that every smallest gap gets shrunk
+		  ;; by the same percentage
 		  (force (if (> (zero-force-size e-fun) (line-width method))
-			     0
+			     0 
 			     (force-at-size e-fun (line-width method)))))
 	     nil)
 	   (let ((widths (compute-widths measures method)))




More information about the Gsharp-cvs mailing list