| 1 |
;; 2008-01-15: currently not used in the production core |
|---|
| 2 |
|
|---|
| 3 |
(in-package :cl-user) |
|---|
| 4 |
|
|---|
| 5 |
(defconstant +max-node-objects+ 10) |
|---|
| 6 |
|
|---|
| 7 |
(defclass qt-object () |
|---|
| 8 |
((x :initarg :x :reader qt-object-x) |
|---|
| 9 |
(y :initarg :y :reader qt-object-y) |
|---|
| 10 |
(object :initarg :object :reader qt-object-object))) |
|---|
| 11 |
|
|---|
| 12 |
(defclass qt-node () |
|---|
| 13 |
((x :initarg :x :reader qt-node-x) |
|---|
| 14 |
(y :initarg :y :reader qt-node-y) |
|---|
| 15 |
(half-width :initarg :half-width :reader qt-node-half-width) |
|---|
| 16 |
(objects :initarg :objects :accessor qt-node-objects :initform nil) |
|---|
| 17 |
(children :initarg :children :accessor qt-node-children :initform nil))) |
|---|
| 18 |
|
|---|
| 19 |
(defclass quadtree () |
|---|
| 20 |
((root :reader quadtree-root))) |
|---|
| 21 |
|
|---|
| 22 |
(defun dump-node (node &optional (depth 0)) |
|---|
| 23 |
(let ((indent (make-string depth :initial-element #\Space))) |
|---|
| 24 |
(format t "~anode x: ~a y: ~a width: ~a~%" indent (qt-node-x node) (qt-node-y node) (* 2 (qt-node-half-width node))) |
|---|
| 25 |
(dolist (child (qt-node-children node)) |
|---|
| 26 |
(dump-node child (1+ depth))) |
|---|
| 27 |
(dolist (object (qt-node-objects node)) |
|---|
| 28 |
(format t "~a x: ~a y: ~a object: ~a~%" indent (qt-object-x object) (qt-object-y object) (qt-object-object object))))) |
|---|
| 29 |
|
|---|
| 30 |
(defmethod in-bbox-p ((object qt-object) x1 y1 x2 y2) |
|---|
| 31 |
(let ((x (qt-object-x object)) |
|---|
| 32 |
(y (qt-object-y object))) |
|---|
| 33 |
(and (>= x x1) |
|---|
| 34 |
(<= x x2) |
|---|
| 35 |
(>= y y1) |
|---|
| 36 |
(<= y y2)))) |
|---|
| 37 |
|
|---|
| 38 |
(defmethod overflow ((node qt-node) (object qt-object)) |
|---|
| 39 |
(let ((children-half-width (/ (qt-node-half-width node) 2))) |
|---|
| 40 |
(setf (qt-node-children node) |
|---|
| 41 |
(list (make-instance 'qt-node |
|---|
| 42 |
:x (qt-node-x node) |
|---|
| 43 |
:y (qt-node-y node) |
|---|
| 44 |
:half-width children-half-width) |
|---|
| 45 |
(make-instance 'qt-node |
|---|
| 46 |
:x (+ (qt-node-half-width node) (qt-node-x node)) |
|---|
| 47 |
:y (qt-node-y node) |
|---|
| 48 |
:half-width children-half-width) |
|---|
| 49 |
(make-instance 'qt-node |
|---|
| 50 |
:x (qt-node-x node) :y (+ (qt-node-half-width node) (qt-node-y node)) |
|---|
| 51 |
:half-width children-half-width) |
|---|
| 52 |
(make-instance 'qt-node |
|---|
| 53 |
:x (+ (qt-node-half-width node) (qt-node-x node)) |
|---|
| 54 |
:y (+ (qt-node-half-width node) (qt-node-y node)) |
|---|
| 55 |
:half-width children-half-width))) |
|---|
| 56 |
(push object (qt-node-objects node)) ; append new object temporarily |
|---|
| 57 |
(dolist (object (qt-node-objects node)) ; push all objects into child nodes |
|---|
| 58 |
(insert (find-node node (qt-object-x object) (qt-object-y object)) object)) |
|---|
| 59 |
(setf (qt-node-objects node) nil))) |
|---|
| 60 |
|
|---|
| 61 |
(defmethod insert ((node qt-node) (object qt-object)) |
|---|
| 62 |
(if (< (length (qt-node-objects node)) +max-node-objects+) |
|---|
| 63 |
(push object (qt-node-objects node)) |
|---|
| 64 |
(overflow node object))) |
|---|
| 65 |
|
|---|
| 66 |
(defmethod find-node ((node qt-node) x y) |
|---|
| 67 |
(if (qt-node-children node) |
|---|
| 68 |
(let ((x-quadrant (if (minusp (- x (qt-node-x node) (qt-node-half-width node))) 0 1)) |
|---|
| 69 |
(y-quadrant (if (minusp (- y (qt-node-y node) (qt-node-half-width node))) 0 2))) |
|---|
| 70 |
(find-node (nth (+ x-quadrant y-quadrant) (qt-node-children node)) |
|---|
| 71 |
x y)) |
|---|
| 72 |
node)) |
|---|
| 73 |
|
|---|
| 74 |
(defmethod insert-object ((quadtree quadtree) x y object) |
|---|
| 75 |
(insert (find-node (quadtree-root quadtree) x y) |
|---|
| 76 |
(make-instance 'qt-object :x x :y y :object object))) |
|---|
| 77 |
|
|---|
| 78 |
(defun add-nodes (qt count) |
|---|
| 79 |
(loop for i from 0 below count |
|---|
| 80 |
do (insert-object qt (random 100) (random 100) i))) |
|---|