gpt4 book ai didi

functional-programming - 如何用类似 lisp 的语言分解几何图形构建?

转载 作者:太空宇宙 更新时间:2023-11-03 18:49:46 25 4
gpt4 key购买 nike

我怎样才能用类似 lisp 的语言分解这个过程?

  • 从一些几何图形开始。
  • 我们将它相乘并得到多个副本。
  • 然后我们将这个副本设置在其他图形的边框上,e.q.副本之间的距离相等。
  • 然后我们设置边框上每个对象的旋转依赖于其在边界上的位置。

有哪些方法可以将这个过程分解为一个整体:复制一个对象,将其副本排列在其他对象的边界上,设置其副本的旋转?

最后一步特别有趣,还有如何将它与前面的步骤组合起来的方法。

最佳答案

你的问题很宽泛,让我们举一个简单的二维形状示例。

下面的代码定义为我们可以这样写:

(isomorphism (alexandria:compose (scale 10)
(lift #'round)
(rotate 90))
(triangle (point 0 0)
(point 1 0)
(point 0 1)))

=> (TRIANGLE (POINT 0 0) (POINT 0 10) (POINT -10 0))

这会计算一个简单的变换函数,称为同构(保留形状),首先是旋转,然后是计算点的舍入,然后是缩放操作。结果是一个描述结果形状的列表。复制形状只是函数#'identity 的同构(但如果你采用纯函数方式,它就有点没用了)。

注意:此处四舍五入,例如当 cos/sin 给出非常小的 float 时回落到零; float 的使用破坏了形状的保持,舍入也是如此,但是当它们组合在一起时,结果形状是一个实际的同构。根据您的需求目的,这一点正确性/准确性可能重要也可能不重要。您还可以描述应用了哪些转换并仅“光栅化”它们以供显示。

变换函数处理坐标列表,并返回坐标列表:

(defun translate (dx &optional (dy dx))
(lambda (xy) (mapcar #'+ xy (list dx dy))))

(defun scale (sx &optional (sy sx))
(lambda (xy) (mapcar #'* xy (list sx sy))))

(defun rotate (degrees)
(let* ((radians (* degrees pi 1/180))
(cos (cos radians))
(sin (sin radians)))
(lambda (xy)
(destructuring-bind (x y) xy
(list (- (* x cos) (* y sin))
(+ (* y cos) (* x sin)))))))

(defun lift (fn)
(lambda (things)
(mapcar fn things)))

isomorphism 函数定义如下,递归地将形状解构为类型标签(兼作构造函数)和组件,对于点,应用变换函数:

(defun isomorphism (transform shape)
(flet ((isomorphism (s) (isomorphism transform s)))
(with-shape (constructor components) shape
(apply constructor
(if (eq constructor 'point)
(funcall transform components)
(mapcar #'isomorphism components))))))

我将 shapewith-shape 定义如下,以便对它们的表示方式进行一些抽象:

(defun shape (constructor components)
(list* constructor components))

(defmacro with-shape ((constructor components) shape &body body)
`(destructuring-bind (,constructor &rest ,components) ,shape
,@body))

我可以用简单的函数定义形状,这些函数可能会也可能不会执行一些检查和规范化:

(defun point (&rest coords)
(shape 'point coords))

(defun triangle (a b c)
(shape 'triangle (list a b c)))

(defun rectangle (x0 y0 x1 y1)
(shape 'rectangle
(list (min x0 x1)
(min y0 y1)
(max x0 x1)
(max y0 y1))))

请注意构造函数如何始终与函数名称具有相同的符号。这可以通过宏来强制执行,您只需要返回组件列表:

(defconstructor point (x y)
(list x y))

您还可以从上面的构建派生构造函数:

(defun rectangle-xywh (x y width height)
(rectangle x y (+ x width) (+ y height)))

上面的形状是根据点定义的,但你可以想象形状是由更小的形状组合而成的:

(defun group (&rest shapes)
(shape 'group shapes))

这是一个玩具示例,但作为起点可能很有用。

然后,如果你想制作一个形状并制作以 90° 为增量旋转的不同副本,你可以这样做:

(loop
for angle from 0 below 360 by 90
collect
(isomorphism (compose (lift #'round)
(rotate angle)
(scale 2)
(translate 10 0))
(group (triangle (point 0 0)
(point 1 0)
(point 0 1)))))

关于functional-programming - 如何用类似 lisp 的语言分解几何图形构建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55435596/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com