cl-scopes/csys/space.lisp

71 lines
2 KiB
Common Lisp

;;;; cl-scopes/csys/space
;;;; definitions for (spatial) registering and retrieving objects by location
(defpackage :scopes/csys/space
(:use :common-lisp)
(:local-nicknames (:alx :alexandria)
(:util :scopes/util))
(:export #:create #:put #:del #:fetch #:query
#:neighbors #:free-loc-at #:distance-sq
#:loc-iterator))
(in-package :scopes/csys/space)
(defun create ()
(make-hash-table :test #'equalp))
(defun put (spc loc obj)
(let ((current (gethash loc spc)))
(if current
(error "location already occupied! space: ~s, loc: ~s, current: ~s, new: ~s"
spc loc current obj)
(setf (gethash loc spc) obj))))
(defun del (spc loc)
(remhash loc spc))
(defun fetch (spc loc)
(gethash loc spc))
(defun query (spc pattern)
nil)
(defun neighbors (spc loc &key (dist 2))
(let* ((range (floor (sqrt dist)))
nbrs)
(util:with-iterator (loc-iterator range)
(lambda (rloc)
(let* ((cloc (loc-add rloc loc))
(cell (fetch spc cloc)))
(when cell (push cell nbrs)))))
nbrs))
(defun free-loc-at (spc loc &key (dist 2)))
(defun distance-sq (spc loc1 loc2))
(defun loc-iterator (range &key (dim 2))
(let* ((from (- range))
(zero (make-array dim :initial-element 0))
(cur (make-array dim :initial-element from)))
(labels (
(inc (cur &optional (idx 0))
(when (< idx dim)
(let ((new (1+ (aref cur idx))))
(setf (aref cur idx) new)
(when (> new range)
(setf (aref cur idx) from)
(setf cur (inc cur (1+ idx))))
cur))))
(lambda ()
(when (equalp cur zero)
(setf cur (inc cur)))
(when cur
(prog1 (make-array dim :initial-contents cur)
(setf cur (inc cur))))))))
(defun loc-add (l1 l2)
(let* ((dim (car (array-dimensions l1)))
(loc (make-array dim :initial-contents l1)))
(loop for i to (1- dim) do (setf (aref loc i) (+ (aref l1 i) (aref l2 i))))
loc))