Page 1 of 1

eLOGO plugin ...

PostPosted: Thu Mar 06, 2014 10:23 pm
by Pixel_Outlaw
So I'm making a little LOGO system again, this time in elisp.

Ideally you could even have source code that spits out diagrams for more visual parts of a program by embedding small elisp snippets.
Or perhaps you could use it to create elisp games that need a more visual presentation. (I know there is a way to have it read SVG files after exporting them :) )

I just think it is kind of an *ah ha!* moment to have source code that generates some pictorial documentation when you run a program.
This is useful when you are working with things easily described with pictures.

I've still got to write a function to export .SVG but I've worked with the format before and it is simple to write a small subset.

Please feel free to hack and help if anyone wants.

Re: eLOGO plugin ...

PostPosted: Sat Mar 08, 2014 2:43 pm
by Pixel_Outlaw
Did some more work on this...

Code: Select all
;;;; Author: Ryan Burnside
;;;; Date: 2014-03-06
;;;; Released under GPL v4

;;; This is the beginning of a LOGO like module to draw vector shapes
;;; Historically the cursor is called a "turtle"
;;; It has a small set of commands to draw primative line graphics

;;; Global variables for turtle maintenance

(defvar *canvas-width* 500)
(defvar *canvas-height* 500)
(defvar *x-pos* (/ *canvas-width* 2.0))
(defvar *y-pos* (/ *canvas-height* 2.0))
(defvar *previous-x-pos* *x-pos*)
(defvar *previous-y-pos* *y-pos*)

(defvar *direction* 0)
(defvar *step* 0)
(defvar *is-drawing* t)
(defvar *color* '(0 0 0))
(defvar *line-list* '()) ; Elements are (x y x2 y2 '(R G B))

;;; Turtle manipulation commands
(defun move ()
  "Move at the current angle and step size, save line to list if *is-drawing*"
  (if *is-drawing*
   (setf *line-list*
     (cons (list *previous-x-pos* *previous-y-pos* *x-pos* *y-pos* *color*)
  (setf *previous-x-pos* *x-pos*)
  (setf *previous-y-pos* *y-pos*))

(defun rt (dir)
  "Turn the turtle right in degrees"
  (incf *direction* dir))

(defun lt (dir)
  "Turn the turtle left in degrees"
  (decf *direction* dir))

(defun fd (length)
  "Move forward in pixels at current heading"
  (setf *step* length)
  (setf *x-pos* (+ *x-pos* (* (cos (degrees-to-radians *direction*)) *step*)))
  (setf *y-pos* (+ *y-pos* (* (sin (degrees-to-radians *direction*)) *step*)))

(defun bk (length)
  "Turn 180 degrees and move backward from current heading"
  (setf *step* length)
  (incf *direction* 180)
  (setf *x-pos* (+ *x-pos* (* (cos (degrees-to-radians *direction*)) *step*)))
  (setf *y-pos* (+ *y-pos* (* (sin (degrees-to-radians *direction*)) *step*)))

(defun jump (x y)
  "Make the turtle jump to a new position"
  (setf *x-pos* x)
  (setf *y-pos* y)

(defun lk (direction)
  "Make the turtle look in a direction"
  (setf *direction* direction))

(defun set-pen-color (red green blue)
  "Set the RGB triplet for the turtle's line color"
  (setf *color* (list red green blue)))

(defun tail-up ()
  "Don't draw following step commands"
  (setf *is-drawing* nil))

(defun tail-down ()
  "Start drawing following step commands"
  (setf *is-drawing* t))

(defun clear-drawing ()
  "Reset the global line list"
  (setf *line-list* '())
  (setf *x-pos* (/ *canvas-width* 2.0))
  (setf *y-pos* (/ *canvas-height* 2.0))
  (setf *previous-x-pos* *x-pos*)
  (setf *previous-y-pos* *y-pos*)
  (setf *direction* 0)
  (setf *step* 0)
  (setf *is-drawing* t)
  (setf *color* '(0 0 0)))

;;; We'll need to impliment a very small subset of SVG file writing below

(defun SVG-string-line (list-line)
  "This converts our line from a list to the SVG syntax analog"
  (let ((x1 (car list-line))
    (y1 (cadr list-line))
    (x2 (nth 2 list-line))
    (y2 (nth 3 list-line))
    (r (number-to-string (floor (car (nth 4 list-line)))))
    (g (number-to-string (floor (cadr (nth 4 list-line)))))
    (b (number-to-string (floor (nth 2 (nth 4 list-line))))))
     "<line x1=\"%3f\" y1=\"%3f\" x2=\"%3f\" y2=\"%3f\" style=\"stroke:rgb(%s,%s,%s)\"/>" 
     x1 y1 x2 y2 r g b)))

(defun write-SVG_buffer ()
  "This writes the complete SVG file to a buffer you can save it on your own"
  (switch-to-buffer (get-buffer-create "*SVG-out*"))
  (set-buffer "*SVG-out*")
  (insert-string "<svg height=\"500\" width=\"500\">")
  (dotimes (i (length *line-list*))
    (insert-string (SVG-string-line (nth i *line-list*))))
  (insert-string "</svg>"))

;; Test here little housey
  (progn  ;; roof
    (set-pen-color 255 0 0)
    (dotimes (i 3)
      (fd 100)
      (lt 120))
    (lk 90)
  (progn ;; base
    (set-pen-color 255 255 255)
    (dotimes (i 3)
      (fd 100)
      (lt 90)))