# Penrose * 概述 * 数学思想有效的交流 是一个主要挑战 对于学生、教育者和研究者来说。虽然现代的数学已经有了一个很好的文化对于正式的语言, 可视化和说明毫无疑问也同样对数学发展有很大的影响。现今把抽象的概念转换成准确的表达的能力经常限制在这些被选中的人身上,他们同时拥有对数学深度的理解和精通图形化工具的能力。结果,图像往往在数学写作中很缺乏——例如,最近的数学论文在 arXiv 上平均十页才有一张图。这项工作的一个核心的目标是降低把数学思想转换成高效的高质量可视化图像的阻碍。同样的,TEX 和 LATEX 已经让数学写作大众化通过在算法上编纂最好地专业排字时间, Penrose 目标是训练最好的数学插图画家学会一个可以循环利用以及广泛接受的格式。 * 我们的方法根植于将数学自然地分割于抽象定义和具体表现之间。特别地,Penrose 系统紧紧围绕一个映射的规格——从数学对象到可视化图标。这种映射通过 DSLs 语言来表达,反映成熟悉的数学符号以及可以应用于获取新的功能,同时难以用现存的工具来实现。一个关键区别是 Penrose 项目把一系列可能的可视化信息编码,而不是一个特殊图表。因此,绘制图表的努力可以被简单地复用、修改以及推广。这个方法有许多广泛地优点: * 易得性:新用户可以绘制图表通过简单利用熟悉的符号输入数学定义,开发人员也可以努力使用更专业的包 * 分割内容和表示:简易置换不同的可视化表现的功能帮助更深的理解,通过从不同的可视化视点图解相同的数学概念 * 集合的进化:现存的集合图标可以简单地被改进和修改来满足目标平台的需要,例如,桌面端和手机端,不同的打印过程,或者不同的语言局限。 * 大规模生产:使生产大量图解来探索一个想法或者随机生成家庭作业的配图和说明 * 系统设计 * 我们的目的是构造一个系统来转换抽象的数学思想变成可视化图像。系统设计的选项由一些特殊的目标引导,其中许多是由我们之前对作图工具的使用者的采访提出的: 1. 数学对象应该用熟悉的方式表达 2. 系统不应该被限制在确定的一系列领域中 3. 应该可以用使用不同的可视化方式来表达相同的数学内容 4. 不应该有固有限制在视觉复杂性上 5. 应该足够快以致于能促进迭代工作流程 6. 在图像上的付出应该是可概括以及可复用的 * 为了达到这些目标,我们从通常用手绘制图像的方式上获得灵感。在许多数学领域,每种对象都是约定俗成关联于一个标准的可视化图标。例如,点是小黑点,向量是小箭头等等。为了产生一张图,符号会系统化地翻译成图标;一个绘图者之后管理并凝聚这些图标在纸上。我们把这个过程形式化为了图像可以被计算化绘制而不是手绘。 * 特别的,Penrose 的两个管理原则是: 1. 指定图像通过映射数学对象以及可视化图标 2. 合成图像通过解决一个最优化关联约束问题 * 就像约翰·希尔勒的“中文房间”实验没有真的理解一门外国语言,一个这样设计的系统没有必要对数学有深度理解,即它只是简单地完成翻译。因此我们没有期待我们的系统能解决所有绘图上的挑战。用户仍然需要负责: * 选择有意义的符号在某一个数学领域 * 创造有用的可视化表现在那个领域 * 确保图像能正确传递意义 * 因此,一个系统不能被期待解决复杂计算或者数学问题(例如,图灵停机问题或费马大定理)为了构造图像。但是除了这些浅显的理由,Penrose 能够生成十分复杂的图像。实际上,即使没有这些理由,稚嫩的可视化也常常提供有用的观察。(Fig. 2) * 产生的系统有效地把绘图过程模型化为一个编译过程,编译目的是一个最优化关联约束问题而不是一个二进制可执行文件或静止图像。一旦编译,这个问题就可以被使用和复用来生成可视化图像;Fig.3 说明了系统流的高层。从程序语言的角度来看,映射表达在这个框架中定义了可执行的视觉语义。就是说,它提供了特定的、可视化的以及可计算的解释对于原来仅仅是抽象的逻辑关系。 * 基于语言的规则 * 在 Penrose 中一个主要决策是使用编程语言来指定数学对象以及他们的可视化表现。绘图的规则(例如,sketch-based)需要用户已经了解如何可视化抽象概念,它使数学内容和一种特定的可视化表现捆绑在一起,因而与目标 3 冲突。一个基于语言的规则提供了抽象层用于分割内容和可视化。这个技术确保了目标 1 ,因为语言是最通常的方式来表达数学思想。从一个系统设计的角度来看,一个基于语言的编码提供了一个统一的表现对于确认和翻译数学对象通过管道。而且,一个基于语言的接口使 Penrose 提供一个平台让其他的编程工具可以嵌入。一个权衡是基于语言的方法需要用户用正式的数学或计算机语言来表达自己,使得对于可视化艺术家和设计者更难贡献新的表现形式。 * 第二个决策是分割数学内容以及可视化的规则通过两种特定领域的语言:SUBSTANCE 和 STYLE。一个很好的对于两者之间的关系的类比是 HTML(规定了内容)和 CSS (描述了如何渲染)。一个规划叫做 DOMAIN (类似于 XML 或者 JSON 概念)定义了感兴趣的数学领域,支持了目标 2。为了符合目标 3,分割允许了相同的风格重用于不同的内容,同样,相同的内容可以在不同的风格中展示。我们分割的目标是支持一个生态系统使新手能从更有经验的开发者写的包中获利。最后,在数学中,采纳用户定义的特定领域的符号可以有效地用一种简便和易于理解的方式来表达复杂的关系。编码思想直接在问题领域通常导致更好地程序理解比起一系列库产生的泛用性语言。我们将在 Sec. 6 讨论我们的语言的范围以及局限性。 1. 数学领域(DOMAIN) * 我们的一个基础目标(目标 2)是创建一个统一的系统来绘图,而不是聚焦于特殊的领域。一个统一的设计使得不同领域的对象可以共存在同一张图中,通常只需加入一些连接的源文件。同时,对系统性能和渲染质量的努力会平摊在许多不同的领域。 * 用户可以在数学的任何领域作图通过书写叫做 DOMAIN 的规划,定义了针对某一特定领域的 DSLs。这个设计也授权用户采纳他们自己的符号和约定来模范化领域。使用领域特定和用户特定的符号反映了常见的数学写作,符号的意义常常重度依赖于内容。更重要的是,一个 DOMAIN 规划是完全抽象的:它没定义一个对象内在的表现,也没有给出方法和谓词的定义。这个抽象层对目标 3 很重要,因为它允许多个可视化表现应用于同一个领域的对象上 2. 数学内容(SUBSTANCE) * 为了定义一个图的内容,必须能够确定(i)图中的对象(ii)对象之间的关系。为了符合目标 1,SUBSTANCE 使用简便的断言类似于标准数学散文。正式地,它可以使任何领域可表达通过种类,函数和谓词语言,这些是在常见的数学符号中发现的基础结构。就像定义在数学中是不变的,SUBSTANCE 从强规范的函数语言中绘制灵感(例如 ML),其中对象是没有状态的。这个选择也简化系统实现,因为编译器可以假定确定的定义。一个故意的设计决策,为了符合目标 3,是排除所有图像数据(坐标,大小,颜色等等)从 SUBSTANCE 中,因为唯一的目的是指定抽象关系而不是数量资料。所有这些数据都指定在 STYLE 或者通过优化决定。这个分割把用户从冗长且复杂的图形化编程中解放出来,可以分解成可重用的 STYLE 编码。 * 现存的语言在 SUBSTANCE 中很难使用因为它们缺乏编码复杂逻辑关系的语义以及没有提供语言层级的扩展性。比如,TEX 和 MathML 风格仅仅提供足够的信息把文字翻译成数学符号;计算机代数系统比如 Mathematica 和 Maple 限制了风格系统或提供仅仅一小些固定的谓词(比如,规定数字是实数)。相反地,用于自动化定理验证和证明助理的更丰富的语言过度简化了指定图表功能。一个常规语言提供了简单,熟悉的语法同时明确错误信息。然而我们确实从 Coq 中获得一些想法,比如自定义语法的能力。 3. 数学可视化(STYLE) * 一张图的意义主要通过关联关系来传递,而不是绝对坐标。而且,图通常约束很少:传递意图意义所需的关系决定了一系列可能的解,而不是唯一的图。STYLE 因此采纳了一个基于约束的方法来图形化规范本着 Sketchpad 的精神:图是由强约束构建的,必须得到满意的轻的最小的处罚,然后没有指明的数量通过数值优化解决。虽然过程定义仍然可以被使用,但是程序员不需要提供绝对坐标。虽然一个隐含的策略描述可以使结果更难被预测,但 Penrose 吸引人的一个地方就是找到有趣和令人惊喜的例子的潜力。而且,这个方法产生了更多简便的编码;比如,STYLE 程序比他们生成的 SVG 文件短很多。 * 一个可选的设计可能是用 API,虽然历史上的 API 都避开规范语言因为很好的理由。语言提供更多简便的表达关于复杂关系——想象设计一整个网站通过 DOM API 中的 getElementById() and setStyle() 方法,与几行 CSS 代码相比。可视化编程语言能满足基本规范的需要,但是不能拓展到通过语言可以简单表达的复杂概念。 * 一个关键设计挑战是识别出现在 SUBSTANCE 程序中的对象。数学领域给出的对象被识别不仅通过他们的类型,也通过和其他对象之间的关系。一个广泛使用的原理是确定这些关系通过类 CSS 选择器。STYLE 采纳一个相似的原理,执行模式匹配对于出现在 DOMAIN 规划中的类型、函数和谓词上。 * 基于优化的整合 * Penrose 的第二个主要设计决策是使用限制的优化整合图来满足给定的规格。这个方法再次受到启发于人满经常手画图的方式:可视化的图标放在画布上然后反复调整直到没有进一步的改进。在困难的情况下,一个绘图者可能常识一些全局管理在精炼最终设计之前,虽然通常不会超过几个。自动化这个过程使完成布置的手工完成很乏味的任务变得简单。 * 有很好的理由来相信一个基于优化的方法可以拓展到非常复杂的图。首先,吸引人的图不需要在全局范围保持最优——它们不应该允许明显的局部改善,例如文本可以简单地移动更靠近它标注的项目。实际上,不同的局部最小值可以提供有用的例子帮助构建直觉。第二,即使是复杂的图自由度少的惊人与许多现代优化问题相比。最后,专业绘图者的策略可以应用于管理复杂度,例如独立优化图表的小组件,而不是同时优化所有的自由度。 * 为了符合目标 2 和 3,一个基于优化的方法可以被一般且自动应用于任何用户定义的域和可视化表现,不需要程序员思考布局过程的细节。在我们的系统中,优化问题被定义为使用常识的关键词在 STYLE 中以及将基本操作连接在一起。因为图的规划与解题的细节是分离的,优化策略可以被改变和改进在系统未来的版本中同时保持与现有代码的兼容性。基于优化的方法的主要开销是把需求放在上游系统设计:所有用来定义可视化风格的表达都是可区分的。就如在 Sec. 4.2 中讨论的,这些需求可以通过标准技术来极大满足。 * 通常来说,图优化是一个有挑战的问题就其本身而言,我们当然不是为了最后在这篇文章中解决。当前,我们仅仅用一个通用的约束下降求解。然而,我们很高兴找到这个简单的方法来处理很多种来自不同领域的例子而不需要领域特定的策略。 * 插件 * Penrose 最后的设计决策是提供系统层级的可扩展性通过插件接口来调用外部编码在 SUBSTANCE 和 STYLE 中。提供一个插件系统是基本的让用户整合特定的解决特殊的图形和逻辑问题的外部编码。事实上,这些整合外部编码的接口已经由许多系统提供了。Penrose 插件的接口被设计定义一个清楚和简单的边界在 Penrose 系统和插件之间,使每一个部分能专攻于特长。一个插件可以分析和增加定义在 SUBSTANCE 中的抽象对象也可以分析和增加 STYLE 中的数字信息。这个简单的接口允许插件用任何语言编写(或特制于其他系统)而且独立运算于 Penrose 的实现细节。然而,一个插件不能改变现存的 SUBSTANCE 或 STYLE 程序或直接生成静态的图形内容,因为这些插件会遗弃 Penrose 提供的优点,比如重塑内容和避免绝对坐标使用的能力。Fig.4 说明了一个简单插件如何用于 SUBSTANCE 和 STYLE 信息来创建相应的图。 * 相关的系统 * 这里我们考虑了我们的系统设计如何关联其他把抽象数学关系转换成可视化图像的系统。其他类型的工具,例如通用绘图工具也可以用来作图,虽然很快就会遇到障碍,比如大规模图形生成或发展大量现有图的风格。一个关联工作的更广的讨论可以被发现在我们的一次试验性研究关于人们如何使用图形工具。 * 有三种主要系统来转换抽象的输入为可视化表达。基于语言的系统,例如 TikZ,是域无关的以及提供了重要的灵活性对于可视化表达。类数学的语言的使用影响了 SUBSTANCE 的设计。然而,现存的系统没有分割数学内容和可视化表达。例如,TikZ 是域无关和表现无关的因为它需要指定图在一个低层级(例如自定义坐标和风格),使得程序更难修改和重用。而且,因为只有浅层的数学语义,很难推出在域层级的程序。 * 基于绘制的系统,例如 Mathematica 和 GeoGebra,使标准化数学表达可以被使用作为输入然后自动化生成富有吸引力的图。仅仅作为一个图形计算器很容易拿起来和使用对大多数数学学生来说,这些工具给我们灵感来提供一个分层布置的方法给 Penrose 使得它在说明上对不那么专业的用户来说也可以接受。然而,就像一个图形计算器,可视化表达在这些系统是极大封装的,容易接受的域也是比较确定的。例如,Mathematica 不允许用户定义类型,为了走出系统提供的可视化工具,必须提供低层的指令。 * 最后,像 graphviz 和 Geometry Constructions Language 的系统把熟悉的特定域语言转换成高质量的图。域相当狭窄,几乎没有机会扩展语言或定义新的可视化。然后这些系统的便利性和力量在他们各自的域内给我们提供了灵感构建一个系统有更好的扩展性。更广泛地,所有这些系统和我们共享一些设计目标,一个主要的不同是 Penrose 被设计从头作为一个可延展的平台来构建绘图工具,而不是单片终端用户工具。 * 语言框架 * Penrose 的语言框架包含三种不同作用的语言: * DOMAIN 声明了对象,关系和在数学域中可获得的符号 * SUBSTANCE 创造确定的数学断言在一些域中 * STYLE 定义了一个一般的映射从数学断言在一些域到一个可视化表达 * 一个包包含一个 DOMAIN 和一个或更多可共存的 STYLE 程序,可以被用来说明 SUBSTANCE 程序从给出的域。虽然一些开始的包是从在 Sec.5 讨论的例子中给出的,STYLE 和 DOMAIN 真正的用处可以使 Penrose 变得更容易扩展。在这个部分我们说明这些语言通过运行一个线性代数包的例子。这三个语言的语法在辅助材料中给出。 * DOMAIN 语言 * 一个 DOMAIN 脚本描述了数学的域通过定义对象和符号可以被关联的 SUBSTANCE 和 STYLE 程序使用。一个局部的例子对线性代数被展现在 Fig.10。type 行定义了可用的对象类型,function 行定义了域和陪域对可用的函数,Predicate 行定义了对象间可能的关系,包括一元谓词。更重要的是,DOMAIN 脚本是完全抽象的:它没有定义对象的特定表示,也没有定义函数和谓词的内容。例如,我们在这里没有说一个向量是由一系列坐标编码的,我们也没有写一个额外操作在这些坐标上。具体的可视化解释对这些定义是由 STYLE 程序给出的。类型可以通过 constructors 给出字段。例如,语句 * constructor MakeInterval: Real min * Real max -> Interval * 指定了类型 min 和 max 为 Interval 可以被从 SUBSTANCE 或 STYLE 程序获得。通过语法的子类型 Subtype <: Type 促进了一般化编程。最后,符号行定义了可选的语法糖可以简化编码。 * SUBSTANCE 语言 * 每一个 SUBSTANCE 语言或: 1. 声明了一个对象 2. 指定一个对象的属性 3. 指定对象之间的关系在 DOMAIN 语言中 * 就像在数学中,不是全部属性都需要被完全指定。例如,可以仅仅讨论一个点不给出其明确的坐标。同时,这些断言描述了上下文围绕所有的被定义的数学对象和关系。 * Fig.11 展现了一个例子 SUBSTANCE 编码如何指定一对向量的属性和关系。更重要的是,这些断言不包括任何数值计算。比如,没有坐标指定给 x1 为了保持其单位化,事实上,向量空间 X 甚至没有明确的尺寸。相对的,断言指定了持久的纯粹象征的关系给可视化提供关键;指定坐标和属性之后会由布局引擎决定。最后两行标注了字符串可以被 STYLE 程序使用,这里用的是 TEX 符号。Fig.11,中间展示了一个 “sugared” 版本的程序使用了符号定义在 DOMAIN 中。用户可以用任何方式写程序,依赖于他们编辑器的功能。 * STYLE 语言 * STYLE 指定了 SUBSTANCE 程序中的表达如何转换成图形对象和关系。它是一个规格声明语言共享了许多 CSS 的特点。核心原则是概述基本规则然后重定义这些规则通过 cascading。每一个规则使用一个选择器来模式匹配出现在 SUBSTANCE 编码中的对象和关系。一系列声明指定了一个相应的可视化,例如,通过发散图形基元或施加约束。每一个生命或指定了一个值给一个类型,或指定了一个约束或目标。一个例子被显示在 Fig.12 中,定义了在 Fig.11 中的 SUBSTANCE 程序中用的部分风格。我们还用这个例子来强调这个语言的基本特点。 * 选择器 * 一个选择器使用模式匹配来指定哪些对象会被一个规则风格化。不像常规表示,选择器不匹配 SUBSTANCE 编码的文字串,也不匹配对象和关系定义在上下文中。一个简单的例子是一个选择器,匹配一个类型的每个实例,由关键词 forall 指定。例如,第一行匹配了所有的向量空间。在随后的声明中,U 引用的向量空间 X 从 SUBSTANCE 程序中。关键词 where 限制了匹配满足一个或更多关系的对象;例如,第 37 行匹配所有的正交向量。也可以用带引号的名字匹配;例如,第 48 行仅仅匹配向量 x2。选择器可以在未来被填充来允许其他的一阶逻辑声明。 * 串联 * 一个串联机制允许规则来重定义更多特定的对象或关系。例如,第 48 行的选择器匹配了一个特定向量,重定义一个更早的应用于所有向量的一个规则。优先规则被定义在 STYLE 文件中,之后的规则可以设计任何之前被定义的类型。关键词 override 说明一个规则会改写现存的一个类型,否则编译器会发出警告 * 类型 * 一个对象的可视化表现被特定通过创造指定值的类型。例如,第 17-23 行一个类型叫做 u.arrow 被创造和指定了一个表达来描述一个箭头。类型创建在分配之上可以有任何与保留字不冲突的命名。类型同创不和单个对象关联,也可以被局部指定为一个规则。例如,第 38 行被用来画直角标记在任何正交向量对之间。每个对象自动有 name 和 label 类型存储它的 SUBSTANCE 名字和标签支付穿,以及任何通过构造器创造的类型。 * 属性 * STYLE 提供了嵌入的图元伴随一系列属性。就像类型,属性可以被赋值。如果一个值没有被赋予,它会被赋默认值,可能是一个等待值。例如,一个箭头可能默认是黑的,然而盒子的宽度可能会被优化。 * 值和表达 * 原子的值可以与表达结合。例如,第 10 - 12 行赋值,然而第 6 - 9 行指定复合表达式包括行内计算。第 26 行指定值通过一个路径对象(一系列表达式用.隔开)。这种赋值通过引用完成。表达式也可以从插件获得值。一个非常重要的构造是等待值,就像在第 20 行中的 ?。这一行指定箭头终点的位置没有确定,之后会被解决器自动决定。 * 约束和目标 * 约束和目标描述了等待值应该怎么表现。实际上,关键词 ensure 定义了一个强约束,图必须要满足。例如,第 45 行特指两个正交向量一定要画直角。关键词 encourage 指定一个关系应该要尽可能被满足。例如,第 33 行说明一个向量的标签应该被放在终点尽可能近的地方。这些表达被翻译成约束和能量函数来构成数值优化问题。 * 布局引擎 * 布局引擎把 Penrose 编码翻译成图像,有两个主要的阶段:编译器翻译编码成一个优化问题描述了可能的图像,解题器来解决这个问题。这些值用来绘制最后的图像。为简单起见,目标是自动生成一个静态的图,但同一个管线可以被延展来支持功能,比如交互。 * 编译器 * 编译器的输入是三种文件:一个 DOMAIN 伴随着 SUBSTANCE 和 STYLE 程序。输出是一个最优化约束问题,表达为一个计算图 * 解析和类型检查:我们解析每一个输入文件为 ASTs (抽象语法树),采用静态的类型检查来确保类型是符合语法规则的以及变量是类型良好的。我们首先类型检查 DOMAIN 程序因为它定义了 SUBSTANCE 和 STYLE 程序的有效类型,然后用这些类型检查 SUBSTANCE 程序和 STYLE 编码里的选择器。 * 计算图:AST 相结合来定义一个计算图,计算图编码操作来定义最后的图。为了构建这个计算图,我们应用了一个标准模式匹配和串联过程:遍历 STYLE 程序里的规则,找到 SUBSTANCE 变量的元祖匹配选择器的模式,然后修改图根据声明在匹配规则内。例如,当第一个选择器 VectorSpace U 从 Fig.12 匹配了变量 X 从 Fig.11,我们把节点加入图然后编码这个向量空间的轴。通常来说,声明也能从图中删除节点或者连接之前加入的节点。一旦这个转换完成,我们就把全部抽象的数学描述替换成具体的图形代表。剩下的工作是决定等待值和那些依赖他们的值,会由解决器完成。 * 优化图:为了编码可优化问题,我们从计算图中收集术语变为一个客观约束图。每一个 ensure 和 encourage 声明都被替代为相应的数学表达式。例如,ensure equal(x, y) 被翻译成约束 x - y = 0,解决器追求执行到底,然而 encourage equal(x, y) 变成了客观表达 (x - y)^2,解决器追求尽可能最小化。整体约束集是所有约束的交集,整体客观表达是一系列客观表达式。现在 Penrose 提供一个确定的约束和客观表达集合,虽然能很直接扩展 STYLE 来允许用户定义的行内表达式。 * 解决器 * 编译器制造的优化图描述了一个优化问题用标准形式,例如目标函数依照等式和不等式的约束的最小值。这些问题可以被许多标准方法解决。我们目前使用外点方法以一个不可到达的点开始,然后把它推行到一个可行的配制通过更严格的惩罚函数——镜像手写的过程。同时,外点方法是一个恰当地选择因为: * 一个可行的起始点通常是未知的 * 通过把约束转化为严格的惩罚函数,我们可以使用梯度下降算法不直接支持约束下的优化 * 实际上,我们使用 L-BFGS 通过一个线搜索策略适配非光滑目标。考虑到我们优化图的丰富结构,可以被关联回程序语义学,有大量机会来改进这个基本策略,例如把问题分解成更小可以独立优化或采用一个 SMT 解决器来找到一个可行的初始状态。 * 初始化:就像一个人类画图者可能会考虑一些初始管理,我们随机采样一些设置然后优化最有希望的几个,例如在外点问题中总能量最小的。初始值被均匀随机列出从一个与他们类型相关的范围中;例如,RGB 值从 [0, 1] 中采样 * 错误和警告:由于我们的语言框架很普通,一个变成这可能定义困难或不可能的优化问题。因此,我们不能保证 Penrose 产生一个有效的图。然而,系统可以提供反馈通过打印一个错误信息如果任何约束值不为 0。无效的结果图也可以提供有用的视觉参考为什么 STYLE 程序失败了。 * 插件 * 插件是一段外部代码,使用任何语言编写,从特殊的一对 SUBSTANCE 和 STYLE 文件中提供信息,可以产生更多 SUBSTANCE 和 STYLE 信息在特殊的文件中给 Penrose 使用。一个插件运行当使用特殊 STYLE 绘图的时候。一个 STYLE 可以声明使用的插件在文件头伴随符号 plugin "myPlugin"(args),声明了插件 myPlugin 可以运行在给出的变元表。当一个图被创建,插件给 SUBSTANCE 程序是一个 JSON 文件,变量给 STYLE 的是命令行变元。插件可以输出新的 SUBSTANCE 编码作为一个文本文件或一系列值给 SUBSTANCE 变量的域,编码为一个 JSON 文件。插件生成的 SUBSTANCE 编码加入到现存的 SUBSTANCE 程序中,插件产生的值可以被 STYLE 访问通过符号 myPlugin[variable][field]。记住插件只会运行一次,优先于整个 Penrose 编码的处理。因此,插件生成的值不会被布局引擎优化,所以插件代码没有必要可区分的。插件的使用例子,看 Sec.5.2 和 Sec.5.5。 * 渲染 * 在这篇文章中我们聚焦于绘制 2D 向量图形,但是原则上没有任何我们的系统设计限制我们只能完成这个特殊目标。例如,基于约束的方法恰好适用于产生 3D 对象的管理可以被渲染通过逼真射线跟踪,或者甚至约束的交互图可以被用在 VR。在我们现在的实现中,图元被翻译成原生 SVG 元素通过 React.js,标签被后处理从原生 TEX 到 SVG 路径使用 MathJax。因此 Penrose 编码是非常简便的,我们把它作为 metadata 嵌入 SVG,简化再现。我们也把 SUBSTANCE 名字作为工具提示嵌入来提高可接受性。 * 开发环境 * 为了安装开发,我们构建了一个基于网页的 IDE 高亮有潜力的高级图形工具在 Penrose 中。例如,由于 DOMAIN 语法有标准的结构,IDE 可以提供特性例如自动完成和符号高亮对任何域。我们乐观于再 Sec.2 中的设计选择会支持 Penrose 的使用作为一个平台来构建绘图工具与用户案例无关在这篇论文。 * 实现 * Penrose 系统用 Haskell 编写,渲染前后端使用 Typescript。我们使用 Haskell 库写我们自己的解释器来实现自动区分。我们提供一个输出目标和渲染器,伴随一系列图元宽松基于 SVG,增加通常 SVG 用户手写增加的特性,例如箭头。我们也提供一系列对象和约束来指定布局空间,例如形状控制和邻接关系,其他函数来实现空间查询,例如计算盒状边界和两两距离。通过社区用户的可持续运用可以指向标准库的方法。这个系统已经开源:github.com/penrose/penrose