如何将计算结果添加到二维列表?Lisp球顶点坐标生成问题
解决Common Lisp中球体顶点坐标表达式未求值的问题
你的问题出在单引号'的引用行为上:Lisp里单引号会阻止列表内的表达式求值,所以'(0 (sin (/ pi 6)) (cos (/ pi 6)))会直接保留sin、cos这些符号,而不会计算它们的结果。
直接解决方案:用list函数替代单引号列表
list函数会对每个传入的参数求值,再将结果组合成列表,这正是你需要的:
(setf (elt sphereverticeslist 1) (list 0 (sin (/ pi 6)) (cos (/ pi 6))))
执行后,这个位置的元素会变成(0 0.5 0.8660254)(近似值),符合预期。
批量生成顶点的完整示例
如果要生成所有球体顶点,可以用循环批量计算,避免逐个手动设置:
(defvar spherelatamount 7) (defvar spherelonamount 8) (defparameter sphereverticeslist (make-list (+ 2 (* (- spherelatamount 2) spherelonamount)))) ;; 设置北极点 (setf (elt sphereverticeslist 0) '(0 0 1)) ;; 生成中间纬度层的所有顶点 (loop for lat-index from 1 to (- spherelatamount 2) ;; 计算当前纬度的极角(从北极点向下) for polar-angle = (* pi (/ lat-index spherelatamount)) do (loop for lon-index from 0 to (- spherelonamount 1) ;; 计算当前顶点在列表中的索引 for vertex-index = (+ 1 (* (- lat-index 1) spherelonamount) lon-index) ;; 计算球坐标转笛卡尔坐标的三个分量 for x = (* (sin polar-angle) (cos (* 2 pi (/ lon-index spherelonamount)))) for y = (* (sin polar-angle) (sin (* 2 pi (/ lon-index spherelonamount)))) for z = (cos polar-angle) ;; 用list求值后存入列表 do (setf (elt sphereverticeslist vertex-index) (list x y z)))) ;; 设置南极点 (setf (elt sphereverticeslist (1- (length sphereverticeslist))) '(0 0 -1))
补充:准引用的替代方式
如果遇到需要部分元素保留字面量、部分求值的场景,可以用**反引号 **配合逗号, 强制求值单个元素(不过这个场景下没必要,仅作拓展):
(setf (elt sphereverticeslist 1) `(0 ,(sin (/ pi 6)) ,(cos (/ pi 6))))
逗号会让后面的表达式被求值,其余部分保留字面量。
内容的提问来源于stack exchange,提问作者nadirkazan
相关产品推荐
相关产品推荐

