Paste number 71465: code to generate wedding logo

Paste number 71465: code to generate wedding logo
Pasted by: ryepup
When:1 year, 2 months ago
Share:Tweet this! | http://paste.lisp.org/+1J55
Channel:None
Paste contents:
Raw Source | XML | Display As
(require 'vecto)
(require 'cl-ppcre)

(defpackage #:wedding
  (:use #:cl #:vecto))

(in-package #:wedding)

(defvar *r* 400)
(defvar *gear-height* 5)

(defun draw-outer-heart ()
  "draw the heart outline, a square with 2 half-circles"
  (with-graphics-state
    (set-line-width 3)
    (move-to 0 0)
    (line-to 0 *r*)
    (arcn (/ *r* 2) *r* (/ *r* 2) pi 0)
    (arcn *r* (/ *r* 2) (/ *r* 2) (/ pi 2) (- (/ pi 2)))
    (line-to 0 0)
    (stroke)))

(defgeneric gear-internal (style radius)
  (:documentation "draws the internals of a gear, everything
inside the teeth")
  (:method ((style (eql :simple)) radius)
    "a simple solid gear with a hole in the middle"
    (centered-circle-path 0 0 radius)
    (fill-path)
    (centered-circle-path 0 0 (/ radius 5))
    (set-rgb-fill 1 1 1)
    (fill-path)))

(defun spoked-gear-internal (radius spokes)
  "draws internals with spokes"
  ;;outer ring
  (centered-circle-path 0 0 radius)
  (fill-path)
  ;;clear the way
  (with-graphics-state
    (set-rgb-fill 1 1 1)
    (centered-circle-path 0 0 (* 0.8 radius))
    (fill-path))
  (with-graphics-state
    (let ((spoke-width (* 0.1 (/ (* pi (* 2 radius))
				 spokes))))
    (dotimes (i spokes)
      (rectangle (- (/ spoke-width 2)) 0
		 spoke-width radius)
      (fill-path)
      (rotate (/ (* pi 2)
		 spokes)))))

  (centered-circle-path 0 0 (* 0.4 radius))
  (fill-path)
  (with-graphics-state
    (set-rgb-fill 1 1 1)
    (centered-circle-path 0 0 (* 0.2 radius))
    (fill-path))
  )

(defmethod gear-internal :around (style radius)
  (with-graphics-state
    (call-next-method)))

(defun gear (x y radius teeth rotation &optional (spokes (random 10)))
  "draw a gear"
  (with-graphics-state
    (let ((gw (/ (* pi (* 2 radius)) 2 teeth)))
      (translate x y)
      (rotate (* gw rotation))
      (with-graphics-state
	(dotimes (i teeth)
	  (rectangle (- (/ gw 2)) 0
		     gw radius)
	  (fill-path)
	  (rotate (/ (* 2 pi) teeth))))
      (let ((radius (- radius *gear-height*)))
	(format T "gear internal radius: ~a~%" radius)
	(if (< spokes 3)
	    (gear-internal :simple radius)
	    (spoked-gear-internal radius spokes)))

      (values radius gw))))

(defun save-logo (&key (filename "heart-logo.png")
		  (font-file "Lucida Handwriting Italic.ttf")
		  )
  "draw the logo, saving to filename and using font-file for text"
  (with-canvas (:width (* 2 *r*)
		       :height (truncate
				(* 2.25 *r*)))
    (set-rgb-fill 1 1 1)
    (clear-canvas)
    (set-rgb-fill 0 0 0)
    (set-rgb-stroke 0 0 0)
    (with-graphics-state
      (translate *r* (- *r* (* (sqrt 2) (/ *r* 2))))
      (rotate (/ pi 4))
      (draw-outer-heart)
      (let ((*r* (* .985 *r*)))
	(loop for (x y r teeth rotation) in '((.1 .1 .1 16 0)
					      (.2 .35 .19 30 .25)
					      (.4 .83 .35 50 .25)
					      (.3 1.29 .14 20 0)
					      (.51 1.39 .11 14 .5)
					      (.73 1.22 .18 28 0)
					      (.87 .99 .11 15 .2)
					      (1.1 .65 .32 40 0)
					      (1.275 .26 .125 17 .1)
					      (1.05 .15 .15 19 .1)
					      (.8 .13 .12 14 .05)
					      (.6 .31 .17 24 0)
					      (.4 .15 .11 16 .15))
	      do
	   (gear (* x *r*)
		 (* y *r*)
		 (* r *r*)
		 teeth
		 rotation))))
    (let* ((font-size 50)
	   (label-height (aref (string-bounding-box
				"g" font-size
				(get-font font-file))
			       3)))
      (set-font (get-font font-file) font-size)
            (draw-centered-string *r*
				  (+ *r*
				     (* (sqrt 2) (/ *r* 2))
				     (* 3 label-height))
			    "Davis-Fullen Wedding")
      (draw-centered-string *r* (- *r*
				   (* (sqrt 2) (/ *r* 2))
				   (* 2 label-height))
			    "New Year's Eve 2008"))
    (save-png filename)
    )
  )

(defun make-samples (&optional (n 20))
  "make a bunch to try and get a good random set"
  (dotimes (i n)
    (save-logo :filename (format nil "heart_~a.png" i))
    )
  )

(defun test-fonts ()
  "renders a logo in a variety of fonts so I can see what looks good."
  (let ((r (cl-ppcre:create-scanner "/")))
    (with-open-file (f "/home/ryan/clbuild/source/wedding/fonts.txt")
      (loop for fontfile = (read-line f nil nil)
	    while fontfile
	    do
	 (save-logo :font-file fontfile
	      :filename (format nil "/home/ryan/clbuild/source/wedding/~a.png"
				    (cl-ppcre:regex-replace-all
				     r fontfile ".")))))))

This paste has no annotations.

Colorize as:
Show Line Numbers

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.