From: Alex Kost <alezost@gmail.com>
To: Matthew Keeter <matt.j.keeter@gmail.com>
Cc: guile-user@gnu.org
Subject: Re: Solid modeling in Guile
Date: Fri, 19 Aug 2016 12:29:46 +0300 [thread overview]
Message-ID: <87tweh3y45.fsf@gmail.com> (raw)
In-Reply-To: <AD3A0E6E-85CD-4E2B-8F5B-8782F6A26629@gmail.com> (Matthew Keeter's message of "Thu, 18 Aug 2016 17:44:46 -0400")
Matthew Keeter (2016-08-19 00:44 +0300) wrote:
> Hi Guile-folks,
>
> I wrote a computer-aided design (CAD) tool that you may find interesting.
>
> It’s a solid modeling tool that uses Guile scripts to define objects (and
> constructive solid geometry + functional representations under the hood).
>
> Project page: http://www.mattkeeter.com/projects/ao/
> Source: https://github.com/mkeeter/ao
Wow, this looks very impressive, and you have so many great projects!
> I’d love feedback – Scheme is relatively new to me, so I’m sure there are
> more elegant ways to accomplish a lot of what the code implements.
You use ‘(- (inf))’ several times, it can be replaced with ‘-inf.0’.
From "bind/guile/ao/bind.scm":
--8<---------------cut here---------------start------------->8---
(define-module (ao bind))
(use-modules (srfi srfi-1))
(use-modules (ice-9 i18n))
(use-modules (system foreign))
--8<---------------cut here---------------end--------------->8---
Usually modules are defined like this:
--8<---------------cut here---------------start------------->8---
(define-module (ao bind)
#:use-modules (srfi srfi-1)
#:use-modules (ice-9 i18n)
#:use-modules (system foreign))
--8<---------------cut here---------------end--------------->8---
From "bind/guile/ao/bounds.scm":
--8<---------------cut here---------------start------------->8---
(define-public (bounds-intersection bs)
"bounds-intersection bs
bs should be a list of '((xmin ymin zmin) (xmax ymax zmax)) lists
Finds the intersection along each dimension
If bounds are disjoint, returns empty interval (0, 0)"
(let* ((lower (map car bs))
(upper (map cadr bs))
(xmin (apply max (map (lambda (b) (car b)) lower)))
(ymin (apply max (map (lambda (b) (cadr b)) lower)))
(zmin (apply max (map (lambda (b) (caddr b)) lower)))
(xmax (apply min (map (lambda (b) (car b)) upper)))
(ymax (apply min (map (lambda (b) (cadr b)) upper)))
(zmax (apply min (map (lambda (b) (caddr b)) upper))))
;; Clamp intervals to empty (0,0) if bounds are disjoint
(if (< xmax xmin) (begin (set! xmin 0) (set! xmax 0)))
(if (< ymax ymin) (begin (set! ymin 0) (set! ymax 0)))
(if (< zmax zmin) (begin (set! zmin 0) (set! zmax 0)))
(list (list xmin ymin zmin) (list xmax ymax zmax))))
--8<---------------cut here---------------end--------------->8---
All these cadr, caddr are hard to understand. I would rather make some
level of abstraction for coordinates and bounds. (if I understand it
right) the simplest would be:
--8<---------------cut here---------------start------------->8---
(define make-coordinates list)
(define x first)
(define y second)
(define z third)
(define make-bound cons) ; bound of lower and upper coordinates
(define lower-coordinates car)
(define upper-coordinates cdr)
(define (extremum min-or-max coordinate coordinates)
"Return minimal or maximal coordinate from COORDINATES.
MIN-OR-MAX is 'min' or 'max' procedure.
COORDINATE is either 'x', 'y' or 'z' procedure."
(apply min-or-max (map coordinate coordinates)))
--8<---------------cut here---------------end--------------->8---
And now this 'bounds-intersection' can be written like this:
--8<---------------cut here---------------start------------->8---
(define-public (bounds-intersection bounds)
"Finds the intersection along each dimension of BOUNDS.
If bounds are disjoint, returns empty interval (0, 0)."
(let* ((lower (map lower-coordinates bounds))
(upper (map upper-coordinates bounds))
(xmin (extremum max x lower))
(ymin (extremum max y lower))
(zmin (extremum max z lower))
(xmax (extremum min x upper))
(ymax (extremum min y upper))
(zmax (extremum min z upper)))
;; Clamp intervals to empty (0,0) if bounds are disjoint
(when (< xmax xmin) (set! xmin 0) (set! xmax 0))
(when (< ymax ymin) (set! ymin 0) (set! ymax 0))
(when (< zmax zmin) (set! zmin 0) (set! zmax 0))
(make-bound (make-coordinates xmin ymin zmin)
(make-coordinates xmax ymax zmax))))
--8<---------------cut here---------------end--------------->8---
Actually using 'set!' for local variables is not considered a good
style, but, well, who cares :-)
Note that those 'first', 'second', 'third' procedures come from (srfi
srfi-1) module.
I'm not an expert, so do not consider this is the best (or even a good)
way. I just wanted to point that instead of using lists, cars and cdrs
directly, it is better to have some higher-level procedures.
BTW, the indentation in .scm files is *very* unusual :-)
--
Alex
next prev parent reply other threads:[~2016-08-19 9:29 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-18 21:44 Solid modeling in Guile Matthew Keeter
2016-08-19 1:26 ` dsmich
2016-08-19 7:37 ` Mark H Weaver
2016-09-22 17:40 ` Mark H Weaver
2016-09-22 17:42 ` Matthew Keeter
2016-08-19 9:29 ` Alex Kost [this message]
2016-08-25 16:08 ` Thien-Thi Nguyen
2016-08-19 17:05 ` Thompson, David
2016-08-20 13:23 ` Ralf Mattes
2016-08-20 14:26 ` Matthew Keeter
2016-08-21 11:54 ` Ralf Mattes
2016-08-21 12:00 ` Ralf Mattes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87tweh3y45.fsf@gmail.com \
--to=alezost@gmail.com \
--cc=guile-user@gnu.org \
--cc=matt.j.keeter@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).