Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
;; esvg-xy.el. -*- lexical-binding: nil; -*-
;; This file:
;;    https://anggtwu.net/elisp/esvg-xy.el.html
;;    https://anggtwu.net/elisp/esvg-xy.el
;;            (find-angg "elisp/esvg-xy.el")
;;                  (find-esvg "esvg-xy.el")
;;     See: https://anggtwu.net/2026-eepitch-svg.html
;;  Author: Eduardo Ochs <eduardoochs@gmail.com>
;; Version: 2026aug24
;;
;; The _basic_ part of esvg consists of these four files,
;;   (find-esvg "esvg-append.el")
;;   (find-esvg "esvg-show.el")
;;   (find-esvg "esvg-eepitch.el")
;;   (find-esvg "esvg-build.el")
;; and this fifth file with demos:
;;   (find-esvg "esvg-demos.el")
;;
;; This file contains an experimental extension of esvg that I am
;; using to draw figures in the (x,y) plane on top a grid with axes
;; and ticks. See:
;;
;;   https://anggtwu.net/2026-eepitch-svg.html#pict2e
;;
;; This file contains some definitions AND its demos (in tests blocks).
;; It is "experimental" in the sense that I am probably still going to
;; rewrite it completely several times.
;;
;; Index:
;; «.S-B-G-A-T»			(to "S-B-G-A-T")
;;   «.esvg-xy-svg»		(to "esvg-xy-svg")
;;   «.esvg-xy-rect»		(to "esvg-xy-rect")
;;   «.esvg-xy-grid»		(to "esvg-xy-grid")
;;   «.esvg-xy-axes»		(to "esvg-xy-axes")
;;   «.esvg-xy-ticks»		(to "esvg-xy-ticks")
;;   «.S-B-G-A-T-test»		(to "S-B-G-A-T-test")
;; «.SBGAT-nod»			(to "SBGAT-nod")
;;   «.esvg-xy-sbgat-nod»	(to "esvg-xy-sbgat-nod")
;;   «.esvg-xy-sbgat-nod-test»	(to "esvg-xy-sbgat-nod-test")
;; «.SBGAT»			(to "SBGAT")
;;   «.esvg-xy-sbgat»		(to "esvg-xy-sbgat")
;;   «.SBGAT-test-1»		(to "SBGAT-test-1")
;;   «.esvg-xy-sbgat-test-1»	(to "esvg-xy-sbgat-test-1")
;;   «.esvg-xy-sbgat-test»	(to "esvg-xy-sbgat-test")
;;   «.esvg-xy-circles»		(to "esvg-xy-circles")
;;   «.esvg-xy-dots»		(to "esvg-xy-dots")
;;   «.SBGAT-test-2»		(to "SBGAT-test-2")
;; «.tricks-with-g-test-1»	(to "tricks-with-g-test-1")
;; «.tricks-with-g-test-2»	(to "tricks-with-g-test-2")
;; «.comprehension-test-1»	(to "comprehension-test-1")



(require 'esvg-show)		; (find-esvg "esvg-show.el")
(require 'esvg-eepitch)		; (find-esvg "esvg-eepitch.el")
(require 'esvg-append)		; (find-esvg "esvg-append.el")
(require 'esvg-build)		; (find-esvg "esvg-build.el")



;;;  ____    ____     ____      _      _____ 
;;; / ___|  | __ )   / ___|    / \    |_   _|
;;; \___ \  |  _ \  | |  _    / _ \     | |  
;;;  ___) | | |_) | | |_| |  / ___ \    | |  
;;; |____/  |____/   \____| /_/   \_\   |_|  
;;;                                          
;; «S-B-G-A-T»  (to ".S-B-G-A-T")
;; In this section we define five low-level functions that create:
;;   1. an `S'VG with a viewbox
;;   2. its white `B'ackground, using a white rectangle
;;   3. its `G'rid,
;;   4. its `A'xes,
;;   5. its `T'icks,


;; «esvg-xy-svg»  (to ".esvg-xy-svg")
;; Some tests (hint: use `M-2 M-e'):
;; (find-epp (esvg-xy-svg  0 0  4 3   0    400 300))
;; (find-epp (esvg-xy-svg  0 0  4 3   0    nil 300))
;; (find-epp (esvg-xy-svg  0 0  4 3   0    400 nil))
;; (find-epp (esvg-xy-svg  0 0  4 3   0.1  400 nil))
;; (find-epp (esvg-xy-svg  0 0  4 3   0.1  400 nil :fill "none"))
(defun esvg-xy-svg (x0 y0 x1 y1 e width height &rest rest)
  "This is a wrapper around `svg-create' that returns an SVG with a viewBox.
It supposes that (x0,y0) are the coordinates of the lower left corner of
a viewBox, that (x1,y1) are the coordinates of its upper right corner,
and that E is an amount of extra space that needs to be added above,
below, and left and right of that box, yielding a new viewbox whose
extremities are (x0-e,y0-e) and (x1+e,y1+e). This function creates an
SVG object whose dimensions in pixels are WIDTH and HEIGHT, and whose
viewBox has extremities (x0-e,y0-e) and (x1+e,y1+e).

This function uses uses transform=\"scale(1,-1) translate(0,-<height>)\"
to make the y coordinate grow upwards. If WIDTH is nil it is calculated
from HEIGHT in the natural way; if HEIGHT is nil it is calculated from
WIDTH in the natural way."
  (let* ((x0e (- x0 e))
         (y0e (- y0 e))
         (x1e (+ x1 e))
         (y1e (+ y1 e))
	 (w   (- x1e x0e))
	 (h   (- y1e y0e))
	 (w/h (/ w 1.0 h))
	 (h/w (/ h 1.0 w)))
    (if (not width)  (setq width  (* height w/h)))
    (if (not height) (setq height (* width  h/w)))
    (let* ((transform (format "scale(1,-1) translate(0,%S)" (- height)))
	   (viewbox   (format "%S %S %S %S" x0e y0e w h)))
      (apply 'svg-create width height
	     :transform transform :viewBox viewbox rest))))

;; «esvg-xy-rect»  (to ".esvg-xy-rect")
;; Test: (find-epp (esvg-xy-axes 0 0 4 3 0.1 :stroke "black"))
(defun esvg-xy-rect (x0 y0 x1 y1 e &rest rest)
  (let* ((x0e (- x0 e))
         (y0e (- y0 e))
         (x1e (+ x1 e))
         (y1e (+ y1 e)))
    (apply 'esvg-rectangle x0e y0e (- x1e x0e) (- y1e y0e) rest)))

;; «esvg-xy-grid»  (to ".esvg-xy-grid")
;; Test: (find-epp (esvg-xy-grid 0 0 4 3 0.1 :stroke "gray"))
(defun esvg-xy-grid (x0 y0 x1 y1 e &rest rest)
  (cl-letf* ((svg-a (apply 'esvg-g rest))
	     ((symbol-function 'f) (lambda (o) (esvg-append svg-a o))))
    (cl-loop for x from x0 to x1
	     do (f (esvg-line x (- y0 e)  x (+ y1 e)))) ; vertical line on x
    (cl-loop for y from y0 to y1
	     do (f (esvg-line (- x0 e) y  (+ x1 e) y))) ; horizontal line on y
    svg-a))

;; «esvg-xy-axes»  (to ".esvg-xy-axes")
;; Test: (find-epp (esvg-xy-axes 0 0 4 3 0.1 :stroke "black"))
(defun esvg-xy-axes (x0 y0 x1 y1 e &rest rest)
  (cl-letf* ((svg-a (apply 'esvg-g rest))
	     ((symbol-function 'f) (lambda (o) (esvg-append svg-a o))))
    (f (esvg-line (- x0 e) 0  (+ x1 e) 0)) ; x axis
    (f (esvg-line 0 (- y0 e)  0 (+ y1 e))) ; y axis
    svg-a))

;; «esvg-xy-ticks»  (to ".esvg-xy-ticks")
;; Test: (find-epp (esvg-xy-ticks 0 0 4 3 0.1 :stroke "black"))
(defun esvg-xy-ticks (x0 y0 x1 y1 e &rest rest)
  (cl-letf* ((svg-a (apply 'esvg-g rest))
	     ((symbol-function 'f) (lambda (o) (esvg-append svg-a o))))
    (cl-loop for x from x0 to x1
	     do (f (esvg-line x (- e)  x e))) ; vertical tick on x
    (cl-loop for y from y0 to y1
	     do (f (esvg-line (- e) y  e y))) ; horizontal tick on y
    svg-a))


;; «S-B-G-A-T-test»  (to ".S-B-G-A-T-test")
;; In this demo we draw, in separate steps:
;;   1. an `S'VG with a viewbox
;;   2. its white `B'ackground, using a white rectangle
;;   3. its `G'rid,
;;   4. its `A'xes,
;;   5. its `T'icks,
;;   6. a polyline.
;; It the next section we will define a function that creates a SBGAT.
;;
'("This is a test block for `eepitch-svg'! Use <f9>s!"

* (load-esvg)  ; (find-angg ".emacs" "load-esvg")
  (defun f (o) (esvg-append svg-a o) (show-svg-pp))
  (defun f (o) (esvg-append svg-a o) (show-svg))
  (setq svg (esvg-xy-svg  0 0  5 4  0.5  nil 350  :fill "none" :stroke-width 0.1))
  (setq svg-a svg)
  (show-svg)
  (f (esvg-xy-rect  0 0  5 4  0.5   :fill "white"  :stroke "none"))
  (f (esvg-xy-grid  0 0  5 4  0.15  :stroke "#cccccc" :stroke-width 0.015))
  (f (esvg-xy-axes  0 0  5 4  0.25  :stroke "black"   :stroke-width 0.05))
  (f (esvg-xy-ticks 0 0  5 4  0.15  :stroke "black"   :stroke-width 0.02))
  (f (esvg-polyline "1 1  2 1  3 2  4 2"  :stroke "red"))

"--")



;;;  ____  ____   ____    _  _____    __                 ___  
;;; / ___|| __ ) / ___|  / \|_   _|  / / __   ___     __| \ \ 
;;; \___ \|  _ \| |  _  / _ \ | |   | | '_ \ / _ \   / _` || |
;;;  ___) | |_) | |_| |/ ___ \| |   | | | | | (_) | | (_| || |
;;; |____/|____/ \____/_/   \_\_|   | |_| |_|\___/   \__,_|| |
;;;                                  \_\                  /_/ 
;;
;; «SBGAT-nod»  (to ".SBGAT-nod")
;; «esvg-xy-sbgat-nod»  (to ".esvg-xy-sbgat-nod")
;; This is a low-level way to create a SBGAT ("with no defaults").
;; The `S', `B', `G', `A', and `T' parts all use the same values for
;; the coordinates (x0,y0) and (x1,y1) of the "inner viewBox"; the `S'
;; and `B' parts use the same `e'xtra space; the `width' and `height'
;; in pixels are only used by the `S' part...
;; A test:
;;
;;   (setq o (esvg-xy-sbgat-nod 0 0 4 3  0 40 30 '() '() '(0) '(0) '(0)))
;;   (find-2a nil '(find-epp o))
;;
(defun esvg-xy-sbgat-nod (x0 y0 x1 y1   e width height
	                     opts-svg
	                     opts-background
	                     opts-grid
	                     opts-axes
	                     opts-ticks)
  "`S'vg with viewBox + `B'ackround + `G'rid + `A'xes + `T'icks.
This is the version with `NO' `D'efaults."
  (let* ((svg   (apply 'esvg-xy-svg    x0 y0 x1 y1  e width height  opts-svg))
	 (bg    (apply 'esvg-xy-rect   x0 y0 x1 y1  e   opts-background))
	 (grid  (apply 'esvg-xy-grid   x0 y0 x1 y1      opts-grid))
	 (axes  (apply 'esvg-xy-axes   x0 y0 x1 y1      opts-axes))
	 (ticks (apply 'esvg-xy-ticks  x0 y0 x1 y1      opts-ticks)))
    (esvg-append svg bg)
    (esvg-append svg grid)
    (esvg-append svg axes)
    (esvg-append svg ticks)
    svg))

;; «esvg-xy-sbgat-nod-test»  (to ".esvg-xy-sbgat-nod-test")
'("This is a test block for `eepitch-svg'! Use <f9>s!"

* (load-esvg)  ; (find-angg ".emacs" "load-esvg")
  (defun f (o) (esvg-append svg-a o) (show-svg))
  (setq svg (esvg-xy-sbgat-nod
	     0 0 5 4   0.5   nil 300
	     '(:fill "none" :stroke-width 0.1) ; for `esvg-xy-svg'
	     '(:fill "white" :stroke "none")   ; for the background
	     '(0.15 :stroke "#cccccc" :stroke-width 0.015)  ; for the grid
	     '(0.25 :stroke "black"   :stroke-width 0.05)   ; for the axes
	     '(0.15 :stroke "black"   :stroke-width 0.02))) ; for the ticks
  (setq svg-a svg)
  (show-svg)
  (f (esvg-polyline "1 1  2 1  3 2  4 2"  :stroke "red"))

"--")



;;;  ____  ____   ____    _  _____ 
;;; / ___|| __ ) / ___|  / \|_   _|
;;; \___ \|  _ \| |  _  / _ \ | |  
;;;  ___) | |_) | |_| |/ ___ \| |  
;;; |____/|____/ \____/_/   \_\_|  
;;;                                
;; «SBGAT»          (to ".SBGAT")
;; «esvg-xy-sbgat»  (to ".esvg-xy-sbgat")
;; Like `esvg-xy-sbgat-nod', but with good defaults.
;;
(defun esvg-xy-sbgat (x0 y0 x1 y1       width height  &rest rest)
  (esvg-xy-sbgat-nod  x0 y0 x1 y1  0.5  width height
                      `(:fill "none"  :stroke-width 0.1 ,@rest) ; SVG
                      '(:fill "white" :stroke "none")           ; background
                      '(0.10  :stroke "#cccccc" :stroke-width 0.015)  ; grid
                      '(0.25  :stroke "black"   :stroke-width 0.05)   ; axes
                      '(0.10  :stroke "black"   :stroke-width 0.03)   ; ticks
                      ))

(defalias 'esvg-sbgat 'esvg-xy-sbgat)


;; «SBGAT-test-1»  (to ".SBGAT-test-1")
;; See: https://svgwg.org/svg2-draft/paths.html#PathData
;;      https://svgwg.org/svg2-draft/paths.html#PathDataCubicBezierCommands
;;
'("This is a test block for `eepitch-svg'! Use <f9>s!"

* (load-esvg)  ; (find-angg ".emacs" "load-esvg")
  (defun d (&rest r) (show-svg))                ; display
  (defun st  (o)     (setq svg   o))            ; set top-level svg
  (defun sa  (o)     (setq svg-a o))            ; set where appends happen
  (defun sta (o)     (setq svg o svg-a o))      ; set top-level and append
  (defun ad  (o)     (d (esvg-append svg-a o))) ; append and display

  (d (sta (esvg-xy-sbgat  0 0  5 4   nil 500)))
  (ad (esvg-polyline "1 1  2 1  3 2  4 2"  :stroke "red"))
  (ad (esvg-path "M 1 3  C 2 3  2 1  3 1"  :stroke "orange"))

"--")


;; «esvg-xy-circles»  (to ".esvg-xy-circles")
;;   See: https://anggtwu.net/2026-eepitch-svg.html#pict2e
;;        https://anggtwu.net/IMAGES/2026-eepitch-svg-xy-2.png
;; Tests: (find-epp (esvg-xy-circles '((0 1) (2 3) (4 5)) 9))
;;        (to "SBGAT-test-2")
(defun esvg-xy-circles (points radius &rest rest)
  (let ((colors '("red" "orange" "yellow" "green" "blue" "violet")))
    (cl-letf* ((svg-a (apply 'esvg-g rest))
	       ((symbol-function 'f) (lambda (o) (esvg-append svg-a o))))
      (cl-loop for (cx cy) in points
	       for i from 0
	       do (f (esvg-circle cx cy radius
				  :fill (nth i colors))))
      svg-a)))


;; «esvg-xy-dots»  (to ".esvg-xy-dots")
;; Based on: https://anggtwu.net/eev-maxima.html#set-comprehensions
;;           https://anggtwu.net/IMAGES/2025-maxima-set-comprehensions.png
;;    Tests: (find-epp (esvg-xy-dots '((0 1) (2 3) (4 5)) 0.6 :fill "blue"))
(defun esvg-xy-dots (points radius &rest rest)
  (cl-letf* ((svg-a (apply 'esvg-g rest))
	     ((symbol-function 'f) (lambda (o) (esvg-append svg-a o))))
    (cl-loop for (cx cy) in points
	     do (f (esvg-circle cx cy radius)))
    svg-a))



;; «SBGAT-test-2»  (to ".SBGAT-test-2")
'("This is a test block for `eepitch-svg'! Use <f9>s!"

* (load-esvg)  ; (find-angg ".emacs" "load-esvg")
  (defun d (&rest r) (show-svg))            ; display
  (defun st   (o)    (setq svg   o))        ; set top-level svg
  (defun sa   (o)    (setq svg-a o))        ; set where appends happen
  (defun sta  (o)    (setq svg o svg-a o))  ; set top-level and append
  (defun a    (o)    (esvg-append svg-a o)) ; append
  (defun ad   (o)    (a o) (d))             ; append and display
  (defun asad (o)    (a o) (sa o) (d))      ; append, set append, display

  ;; First drawing: two polylines, drawn with paths.
  ;; See: https://svgwg.org/svg2-draft/paths.html#PathData
  (d (sta (esvg-xy-sbgat  0 0  5 4   nil 500)))
  (asad (esvg-g :stroke "orange"))
  (ad (esvg-path "M 1 2  L 2 2  M 3 1  L 4 1")) ; use absolute movement
  (ad (esvg-path "M 1 1  l 1 0  l 1 1  l 1 0")) ; use relative movement

  ;; Second drawing: circles.
  (setq pts '((1 1) (1 2) (2 3) (3 3)))
  (d (sta (esvg-xy-sbgat  0 0  5 4   nil 500)))
  (ad (esvg-xy-circles pts 0.15 :stroke "none" :id "circles"))

  ;; Third drawing: a cubic bezier curve and its control points.
  ;; When we modify the control points everything changes.
  (defun p (n) (nth n pts))
  (defun drawp  () (ad (esvg-path `(M ,(p 0) C ,(p 1) ,(p 2) ,(p 3)) :id "p")))
  (defun drawcs () (ad (esvg-xy-circles pts 0.15 :stroke "none" :id "circles")))
  (defun spdraw (newpts) (setq pts newpts) (drawp) (drawcs))

  (d (sta (esvg-xy-sbgat  0 0  5 4   nil 500)))
  (asad (esvg-g :stroke "gray"))

  (spdraw '((1 1) (1 2)   (2 3)   (3 3)))
  (spdraw '((1 1) (1 2)   (2 3.5) (3 3)))
  (spdraw '((1 1) (1 2)   (2 3)   (3 3)))
  (spdraw '((1 1) (0.5 2) (2 3)   (3 3)))
  (spdraw '((1 1) (1 2)   (2 3)   (3 3)))

"--")


;; «tricks-with-g-test-1»  (to ".tricks-with-g-test-1")
;; In this test I draw some objects inside a named group, and then I
;; use `use' to draw copies of that group in other places of the plane.
;; Its "Second test" use several functions defined here:
;;   (find-esvg "esvg-build.el" "tricks-with-g")
;;
'("This is a test block for `eepitch-svg'! Use <f9>s!"

* (load-esvg)  ; (find-angg ".emacs" "load-esvg")
  (defun d (&rest r) (show-svg))            ; display
  (defun st   (o)    (setq svg   o))        ; set top-level svg
  (defun sa   (o)    (setq svg-a o))        ; set where appends happen
  (defun sta  (o)    (setq svg o svg-a o))  ; set top-level and append
  (defun a    (o)    (esvg-append svg-a o)) ; append
  (defun ad   (o)    (a o) (d))             ; append and display
  (defun asad (o)    (a o) (sa o) (d))      ; append, set append, display

  ;; First test, with low-level functions.
  ;; Here the object "grp1" is built by appending subobjects.
  ;;
  (d (sta (esvg-xy-sbgat  -1 -1  5 4   nil 500)))
  (asad (esvg-g :id "grp1"))
    (ad (esvg-rectangle 0 0 1 1  :fill "gray"))
    (ad (esvg-circle    0 0 0.25 :fill "red"))
    (ad (esvg-circle    1 0 0.25 :fill "orange"))
  (d (sa svg))

  (ad (esvg-circle      1 1 0.25 :fill "green")) ; this is outside grp1

  (ad (esvg-use "grp1" :id "use1" :x 2 :y 1))	 ; a shifted copy of grp1
  (ad (esvg-use "grp1" :id "use1" :x 3 :y 1))	 ; move it around
  (ad (esvg-use "grp1" :id "use1" :x 3 :y 2))
  (ad (esvg-use "grp1" :id "use1" :x 2 :y 2))
  (ad (esvg-use "grp1" :id "use1" :x 2 :y 1))

  ;; Second test.
  ;; Here the object "grp1" is built at once, and:
  ;;   :id "grp1"   -->   (esvg-id "grp1" ...)
  ;;   :id "use1"   -->   (esvg-id "use1" ...)
  ;;   :x 2 :y 1    -->   (esvg-translate 2 1 ...)
  ;;
  (d (sta (esvg-xy-sbgat  -1 -1  5 4   nil 500)))
  (ad (esvg-id "grp1"
	(esvg-rectangle 0 0 1 1  :fill "gray")
	(esvg-circle    0 0 0.25 :fill "red")
	(esvg-circle    1 0 0.25 :fill "orange")))

  (ad (esvg-circle      1 1 0.25 :fill "green"))   ; this is outside grp1

  (setq grp1 (esvg-use "grp1"))
  (ad (esvg-id "use1" (esvg-translate 2 1  grp1))) ; a shifted copy of grp1
  (ad (esvg-id "use1" (esvg-translate 3 1  grp1))) ; move it around
  (ad (esvg-id "use1" (esvg-translate 3 2  grp1)))
  (ad (esvg-id "use1" (esvg-translate 2 2  grp1)))
  (ad (esvg-id "use1" (esvg-translate 2 1  grp1)))

"--")



;; «tricks-with-g-test-2»  (to ".tricks-with-g-test-2")
;; Sometimes I need to define objects and then draw copies of them,
;; maybe applying different translations, scalings, rotations, etc, to
;; each copy. The most obvious way to do that is to use a `transform'
;; with several transformation functions in its argument, like this:
;;
;;   transform="scale(1,-1) translate(0,-400)"
;;
;; ...but I saw that my code becomes much simpler if I use nested
;; `g's and the "tricks with `g'" that are defined here:
;;
;;   (find-esvg "esvg-build.el" "tricks-with-g")
;;
;; Note that
;;
;;   (esvg-scale     1 1 ...)
;;   (esvg-translate 0 0 ...)
;;
;; are no-ops.
;;
'("This is a test block for `eepitch-svg'! Use <f9>s!"

* (load-esvg)  ; (find-angg ".emacs" "load-esvg")
  (defun d (&rest r) (show-svg))            ; display
  (defun st   (o)    (setq svg   o))        ; set top-level svg
  (defun sa   (o)    (setq svg-a o))        ; set where appends happen
  (defun sta  (o)    (setq svg o svg-a o))  ; set top-level and append
  (defun a    (o)    (esvg-append svg-a o)) ; append
  (defun ad   (o)    (a o) (d))             ; append and display
  (defun asad (o)    (a o) (sa o) (d))      ; append, set append, display

  (d (sta (esvg-xy-sbgat  -1 -1  5 4   nil 500)))
  (ad (esvg-defs
       (esvg-id "grp1"
	 (esvg-rectangle 0 0 1 1  :fill "gray")
	 (esvg-circle    0 0 0.25 :fill "red")
	 (esvg-circle    1 0 0.25 :fill "orange"))))
  (setq grp1 (esvg-use "grp1"))

  (ad (esvg-id "obj1" (esvg-scale 1  1   grp1)))
  (ad (esvg-id "obj1" (esvg-scale 1  0.5 grp1)))
  (ad (esvg-id "obj1" (esvg-scale 1 -0.5 grp1)))
  (ad (esvg-id "obj1" (esvg-scale 1 -1   grp1)))

  (ad (esvg-id "obj1"                                      grp1))
  (ad (esvg-id "obj1" (esvg-translate 1 0                  grp1)))
  (ad (esvg-id "obj1" (esvg-translate 1 0 (esvg-scale 1 -1 grp1))))
  (ad (esvg-id "obj1" (esvg-translate 1 1 (esvg-scale 1 -1 grp1))))
  (ad (esvg-id "obj1" (esvg-translate 0 1 (esvg-scale 1 -1 grp1))))
  (ad (esvg-id "obj1"                     (esvg-scale 1 -1 grp1)))
  (ad (esvg-id "obj1"                                      grp1))

"--")


;; «comprehension-test-1»  (to ".comprehension-test-1")
;; Based on: (find-myqdraw "myqdraw3.mac" "set-comprehensions")
;;     https://anggtwu.net/eev-maxima.html#set-comprehensions
;;
'("This is a test block for `eepitch-svg'! Use <f9>s!"

* (load-esvg)  ; (find-angg ".emacs" "load-esvg")
  (defun d (&rest r) (show-svg))            ; display
  (defun st   (o)    (setq svg   o))        ; set top-level svg
  (defun sa   (o)    (setq svg-a o))        ; set where appends happen
  (defun sta  (o)    (setq svg o svg-a o))  ; set top-level and append
  (defun a    (o)    (esvg-append svg-a o)) ; append
  (defun ad   (o)    (a o) (d))             ; append and display
  (defun asad (o)    (a o) (sa o) (d))      ; append, set append, display

  (d (sta (esvg-xy-sbgat  -4 -4  4 4   nil 550)))

  (defun dots-square (step)
    (cl-loop for y downfrom 4 to -4 by step
	     append (cl-loop for x from -4 to 4 by step
		     collect (list x y))))

  (defun dot-yes (x y) (>= y (* x x)))	    ; "inside" the parabola y=x^2

  (defun dots-yes (points)
    (cl-loop for (x y) in points
	     if (dot-yes x y)
	     collect (list x y)))

  (defun dots (step &optional radius)
    (setq radius (or radius (* step 0.375)))
    (esvg-xy-dots (dots-yes (dots-square step))
		  radius :id "dots" :fill "blue"))

  ;; Tests that return interesting things
  ;; but that don't draw anything
            (dots-square 8)
            (dots-square 4)
  (dots-yes (dots-square 4))
  (dots-yes (dots-square 2))
  (dots                  2)

  ;; Tests that draw dots inside a parabola
  (ad (dots 2))
  (ad (dots 1))
  (ad (dots 0.5))
  (ad (dots 0.25))
  (ad (dots 0.125))
  (ad (dots 0.25))
  (ad (dots 0.5))
  (ad (dots 1))
  (ad (dots 2))
  (ad (dots 4))

  (ad (dots 0.125))

"--")










(provide 'esvg-xy)



;; Local Variables:
;; coding:  utf-8-unix
;; End: