;|<--------------------------------------------------------------------------- Function: Matrices library. Primarily developed to convert a point in world coordinate system to OCS given the matrix returned for converting from OCS to World and the point in W. References: Functions from: http://www1.acm.org/pubs/tog/GraphicsGems/gems/MatrixInvert.c by Richard Carling Good resource for explanation of matrices as used by Acad. http://3dgraphics.about.com/gi/dynamic/offsite.htm?site=http (wrap to next line) %3A%2F%2Fwww.gamedev.net%2Freference%2Farticles%2Farticle877.asp By Jeff Weeks. Written by Larry Leuallen 5/12/2002 (C) Copyright 2020 Larry Leuallen All rights reserved. Last revision: LARRY LEUALLEN PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. LARRY LEUALLEN SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. LARRY LEUALLEN DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE UNINTERRUPTED OR ERROR FREE. REVISION HISTORY: --------------------------------------------------------------------------->|; ;;; Matrices functions converted from C functions found at ;;; http://www1.acm.org/pubs/tog/GraphicsGems/gems/MatrixInvert.c ;;; /* ;;; Matrix Inversion ;;; by Richard Carling ;;; from "Graphics Gems", Academic Press, 1990 ;;; */ ;;; /* ;;; * double = det2x2( double a, double b, double c, double d ) ;;; * ;;; * calculate the determinant of a 2x2 matrix. ;;; */ ;;; double det2x2( a, b, c, d) ;;; double a, b, c, d; ;;; { ;;; double ans; ;;; ans = a * d - b * c; ;;; return ans; ;;; } ;;; Det a b ;;; c d ;;; (list a b c d) ;;; (list 0 1 2 3) ;; Note: It was easier to translate using what I will call ;; FlatMatrixList, FMatrix, rather that a Matrix list as returned by ;; Acad, which I will call a NestedMatrixList, Matrix. ;; Example: ;; Matrix: ((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 15)) ;; FMatrix: (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 15) ;; Verified using examples from College Algebra by Rosenbach and ;; Whitman. Pages 132 and 133. (defun LLDet:2x2 (Det) (- (* (nth 0 Det) (nth 3 Det)) (* (nth 1 Det) (nth 2 Det))) ) ;end LLDet:2x2 05/12/02 ;;; /* ;;; * double = det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3 ) ;;; * ;;; * calculate the determinant of a 3x3 matrix ;;; * in the form ;;; * ;;; * | a1, b1, c1 | ;;; * | a2, b2, c2 | ;;; * | a3, b3, c3 | ;;; */ ;;; double det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3 ) ;;; double a1, a2, a3, b1, b2, b3, c1, c2, c3; ;;; { ;;; double ans; ;;; double det2x2(); ;;; ans = a1 * det2x2( b2, b3, c2, c3 ) ;;; - b1 * det2x2( a2, a3, c2, c3 ) ;;; + c1 * det2x2( a2, a3, b2, b3 ); ;;; return ans; ;;; } ;;; Det a1 b1 c1 ;;; a2 b2 c2 ;;; a3 b3 c3 ;;; Det (list a1 b1 c1 a2 b2 c2 a3 b3 c3) ;;; (list 0 1 2 3 4 5 6 7 8) ;; Verified using examples from College Algebra by Rosenbach and ;; Whitman. Pages 136 and 137. (defun LLDet:3x3 (Det) (+ (* (nth 0 Det) (LLDet:2x2 (list (nth 4 Det) (nth 5 Det) (nth 7 Det) (nth 8 Det)))) (- (* (nth 3 Det) (LLDet:2x2 (list (nth 1 Det) (nth 2 Det) (nth 7 Det) (nth 8 Det))))) (* (nth 6 Det) (LLDet:2x2 (list (nth 1 Det) (nth 2 Det) (nth 4 Det) (nth 5 Det)))) ) ) ;end LLDet:3x3 05/12/02 ;;; /* ;;; * Double = Det4x4( Matrix ) ;;; * ;;; * Calculate The Determinant Of A 4x4 Matrix. ;;; */ ;;; Double Det4x4( M ) Matrix4 *m; ;;; { ;;; Double Ans; ;;; Double A1, A2, A3, A4, B1, B2, B3, B4, C1, C2, C3, C4, D1, D2, D3, D4; ;;; Double Det3x3(); ;;; /* Assign To Individual Variable Names To Aid Selecting */ ;;; /* Correct Elements */ ;;; A1 = M->Element[0][0]; B1 = M->Element[0][1]; ;;; C1 = M->Element[0][2]; D1 = M->Element[0][3]; ;;; A2 = M->Element[1][0]; B2 = M->Element[1][1]; ;;; C2 = M->Element[1][2]; D2 = M->Element[1][3]; ;;; A3 = M->Element[2][0]; B3 = M->Element[2][1]; ;;; C3 = M->Element[2][2]; D3 = M->Element[2][3]; ;;; A4 = M->Element[3][0]; B4 = M->Element[3][1]; ;;; C4 = M->Element[3][2]; D4 = M->Element[3][3]; ;;; Ans = A1 * Det3x3( B2, B3, B4, C2, C3, C4, D2, D3, D4) ;;; - B1 * Det3x3( A2, A3, A4, C2, C3, C4, D2, D3, D4) ;;; + C1 * Det3x3( A2, A3, A4, B2, B3, B4, D2, D3, D4) ;;; - D1 * Det3x3( A2, A3, A4, B2, B3, B4, C2, C3, C4); ;;; Return Ans; ;;; } ;;; Det a1 b1 c1 d1 ;;; a2 b2 c2 d2 ;;; a3 b3 c3 d3 ;;; a4 b4 c4 d4 ;;; Det (list a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3 a4 b4 c4 d4) ;;; (list 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) ;; Verified using examples from College Algebra by Rosenbach and ;; Whitman. Pages 453. (defun LLDet:4x4 (Det / a1 a2 a3 a4 b1 b2 b3 b4 c1 c2 c3 c4 d1 d2 d3 d4) (setq a1 (nth 0 Det) a2 (nth 1 Det) a3 (nth 2 Det) a4 (nth 3 Det) b1 (nth 4 Det) b2 (nth 5 Det) b3 (nth 6 Det) b4 (nth 7 Det) c1 (nth 8 Det) c2 (nth 9 Det) c3 (nth 10 Det) c4 (nth 11 Det) d1 (nth 12 Det) d2 (nth 13 Det) d3 (nth 14 Det) d4 (nth 15 Det) ) (+ (* a1 (LLDet:3x3 (list b2 b3 b4 c2 c3 c4 d2 d3 d4))) (- (* b1 (LLDet:3x3 (list a2 a3 a4 c2 c3 c4 d2 d3 d4)))) (* c1 (LLDet:3x3 (list a2 a3 a4 b2 b3 b4 d2 d3 d4))) (- (* d1 (LLDet:3x3 (list a2 a3 a4 b2 b3 b4 c2 c3 c4)))) ) ) ;end LLDet:4x4 05/12/02 ;;; /* ;;; * adjoint( original_matrix, inverse_matrix ) ;;; * ;;; * calculate the adjoint of a 4x4 matrix ;;; * ;;; * Let a denote the minor determinant of matrix A obtained by ;;; * ij ;;; * ;;; * deleting the ith row and jth column from A. ;;; * ;;; * i+j ;;; * Let b = (-1) a ;;; * ij ji ;;; * ;;; * The matrix B = (b ) is the adjoint of A ;;; * ij ;;; */ ;;; adjoint( in, out ) Matrix4 *in; Matrix4 *out; ;;; { ;;; double a1, a2, a3, a4, b1, b2, b3, b4; ;;; double c1, c2, c3, c4, d1, d2, d3, d4; ;;; double det3x3(); ;;; /* assign to individual variable names to aid */ ;;; /* selecting correct values */ ;;; a1 = in->element[0][0]; b1 = in->element[0][1]; ;;; c1 = in->element[0][2]; d1 = in->element[0][3]; ;;; a2 = in->element[1][0]; b2 = in->element[1][1]; ;;; c2 = in->element[1][2]; d2 = in->element[1][3]; ;;; a3 = in->element[2][0]; b3 = in->element[2][1]; ;;; c3 = in->element[2][2]; d3 = in->element[2][3]; ;;; a4 = in->element[3][0]; b4 = in->element[3][1]; ;;; c4 = in->element[3][2]; d4 = in->element[3][3]; ;;; /* row column labeling reversed since we transpose rows & columns */ ;;; out->element[0][0] = det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4); ;;; out->element[1][0] = - det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4); ;;; out->element[2][0] = det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4); ;;; out->element[3][0] = - det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4); ;;; out->element[0][1] = - det3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4); ;;; out->element[1][1] = det3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4); ;;; out->element[2][1] = - det3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4); ;;; out->element[3][1] = det3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4); ;;; out->element[0][2] = det3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4); ;;; out->element[1][2] = - det3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4); ;;; out->element[2][2] = det3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4); ;;; out->element[3][2] = - det3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4); ;;; out->element[0][3] = - det3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3); ;;; out->element[1][3] = det3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3); ;;; out->element[2][3] = - det3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3); ;;; out->element[3][3] = det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3); ;;; } (defun LLDet:Adjoint (Det / Return a1 a2 a3 a4 b1 b2 b3 b4 c1 c2 c3 c4 d1 d2 d3 d4) (setq a1 (nth 0 Det) a2 (nth 1 Det) a3 (nth 2 Det) a4 (nth 3 Det) b1 (nth 4 Det) b2 (nth 5 Det) b3 (nth 6 Det) b4 (nth 7 Det) c1 (nth 8 Det) c2 (nth 9 Det) c3 (nth 10 Det) c4 (nth 11 Det) d1 (nth 12 Det) d2 (nth 13 Det) d3 (nth 14 Det) d4 (nth 15 Det) ) (list (LLDet:3x3 (list b2 b3 b4 c2 c3 c4 d2 d3 d4)) (- (LLDet:3x3 (list a2 a3 a4 c2 c3 c4 d2 d3 d4))) (LLDet:3x3 (list a2 a3 a4 b2 b3 b4 d2 d3 d4)) (- (LLDet:3x3 (list a2 a3 a4 b2 b3 b4 c2 c3 c4))) (- (LLDet:3x3 (list b1 b3 b4 c1 c3 c4 d1 d3 d4))) (LLDet:3x3 (list a1 a3 a4 c1 c3 c4 d1 d3 d4)) (- (LLDet:3x3 (list a1 a3 a4 b1 b3 b4 d1 d3 d4))) (LLDet:3x3 (list a1 a3 a4 b1 b3 b4 c1 c3 c4)) (LLDet:3x3 (list b1 b2 b4 c1 c2 c4 d1 d2 d4)) (- (LLDet:3x3 (list a1 a2 a4 c1 c2 c4 d1 d2 d4))) (LLDet:3x3 (list a1 a2 a4 b1 b2 b4 d1 d2 d4)) (- (LLDet:3x3 (list a1 a2 a4 b1 b2 b4 c1 c2 c4))) (- (LLDet:3x3 (list b1 b2 b3 c1 c2 c3 d1 d2 d3))) (LLDet:3x3 (list a1 a2 a3 c1 c2 c3 d1 d2 d3)) (- (LLDet:3x3 (list a1 a2 a3 b1 b2 b3 d1 d2 d3))) (LLDet:3x3 (list a1 a2 a3 b1 b2 b3 c1 c2 c3)) ) ) ;end LLDet:Adjoint 05/12/02 ;;; inverse( in, out ) Matrix4 *in, *out; ;;; { ;;; int i, j; ;;; double det, det4x4(); ;;; /* calculate the adjoint matrix */ ;;; adjoint( in, out ); ;;; /* calculate the 4x4 determinant ;;; * if the determinant is zero, ;;; * then the inverse matrix is not unique. ;;; */ ;;; det = det4x4( in ); ;;; if ( fabs( det ) < SMALL_NUMBER) { ;;; printf("Non-singular matrix, no inverse!\n"); ;;; exit(1); ;;; } ;;; /* scale the adjoint matrix to get the inverse */ ;;; for (i=0; i<4; i++) ;;; for(j=0; j<4; j++) ;;; out->element[i][j] = out->element[i][j] / det; ;;; } (defun LLDet:Inverse (Matrix / Return Det) (setq FMatrix (LLDet:FlattenMatrixList Matrix) Return (LLDet:Adjoint FMatrix) Det (LLDet:4x4 FMatrix) Fuzz 1.0e-8 ) (cond ( (< (abs Det) Fuzz) (prompt "\nNon-Singular matrix, no inverse.") nil ) ( T (LLDet:NestFlatMatrix (mapcar '(lambda (X) (/ X Det) ) Return ) ;end mapcar lambda ) ) ) ;end cond. ) ;end LLDet:Inverse 05/12/02 ;; End functions from "Graphics Gems", Academic Press, 1990, by ;; Richard Carling ;; ***************************************************************************** ;; Functions from Jeff Weeks. ;;;--------------------------------- ;;; LLDet:PtXMatrix ;; Multiplies a point times a matrix. The matrix is in nested form. ;; Created to verify functions were equivalent. ;; This is the matrices solution as shown in the Acad help for ;; Nentselp, written using flat matrices. ;; You may use whatever OCS to World function you have. (defun LLDet:PtXMatrix (Pt Matrix / FMatrix) (setq FMatrix (LLDet:FlattenMatrixList Matrix)) (list (+ (* (nth 0 Pt) (nth 0 FMatrix)) (* (nth 1 Pt) (nth 1 FMatrix)) (* (nth 2 Pt) (nth 2 FMatrix)) (nth 3 FMatrix) ) (+ (* (nth 0 Pt) (nth 4 FMatrix)) (* (nth 1 Pt) (nth 5 FMatrix)) (* (nth 2 Pt) (nth 6 FMatrix)) (nth 7 FMatrix) ) (+ (* (nth 0 Pt) (nth 8 FMatrix)) (* (nth 1 Pt) (nth 9 FMatrix)) (* (nth 2 Pt) (nth 10 FMatrix)) (nth 11 FMatrix) ) ) ) ;end LLDet:PtXMatrix 05/12/02 ;; ***************************************************************************** ;; Conversion functions for matrix lists: ;;;--------------------------------- ;;; LLDet:FlattenMatrixList ;; Takes a matrix in the form of a list of four lists and "flattens" ;; into one list. (defun LLDet:FlattenMatrixList (Matrix / Head Mat) (apply 'append Matrix) ) end LLDet:FlattenMatrixList 05/12/02 ;;;--------------------------------- ;;; LLDet:NestFlatMatrix ;; Takes a matrix in the form of one list and creates a list of four ;; lists. (FMatrix -> Matrix) ;(defun LLDet:NestFlatMatrix (FMatrix / Count GroupCount Return Group MatLen) ; (setq Count 0 ; GroupCount 0 ; MatLen (length FMatrix) ; ) ; (while (< Count MatLen) ; (cond ; ( (< GroupCount 4) ; (setq Group (cons (nth Count FMatrix) Group)) ; (setq Count (1+ Count) ; GroupCount (1+ GroupCount) ; ) ; ) ; ( T ; (setq Return (append Return (list (reverse Group))) ; GroupCount 0 ; Group nil ; ) ; ) ; ) ;end cond. ; ) ;end while ; (append Return (list (reverse Group))) ;) ;end LLDet:NestFlatMatrix 05/12/02 (defun LLDet:NestFlatMatrix (FMatrix) (NestListBy FMatrix 4) ) ;end LLDet:NestFlatMatrix 05/12/02 ;;------------------------------------------------------------- ;; NestListBy was Parse_List ;; Function returns a list of data from a continuous list such ;; as returned by (vlax-safearray->list (vlax-variant-value X)) ;; given the input list and the number of elements to ;; include in each item of the list: ;; ;; John Udhen 5/15/2002 (defun NestListBy (Old N / Item New) (foreach Element (reverse Old) (setq Item (cons Element Item)) (if (= (length Item) N) (setq New (cons Item New) Item nil) ) ) New ) ; NestListBy ;; Example (setq Matrix (Parse_List Flat 4)) ;; ***************************************************************************** ;; Transform functions for Acad. ;; Input is a matrix in Acad format. ;;;--------------------------------- ;;; LLDet:WToOCS ;; Matrix is the Matrix as returned by Nentselp. This matrix is ;; used for going from the OCS to the W. It must be inverted, to go ;; from the W to OCS. Pt is is in the OCS and will be returned as W. (defun LLDet:WToOCS (Pt Matrix) (LLDet:PtXMatrix Pt (LLDet:Inverse Matrix)) ) ;end LLDet:WToOCS 05/12/02 ;; ***************************************************************************** ;;;Thanks to Vladimir Nesterovsky ;;;for these four matrix manipulation routines ;;;a dot product of the two vectors, u & v (defun LLDet:DotProd (u v) (apply '+ (mapcar '* u v)) ) ;;;transpose a matrix ;;;code by doug Wilson (defun LLDet:TransposeM (m) (apply 'mapcar (cons 'list m)) ) ;;;Apply a transformation matrix to a vector (defun LLDet:MxV (m v) (mapcar '(lambda (row) (LLDet:DotProd row v) ) m ) ) ;;;Multiply two matrices (defun LLDet:MxM (m q) (setq q (LLDet:TransposeM q)) (mapcar '(lambda (row) (LLDet:MxV q row) ) m ) ) ;; ***************************************************************************** ;; New stuff ;; John, ;; I call that operation RAVEL from the old A.P.L. terminology. ;; Here are a few of the promised matrix functions. There are many ;; more to code. ;D. C. Broad, Jr. - 2002 Matrix functions - 1st installment ;; Returns a vector of sequential numbers ;; Args: N = a number F= a function to be applied to each element ;; N decremented by 1 until <=0 is reached. ;; Vector is a list. ;; N must be greater than 0. ;; Use +, -, etc or unquoted lambda for function. ;; Applies N to F. ;; (Iota 10 nil) ;; (1 2 3 4 5 6 7 8 9 10) ;; (Iota 0.1 nil) ;; (0.1) ;; (Iota 10 (lambda (X) (+ x 2))) ;; (3 4 5 6 7 8 9 10 11 12) ;; (Iota 10 (lambda (X) (/ x 2.0)) ) ;; (0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0) (defun Iota (N F / R) (or F (setq F +)) (while (> N 0) (setq R (cons (F N) R) N (1- N) ) ) R ) ;;Returns an outer operation between 2 vectors ;;Args: U - first vector, V - second vector, F - function to be applied ;;Example: To obtain multiplication table: (outer (iota 9 nil) (iota 9 nil) *) (defun Outer (U V F / R M) (foreach A (reverse U) (foreach B (reverse V) (setq R (cons (F A B) R)) ) (setq M (cons R M) R nil ) ) M ) ;;Convert Matrix to Vector ;;Arg: M = matrix (defun Ravel (M) (apply 'append M)) ;;Will chop or extend a vector by recyling or truncating ;;Args: N = integer , V = vector (defun Take (N V / X R) (setq X V) (repeat N (setq R (cons (car X) R) X (cdr X) X (if X X V ) ) ) (reverse R) ) ;;Returns the shape of a matrix(length = number of dimensions) ;;ARG: M = matrix ;;Return value = a list. The length of the return list is number ;;of dimensions of the matrix. (defun Shape (M) (if (atom m) nil (cons (length M) (Shape (car M))) ) ) ;; Stay tuned.... Will recode the rest of APL ;; soon. ;; Regards, ;; Doug ;; Correction for RAVEL. This is applicable to an N-dimensional array. ;; Previous version (apply 'append...) only applied to 2D array. ;;Convert N-dimensional Matrix to Vector ;;Row priority ;;D. C. Broad, Jr. 2002 (defun ravel (M / dims rav1) (setq dims (length (shape M))) (defun rav1 ( M dims) (cond ((null m) nil) ((= dims 1) M) (t (append (rav1 (car M) (1- dims))(rav1 (cdr M) dims))))) (rav1 M dims)) ;;Returns the shape of a matrix(length = number of dimensions) ;;ARG: M = matrix ;;Return value = a list. The length of the return list is number ;;of dimensions of the matrix. (defun shape (M) (if (atom m) nil (cons (length M) (shape (car M))))) ;; "John Uhden" wrote in message ;; > Doug: ;; > ;; > When/how might I run into a 3D array? What does one look like? ;; > ;; > ;; A ;; 1 2 3 4 ;; 5 6 7 8 <-----plane 0 ;; 9 10 11 12 ;; 13 14 15 16 ;; 17 18 19 20 <-------plane 1 ;; 21 22 23 24 ;; Good analogy: Spreadsheets in a workbook for 3D array. ;; Think of each dimension as a possible sub-category. ;; Top level: Store1-StoreN ;; Next level:Product1-ProductN ;; Next level:CostsbyMonth, Suppliers, Deliverydates... ;; Hoo boy... I get a head-ache after that. APL could handle ;; arrays with 64 dimensions. ;; For a point list, 2D array is sufficient. How about a point ;; list over time? ;; BTW: If the source list is not guaranteed to be rectangular ;; at each level, then the following ravel function is preferred: ;; ;;Generalized version N-dimensional but does not ;; ;;need square array. This works for any binary tree. ;; ;;but is a little slower(yet more thorough) (defun ravel (M) (cond ((null m) nil) ((atom m) (list m)) (t (append (ravel (car m))(ravel (cdr m)))))) ;; Regards, ;; Doug ;; ***************************************************************************** ;;;--------------------------------- ;;; LLDet:TransM ;; Translation matrix where X is the x displacement, Y is the y ;; displacement, and Z is the z displacement. (defun LLDet:TransM (Disp) (list (list 1.0 0.0 0.0 (car Disp)) (list 0.0 1.0 0.0 (cadr Disp)) (list 0.0 0.0 1.0 (caddr Disp)) (list 0.0 0.0 0.0 1.0) ) ) ;end LLDet:TransM 05/20/02 ;;;--------------------------------- ;;; LLDet:RotZM ;; Return matrix for rotation about the Z-axis. Ang is in radians. (defun LLDet:RotZM (Ang) (list (list (cos Ang) (- (sin Ang)) 0.0 0.0) (list (sin Ang) (cos Ang) 0.0 0.0) (list 0.0 0.0 1.0 0.0) (list 0.0 0.0 0.0 1.0) ) ) ;end LLDet:RotZM 05/20/02 (defun LLDet:RotXM (Ang) (list (list 1.0 0.0 0.0 0.0) (list 0.0 (cos Ang) (- (sin Ang)) 0.0) (list 0.0 (sin Ang) (cos Ang) 0.0) (list 0.0 0.0 0.0 1.0) ) ) ;end LLDet:RotXM 05/20/02 (defun LLDet:RotYM (Ang) (list (list (cos Ang) 0.0 (sin Ang) 0.0) (list 0.0 1.0 0.0 0.0) (list (- (sin Ang)) 0.0 (cos Ang) 0.0) (list 0.0 0.0 0.0 1.0) ) ) ;end LLDet:RotYM 05/20/02 (defun LLDet:PtoV (Pt) (list (car Pt) (cadr Pt) (caddr Pt) 1.0) ) ;end LLDet:PtoV 05/20/02 (defun LLDet:VtoP (V) (list (car V) (cadr V) (caddr V)) ) ;end LLDet:VtoP 05/22/02 (defun LLDet:AddV (V1 V2) (list (+ (car V1) (car V2)) (+ (cadr V1) (cadr V2)) (+ (caddr V1) (caddr V2)) 1.0 ) ) ;end LLDet:AddV 05/20/02 (defun LLDet:SubV (V1 V2) (list (- (car V1) (car V2)) (- (cadr V1) (cadr V2)) (- (caddr V1) (caddr V2)) 1.0 ) ) ;end LLDet:SubV 05/20/02 (defun LLDet:SxV (S V) (list (* S (car V)) (* S (cadr V)) (* S (caddr V)) 1.0) ) ;end LLDet:SxV 05/22/02