skill.geometry.Points_generateHeartCurve

Last-modified: 2012-10-09 (火) 21:32:14
; -----------------------------------------------------------------------------
; (Points_generateHeartCurve boundaryRect [b])
; -----------------------------------------------------------------------------
; ハート型の点列を生成する汎用の関数。点列を順になぞると一筆書きのハート形状になる。
;   boundaryRect : 描画するハートが外接する四角形の座標(対向する二つの頂点のリスト)
;   b : ハートの形状を微調整するパラメーター。省略可能。規定値は 1.0。
;
; 《例》 (0.0, 0.0) - (20.0, 15.0) の矩形領域に外接するハート形状の点を生成する。
;
;   (Points_generateHeartCurve '((0.0 0.0) (20.0 15.0)))
;
; -----------------------------------------------------------------------------
; ※ 参考資料: http://www16.ocn.ne.jp/~akiko-y/heart/index_heart.html
; -----------------------------------------------------------------------------
(define (Points_generateHeartCurve boundaryRect @optional (b 1.0))
  (letseq
    (
    (heartCurve
      (let
        ((buffer nil) (pi (acos -1.0)) (theta 0))
        (while (lessp theta 360)
          (letseq
            (
            (x (cos (times pi (quotient theta 180.0))))
            (yb (times b (sqrt (abs x))))
            (ya (sqrt (difference 1.0 (times x x))))
            (y (if (lessp theta 180) (plus yb ya) (difference yb ya)))
            )
            (setq buffer (cons (list x y) buffer))
          )
          (setq theta (plus theta 5))
        )
        buffer
      )
    )
    (heartCurve_ys (mapcar 'cadr heartCurve))
    (heartCurve_ymin (apply 'min heartCurve_ys))
    (heartCurve_ymax (apply 'max heartCurve_ys))
    (heartCurve_yc (quotient (plus       heartCurve_ymax heartCurve_ymin) 2.0))
    (heartCurve_hH (quotient (difference heartCurve_ymax heartCurve_ymin) 2.0))
    (unitHeartCurve
      (mapcar
        (lambda (point)
          (list
            (car point)
            (quotient (difference (cadr point) heartCurve_yc) heartCurve_hH)
          )
        )
        heartCurve
      )
    )
    (xs (mapcar 'car  boundaryRect)) (width  (abs (apply 'difference xs))) (xmin (apply 'min xs))
    (ys (mapcar 'cadr boundaryRect)) (height (abs (apply 'difference ys))) (ymin (apply 'min ys))
    )
    (mapcar
      (lambda (point)
        (list
          (plus xmin (times (plus (car  point) 1.0) 0.5 width ))
          (plus ymin (times (plus (cadr point) 1.0) 0.5 height))
        )
      )
      unitHeartCurve
    )
  )
)