Регистрация | Войти
Lisp — программируемый язык программирования
Автор: Paul.Alkhimov - 2010-03-26T14:01:10.000000+03:00

;; Vertex is just plain _array_ of three doubles: (0 0 0). Here three
;; values stand for X Y and Z respectively.  Array of 3D vertexes is
;; just plain array, where 3D vertexes are following one after
;; another: ( x0 y0 z0 x1 y1 z1 x2 y2 z2 ... ). Here x# y# and z# are
;; some values of the first, the second and the third vertexes. #
;; means the index of the 3D vertex.  To reference any coordinate use
;; the following form: (ref-of V C) where V is vertex containing three
;; doubles and C is X Y or Z. Also you can use this: (ref-of V C IA I)
;; where V and C are the same to previous example and IA and I mean
;; the following things: IA is array of indexes and I is index in the
;; array IA. So (ref-of COORDS :Z IND i) in C/C++ would mean the
;; following: COORDS[ IND[i] + 2 ]; In fact, last two parameters are
;; representing indirect indexing mechanism. This lets us store the
;; whole geometry in one array. Each part then can be referenced with
;; independent array of indexes. Also, we can reference the same
;; vertex as many times as necessary.

(defmacro ref-of (values coordinate &optional indexes index)
  "Please see DATA STRUCTURE for details."
  (if indexes
      (cond ((eq coordinate :x) `(aref ,values (aref ,indexes ,index)))
            ((eq coordinate :y) `(aref ,values (+ 1 (aref ,indexes ,index))))
            ((eq coordinate :z) `(aref ,values (+ 2 (aref ,indexes ,index))))
            (T (error "The symbol ~S is not :X, :Y or :Z." coordinate))

      (cond ((eq coordinate :x) `(aref ,values 0))
            ((eq coordinate :y) `(aref ,values 1))
            ((eq coordinate :z) `(aref ,values 2))
            (T (error "The symbol ~S is not :X, :Y or :Z." coordinate))

(defmacro zero-p (v &optional indexes index)
  "Checks if the vector is 'almost' zero length."
  `(and (< (ref-of ,v :x ,indexes ,index) *min+*)
        (< (ref-of ,v :y ,indexes ,index) *min+*)
        (< (ref-of ,v :z ,indexes ,index) *min+*)
        (> (ref-of ,v :x ,indexes ,index) *min-*)
        (> (ref-of ,v :y ,indexes ,index) *min-*)
        (> (ref-of ,v :z ,indexes ,index) *min-*)

(defmacro do-op-on (op name1 coord1 name2 coord2 &optional is1 i1 is2 i2)
  "Replaces provided names with two vectors and coordinates. Indexes supplied as well.
Example: (do-op-on * A :x B :y i n) == A[i[n]].x*B.y"

  `(,op (ref-of ,name1 ,coord1 ,is1 ,i1) (ref-of ,name2 ,coord2 ,is2 ,i2))

(defun make-v3 (x y z)
  "VECTOR of 3 doubles: X Y Z."
  (make-array 3 :element-type 'double-float :initial-contents (list x y z))

(defun normalize (a &optional indexes i)
  "Returns normalized A."
   (format t "Data=~A ~A ~A" a indexes i)
   (if (zero-p a indexes i)
      a ;; cannot normalize empty vector
    (let* ((mmm (format t "Zero?=~a" (zero-p a indexes i)))
             (L (sqrt (+ (do-op-on * a :x a :x indexes i indexes i)
                         (do-op-on * a :y a :y indexes i indexes i)
                         (do-op-on * a :z a :z indexes i indexes i)

             (mmm (format t "L=~a" L))
             (L (/ 1D0 L))
             (mmm (format t "L=~a" L))
; L=1/length(A)
      (make-V3 (* (ref-of a :x indexes i) l)
                 (* (ref-of a :y indexes i) l)
                 (* (ref-of a :z indexes i) l)
@2009-2013 lisper.ru